super.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *   Copyright (c) International Business Machines Corp., 2000-2002
  3.  *   Portions Copyright (c) Christoph Hellwig, 2001-2002
  4.  *
  5.  *   This program is free software;  you can redistribute it and/or modify
  6.  *   it under the terms of the GNU General Public License as published by
  7.  *   the Free Software Foundation; either version 2 of the License, or 
  8.  *   (at your option) any later version.
  9.  * 
  10.  *   This program is distributed in the hope that it will be useful,
  11.  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
  12.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  13.  *   the GNU General Public License for more details.
  14.  *
  15.  *   You should have received a copy of the GNU General Public License
  16.  *   along with this program;  if not, write to the Free Software 
  17.  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18.  */
  19. #include <linux/config.h>
  20. #include <linux/fs.h>
  21. #include <linux/module.h>
  22. #include <linux/completion.h>
  23. #include <asm/uaccess.h>
  24. #include "jfs_incore.h"
  25. #include "jfs_filsys.h"
  26. #include "jfs_metapage.h"
  27. #include "jfs_superblock.h"
  28. #include "jfs_dmap.h"
  29. #include "jfs_imap.h"
  30. #include "jfs_debug.h"
  31. MODULE_DESCRIPTION("The Journaled Filesystem (JFS)");
  32. MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM");
  33. MODULE_LICENSE("GPL");
  34. static struct super_operations jfs_super_operations;
  35. static struct file_system_type jfs_fs_type;
  36. int jfs_stop_threads;
  37. static pid_t jfsIOthread;
  38. static pid_t jfsCommitThread;
  39. static pid_t jfsSyncThread;
  40. DECLARE_COMPLETION(jfsIOwait);
  41. #ifdef CONFIG_JFS_DEBUG
  42. int jfsloglevel = 1;
  43. MODULE_PARM(jfsloglevel, "i");
  44. MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
  45. #endif
  46. /*
  47.  * External declarations
  48.  */
  49. extern int jfs_mount(struct super_block *);
  50. extern int jfs_mount_rw(struct super_block *, int);
  51. extern int jfs_umount(struct super_block *);
  52. extern int jfs_umount_rw(struct super_block *);
  53. extern int jfsIOWait(void *);
  54. extern int jfs_lazycommit(void *);
  55. extern int jfs_sync(void *);
  56. extern void jfs_clear_inode(struct inode *inode);
  57. extern void jfs_read_inode(struct inode *inode);
  58. extern void jfs_dirty_inode(struct inode *inode);
  59. extern void jfs_delete_inode(struct inode *inode);
  60. extern void jfs_write_inode(struct inode *inode, int wait);
  61. extern int jfs_extendfs(struct super_block *, s64, int);
  62. #ifdef PROC_FS_JFS /* see jfs_debug.h */
  63. extern void jfs_proc_init(void);
  64. extern void jfs_proc_clean(void);
  65. #endif
  66. extern wait_queue_head_t jfs_IO_thread_wait;
  67. extern wait_queue_head_t jfs_commit_thread_wait;
  68. extern wait_queue_head_t jfs_sync_thread_wait;
  69. static int jfs_statfs(struct super_block *sb, struct statfs *buf)
  70. {
  71. struct jfs_sb_info *sbi = JFS_SBI(sb);
  72. s64 maxinodes;
  73. struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap;
  74. jFYI(1, ("In jfs_statfsn"));
  75. buf->f_type = JFS_SUPER_MAGIC;
  76. buf->f_bsize = sbi->bsize;
  77. buf->f_blocks = sbi->bmap->db_mapsize;
  78. buf->f_bfree = sbi->bmap->db_nfree;
  79. buf->f_bavail = sbi->bmap->db_nfree;
  80. /*
  81.  * If we really return the number of allocated & free inodes, some
  82.  * applications will fail because they won't see enough free inodes.
  83.  * We'll try to calculate some guess as to how may inodes we can
  84.  * really allocate
  85.  *
  86.  * buf->f_files = atomic_read(&imap->im_numinos);
  87.  * buf->f_ffree = atomic_read(&imap->im_numfree);
  88.  */
  89. maxinodes = min((s64) atomic_read(&imap->im_numinos) +
  90. ((sbi->bmap->db_nfree >> imap->im_l2nbperiext)
  91.  << L2INOSPEREXT), (s64) 0xffffffffLL);
  92. buf->f_files = maxinodes;
  93. buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) -
  94.     atomic_read(&imap->im_numfree));
  95. buf->f_namelen = JFS_NAME_MAX;
  96. return 0;
  97. }
  98. static void jfs_put_super(struct super_block *sb)
  99. {
  100. struct jfs_sb_info *sbi = JFS_SBI(sb);
  101. int rc;
  102. jFYI(1, ("In jfs_put_supern"));
  103. rc = jfs_umount(sb);
  104. if (rc) {
  105. jERROR(1, ("jfs_umount failed with return code %dn", rc));
  106. }
  107. unload_nls(sbi->nls_tab);
  108. sbi->nls_tab = NULL;
  109. kfree(sbi);
  110. }
  111. static int parse_options(char *options, struct super_block *sb, s64 *newLVSize)
  112. {
  113. void *nls_map = NULL;
  114. char *this_char;
  115. char *value;
  116. struct jfs_sb_info *sbi = JFS_SBI(sb);
  117. *newLVSize = 0;
  118. if (!options)
  119. return 1;
  120. while ((this_char = strsep(&options, ",")) != NULL) {
  121. if (!*this_char)
  122. continue;
  123. if ((value = strchr(this_char, '=')) != NULL)
  124. *value++ = 0;
  125. if (!strcmp(this_char, "iocharset")) {
  126. if (!value || !*value)
  127. goto needs_arg;
  128. if (nls_map) /* specified iocharset twice! */
  129. unload_nls(nls_map);
  130. nls_map = load_nls(value);
  131. if (!nls_map) {
  132. printk(KERN_ERR "JFS: charset not foundn");
  133. goto cleanup;
  134. }
  135. } else if (!strcmp(this_char, "resize")) {
  136. if (!value || !*value) {
  137. *newLVSize = sb->s_bdev->bd_inode->i_size >>
  138. sb->s_blocksize_bits;
  139. if (*newLVSize == 0)
  140. printk(KERN_ERR
  141.  "JFS: Cannot determine volume sizen");
  142. } else
  143. *newLVSize = simple_strtoull(value, &value, 0);
  144. /* Silently ignore the quota options */
  145. } else if (!strcmp(this_char, "grpquota")
  146.    || !strcmp(this_char, "noquota")
  147.    || !strcmp(this_char, "quota")
  148.    || !strcmp(this_char, "usrquota"))
  149. /* Don't do anything ;-) */ ;
  150. else {
  151. printk("jfs: Unrecognized mount option %sn",
  152.        this_char);
  153. goto cleanup;
  154. }
  155. }
  156. if (nls_map) {
  157. /* Discard old (if remount) */
  158. if (sbi->nls_tab)
  159. unload_nls(sbi->nls_tab);
  160. sbi->nls_tab = nls_map;
  161. }
  162. return 1;
  163. needs_arg:
  164. printk(KERN_ERR "JFS: %s needs an argumentn", this_char);
  165. cleanup:
  166. if (nls_map)
  167. unload_nls(nls_map);
  168. return 0;
  169. }
  170. int jfs_remount(struct super_block *sb, int *flags, char *data)
  171. {
  172. s64 newLVSize = 0;
  173. int rc = 0;
  174. if (!parse_options(data, sb, &newLVSize)) {
  175. return -EINVAL;
  176. }
  177. if (newLVSize) {
  178. if (sb->s_flags & MS_RDONLY) {
  179. printk(KERN_ERR
  180.   "JFS: resize requires volume to be mounted read-writen");
  181. return -EROFS;
  182. }
  183. rc = jfs_extendfs(sb, newLVSize, 0);
  184. if (rc)
  185. return rc;
  186. }
  187. if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY))
  188. return jfs_mount_rw(sb, 1);
  189. else if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY))
  190. return jfs_umount_rw(sb);
  191. return 0;
  192. }
  193. static struct super_block *jfs_read_super(struct super_block *sb,
  194.   void *data, int silent)
  195. {
  196. struct jfs_sb_info *sbi;
  197. struct inode *inode;
  198. int rc;
  199. s64 newLVSize = 0;
  200. jFYI(1,
  201.      ("In jfs_read_super s_dev=0x%x s_flags=0x%lxn", sb->s_dev,
  202.       sb->s_flags));
  203. sbi = kmalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
  204. if (!sbi)
  205. return NULL;
  206. memset(sbi, 0, sizeof (struct jfs_sb_info));
  207. sb->u.generic_sbp = sbi;
  208. if (!parse_options((char *) data, sb, &newLVSize)) {
  209. kfree(sbi);
  210. return NULL;
  211. }
  212. if (newLVSize) {
  213. printk(KERN_ERR "resize option for remount onlyn");
  214. return NULL;
  215. }
  216. /*
  217.  * Initialize blocksize to 4K.
  218.  */
  219. sb_set_blocksize(sb, PSIZE);
  220. /*
  221.  * Set method vectors.
  222.  */
  223. sb->s_op = &jfs_super_operations;
  224. rc = jfs_mount(sb);
  225. if (rc) {
  226. if (!silent) {
  227. jERROR(1,
  228.        ("jfs_mount failed w/return code = %dn", rc));
  229. }
  230. goto out_kfree;
  231. }
  232. if (sb->s_flags & MS_RDONLY)
  233. sbi->log = 0;
  234. else {
  235. rc = jfs_mount_rw(sb, 0);
  236. if (rc) {
  237. if (!silent) {
  238. jERROR(1,
  239.        ("jfs_mount_rw failed w/return code = %dn",
  240. rc));
  241. }
  242. goto out_no_rw;
  243. }
  244. }
  245. sb->s_magic = JFS_SUPER_MAGIC;
  246. inode = iget(sb, ROOT_I);
  247. if (!inode || is_bad_inode(inode))
  248. goto out_no_root;
  249. sb->s_root = d_alloc_root(inode);
  250. if (!sb->s_root)
  251. goto out_no_root;
  252. if (!sbi->nls_tab)
  253. sbi->nls_tab = load_nls_default();
  254. /* logical blocks are represented by 40 bits in pxd_t, etc. */
  255. sb->s_maxbytes = ((u64) sb->s_blocksize) << 40;
  256. #if BITS_PER_LONG == 32
  257. /*
  258.  * Page cache is indexed by long.
  259.  * I would use MAX_LFS_FILESIZE, but it's only half as big
  260.  */
  261. sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes);
  262. #endif
  263. return sb;
  264. out_no_root:
  265. jEVENT(1, ("jfs_read_super: get root inode failedn"));
  266. if (inode)
  267. iput(inode);
  268. out_no_rw:
  269. rc = jfs_umount(sb);
  270. if (rc) {
  271. jERROR(1, ("jfs_umount failed with return code %dn", rc));
  272. }
  273. out_kfree:
  274. if (sbi->nls_tab)
  275. unload_nls(sbi->nls_tab);
  276. kfree(sbi);
  277. return NULL;
  278. }
  279. static void jfs_write_super_lockfs(struct super_block *sb)
  280. {
  281. struct jfs_sb_info *sbi = JFS_SBI(sb);
  282. struct jfs_log *log = sbi->log;
  283. if (!(sb->s_flags & MS_RDONLY)) {
  284. txQuiesce(sb);
  285. lmLogShutdown(log);
  286. }
  287. }
  288. static void jfs_unlockfs(struct super_block *sb)
  289. {
  290. struct jfs_sb_info *sbi = JFS_SBI(sb);
  291. struct jfs_log *log = sbi->log;
  292. int rc = 0;
  293. if (!(sb->s_flags & MS_RDONLY)) {
  294. if ((rc = lmLogInit(log)))
  295. jERROR(1,
  296.        ("jfs_unlock failed with return code %dn", rc));
  297. else
  298. txResume(sb);
  299. }
  300. }
  301. static struct super_operations jfs_super_operations = {
  302. .read_inode = jfs_read_inode,
  303. .dirty_inode = jfs_dirty_inode,
  304. .write_inode = jfs_write_inode,
  305. .clear_inode = jfs_clear_inode,
  306. .delete_inode = jfs_delete_inode,
  307. .put_super = jfs_put_super,
  308. .write_super_lockfs = jfs_write_super_lockfs,
  309. .unlockfs       = jfs_unlockfs,
  310. .statfs = jfs_statfs,
  311. .remount_fs = jfs_remount,
  312. };
  313. static struct file_system_type jfs_fs_type = {
  314. .owner = THIS_MODULE,
  315. .name = "jfs",
  316. .read_super = jfs_read_super,
  317. .fs_flags = FS_REQUIRES_DEV,
  318. };
  319. extern int metapage_init(void);
  320. extern int txInit(void);
  321. extern void txExit(void);
  322. extern void metapage_exit(void);
  323. static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
  324. {
  325. struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
  326. if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
  327.     SLAB_CTOR_CONSTRUCTOR) {
  328. INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
  329. INIT_LIST_HEAD(&jfs_ip->mp_list);
  330. init_rwsem(&jfs_ip->rdwrlock);
  331. init_MUTEX(&jfs_ip->commit_sem);
  332. jfs_ip->atlhead = 0;
  333. jfs_ip->active_ag = -1;
  334. }
  335. }
  336. static int __init init_jfs_fs(void)
  337. {
  338. int rc;
  339. jfs_inode_cachep =
  340.     kmem_cache_create("jfs_ip", sizeof (struct jfs_inode_info), 0, 0,
  341.       init_once, NULL);
  342. if (jfs_inode_cachep == NULL)
  343. return -ENOMEM;
  344. /*
  345.  * Metapage initialization
  346.  */
  347. rc = metapage_init();
  348. if (rc) {
  349. jERROR(1, ("metapage_init failed w/rc = %dn", rc));
  350. goto free_slab;
  351. }
  352. /*
  353.  * Transaction Manager initialization
  354.  */
  355. rc = txInit();
  356. if (rc) {
  357. jERROR(1, ("txInit failed w/rc = %dn", rc));
  358. goto free_metapage;
  359. }
  360. /*
  361.  * I/O completion thread (endio)
  362.  */
  363. jfsIOthread = kernel_thread(jfsIOWait, 0,
  364.     CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
  365. if (jfsIOthread < 0) {
  366. jERROR(1,
  367.        ("init_jfs_fs: fork failed w/rc = %dn", jfsIOthread));
  368. goto end_txmngr;
  369. }
  370. wait_for_completion(&jfsIOwait); /* Wait until thread starts */
  371. jfsCommitThread = kernel_thread(jfs_lazycommit, 0,
  372. CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
  373. if (jfsCommitThread < 0) {
  374. jERROR(1,
  375.        ("init_jfs_fs: fork failed w/rc = %dn",
  376. jfsCommitThread));
  377. goto kill_iotask;
  378. }
  379. wait_for_completion(&jfsIOwait); /* Wait until thread starts */
  380. jfsSyncThread = kernel_thread(jfs_sync, 0,
  381.       CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
  382. if (jfsSyncThread < 0) {
  383. jERROR(1,
  384.        ("init_jfs_fs: fork failed w/rc = %dn", jfsSyncThread));
  385. goto kill_committask;
  386. }
  387. wait_for_completion(&jfsIOwait); /* Wait until thread starts */
  388. #ifdef PROC_FS_JFS
  389. jfs_proc_init();
  390. #endif
  391. return register_filesystem(&jfs_fs_type);
  392. kill_committask:
  393. jfs_stop_threads = 1;
  394. wake_up(&jfs_commit_thread_wait);
  395. wait_for_completion(&jfsIOwait); /* Wait for thread exit */
  396. kill_iotask:
  397. jfs_stop_threads = 1;
  398. wake_up(&jfs_IO_thread_wait);
  399. wait_for_completion(&jfsIOwait); /* Wait for thread exit */
  400. end_txmngr:
  401. txExit();
  402. free_metapage:
  403. metapage_exit();
  404. free_slab:
  405. kmem_cache_destroy(jfs_inode_cachep);
  406. return -rc;
  407. }
  408. static void __exit exit_jfs_fs(void)
  409. {
  410. jFYI(1, ("exit_jfs_fs calledn"));
  411. jfs_stop_threads = 1;
  412. txExit();
  413. metapage_exit();
  414. wake_up(&jfs_IO_thread_wait);
  415. wait_for_completion(&jfsIOwait); /* Wait for IO thread exit */
  416. wake_up(&jfs_commit_thread_wait);
  417. wait_for_completion(&jfsIOwait); /* Wait for Commit thread exit */
  418. wake_up(&jfs_sync_thread_wait);
  419. wait_for_completion(&jfsIOwait); /* Wait for Sync thread exit */
  420. #ifdef PROC_FS_JFS
  421. jfs_proc_clean();
  422. #endif
  423. unregister_filesystem(&jfs_fs_type);
  424. kmem_cache_destroy(jfs_inode_cachep);
  425. }
  426. EXPORT_NO_SYMBOLS;
  427. module_init(init_jfs_fs)
  428. module_exit(exit_jfs_fs)