root/fs/affs/inode.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. affs_put_super
  2. affs_write_super
  3. affs_parent_ino
  4. parse_options
  5. affs_read_super
  6. affs_statfs
  7. affs_read_inode
  8. affs_write_inode
  9. affs_notify_change
  10. affs_put_inode
  11. affs_new_inode
  12. affs_add_entry
  13. init_affs_fs
  14. init_module
  15. cleanup_module

   1 /*
   2  *  linux/fs/affs/inode.c
   3  *
   4  *  (c) 1996  Hans-Joachim Widmaier - Modified for larger blocks.
   5  *
   6  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
   7  * 
   8  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
   9  *
  10  *  (C) 1991  Linus Torvalds - minix filesystem
  11  */
  12 
  13 #include <linux/module.h>
  14 #include <linux/errno.h>
  15 #include <linux/fs.h>
  16 #include <linux/malloc.h>
  17 #include <linux/stat.h>
  18 #include <linux/sched.h>
  19 #include <linux/affs_fs.h>
  20 #include <linux/kernel.h>
  21 #include <linux/mm.h>
  22 #include <linux/string.h>
  23 #include <linux/locks.h>
  24 #include <linux/errno.h>
  25 #include <linux/genhd.h>
  26 #include <linux/major.h>
  27 #include <linux/amigaffs.h>
  28 #include <asm/system.h>
  29 #include <asm/segment.h>
  30 
  31 extern int *blk_size[];
  32 extern struct timezone sys_tz;
  33 
  34 void affs_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  35 {
  36         int      i;
  37 
  38         pr_debug("affs_put_super()\n");
  39 
  40         lock_super(sb);
  41         if (!(sb->s_flags & MS_RDONLY)) {
  42                 for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
  43                         affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);
  44                 ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1);
  45                 secs_to_datestamp(CURRENT_TIME,
  46                                   &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
  47                 affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
  48                 mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);
  49         }
  50         if (sb->u.affs_sb.s_flags & SF_PREFIX)
  51                 kfree(sb->u.affs_sb.s_prefix);
  52         kfree(sb->u.affs_sb.s_bitmap);
  53         affs_brelse(sb->u.affs_sb.s_root_bh);
  54         set_blocksize(sb->s_dev,BLOCK_SIZE);
  55         sb->s_dev = 0;
  56         unlock_super(sb);
  57         MOD_DEC_USE_COUNT;
  58         return;
  59 }
  60 
  61 static void affs_write_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63         int      i, clean = 2;
  64 
  65         if (!(sb->s_flags & MS_RDONLY)) {
  66                 for (i = 0, clean = 1; i < sb->u.affs_sb.s_bm_count; i++) {
  67                         if (buffer_dirty(sb->u.affs_sb.s_bitmap[i].bm_bh)) {
  68                                 clean = 0;
  69                                 break;
  70                         }
  71                 }
  72                 ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(clean);
  73                 secs_to_datestamp(CURRENT_TIME,
  74                                   &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
  75                 affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
  76                 mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);
  77                 sb->s_dirt = !clean;    /* redo until bitmap synced */
  78         } else
  79                 sb->s_dirt = 0;
  80 
  81         pr_debug("AFFS: write_super() at %d, clean=%d\n",CURRENT_TIME,clean);
  82 }
  83 
  84 static struct super_operations affs_sops = { 
  85         affs_read_inode,
  86         affs_notify_change,
  87         affs_write_inode,
  88         affs_put_inode, 
  89         affs_put_super,
  90         affs_write_super,
  91         affs_statfs,
  92         NULL                    /* remount */
  93 };
  94 
  95 int affs_parent_ino(struct inode *dir)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         int root_ino = (dir->i_sb->u.affs_sb.s_root_block);
  98 
  99         if (!S_ISDIR (dir->i_mode)) {
 100                 printk ("affs_parent_ino: argument is not a directory\n");
 101                 return root_ino;
 102         }
 103         if (dir->i_ino == root_ino)
 104                 return root_ino;
 105         return dir->u.affs_i.i_parent;
 106 }
 107 
 108 
 109 static int
 110 parse_options(char *options, uid_t *uid, gid_t *gid, int *mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 111               int *reserved, int *root, int *blocksize, char **prefix,
 112               char *volume, unsigned long *mount_opts)
 113 {
 114         char    *this_char, *value;
 115         int      f;
 116 
 117         /* Fill in defaults */
 118 
 119         *uid        = 0;
 120         *gid        = 0;
 121         *reserved   = 2;
 122         *root       = -1;
 123         *blocksize  = -1;
 124         *prefix     = "/";
 125         volume[0]   = ':';
 126         volume[1]   = 0;
 127         *mount_opts = 0;
 128         if (!options)
 129                 return 1;
 130         for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
 131                 f = 0;
 132                 if ((value = strchr(this_char,'=')) != NULL)
 133                         *value++ = 0;
 134                 if (!strcmp(this_char,"protect")) {
 135                         if (value) {
 136                                 printk("AFFS: option protect does not take an argument\n");
 137                                 return 0;
 138                         }
 139                         *mount_opts |= SF_IMMUTABLE;
 140                 }
 141                 else if (!strcmp(this_char,"verbose")) {
 142                         if (value) {
 143                                 printk("AFFS: option verbose does not take an argument\n");
 144                                 return 0;
 145                         }
 146                         *mount_opts |= SF_VERBOSE;
 147                 }
 148                 else if ((f = !strcmp(this_char,"uid")) || !strcmp(this_char,"setuid")) {
 149                         if (!value)
 150                                 *uid = current->uid;
 151                         else if (!*value) {
 152                                 printk("AFFS: argument for uid option missing\n");
 153                                 return 0;
 154                         } else {
 155                                 *uid = simple_strtoul(value,&value,0);
 156                                 if (*value)
 157                                         return 0;
 158                                 if (!f)
 159                                         *mount_opts |= SF_SETUID;
 160                         }
 161                 }
 162                 else if ((f = !strcmp(this_char,"gid")) || !strcmp(this_char,"setgid")) {
 163                         if (!value)
 164                                 *gid = current->gid;
 165                         else if (!*value) {
 166                                 printk("AFFS: argument for gid option missing\n");
 167                                 return 0;
 168                         } else {
 169                                 *gid = simple_strtoul(value,&value,0);
 170                                 if (*value)
 171                                         return 0;
 172                                 if (!f)
 173                                         *mount_opts |= SF_SETGID;
 174                         }
 175                 }
 176                 else if (!strcmp(this_char,"prefix")) {
 177                         if (!value) {
 178                                 printk("AFFS: The prefix option requires an argument\n");
 179                                 return 0;
 180                         }
 181                         *prefix = kmalloc(strlen(value) + 1,GFP_KERNEL);
 182                         if (!*prefix)
 183                                 return 0;
 184                         strcpy(*prefix,value);
 185                         *mount_opts |= SF_PREFIX;
 186                 }
 187                 else if (!strcmp(this_char,"volume")) {
 188                         if (!value) {
 189                                 printk("AFFS: The volume option requires an argument\n");
 190                                 return 0;
 191                         }
 192                         if (strlen(value) > 30)
 193                                 value[30] = 0;
 194                         strcpy(volume,value);
 195                 }
 196                 else if (!strcmp(this_char,"mode")) {
 197                         if (!value || !*value) {
 198                                 printk("AFFS: The mode option requires an argument\n");
 199                                 return 0;
 200                         }
 201                         *mode = simple_strtoul(value,&value,8) & 0777;
 202                         if (*value)
 203                                 return 0;
 204                         *mount_opts |= SF_SETMODE;
 205                 }
 206                 else if (!strcmp(this_char,"reserved")) {
 207                         if (!value || !*value) {
 208                                 printk("AFFS: The reserved option requires an argument\n");
 209                                 return 0;
 210                         }
 211                         *reserved = simple_strtoul(value,&value,0);
 212                         if (*value)
 213                                 return 0;
 214                 }
 215                 else if (!strcmp(this_char,"root")) {
 216                         if (!value || !*value) {
 217                                 printk("AFFS: The root option requires an argument\n");
 218                                 return 0;
 219                         }
 220                         *root = simple_strtoul(value,&value,0);
 221                         if (*value)
 222                                 return 0;
 223                 }
 224                 else if (!strcmp(this_char,"bs")) {
 225                         if (!value || !*value) {
 226                                 printk("AFFS: The bs option requires an argument\n");
 227                                 return 0;
 228                         }
 229                         *blocksize = simple_strtoul(value,&value,0);
 230                         if (*value)
 231                                 return 0;
 232                         if (*blocksize != 512 && *blocksize != 1024 && *blocksize != 2048
 233                             && *blocksize != 4096) {
 234                                 printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed).\n");
 235                                 return 0;
 236                         }
 237                 }
 238                 /* Silently ignore the quota options */
 239                 else if (!strcmp (this_char, "grpquota")
 240                          || !strcmp (this_char, "noquota")
 241                          || !strcmp (this_char, "quota")
 242                          || !strcmp (this_char, "usrquota"))
 243                         ;
 244                 else {
 245                         printk("AFFS: Unrecognized mount option %s\n",
 246                                this_char);
 247                         return 0;
 248                 }
 249         }
 250         return 1;
 251 }
 252 
 253 struct super_block *
 254 affs_read_super(struct super_block *s,void *data, int silent)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256         struct buffer_head      *bh = NULL;
 257         struct buffer_head      *bb;
 258         kdev_t                   dev = s->s_dev;
 259         int                      root_block;
 260         int                      size;
 261         ULONG                    chksum;
 262         ULONG                   *bm;
 263         LONG                     ptype, stype;
 264         int                      mapidx = 0;
 265         int                      num_bm;
 266         int                      i;
 267         int                      key;
 268         int                      blocksize;
 269         uid_t                    uid;
 270         gid_t                    gid;
 271         int                      mode, reserved;
 272         int                      zm_size;
 273         unsigned long            mount_flags;
 274         ULONG                    offset;
 275 
 276         pr_debug("affs_read_super(%s)\n",(const char *)data);
 277 
 278         MOD_INC_USE_COUNT;
 279 
 280         if (!parse_options(data,&uid,&gid,&mode,&reserved,&root_block,
 281             &blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) {
 282                 s->s_dev = 0;
 283                 printk("AFFS: error parsing options.\n");
 284                 MOD_DEC_USE_COUNT;
 285                 return NULL;
 286         }
 287         lock_super(s);
 288 
 289         /* Get the size of the device in 512-byte blocks.
 290          * If we later see that the partition uses bigger
 291          * blocks, we will have to change it.
 292          */
 293 
 294         size                      = 2 * blk_size[MAJOR(dev)][MINOR(dev)];
 295         s->u.affs_sb.s_bitmap     = NULL;
 296         s->u.affs_sb.s_root_bh    = NULL;
 297         s->u.affs_sb.s_flags      = mount_flags;
 298         s->u.affs_sb.s_mode       = mode;
 299         s->u.affs_sb.s_uid        = uid;
 300         s->u.affs_sb.s_gid        = gid;
 301 
 302         if (size == 0) {
 303                 s->s_dev = 0;
 304                 unlock_super(s);
 305                 printk("affs_read_super: could not determine device size\n");
 306                 goto out;
 307         }
 308         s->u.affs_sb.s_partition_size = size;
 309         s->u.affs_sb.s_reserved       = reserved;
 310 
 311         /* Try to find root block. It's location may depend on the block size. */
 312 
 313         s->u.affs_sb.s_hashsize = 0;
 314         if (blocksize > 0) {
 315                 chksum = blocksize;
 316                 num_bm = blocksize;
 317         } else {
 318                 chksum = 512;
 319                 num_bm = 4096;
 320         }
 321         for (blocksize = chksum; blocksize <= num_bm; blocksize <<= 1, size >>= 1) {
 322                 if (root_block < 0)
 323                     if (MAJOR(dev) == FLOPPY_MAJOR)
 324                         s->u.affs_sb.s_root_block = size/4;
 325                     else
 326                         s->u.affs_sb.s_root_block = (reserved + size - 1) / 2;
 327                 else
 328                         s->u.affs_sb.s_root_block = root_block;
 329                 pr_debug("Trying bs=%d bytes, root at %d, size=%d blocks (%d reserved)\n",
 330                         blocksize,s->u.affs_sb.s_root_block,size,reserved);
 331                 set_blocksize(dev,blocksize);
 332                 bh = affs_bread(dev,s->u.affs_sb.s_root_block,blocksize);
 333                 if (!bh) {
 334                         printk("AFFS: unable to read root block\n");
 335                         goto out;
 336                 }
 337                 if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) &&
 338                     ptype == T_SHORT && stype == ST_ROOT) {
 339                         s->s_blocksize          = blocksize;
 340                         s->u.affs_sb.s_hashsize = blocksize / 4 - 56;
 341                         break;
 342                 }
 343                 affs_brelse(bh);
 344                 bh = NULL;
 345         }
 346         if (!s->u.affs_sb.s_hashsize) {
 347                 affs_brelse(bh);
 348                 if (!silent)
 349                         printk("AFFS: Can't find a valid root block on device %s\n",kdevname(dev));
 350                 goto out;
 351         }
 352         root_block = s->u.affs_sb.s_root_block;
 353 
 354         s->u.affs_sb.s_partition_size   = size;
 355         s->s_blocksize_bits             = blocksize == 512 ? 9 :
 356                                           blocksize == 1024 ? 10 :
 357                                           blocksize == 2048 ? 11 : 12;
 358 
 359         /* Find out which kind of FS we have */
 360         bb = affs_bread(dev,0,s->s_blocksize);
 361         if (bb) {
 362                 chksum = htonl(*(ULONG *)bb->b_data);
 363                 switch (chksum) {
 364                         case MUFS_FS:
 365                         case MUFS_INTLFFS:
 366                                 s->u.affs_sb.s_flags |= SF_MUFS;
 367                                 /* fall thru */
 368                         case FS_INTLFFS:
 369                                 s->u.affs_sb.s_flags |= SF_INTL;
 370                                 break;
 371                         case MUFS_FFS:
 372                                 s->u.affs_sb.s_flags |= SF_MUFS;
 373                                 break;
 374                         case FS_FFS:
 375                                 break;
 376                         case MUFS_OFS:
 377                                 s->u.affs_sb.s_flags |= SF_MUFS;
 378                                 /* fall thru */
 379                         case FS_OFS:
 380                                 s->u.affs_sb.s_flags |= SF_OFS;
 381                                 break;
 382                         case MUFS_INTLOFS:
 383                                 s->u.affs_sb.s_flags |= SF_MUFS;
 384                                 /* fall thru */
 385                         case FS_INTLOFS:
 386                                 s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;
 387                                 break;
 388                         case FS_DCOFS:
 389                         case FS_DCFFS:
 390                         case MUFS_DCOFS:
 391                         case MUFS_DCFFS:
 392                                 if (!silent)
 393                                         printk("AFFS: Unsupported filesystem on device %s: %08X\n",
 394                                                 kdevname(dev),chksum);
 395                                 if (0)
 396                         default:
 397                                 printk("AFFS: Unknown filesystem on device %s: %08X\n",
 398                                        kdevname(dev),chksum);
 399                                 affs_brelse(bb);
 400                                 goto out;
 401                 }
 402                 affs_brelse(bb);
 403         } else {
 404                 printk("AFFS: Can't get boot block.\n");
 405                 goto out;
 406         }
 407         if (mount_flags & SF_VERBOSE) {
 408                 chksum = ntohl(chksum);
 409                 printk("AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n",
 410                        GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0],
 411                        &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1],
 412                        (char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
 413         }
 414 
 415         s->s_magic = AFFS_SUPER_MAGIC;
 416         s->s_flags = MS_NODEV | MS_NOSUID;
 417 
 418         /* Keep super block in cache */
 419         if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) {
 420                 printk("AFFS: Can't read root block a second time\n");
 421                 goto out;
 422         }
 423 
 424         /* Allocate space for bitmap pointers and read the bitmap */
 425 
 426         size    = s->u.affs_sb.s_partition_size - reserved;
 427         num_bm  = (size + s->s_blocksize * 8 - 32 - 1) / (s->s_blocksize * 8 - 32);
 428         zm_size = (num_bm *  (1 << (s->s_blocksize_bits - 8)) + 7) / 8;
 429         ptype   = num_bm * sizeof(struct affs_bm_info) + zm_size +
 430                   MAX_ZONES * sizeof(struct affs_zone);
 431         if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype,GFP_KERNEL))) {
 432                 printk("AFFS: Can't get memory for bitmap info.\n");
 433                 goto out;
 434         }
 435         memset(s->u.affs_sb.s_bitmap,0,ptype);
 436 
 437         if( (ULONG)((UBYTE *)bh->b_data + s->s_blocksize - 200) == 0 ) {
 438                 if (!(s->s_flags & MS_RDONLY)) {
 439                         printk("AFFS: Bitmap invalid - mounting %s read only.\n",kdevname(dev));
 440                         s->s_flags |= MS_RDONLY;
 441                 }
 442                 affs_brelse(bh);
 443                 bh = NULL;
 444                 goto nobitmap;
 445         }
 446 
 447         pr_debug("AFFS: %d bitmap blocks\n",num_bm);
 448 
 449         key    = root_block;
 450         ptype  = s->s_blocksize / 4 - 49;
 451         stype  = ptype + 25;
 452         offset = s->u.affs_sb.s_reserved;
 453         while (bh) {
 454                 bm = (ULONG *)bh->b_data;
 455                 for (i = ptype; i < stype && bm[i]; i++, mapidx++) {
 456                         if (mapidx >= num_bm) {
 457                                 printk("AFFS: Not enough bitmap space!?\n");
 458                                 goto out;
 459                         }
 460                         bb = affs_bread(s->s_dev,htonl(bm[i]),s->s_blocksize);
 461                         if (bb) {
 462                                 if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) /*&&
 463                                     !(s->s_flags & MS_RDONLY)*/) {
 464                                         printk("AFFS: Bitmap (%d,key=%lu) invalid - mounting %s read only.\n",
 465                                                mapidx, htonl(bm[i]),
 466                                                kdevname(dev));
 467                                         s->s_flags |= MS_RDONLY;
 468                                 }
 469                                 if (size <= s->s_blocksize * 8 - 32) {  /* last bitmap */
 470                                         ptype = size / 32 + 1;          /* word number */
 471                                         key   = size & 0x1F;            /* used bits */
 472                                         if (key) {
 473                                                 chksum = ntohl(0x7FFFFFFF >> (31 - key));
 474                                                 ((ULONG *)bb->b_data)[ptype] &= chksum;
 475                                                 affs_fix_checksum(s->s_blocksize,bb->b_data,0);
 476                                                 /* no need to mark buffer as dirty */
 477                                         }
 478                                         ptype = (size + 31) & ~0x1F;
 479                                         size  = 0;
 480                                         if (!(s->s_flags & MS_RDONLY))
 481                                                 s->u.affs_sb.s_flags |= SF_BM_VALID;
 482                                 } else {
 483                                         ptype = s->s_blocksize * 8 - 32;
 484                                         size -= ptype;
 485                                 }
 486                                 s->u.affs_sb.s_bitmap[mapidx].bm_firstblk = offset;
 487                                 s->u.affs_sb.s_bitmap[mapidx].bm_size     = ptype;
 488                                 s->u.affs_sb.s_bitmap[mapidx].bm_bh       = bb;
 489                                 s->u.affs_sb.s_bitmap[mapidx].bm_free     =
 490                                   affs_count_free_bits(ptype/8,bb->b_data + 4);
 491                                 offset += ptype;
 492                         } else {
 493                                 printk("AFFS: Can't read bitmap.\n");
 494                                 goto out;
 495                         }
 496                 }
 497                 key   = htonl(bm[stype]);   /* Next block of bitmap pointers */
 498                 ptype = 0;
 499                 stype = s->s_blocksize / 4 - 1;
 500                 affs_brelse(bh);
 501                 if (key) {
 502                         if (!(bh = affs_bread(s->s_dev,key,s->s_blocksize))) {
 503                                 printk("AFFS: Can't read bitmap extension.\n");
 504                                 goto out;
 505                         }
 506                 } else
 507                         bh = NULL;
 508         }
 509         if (mapidx != num_bm) {
 510                 printk("AFFS: Got only %d bitmap blocks, expected %d\n",
 511                        mapidx, num_bm);
 512                 goto out;
 513         }
 514         s->u.affs_sb.s_num_zones = ((num_bm - 1) << (s->s_blocksize_bits - 8))+
 515                                    (s->u.affs_sb.s_bitmap[num_bm - 1].bm_size + 2047) / 2048;
 516 nobitmap:
 517         s->u.affs_sb.s_bm_count  = mapidx;
 518         s->u.affs_sb.s_zones     = (struct affs_zone *)&s->u.affs_sb.s_bitmap[num_bm];
 519         s->u.affs_sb.s_zonemap   = (char *)&s->u.affs_sb.s_zones[MAX_ZONES];
 520 
 521         /* set up enough so that it can read an inode */
 522 
 523         s->s_dev       = dev;
 524         s->s_op        = &affs_sops;
 525         s->s_mounted   = iget(s,root_block);
 526         unlock_super(s);
 527 
 528         if (!(s->s_mounted)) {
 529                 s->s_dev = 0;
 530                 printk("AFFS: get root inode failed\n");
 531                 MOD_DEC_USE_COUNT;
 532                 return NULL;
 533         }
 534 
 535         /* If the fs is mounted r/w, create data zones, else free bitmaps. */
 536 
 537         if (!(s->s_flags & MS_RDONLY)) {
 538                 ROOT_END(s->u.affs_sb.s_root_bh->b_data,s->s_mounted)->bm_flag = 0;
 539                 secs_to_datestamp(CURRENT_TIME,&ROOT_END(s->u.affs_sb.s_root_bh->b_data,
 540                                   s->s_mounted)->disk_altered);
 541                 affs_fix_checksum(s->s_blocksize,s->u.affs_sb.s_root_bh->b_data,5);
 542                 mark_buffer_dirty(s->u.affs_sb.s_root_bh,1);
 543                 affs_make_zones(s);
 544         } else {
 545                 for (i = 0; i < s->u.affs_sb.s_bm_count; i++) {
 546                         affs_brelse(s->u.affs_sb.s_bitmap[i].bm_bh);
 547                         s->u.affs_sb.s_bitmap[i].bm_bh = NULL;
 548                 }
 549         }
 550 
 551 
 552         pr_debug("AFFS: s_flags=%lX\n", s->s_flags);
 553         return s;
 554 
 555  out: /* Kick out for various error conditions */
 556         affs_brelse (bh);
 557         affs_brelse(s->u.affs_sb.s_root_bh);
 558         if (s->u.affs_sb.s_bitmap) {
 559                 for (i = 0; i < mapidx; i++)
 560                         affs_brelse(s->u.affs_sb.s_bitmap[i].bm_bh);
 561                 kfree(s->u.affs_sb.s_bitmap);
 562         }
 563         s->s_dev = 0;
 564         unlock_super(s);
 565         MOD_DEC_USE_COUNT;
 566         return NULL;
 567 }
 568 
 569 void
 570 affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 571 {
 572         ULONG            free;
 573         struct statfs    tmp;
 574 
 575         pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",
 576                 sb->u.affs_sb.s_partition_size, sb->u.affs_sb.s_reserved);
 577 
 578         free          = affs_count_free_blocks(sb);
 579         tmp.f_type    = AFFS_SUPER_MAGIC;
 580         tmp.f_bsize   = sb->s_blocksize;
 581         tmp.f_blocks  = sb->u.affs_sb.s_partition_size - sb->u.affs_sb.s_reserved;
 582         tmp.f_bfree   = free;
 583         tmp.f_bavail  = free;
 584         tmp.f_files   = 0;
 585         tmp.f_ffree   = 0;
 586         memcpy_tofs(buf,&tmp,bufsiz);
 587 }
 588 
 589 void
 590 affs_read_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 591 {
 592         struct buffer_head      *bh, *lbh;
 593         struct file_front       *file_front;
 594         struct file_end         *file_end;
 595         LONG                     block;
 596         ULONG                    prot;
 597         LONG                     ptype, stype;
 598         unsigned short           id;
 599 
 600         pr_debug("AFFS: read_inode(%lu)\n",inode->i_ino);
 601         lbh   = NULL;
 602         block = inode->i_ino;
 603         if (!(bh = affs_bread(inode->i_dev,block,AFFS_I2BSIZE(inode)))) {
 604                 printk("AFFS: unable to read i-node block %d\n",block);
 605                 return;
 606         }
 607         if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) || ptype != T_SHORT) {
 608                 printk("AFFS: read_inode(): checksum or type (ptype=%d) error on inode %d\n",
 609                        ptype, block);
 610                 affs_brelse(bh);
 611                 return;
 612         }
 613 
 614         file_front = (struct file_front *)bh->b_data;
 615         file_end   = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode));
 616         prot       = (htonl(file_end->protect) & ~0x10) ^ FIBF_OWNER;
 617 
 618         inode->u.affs_i.i_protect  = prot;
 619         inode->u.affs_i.i_parent   = htonl(file_end->parent);
 620         inode->u.affs_i.i_original = 0; 
 621         inode->u.affs_i.i_zone     = 0;
 622         inode->u.affs_i.i_hlink    = 0;
 623         inode->u.affs_i.i_pa_cnt   = 0;
 624         inode->u.affs_i.i_pa_next  = 0;
 625         inode->u.affs_i.i_pa_last  = 0;
 626         inode->u.affs_i.i_ext[0]   = 0;
 627         inode->u.affs_i.i_max_ext  = 0;
 628         inode->i_nlink             = 1;
 629         inode->i_mode              = 0;
 630 
 631         if (inode->i_sb->u.affs_sb.s_flags & SF_SETMODE)
 632                 inode->i_mode = inode->i_sb->u.affs_sb.s_mode;
 633         else
 634                 inode->i_mode = prot_to_mode(prot);
 635         
 636         if (inode->i_sb->u.affs_sb.s_flags & SF_SETUID)
 637                 inode->i_uid = inode->i_sb->u.affs_sb.s_uid;
 638         else {
 639                 id = htons(file_end->owner_uid);
 640                 if (inode->i_sb->u.affs_sb.s_flags & SF_MUFS) {
 641                         if (id == 0 || id == 0xFFFF)
 642                                 id ^= ~0;
 643                 }
 644                 inode->i_uid = id;
 645         }
 646         if (inode->i_sb->u.affs_sb.s_flags & SF_SETGID)
 647                 inode->i_gid = inode->i_sb->u.affs_sb.s_gid;
 648         else {
 649                 id = htons(file_end->owner_gid);
 650                 if (inode->i_sb->u.affs_sb.s_flags & SF_MUFS) {
 651                         if (id == 0 || id == 0xFFFF)
 652                                 id ^= ~0;
 653                 }
 654                 inode->i_gid = id;
 655         }
 656 
 657         switch (htonl(file_end->secondary_type)) {
 658                 case ST_ROOT:
 659                         inode->i_uid   = inode->i_sb->u.affs_sb.s_uid;
 660                         inode->i_gid   = inode->i_sb->u.affs_sb.s_gid;
 661                 case ST_USERDIR:
 662                         if (htonl(file_end->secondary_type) == ST_USERDIR ||
 663                             inode->i_sb->u.affs_sb.s_flags & SF_SETMODE) {
 664                                 if (inode->i_mode & S_IRUSR)
 665                                         inode->i_mode |= S_IXUSR;
 666                                 if (inode->i_mode & S_IRGRP)
 667                                         inode->i_mode |= S_IXGRP;
 668                                 if (inode->i_mode & S_IROTH)
 669                                         inode->i_mode |= S_IXOTH;
 670                                 inode->i_mode |= S_IFDIR;
 671                         } else
 672                                 inode->i_mode = S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR;
 673                         inode->i_size  = 0;
 674                         break;
 675                 case ST_LINKDIR:
 676                         inode->u.affs_i.i_original = htonl(file_end->original);
 677                         inode->u.affs_i.i_hlink    = 1;
 678                         inode->i_mode             |= S_IFDIR;
 679                         inode->i_size              = 0;
 680                         break;
 681                 case ST_LINKFILE:
 682                         inode->u.affs_i.i_original = htonl(file_end->original);
 683                         inode->u.affs_i.i_hlink    = 1;
 684                         if (!(lbh = affs_bread(inode->i_dev,inode->u.affs_i.i_original,
 685                                           AFFS_I2BSIZE(inode)))) {
 686                                 affs_brelse(bh);
 687                                 printk("AFFS: unable to read i-node block %ld\n",inode->i_ino);
 688                                 return;
 689                         }
 690                         file_end = GET_END_PTR(struct file_end,lbh->b_data,AFFS_I2BSIZE(inode));
 691                 case ST_FILE:
 692                         inode->i_mode |= S_IFREG;
 693                         inode->i_size  = htonl(file_end->byte_size);
 694                         break;
 695                 case ST_SOFTLINK:
 696                         inode->i_mode |= S_IFLNK;
 697                         inode->i_size  = 0;
 698                         break;
 699         }
 700 
 701         inode->i_mtime = inode->i_atime = inode->i_ctime
 702                        = (htonl(file_end->created.ds_Days) * (24 * 60 * 60) +
 703                          htonl(file_end->created.ds_Minute) * 60 +
 704                          htonl(file_end->created.ds_Tick) / 50 +
 705                          ((8 * 365 + 2) * 24 * 60 * 60)) +
 706                          sys_tz.tz_minuteswest * 60;
 707         affs_brelse(bh);
 708         affs_brelse(lbh);
 709         
 710         inode->i_op = NULL;
 711         if (S_ISREG(inode->i_mode)) {
 712                 if (inode->i_sb->u.affs_sb.s_flags & SF_OFS)
 713                         inode->i_op = &affs_file_inode_operations_ofs;
 714                 else
 715                         inode->i_op = &affs_file_inode_operations;
 716         } else if (S_ISDIR(inode->i_mode))
 717                 inode->i_op = &affs_dir_inode_operations;
 718         else if (S_ISLNK(inode->i_mode))
 719                 inode->i_op = &affs_symlink_inode_operations;
 720 }
 721 
 722 void
 723 affs_write_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 724 {
 725         struct buffer_head *bh;
 726         struct file_end    *file_end;
 727         short               uid, gid;
 728 
 729         pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino);
 730 
 731         inode->i_dirt = 0;
 732         if (!inode->i_nlink)
 733                 return;
 734         if (!(bh = bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)))) {
 735                 printk("AFFS: Unable to read block of inode %ld on %s\n",
 736                        inode->i_ino,kdevname(inode->i_dev));
 737                 return;
 738         }
 739         file_end = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode));
 740         if (file_end->secondary_type == htonl(ST_ROOT)) {
 741                 secs_to_datestamp(inode->i_mtime,&ROOT_END(bh->b_data,inode)->disk_altered);
 742         } else {
 743                 file_end->protect   = ntohl(inode->u.affs_i.i_protect ^ FIBF_OWNER);
 744                 file_end->byte_size = ntohl(inode->i_size);
 745                 secs_to_datestamp(inode->i_mtime,&file_end->created);
 746                 if (!(inode->i_ino == inode->i_sb->u.affs_sb.s_root_block)) {
 747                         uid = inode->i_uid;
 748                         gid = inode->i_gid;
 749                         if (inode->i_sb->u.affs_sb.s_flags & SF_MUFS) {
 750                                 if (inode->i_uid == 0 || inode->i_uid == 0xFFFF)
 751                                         uid = inode->i_uid ^ ~0;
 752                                 if (inode->i_gid == 0 || inode->i_gid == 0xFFFF)
 753                                         gid = inode->i_gid ^ ~0;
 754                         }
 755                         if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETUID))
 756                                 file_end->owner_gid = ntohs(uid);
 757                         if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETGID))
 758                                 file_end->owner_gid = ntohs(gid);
 759                 }
 760         }
 761         affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
 762         mark_buffer_dirty(bh,1);
 763         brelse(bh);
 764 }
 765 
 766 int
 767 affs_notify_change(struct inode *inode, struct iattr *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
 768 {
 769         int error;
 770 
 771         pr_debug("AFFS: notify_change(%lu,0x%x)\n",
 772                 inode->i_ino,attr->ia_valid);
 773 
 774         error = inode_change_ok(inode,attr);
 775         if (error)
 776                 return error;
 777         
 778         if (((attr->ia_valid & ATTR_UID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETUID)) ||
 779             ((attr->ia_valid & ATTR_GID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETGID)) ||
 780             ((attr->ia_valid & ATTR_MODE) &&
 781              (inode->i_sb->u.affs_sb.s_flags & (SF_SETMODE | SF_IMMUTABLE))))
 782                 error = -EPERM;
 783         
 784         if (error)
 785                 return (inode->i_sb->u.affs_sb.s_flags & SF_QUIET) ? 0 : error;
 786         
 787         if (attr->ia_valid & ATTR_MODE)
 788                 inode->u.affs_i.i_protect = mode_to_prot(attr->ia_mode);
 789 
 790         inode_setattr(inode,attr);
 791 
 792         return 0;
 793 }
 794 
 795 void
 796 affs_put_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 797 {
 798         pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",
 799                 inode->i_ino,inode->i_nlink);
 800         if (inode->i_nlink) {
 801                 return;
 802         }
 803         inode->i_size = 0;
 804         if (S_ISREG(inode->i_mode) && !inode->u.affs_i.i_hlink)
 805                 affs_truncate(inode);
 806         affs_free_block(inode->i_sb,inode->i_ino);
 807         clear_inode(inode);
 808 }
 809 
 810 struct inode *
 811 affs_new_inode(const struct inode *dir)
     /* [previous][next][first][last][top][bottom][index][help] */
 812 {
 813         struct inode            *inode;
 814         struct super_block      *sb;
 815         ULONG                    block;
 816 
 817         if (!dir || !(inode = get_empty_inode()))
 818                 return NULL;
 819         
 820         sb = dir->i_sb;
 821         inode->i_sb    = sb;
 822         inode->i_flags = sb->s_flags;
 823 
 824         if (!(block = affs_new_header((struct inode *)dir))) {
 825                 iput(inode);
 826                 return NULL;
 827         }
 828 
 829         inode->i_count   = 1;
 830         inode->i_nlink   = 1;
 831         inode->i_dev     = sb->s_dev;
 832         inode->i_uid     = current->fsuid;
 833         inode->i_gid     = current->fsgid;
 834         inode->i_dirt    = 1;
 835         inode->i_ino     = block;
 836         inode->i_op      = NULL;
 837         inode->i_blocks  = 0;
 838         inode->i_size    = 0;
 839         inode->i_mode    = 0;
 840         inode->i_blksize = 0;
 841         inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 842 
 843         inode->u.affs_i.i_original = 0;
 844         inode->u.affs_i.i_parent   = dir->i_ino;
 845         inode->u.affs_i.i_zone     = 0;
 846         inode->u.affs_i.i_hlink    = 0;
 847         inode->u.affs_i.i_pa_cnt   = 0;
 848         inode->u.affs_i.i_pa_next  = 0;
 849         inode->u.affs_i.i_pa_last  = 0;
 850         inode->u.affs_i.i_ext[0]   = 0;
 851         inode->u.affs_i.i_max_ext  = 0;
 852 
 853         insert_inode_hash(inode);
 854 
 855         return inode;
 856 }
 857 
 858 int
 859 affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
     /* [previous][next][first][last][top][bottom][index][help] */
 860                const char *name, int len, LONG type)
 861 {
 862         struct buffer_head      *dir_bh;
 863         struct buffer_head      *inode_bh;
 864         struct buffer_head      *link_bh;
 865         ULONG                    hash;
 866 
 867         pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%ld\n",
 868                 dir->i_ino,inode->i_ino, len,name,type);
 869 
 870         dir_bh     = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir));
 871         inode_bh   = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
 872         link_bh    = NULL;
 873         if (!dir_bh || !inode_bh) {
 874                 affs_brelse(dir_bh);
 875                 affs_brelse(inode_bh);
 876                 return -ENOSPC;
 877         }
 878         if (link) {
 879                 link_bh = affs_bread(link->i_dev,link->i_ino,AFFS_I2BSIZE(link));
 880                 if (!link_bh) {
 881                         affs_brelse(dir_bh);
 882                         affs_brelse(inode_bh);
 883                         return -EINVAL;
 884                 }
 885         }
 886         ((struct dir_front *)inode_bh->b_data)->primary_type = ntohl(T_SHORT);
 887         ((struct dir_front *)inode_bh->b_data)->own_key      = ntohl(inode->i_ino);
 888 
 889         if (len > 30)           /* truncate name quietly */
 890                 len = 30;
 891         DIR_END(inode_bh->b_data,inode)->dir_name[0] = len;
 892         strncpy(DIR_END(inode_bh->b_data,inode)->dir_name + 1,name,len);
 893         DIR_END(inode_bh->b_data,inode)->secondary_type = ntohl(type);
 894         DIR_END(inode_bh->b_data,inode)->parent         = ntohl(dir->i_ino);
 895         hash = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir));
 896 
 897         lock_super(inode->i_sb);
 898         DIR_END(inode_bh->b_data,inode)->hash_chain = 
 899                          ((struct dir_front *)dir_bh->b_data)->hashtable[hash];
 900         ((struct dir_front *)dir_bh->b_data)->hashtable[hash] = ntohl(inode->i_ino);
 901         if (link_bh) {
 902                 LINK_END(inode_bh->b_data,inode)->original   = ntohl(link->i_ino);
 903                 LINK_END(inode_bh->b_data,inode)->link_chain = 
 904                                     FILE_END(link_bh->b_data,link)->link_chain;
 905                 FILE_END(link_bh->b_data,link)->link_chain   = ntohl(inode->i_ino);
 906                 affs_fix_checksum(AFFS_I2BSIZE(link),link_bh->b_data,5);
 907                 link->i_version = ++event;
 908                 link->i_dirt    = 1;
 909                 mark_buffer_dirty(link_bh,1);
 910         }
 911         affs_fix_checksum(AFFS_I2BSIZE(inode),inode_bh->b_data,5);
 912         affs_fix_checksum(AFFS_I2BSIZE(dir),dir_bh->b_data,5);
 913         dir->i_version = ++event;
 914         dir->i_mtime   = dir->i_atime = dir->i_ctime = CURRENT_TIME;
 915         unlock_super(inode->i_sb);
 916 
 917         dir->i_dirt    = 1;
 918         inode->i_dirt  = 1;
 919         mark_buffer_dirty(dir_bh,1);
 920         mark_buffer_dirty(inode_bh,1);
 921         affs_brelse(dir_bh);
 922         affs_brelse(inode_bh);
 923         affs_brelse(link_bh);
 924 
 925         return 0;
 926 }
 927 
 928 static struct file_system_type affs_fs_type = {
 929         affs_read_super,
 930         "affs",
 931         1,
 932         NULL
 933 };
 934 
 935 int
 936 init_affs_fs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 937 {
 938         return register_filesystem(&affs_fs_type);
 939 }
 940 
 941 #ifdef MODULE
 942 
 943 int
 944 init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 945 {
 946         int      status;
 947         if ((status = init_affs_fs()) == 0)
 948                 register_symtab(0);
 949         return status;
 950 }
 951 
 952 void
 953 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 954 {
 955         unregister_filesystem(&affs_fs_type);
 956 }
 957 
 958 #endif

/* [previous][next][first][last][top][bottom][index][help] */