super.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:14k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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. #include <linux/module.h>
  13. #include <linux/errno.h>
  14. #include <linux/fs.h>
  15. #include <linux/slab.h>
  16. #include <linux/stat.h>
  17. #include <linux/sched.h>
  18. #include <linux/affs_fs.h>
  19. #include <linux/kernel.h>
  20. #include <linux/mm.h>
  21. #include <linux/string.h>
  22. #include <linux/locks.h>
  23. #include <linux/genhd.h>
  24. #include <linux/amigaffs.h>
  25. #include <linux/major.h>
  26. #include <linux/blkdev.h>
  27. #include <linux/init.h>
  28. #include <asm/system.h>
  29. #include <asm/uaccess.h>
  30. extern int *blk_size[];
  31. extern struct timezone sys_tz;
  32. static int affs_statfs(struct super_block *sb, struct statfs *buf);
  33. static int affs_remount (struct super_block *sb, int *flags, char *data);
  34. static void
  35. affs_put_super(struct super_block *sb)
  36. {
  37. pr_debug("AFFS: put_super()n");
  38. if (!(sb->s_flags & MS_RDONLY)) {
  39. AFFS_ROOT_TAIL(sb, AFFS_SB->s_root_bh)->bm_flag = be32_to_cpu(1);
  40. secs_to_datestamp(CURRENT_TIME,
  41.   &AFFS_ROOT_TAIL(sb, AFFS_SB->s_root_bh)->disk_change);
  42. affs_fix_checksum(sb, AFFS_SB->s_root_bh);
  43. mark_buffer_dirty(AFFS_SB->s_root_bh);
  44. }
  45. affs_brelse(AFFS_SB->s_bmap_bh);
  46. if (AFFS_SB->s_prefix)
  47. kfree(AFFS_SB->s_prefix);
  48. kfree(AFFS_SB->s_bitmap);
  49. affs_brelse(AFFS_SB->s_root_bh);
  50. return;
  51. }
  52. static void
  53. affs_write_super(struct super_block *sb)
  54. {
  55. int clean = 2;
  56. if (!(sb->s_flags & MS_RDONLY)) {
  57. // if (AFFS_SB->s_bitmap[i].bm_bh) {
  58. // if (buffer_dirty(AFFS_SB->s_bitmap[i].bm_bh)) {
  59. // clean = 0;
  60. AFFS_ROOT_TAIL(sb, AFFS_SB->s_root_bh)->bm_flag = be32_to_cpu(clean);
  61. secs_to_datestamp(CURRENT_TIME,
  62.   &AFFS_ROOT_TAIL(sb, AFFS_SB->s_root_bh)->disk_change);
  63. affs_fix_checksum(sb, AFFS_SB->s_root_bh);
  64. mark_buffer_dirty(AFFS_SB->s_root_bh);
  65. sb->s_dirt = !clean; /* redo until bitmap synced */
  66. } else
  67. sb->s_dirt = 0;
  68. pr_debug("AFFS: write_super() at %lu, clean=%dn", CURRENT_TIME, clean);
  69. }
  70. static struct super_operations affs_sops = {
  71. read_inode: affs_read_inode,
  72. write_inode: affs_write_inode,
  73. put_inode: affs_put_inode,
  74. delete_inode: affs_delete_inode,
  75. clear_inode: affs_clear_inode,
  76. put_super: affs_put_super,
  77. write_super: affs_write_super,
  78. statfs: affs_statfs,
  79. remount_fs: affs_remount,
  80. };
  81. static int
  82. parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root,
  83. int *blocksize, char **prefix, char *volume, unsigned long *mount_opts)
  84. {
  85. char *this_char, *value, *optn;
  86. int  f;
  87. /* Fill in defaults */
  88. *uid        = current->uid;
  89. *gid        = current->gid;
  90. *reserved   = 2;
  91. *root       = -1;
  92. *blocksize  = -1;
  93. volume[0]   = ':';
  94. volume[1]   = 0;
  95. *mount_opts = 0;
  96. if (!options)
  97. return 1;
  98. for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
  99. f = 0;
  100. if ((value = strchr(this_char,'=')) != NULL)
  101. *value++ = 0;
  102. if ((optn = "protect") && !strcmp(this_char, optn)) {
  103. if (value)
  104. goto out_inv_arg;
  105. *mount_opts |= SF_IMMUTABLE;
  106. } else if ((optn = "verbose") && !strcmp(this_char, optn)) {
  107. if (value)
  108. goto out_inv_arg;
  109. *mount_opts |= SF_VERBOSE;
  110. } else if ((optn = "mufs") && !strcmp(this_char, optn)) {
  111. if (value)
  112. goto out_inv_arg;
  113. *mount_opts |= SF_MUFS;
  114. } else if ((f = !strcmp(this_char,"setuid")) || !strcmp(this_char,"setgid")) {
  115. if (value) {
  116. if (!*value) {
  117. printk("AFFS: Argument for set[ug]id option missingn");
  118. return 0;
  119. } else {
  120. (f ? *uid : *gid) = simple_strtoul(value,&value,0);
  121. if (*value) {
  122. printk("AFFS: Bad set[ug]id argumentn");
  123. return 0;
  124. }
  125. *mount_opts |= f ? SF_SETUID : SF_SETGID;
  126. }
  127. }
  128. } else if (!strcmp(this_char,"prefix")) {
  129. optn = "prefix";
  130. if (!value || !*value)
  131. goto out_no_arg;
  132. if (*prefix) { /* Free any previous prefix */
  133. kfree(*prefix);
  134. *prefix = NULL;
  135. }
  136. *prefix = kmalloc(strlen(value) + 1,GFP_KERNEL);
  137. if (!*prefix)
  138. return 0;
  139. strcpy(*prefix,value);
  140. *mount_opts |= SF_PREFIX;
  141. } else if (!strcmp(this_char,"volume")) {
  142. optn = "volume";
  143. if (!value || !*value)
  144. goto out_no_arg;
  145. if (strlen(value) > 30)
  146. value[30] = 0;
  147. strncpy(volume,value,30);
  148. } else if (!strcmp(this_char,"mode")) {
  149. optn = "mode";
  150. if (!value || !*value)
  151. goto out_no_arg;
  152. *mode = simple_strtoul(value,&value,8) & 0777;
  153. if (*value)
  154. return 0;
  155. *mount_opts |= SF_SETMODE;
  156. } else if (!strcmp(this_char,"reserved")) {
  157. optn = "reserved";
  158. if (!value || !*value)
  159. goto out_no_arg;
  160. *reserved = simple_strtoul(value,&value,0);
  161. if (*value)
  162. return 0;
  163. } else if (!strcmp(this_char,"root")) {
  164. optn = "root";
  165. if (!value || !*value)
  166. goto out_no_arg;
  167. *root = simple_strtoul(value,&value,0);
  168. if (*value)
  169. return 0;
  170. } else if (!strcmp(this_char,"bs")) {
  171. optn = "bs";
  172. if (!value || !*value)
  173. goto out_no_arg;
  174. *blocksize = simple_strtoul(value,&value,0);
  175. if (*value)
  176. return 0;
  177. if (*blocksize != 512 && *blocksize != 1024 && *blocksize != 2048
  178.     && *blocksize != 4096) {
  179. printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)n");
  180. return 0;
  181. }
  182. } else if (!strcmp (this_char, "grpquota")
  183.  || !strcmp (this_char, "noquota")
  184.  || !strcmp (this_char, "quota")
  185.  || !strcmp (this_char, "usrquota"))
  186.  /* Silently ignore the quota options */
  187. ;
  188. else {
  189. printk("AFFS: Unrecognized mount option %sn", this_char);
  190. return 0;
  191. }
  192. }
  193. return 1;
  194. out_no_arg:
  195. printk("AFFS: The %s option requires an argumentn", optn);
  196. return 0;
  197. out_inv_arg:
  198. printk("AFFS: Option %s does not take an argumentn", optn);
  199. return 0;
  200. }
  201. /* This function definitely needs to be split up. Some fine day I'll
  202.  * hopefully have the guts to do so. Until then: sorry for the mess.
  203.  */
  204. static struct super_block *
  205. affs_read_super(struct super_block *sb, void *data, int silent)
  206. {
  207. struct buffer_head *root_bh = NULL;
  208. struct buffer_head *boot_bh;
  209. struct inode *root_inode = NULL;
  210. kdev_t  dev = sb->s_dev;
  211. s32  root_block;
  212. int  blocks, size, blocksize;
  213. u32  chksum;
  214. int  num_bm;
  215. int  i, j;
  216. s32  key;
  217. uid_t  uid;
  218. gid_t  gid;
  219. int  reserved;
  220. unsigned long  mount_flags;
  221. pr_debug("AFFS: read_super(%s)n",data ? (const char *)data : "no options");
  222. sb->s_magic             = AFFS_SUPER_MAGIC;
  223. sb->s_op                = &affs_sops;
  224. memset(AFFS_SB, 0, sizeof(*AFFS_SB));
  225. init_MUTEX(&AFFS_SB->s_bmlock);
  226. if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
  227. &blocksize,&AFFS_SB->s_prefix,
  228. AFFS_SB->s_volume, &mount_flags)) {
  229. printk(KERN_ERR "AFFS: Error parsing optionsn");
  230. return NULL;
  231. }
  232. /* N.B. after this point s_prefix must be released */
  233. AFFS_SB->s_flags   = mount_flags;
  234. AFFS_SB->s_mode    = i;
  235. AFFS_SB->s_uid     = uid;
  236. AFFS_SB->s_gid     = gid;
  237. AFFS_SB->s_reserved= reserved;
  238. /* Get the size of the device in 512-byte blocks.
  239.  * If we later see that the partition uses bigger
  240.  * blocks, we will have to change it.
  241.  */
  242. blocks = blk_size[MAJOR(dev)] ? blk_size[MAJOR(dev)][MINOR(dev)] : 0;
  243. if (!blocks) {
  244. printk(KERN_ERR "AFFS: Could not determine device sizen");
  245. goto out_error;
  246. }
  247. size = (BLOCK_SIZE / 512) * blocks;
  248. pr_debug("AFFS: initial blksize=%d, blocks=%dn", 512, blocks);
  249. affs_set_blocksize(sb, PAGE_SIZE);
  250. /* Try to find root block. Its location depends on the block size. */
  251. i = 512;
  252. j = 4096;
  253. if (blocksize > 0) {
  254. i = j = blocksize;
  255. size = size / (blocksize / 512);
  256. }
  257. for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) {
  258. AFFS_SB->s_root_block = root_block;
  259. if (root_block < 0)
  260. AFFS_SB->s_root_block = (reserved + size - 1) / 2;
  261. pr_debug("AFFS: setting blocksize to %dn", blocksize);
  262. affs_set_blocksize(sb, blocksize);
  263. AFFS_SB->s_partition_size = size;
  264. /* The root block location that was calculated above is not
  265.  * correct if the partition size is an odd number of 512-
  266.  * byte blocks, which will be rounded down to a number of
  267.  * 1024-byte blocks, and if there were an even number of
  268.  * reserved blocks. Ideally, all partition checkers should
  269.  * report the real number of blocks of the real blocksize,
  270.  * but since this just cannot be done, we have to try to
  271.  * find the root block anyways. In the above case, it is one
  272.  * block behind the calculated one. So we check this one, too.
  273.  */
  274. for (num_bm = 0; num_bm < 2; num_bm++) {
  275. pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, "
  276. "size=%d, reserved=%dn",
  277. kdevname(dev),
  278. AFFS_SB->s_root_block + num_bm,
  279. blocksize, size, reserved);
  280. root_bh = affs_bread(sb, AFFS_SB->s_root_block + num_bm);
  281. if (!root_bh)
  282. continue;
  283. if (!affs_checksum_block(sb, root_bh) &&
  284.     be32_to_cpu(AFFS_ROOT_HEAD(root_bh)->ptype) == T_SHORT &&
  285.     be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) {
  286. AFFS_SB->s_hashsize    = blocksize / 4 - 56;
  287. AFFS_SB->s_root_block += num_bm;
  288. key                        = 1;
  289. goto got_root;
  290. }
  291. affs_brelse(root_bh);
  292. root_bh = NULL;
  293. }
  294. }
  295. if (!silent)
  296. printk(KERN_ERR "AFFS: No valid root block on device %sn",
  297. kdevname(dev));
  298. goto out_error;
  299. /* N.B. after this point bh must be released */
  300. got_root:
  301. root_block = AFFS_SB->s_root_block;
  302. sb->s_blocksize_bits = blocksize == 512 ? 9 :
  303.        blocksize == 1024 ? 10 :
  304.        blocksize == 2048 ? 11 : 12;
  305. /* Find out which kind of FS we have */
  306. boot_bh = sb_bread(sb, 0);
  307. if (!boot_bh) {
  308. printk(KERN_ERR "AFFS: Cannot read boot blockn");
  309. goto out_error;
  310. }
  311. chksum = be32_to_cpu(*(u32 *)boot_bh->b_data);
  312. brelse(boot_bh);
  313. /* Dircache filesystems are compatible with non-dircache ones
  314.  * when reading. As long as they aren't supported, writing is
  315.  * not recommended.
  316.  */
  317. if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
  318.      || chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) {
  319. printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read onlyn",
  320. kdevname(dev));
  321. sb->s_flags |= MS_RDONLY;
  322. AFFS_SB->s_flags |= SF_READONLY;
  323. }
  324. switch (chksum) {
  325. case MUFS_FS:
  326. case MUFS_INTLFFS:
  327. case MUFS_DCFFS:
  328. AFFS_SB->s_flags |= SF_MUFS;
  329. /* fall thru */
  330. case FS_INTLFFS:
  331. case FS_DCFFS:
  332. AFFS_SB->s_flags |= SF_INTL;
  333. break;
  334. case MUFS_FFS:
  335. AFFS_SB->s_flags |= SF_MUFS;
  336. break;
  337. case FS_FFS:
  338. break;
  339. case MUFS_OFS:
  340. AFFS_SB->s_flags |= SF_MUFS;
  341. /* fall thru */
  342. case FS_OFS:
  343. AFFS_SB->s_flags |= SF_OFS;
  344. sb->s_flags |= MS_NOEXEC;
  345. break;
  346. case MUFS_DCOFS:
  347. case MUFS_INTLOFS:
  348. AFFS_SB->s_flags |= SF_MUFS;
  349. case FS_DCOFS:
  350. case FS_INTLOFS:
  351. AFFS_SB->s_flags |= SF_INTL | SF_OFS;
  352. sb->s_flags |= MS_NOEXEC;
  353. break;
  354. default:
  355. printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08Xn",
  356. kdevname(dev), chksum);
  357. goto out_error;
  358. }
  359. if (mount_flags & SF_VERBOSE) {
  360. chksum = cpu_to_be32(chksum);
  361. printk(KERN_NOTICE "AFFS: Mounting volume "%*s": Type=%.3s\%c, Blocksize=%dn",
  362. AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0],
  363. AFFS_ROOT_TAIL(sb, root_bh)->disk_name + 1,
  364. (char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
  365. }
  366. sb->s_flags |= MS_NODEV | MS_NOSUID;
  367. AFFS_SB->s_data_blksize = sb->s_blocksize;
  368. if (AFFS_SB->s_flags & SF_OFS)
  369. AFFS_SB->s_data_blksize -= 24;
  370. /* Keep super block in cache */
  371. AFFS_SB->s_root_bh = root_bh;
  372. /* N.B. after this point s_root_bh must be released */
  373. if (affs_init_bitmap(sb))
  374. goto out_error;
  375. /* set up enough so that it can read an inode */
  376. root_inode = iget(sb, root_block);
  377. sb->s_root = d_alloc_root(root_inode);
  378. if (!sb->s_root) {
  379. printk(KERN_ERR "AFFS: Get root inode failedn");
  380. goto out_error;
  381. }
  382. sb->s_root->d_op = &affs_dentry_operations;
  383. pr_debug("AFFS: s_flags=%lXn",sb->s_flags);
  384. return sb;
  385. /*
  386.  * Begin the cascaded cleanup ...
  387.  */
  388. out_error:
  389. if (root_inode)
  390. iput(root_inode);
  391. if (AFFS_SB->s_bitmap)
  392. kfree(AFFS_SB->s_bitmap);
  393. affs_brelse(root_bh);
  394. if (AFFS_SB->s_prefix)
  395. kfree(AFFS_SB->s_prefix);
  396. return NULL;
  397. }
  398. static int
  399. affs_remount(struct super_block *sb, int *flags, char *data)
  400. {
  401. int  blocksize;
  402. uid_t  uid;
  403. gid_t  gid;
  404. int  mode;
  405. int  reserved;
  406. int  root_block;
  407. unsigned long  mount_flags;
  408. unsigned long  read_only = AFFS_SB->s_flags & SF_READONLY;
  409. pr_debug("AFFS: remount(flags=0x%x,opts="%s")n",*flags,data);
  410. if (!parse_options(data,&uid,&gid,&mode,&reserved,&root_block,
  411.     &blocksize,&AFFS_SB->s_prefix,AFFS_SB->s_volume,&mount_flags))
  412. return -EINVAL;
  413. AFFS_SB->s_flags = mount_flags | read_only;
  414. AFFS_SB->s_mode  = mode;
  415. AFFS_SB->s_uid   = uid;
  416. AFFS_SB->s_gid   = gid;
  417. if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
  418. return 0;
  419. if (*flags & MS_RDONLY) {
  420. sb->s_dirt = 1;
  421. while (sb->s_dirt)
  422. affs_write_super(sb);
  423. sb->s_flags |= MS_RDONLY;
  424. } else if (!(AFFS_SB->s_flags & SF_READONLY)) {
  425. sb->s_flags &= ~MS_RDONLY;
  426. } else {
  427. affs_warning(sb,"remount","Cannot remount fs read/write because of errors");
  428. return -EINVAL;
  429. }
  430. return 0;
  431. }
  432. static int
  433. affs_statfs(struct super_block *sb, struct statfs *buf)
  434. {
  435. int  free;
  436. pr_debug("AFFS: statfs() partsize=%d, reserved=%dn",AFFS_SB->s_partition_size,
  437.      AFFS_SB->s_reserved);
  438. free          = affs_count_free_blocks(sb);
  439. buf->f_type    = AFFS_SUPER_MAGIC;
  440. buf->f_bsize   = sb->s_blocksize;
  441. buf->f_blocks  = AFFS_SB->s_partition_size - AFFS_SB->s_reserved;
  442. buf->f_bfree   = free;
  443. buf->f_bavail  = free;
  444. return 0;
  445. }
  446. static DECLARE_FSTYPE_DEV(affs_fs_type, "affs", affs_read_super);
  447. static int __init init_affs_fs(void)
  448. {
  449. return register_filesystem(&affs_fs_type);
  450. }
  451. static void __exit exit_affs_fs(void)
  452. {
  453. unregister_filesystem(&affs_fs_type);
  454. }
  455. EXPORT_NO_SYMBOLS;
  456. MODULE_DESCRIPTION("Amiga filesystem support for Linux");
  457. MODULE_LICENSE("GPL");
  458. module_init(init_affs_fs)
  459. module_exit(exit_affs_fs)