~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/affs/super.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/fs/affs/inode.c
  3  *
  4  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
  5  *
  6  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  7  *
  8  *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
  9  *
 10  *  (C) 1991  Linus Torvalds - minix filesystem
 11  */
 12 
 13 #define DEBUG 0
 14 #include <linux/module.h>
 15 #include <linux/errno.h>
 16 #include <linux/fs.h>
 17 #include <linux/malloc.h>
 18 #include <linux/stat.h>
 19 #include <linux/sched.h>
 20 #include <linux/affs_fs.h>
 21 #include <linux/kernel.h>
 22 #include <linux/mm.h>
 23 #include <linux/string.h>
 24 #include <linux/locks.h>
 25 #include <linux/genhd.h>
 26 #include <linux/amigaffs.h>
 27 #include <linux/major.h>
 28 #include <linux/blkdev.h>
 29 #include <linux/init.h>
 30 #include <asm/system.h>
 31 #include <asm/uaccess.h>
 32 
 33 extern int *blk_size[];
 34 extern struct timezone sys_tz;
 35 
 36 #define MIN(a,b) (((a)<(b))?(a):(b))
 37 
 38 static int affs_statfs(struct super_block *sb, struct statfs *buf);
 39 static int affs_remount (struct super_block *sb, int *flags, char *data);
 40 
 41 static void
 42 affs_put_super(struct super_block *sb)
 43 {
 44         int      i;
 45 
 46         pr_debug("AFFS: put_super()\n");
 47 
 48         for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
 49                 affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);
 50         if (!(sb->s_flags & MS_RDONLY)) {
 51                 ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = be32_to_cpu(1);
 52                 secs_to_datestamp(CURRENT_TIME,
 53                                   &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
 54                 affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
 55                 mark_buffer_dirty(sb->u.affs_sb.s_root_bh);
 56         }
 57 
 58         if (sb->u.affs_sb.s_prefix)
 59                 kfree(sb->u.affs_sb.s_prefix);
 60         kfree(sb->u.affs_sb.s_bitmap);
 61         affs_brelse(sb->u.affs_sb.s_root_bh);
 62 
 63         /*
 64          * Restore the previous value of this device's blksize_size[][]
 65          */
 66         set_blocksize(sb->s_dev, sb->u.affs_sb.s_blksize);
 67 
 68         return;
 69 }
 70 
 71 static void
 72 affs_write_super(struct super_block *sb)
 73 {
 74         int      i, clean = 2;
 75 
 76         if (!(sb->s_flags & MS_RDONLY)) {
 77                 lock_super(sb);
 78                 for (i = 0, clean = 1; i < sb->u.affs_sb.s_bm_count; i++) {
 79                         if (sb->u.affs_sb.s_bitmap[i].bm_bh) {
 80                                 if (buffer_dirty(sb->u.affs_sb.s_bitmap[i].bm_bh)) {
 81                                         clean = 0;
 82                                         break;
 83                                 }
 84                         }
 85                 }
 86                 unlock_super(sb);
 87                 ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = be32_to_cpu(clean);
 88                 secs_to_datestamp(CURRENT_TIME,
 89                                   &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
 90                 affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
 91                 mark_buffer_dirty(sb->u.affs_sb.s_root_bh);
 92                 sb->s_dirt = !clean;    /* redo until bitmap synced */
 93         } else
 94                 sb->s_dirt = 0;
 95 
 96         pr_debug("AFFS: write_super() at %lu, clean=%d\n", CURRENT_TIME, clean);
 97 }
 98 
 99 static struct super_operations affs_sops = {
100         read_inode:     affs_read_inode,
101         write_inode:    affs_write_inode,
102         put_inode:      affs_put_inode,
103         delete_inode:   affs_delete_inode,
104         put_super:      affs_put_super,
105         write_super:    affs_write_super,
106         statfs:         affs_statfs,
107         remount_fs:     affs_remount,
108 };
109 
110 static int
111 parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root,
112                 int *blocksize, char **prefix, char *volume, unsigned long *mount_opts)
113 {
114         char    *this_char, *value, *optn;
115         int      f;
116 
117         /* Fill in defaults */
118 
119         *uid        = current->uid;
120         *gid        = current->gid;
121         *reserved   = 2;
122         *root       = -1;
123         *blocksize  = -1;
124         volume[0]   = ':';
125         volume[1]   = 0;
126         *mount_opts = 0;
127         if (!options)
128                 return 1;
129         for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
130                 f = 0;
131                 if ((value = strchr(this_char,'=')) != NULL)
132                         *value++ = 0;
133                 if ((optn = "protect") && !strcmp(this_char, optn)) {
134                         if (value)
135                                 goto out_inv_arg;
136                         *mount_opts |= SF_IMMUTABLE;
137                 } else if ((optn = "verbose") && !strcmp(this_char, optn)) {
138                         if (value)
139                                 goto out_inv_arg;
140                         *mount_opts |= SF_VERBOSE;
141                 } else if ((optn = "mufs") && !strcmp(this_char, optn)) {
142                         if (value)
143                                 goto out_inv_arg;
144                         *mount_opts |= SF_MUFS;
145                 } else if ((f = !strcmp(this_char,"setuid")) || !strcmp(this_char,"setgid")) {
146                         if (value) {
147                                 if (!*value) {
148                                         printk("AFFS: Argument for set[ug]id option missing\n");
149                                         return 0;
150                                 } else {
151                                         (f ? *uid : *gid) = simple_strtoul(value,&value,0);
152                                         if (*value) {
153                                                 printk("AFFS: Bad set[ug]id argument\n");
154                                                 return 0;
155                                         }
156                                         *mount_opts |= f ? SF_SETUID : SF_SETGID;
157                                 }
158                         }
159                 } else if (!strcmp(this_char,"prefix")) {
160                         optn = "prefix";
161                         if (!value || !*value)
162                                 goto out_no_arg;
163                         if (*prefix) {          /* Free any previous prefix */
164                                 kfree(*prefix);
165                                 *prefix = NULL;
166                         }
167                         *prefix = kmalloc(strlen(value) + 1,GFP_KERNEL);
168                         if (!*prefix)
169                                 return 0;
170                         strcpy(*prefix,value);
171                         *mount_opts |= SF_PREFIX;
172                 } else if (!strcmp(this_char,"volume")) {
173                         optn = "volume";
174                         if (!value || !*value)
175                                 goto out_no_arg;
176                         if (strlen(value) > 30)
177                                 value[30] = 0;
178                         strncpy(volume,value,30);
179                 } else if (!strcmp(this_char,"mode")) {
180                         optn = "mode";
181                         if (!value || !*value)
182                                 goto out_no_arg;
183                         *mode = simple_strtoul(value,&value,8) & 0777;
184                         if (*value)
185                                 return 0;
186                         *mount_opts |= SF_SETMODE;
187                 } else if (!strcmp(this_char,"reserved")) {
188                         optn = "reserved";
189                         if (!value || !*value)
190                                 goto out_no_arg;
191                         *reserved = simple_strtoul(value,&value,0);
192                         if (*value)
193                                 return 0;
194                 } else if (!strcmp(this_char,"root")) {
195                         optn = "root";
196                         if (!value || !*value)
197                                 goto out_no_arg;
198                         *root = simple_strtoul(value,&value,0);
199                         if (*value)
200                                 return 0;
201                 } else if (!strcmp(this_char,"bs")) {
202                         optn = "bs";
203                         if (!value || !*value)
204                                 goto out_no_arg;
205                         *blocksize = simple_strtoul(value,&value,0);
206                         if (*value)
207                                 return 0;
208                         if (*blocksize != 512 && *blocksize != 1024 && *blocksize != 2048
209                             && *blocksize != 4096) {
210                                 printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
211                                 return 0;
212                         }
213                 } else if (!strcmp (this_char, "grpquota")
214                          || !strcmp (this_char, "noquota")
215                          || !strcmp (this_char, "quota")
216                          || !strcmp (this_char, "usrquota"))
217                          /* Silently ignore the quota options */
218                         ;
219                 else {
220                         printk("AFFS: Unrecognized mount option %s\n", this_char);
221                         return 0;
222                 }
223         }
224         return 1;
225 
226 out_no_arg:
227         printk("AFFS: The %s option requires an argument\n", optn);
228         return 0;
229 out_inv_arg:
230         printk("AFFS: Option %s does not take an argument\n", optn);
231         return 0;
232 }
233 
234 /* This function definitely needs to be split up. Some fine day I'll
235  * hopefully have the guts to do so. Until then: sorry for the mess.
236  */
237 
238 static struct super_block *
239 affs_read_super(struct super_block *s, void *data, int silent)
240 {
241         struct buffer_head      *bh = NULL;
242         struct buffer_head      *bb;
243         struct inode            *root_inode;
244         kdev_t                   dev = s->s_dev;
245         s32                      root_block;
246         int                      blocks, size, blocksize;
247         u32                      chksum;
248         u32                     *bm;
249         s32                      ptype, stype;
250         int                      mapidx;
251         int                      num_bm;
252         int                      i, j;
253         s32                      key;
254         uid_t                    uid;
255         gid_t                    gid;
256         int                      reserved;
257         int                      az_no;
258         int                      bmalt = 0;
259         unsigned long            mount_flags;
260         unsigned long            offset;
261 
262         pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
263 
264         s->s_magic             = AFFS_SUPER_MAGIC;
265         s->s_op                = &affs_sops;
266         s->u.affs_sb.s_bitmap  = NULL;
267         s->u.affs_sb.s_root_bh = NULL;
268         s->u.affs_sb.s_prefix  = NULL;
269         s->u.affs_sb.s_hashsize= 0;
270 
271         if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
272                                 &blocksize,&s->u.affs_sb.s_prefix,
273                                 s->u.affs_sb.s_volume, &mount_flags))
274                 goto out_bad_opts;
275         /* N.B. after this point s_prefix must be released */
276 
277         s->u.affs_sb.s_flags   = mount_flags;
278         s->u.affs_sb.s_mode    = i;
279         s->u.affs_sb.s_uid     = uid;
280         s->u.affs_sb.s_gid     = gid;
281         s->u.affs_sb.s_reserved= reserved;
282 
283         /* Get the size of the device in 512-byte blocks.
284          * If we later see that the partition uses bigger
285          * blocks, we will have to change it.
286          */
287 
288         blocks = blk_size[MAJOR(dev)][MINOR(dev)];
289         if (blocks == 0)
290                 goto out_bad_size;
291         s->u.affs_sb.s_blksize = blksize_size[MAJOR(dev)][MINOR(dev)];
292         if (!s->u.affs_sb.s_blksize)
293                 s->u.affs_sb.s_blksize = BLOCK_SIZE;
294         size = (s->u.affs_sb.s_blksize / 512) * blocks;
295         pr_debug("AFFS: initial blksize=%d, blocks=%d\n",
296                 s->u.affs_sb.s_blksize, blocks);
297 
298         /* Try to find root block. Its location depends on the block size. */
299 
300         i = 512;
301         j = 4096;
302         if (blocksize > 0) {
303                 i = j = blocksize;
304                 size = size / (blocksize / 512);
305         }
306         for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) {
307                 s->u.affs_sb.s_root_block = root_block;
308                 if (root_block < 0)
309                         s->u.affs_sb.s_root_block = (reserved + size - 1) / 2;
310                 pr_debug("AFFS: setting blocksize to %d\n", blocksize);
311                 set_blocksize(dev, blocksize);
312 
313                 /* The root block location that was calculated above is not
314                  * correct if the partition size is an odd number of 512-
315                  * byte blocks, which will be rounded down to a number of
316                  * 1024-byte blocks, and if there were an even number of
317                  * reserved blocks. Ideally, all partition checkers should
318                  * report the real number of blocks of the real blocksize,
319                  * but since this just cannot be done, we have to try to
320                  * find the root block anyways. In the above case, it is one
321                  * block behind the calculated one. So we check this one, too.
322                  */
323                 for (num_bm = 0; num_bm < 2; num_bm++) {
324                         pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, "
325                                 "size=%d, reserved=%d\n",
326                                 kdevname(dev),
327                                 s->u.affs_sb.s_root_block + num_bm,
328                                 blocksize, size, reserved);
329                         bh = affs_bread(dev, s->u.affs_sb.s_root_block + num_bm,
330                                         blocksize);
331                         if (!bh)
332                                 continue;
333                         if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) &&
334                             ptype == T_SHORT && stype == ST_ROOT) {
335                                 s->s_blocksize             = blocksize;
336                                 s->u.affs_sb.s_hashsize    = blocksize / 4 - 56;
337                                 s->u.affs_sb.s_root_block += num_bm;
338                                 key                        = 1;
339                                 goto got_root;
340                         }
341                         affs_brelse(bh);
342                         bh = NULL;
343                 }
344         }
345         goto out_no_valid_block;
346 
347         /* N.B. after this point bh must be released */
348 got_root:
349         root_block = s->u.affs_sb.s_root_block;
350 
351         s->u.affs_sb.s_partition_size   = size;
352         s->s_blocksize_bits             = blocksize == 512 ? 9 :
353                                           blocksize == 1024 ? 10 :
354                                           blocksize == 2048 ? 11 : 12;
355 
356         /* Find out which kind of FS we have */
357         bb = affs_bread(dev,0,s->s_blocksize);
358         if (!bb)
359                 goto out_no_root_block;
360         chksum = be32_to_cpu(*(u32 *)bb->b_data);
361         affs_brelse(bb);
362 
363         /* Dircache filesystems are compatible with non-dircache ones
364          * when reading. As long as they aren't supported, writing is
365          * not recommended.
366          */
367         if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
368              || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) {
369                 printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
370                         kdevname(dev));
371                 s->s_flags |= MS_RDONLY;
372                 s->u.affs_sb.s_flags |= SF_READONLY;
373         }
374         switch (chksum) {
375                 case MUFS_FS:
376                 case MUFS_INTLFFS:
377                         s->u.affs_sb.s_flags |= SF_MUFS;
378                         /* fall thru */
379                 case FS_INTLFFS:
380                         s->u.affs_sb.s_flags |= SF_INTL;
381                         break;
382                 case MUFS_DCFFS:
383                 case MUFS_FFS:
384                         s->u.affs_sb.s_flags |= SF_MUFS;
385                         break;
386                 case FS_DCFFS:
387                 case FS_FFS:
388                         break;
389                 case MUFS_OFS:
390                         s->u.affs_sb.s_flags |= SF_MUFS;
391                         /* fall thru */
392                 case FS_OFS:
393                         s->u.affs_sb.s_flags |= SF_OFS;
394                         s->s_flags |= MS_NOEXEC;
395                         break;
396                 case MUFS_DCOFS:
397                 case MUFS_INTLOFS:
398                         s->u.affs_sb.s_flags |= SF_MUFS;
399                 case FS_DCOFS:
400                 case FS_INTLOFS:
401                         s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;
402                         s->s_flags |= MS_NOEXEC;
403                         break;
404                 default:
405                         goto out_unknown_fs;
406         }
407 
408         if (mount_flags & SF_VERBOSE) {
409                 chksum = cpu_to_be32(chksum);
410                 printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n",
411                         GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0],
412                         &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1],
413                         (char *)&chksum,((char *)&chksum)[3] + '',blocksize);
414         }
415 
416         s->s_flags |= MS_NODEV | MS_NOSUID;
417 
418         /* Keep super block in cache */
419         bb = affs_bread(dev,root_block,s->s_blocksize);
420         if (!bb)
421                 goto out_no_root_block;
422         s->u.affs_sb.s_root_bh = bb;
423         /* N.B. after this point s_root_bh must be released */
424 
425         /* Allocate space for bitmaps, zones and others */
426 
427         size   = s->u.affs_sb.s_partition_size - reserved;
428         num_bm = (size + s->s_blocksize * 8 - 32 - 1) / (s->s_blocksize * 8 - 32);
429         az_no  = (size + AFFS_ZONE_SIZE - 1) / (AFFS_ZONE_SIZE - 32);
430         ptype  = num_bm * sizeof(struct affs_bm_info) +
431                  az_no * sizeof(struct affs_alloc_zone) +
432                  MAX_ZONES * sizeof(struct affs_zone);
433         pr_debug("AFFS: num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype);
434         if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype, GFP_KERNEL)))
435                 goto out_no_bitmap;
436         memset(s->u.affs_sb.s_bitmap,0,ptype);
437         /* N.B. after the point s_bitmap must be released */
438 
439         s->u.affs_sb.s_zones   = (struct affs_zone *)&s->u.affs_sb.s_bitmap[num_bm];
440         s->u.affs_sb.s_alloc   = (struct affs_alloc_zone *)&s->u.affs_sb.s_zones[MAX_ZONES];
441         s->u.affs_sb.s_num_az  = az_no;
442 
443         mapidx = 0;
444 
445         if (ROOT_END_S(bh->b_data,s)->bm_flag == 0) {
446                 if (!(s->s_flags & MS_RDONLY)) {
447                         printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n",
448                                 kdevname(dev));
449                         s->s_flags |= MS_RDONLY;
450                 }
451                 affs_brelse(bh);
452                 bh = NULL;
453                 goto nobitmap;
454         }
455 
456         /* The following section is ugly, I know. Especially because of the
457          * reuse of some variables that are not named properly.
458          */
459 
460         key    = root_block;
461         ptype  = s->s_blocksize / 4 - 49;
462         stype  = ptype + 25;
463         offset = s->u.affs_sb.s_reserved;
464         az_no  = 0;
465         while (bh) {
466                 bm = (u32 *)bh->b_data;
467                 for (i = ptype; i < stype && bm[i]; i++, mapidx++) {
468                         if (mapidx >= num_bm) {
469                                 printk(KERN_ERR "AFFS: Extraneous bitmap pointer - "
470                                                "mounting %s read only.\n",kdevname(dev));
471                                 s->s_flags |= MS_RDONLY;
472                                 s->u.affs_sb.s_flags |= SF_READONLY;
473                                 continue;
474                         }
475                         bb = affs_bread(dev,be32_to_cpu(bm[i]),s->s_blocksize);
476                         if (!bb)
477                                 goto out_no_read_bm;
478                         if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) &&
479                             !(s->s_flags & MS_RDONLY)) {
480                                 printk(KERN_WARNING "AFFS: Bitmap (%d,key=%u) invalid - "
481                                        "mounting %s read only.\n",mapidx,be32_to_cpu(bm[i]),
482                                         kdevname(dev));
483                                 s->s_flags |= MS_RDONLY;
484                                 s->u.affs_sb.s_flags |= SF_READONLY;
485                         }
486                         /* Mark unused bits in the last word as allocated */
487                         if (size <= s->s_blocksize * 8 - 32) {  /* last bitmap */
488                                 ptype = size / 32 + 1;          /* word number */
489                                 key   = size & 0x1F;            /* used bits */
490                                 if (key && !(s->s_flags & MS_RDONLY)) {
491                                         chksum = cpu_to_be32(0x7FFFFFFF >> (31 - key));
492                                         ((u32 *)bb->b_data)[ptype] &= chksum;
493                                         affs_fix_checksum(s->s_blocksize,bb->b_data,0);
494                                         mark_buffer_dirty(bb);
495                                         bmalt = 1;
496                                 }
497                                 ptype = (size + 31) & ~0x1F;
498                                 size  = 0;
499                                 s->u.affs_sb.s_flags |= SF_BM_VALID;
500                         } else {
501                                 ptype = s->s_blocksize * 8 - 32;
502                                 size -= ptype;
503                         }
504                         s->u.affs_sb.s_bitmap[mapidx].bm_firstblk = offset;
505                         s->u.affs_sb.s_bitmap[mapidx].bm_bh       = NULL;
506                         s->u.affs_sb.s_bitmap[mapidx].bm_key      = be32_to_cpu(bm[i]);
507                         s->u.affs_sb.s_bitmap[mapidx].bm_count    = 0;
508                         offset += ptype;
509 
510                         for (j = 0; ptype > 0; j++, az_no++, ptype -= key) {
511                                 key = MIN(ptype,AFFS_ZONE_SIZE);        /* size in bits */
512                                 s->u.affs_sb.s_alloc[az_no].az_size = key / 32;
513                                 s->u.affs_sb.s_alloc[az_no].az_free =
514                                         affs_count_free_bits(key / 8,bb->b_data +
515                                              j * (AFFS_ZONE_SIZE / 8) + 4);
516                         }
517                         affs_brelse(bb);
518                 }
519                 key   = be32_to_cpu(bm[stype]);         /* Next block of bitmap pointers        */
520                 ptype = 0;
521                 stype = s->s_blocksize / 4 - 1;
522                 affs_brelse(bh);
523                 bh = NULL;
524                 if (key) {
525                         bh = affs_bread(dev,key,s->s_blocksize);
526                         if (!bh)
527                                 goto out_no_bm_ext;
528                 }
529         }
530         if (mapidx < num_bm)
531                 goto out_bad_num;
532 
533 nobitmap:
534         s->u.affs_sb.s_bm_count = num_bm;
535 
536         /* set up enough so that it can read an inode */
537 
538         s->s_dirt  = 1;
539         root_inode = iget(s,root_block);
540         if (!root_inode)
541                 goto out_no_root;
542         s->s_root  = d_alloc_root(root_inode);
543         if (!s->s_root)
544                 goto out_no_root;
545         s->s_root->d_op = &affs_dentry_operations;
546 
547         /* Record date of last change if the bitmap was truncated and
548          * create data zones if the volume is writable.
549          */
550 
551         if (!(s->s_flags & MS_RDONLY)) {
552                 if (bmalt) {
553                         secs_to_datestamp(CURRENT_TIME,&ROOT_END(
554                                 s->u.affs_sb.s_root_bh->b_data,root_inode)->disk_altered);
555                         affs_fix_checksum(s->s_blocksize,s->u.affs_sb.s_root_bh->b_data,5);
556                         mark_buffer_dirty(s->u.affs_sb.s_root_bh);
557                 }
558                 affs_make_zones(s);
559         }
560 
561         pr_debug("AFFS: s_flags=%lX\n",s->s_flags);
562         return s;
563 
564 out_bad_opts:
565         printk(KERN_ERR "AFFS: Error parsing options\n");
566         goto out_fail;
567 out_bad_size:
568         printk(KERN_ERR "AFFS: Could not determine device size\n");
569         goto out_free_prefix;
570 out_no_valid_block:
571         if (!silent)
572                 printk(KERN_ERR "AFFS: No valid root block on device %s\n",
573                         kdevname(dev));
574         goto out_restore;
575 out_unknown_fs:
576         printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n",
577                 kdevname(dev), chksum);
578         goto out_free_bh;
579 out_no_root_block:
580         printk(KERN_ERR "AFFS: Cannot read root block\n");
581         goto out_free_bh;
582 out_no_bitmap:
583         printk(KERN_ERR "AFFS: Bitmap allocation failed\n");
584         goto out_free_root_block;
585 out_no_read_bm:
586         printk(KERN_ERR "AFFS: Cannot read bitmap\n");
587         goto out_free_bitmap;
588 out_no_bm_ext:
589         printk(KERN_ERR "AFFS: Cannot read bitmap extension\n");
590         goto out_free_bitmap;
591 out_bad_num:
592         printk(KERN_ERR "AFFS: Got only %d bitmap blocks, expected %d\n",
593                 mapidx, num_bm);
594         goto out_free_bitmap;
595 out_no_root:
596         printk(KERN_ERR "AFFS: Get root inode failed\n");
597 
598         /*
599          * Begin the cascaded cleanup ...
600          */
601         iput(root_inode);
602 out_free_bitmap:
603         kfree(s->u.affs_sb.s_bitmap);
604 out_free_root_block:
605         affs_brelse(s->u.affs_sb.s_root_bh);
606 out_free_bh:
607         affs_brelse(bh);
608 out_restore:
609         set_blocksize(dev, s->u.affs_sb.s_blksize);
610 out_free_prefix:
611         if (s->u.affs_sb.s_prefix)
612                 kfree(s->u.affs_sb.s_prefix);
613 out_fail:
614         return NULL;
615 }
616 
617 static int
618 affs_remount(struct super_block *sb, int *flags, char *data)
619 {
620         int                      blocksize;
621         uid_t                    uid;
622         gid_t                    gid;
623         int                      mode;
624         int                      reserved;
625         int                      root_block;
626         unsigned long            mount_flags;
627         unsigned long            read_only = sb->u.affs_sb.s_flags & SF_READONLY;
628 
629         pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
630 
631         if (!parse_options(data,&uid,&gid,&mode,&reserved,&root_block,
632             &blocksize,&sb->u.affs_sb.s_prefix,sb->u.affs_sb.s_volume,&mount_flags))
633                 return -EINVAL;
634         sb->u.affs_sb.s_flags = mount_flags | read_only;
635         sb->u.affs_sb.s_mode  = mode;
636         sb->u.affs_sb.s_uid   = uid;
637         sb->u.affs_sb.s_gid   = gid;
638 
639         if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
640                 return 0;
641         if (*flags & MS_RDONLY) {
642                 sb->s_dirt = 1;
643                 while (sb->s_dirt)
644                         affs_write_super(sb);
645                 sb->s_flags |= MS_RDONLY;
646         } else if (!(sb->u.affs_sb.s_flags & SF_READONLY)) {
647                 sb->s_flags &= ~MS_RDONLY;
648                 affs_make_zones(sb);
649         } else {
650                 affs_warning(sb,"remount","Cannot remount fs read/write because of errors");
651                 return -EINVAL;
652         }
653         return 0;
654 }
655 
656 static int
657 affs_statfs(struct super_block *sb, struct statfs *buf)
658 {
659         int              free;
660 
661         pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",sb->u.affs_sb.s_partition_size,
662              sb->u.affs_sb.s_reserved);
663 
664         free          = affs_count_free_blocks(sb);
665         buf->f_type    = AFFS_SUPER_MAGIC;
666         buf->f_bsize   = sb->s_blocksize;
667         buf->f_blocks  = sb->u.affs_sb.s_partition_size - sb->u.affs_sb.s_reserved;
668         buf->f_bfree   = free;
669         buf->f_bavail  = free;
670         return 0;
671 }
672 
673 static DECLARE_FSTYPE_DEV(affs_fs_type, "affs", affs_read_super);
674 
675 static int __init init_affs_fs(void)
676 {
677         return register_filesystem(&affs_fs_type);
678 }
679 
680 static void __exit exit_affs_fs(void)
681 {
682         unregister_filesystem(&affs_fs_type);
683 }
684 
685 EXPORT_NO_SYMBOLS;
686 
687 module_init(init_affs_fs)
688 module_exit(exit_affs_fs)
689 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.