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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.