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