make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / fs / jfs / super.c
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
20 #include <linux/config.h>
21 #include <linux/fs.h>
22 #include <linux/module.h>
23 #include <linux/blkdev.h>
24 #include <linux/completion.h>
25 #include <asm/uaccess.h>
26 #include "jfs_incore.h"
27 #include "jfs_filsys.h"
28 #include "jfs_metapage.h"
29 #include "jfs_superblock.h"
30 #include "jfs_dmap.h"
31 #include "jfs_imap.h"
32 #include "jfs_debug.h"
33
34 MODULE_DESCRIPTION("The Journaled Filesystem (JFS)");
35 MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM");
36 MODULE_LICENSE("GPL");
37
38 static struct super_operations jfs_super_operations;
39 static struct file_system_type jfs_fs_type;
40
41 int jfs_stop_threads;
42 static pid_t jfsIOthread;
43 static pid_t jfsCommitThread;
44 static pid_t jfsSyncThread;
45 DECLARE_COMPLETION(jfsIOwait);
46
47 #ifdef CONFIG_JFS_DEBUG
48 int jfsloglevel = 1;
49 MODULE_PARM(jfsloglevel, "i");
50 MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
51 #endif
52
53 /*
54  * External declarations
55  */
56 extern int jfs_mount(struct super_block *);
57 extern int jfs_mount_rw(struct super_block *, int);
58 extern int jfs_umount(struct super_block *);
59 extern int jfs_umount_rw(struct super_block *);
60
61 extern int jfsIOWait(void *);
62 extern int jfs_lazycommit(void *);
63 extern int jfs_sync(void *);
64 extern void jfs_clear_inode(struct inode *inode);
65 extern void jfs_read_inode(struct inode *inode);
66 extern void jfs_dirty_inode(struct inode *inode);
67 extern void jfs_delete_inode(struct inode *inode);
68 extern void jfs_write_inode(struct inode *inode, int wait);
69 extern int jfs_extendfs(struct super_block *, s64, int);
70
71 #ifdef PROC_FS_JFS              /* see jfs_debug.h */
72 extern void jfs_proc_init(void);
73 extern void jfs_proc_clean(void);
74 #endif
75
76 extern wait_queue_head_t jfs_IO_thread_wait;
77 extern wait_queue_head_t jfs_commit_thread_wait;
78 extern wait_queue_head_t jfs_sync_thread_wait;
79
80 static int jfs_statfs(struct super_block *sb, struct statfs *buf)
81 {
82         struct jfs_sb_info *sbi = JFS_SBI(sb);
83         s64 maxinodes;
84         struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap;
85
86         jFYI(1, ("In jfs_statfs\n"));
87         buf->f_type = JFS_SUPER_MAGIC;
88         buf->f_bsize = sbi->bsize;
89         buf->f_blocks = sbi->bmap->db_mapsize;
90         buf->f_bfree = sbi->bmap->db_nfree;
91         buf->f_bavail = sbi->bmap->db_nfree;
92         /*
93          * If we really return the number of allocated & free inodes, some
94          * applications will fail because they won't see enough free inodes.
95          * We'll try to calculate some guess as to how may inodes we can
96          * really allocate
97          *
98          * buf->f_files = atomic_read(&imap->im_numinos);
99          * buf->f_ffree = atomic_read(&imap->im_numfree);
100          */
101         maxinodes = min((s64) atomic_read(&imap->im_numinos) +
102                         ((sbi->bmap->db_nfree >> imap->im_l2nbperiext)
103                          << L2INOSPEREXT), (s64) 0xffffffffLL);
104         buf->f_files = maxinodes;
105         buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) -
106                                     atomic_read(&imap->im_numfree));
107
108         buf->f_namelen = JFS_NAME_MAX;
109         return 0;
110 }
111
112 static void jfs_put_super(struct super_block *sb)
113 {
114         struct jfs_sb_info *sbi = JFS_SBI(sb);
115         int rc;
116
117         jFYI(1, ("In jfs_put_super\n"));
118         rc = jfs_umount(sb);
119         if (rc) {
120                 jERROR(1, ("jfs_umount failed with return code %d\n", rc));
121         }
122         unload_nls(sbi->nls_tab);
123         sbi->nls_tab = NULL;
124
125         kfree(sbi);
126 }
127
128 s64 jfs_get_volume_size(struct super_block *sb)
129 {
130         uint blocks = 0;
131         s64 bytes;
132         kdev_t dev = sb->s_dev;
133         int major = MAJOR(dev);
134         int minor = MINOR(dev);
135
136         if (blk_size[major]) {
137                 blocks = blk_size[major][minor];
138                 if (blocks) {
139                         bytes = ((s64)blocks) << BLOCK_SIZE_BITS;
140                         return bytes >> sb->s_blocksize_bits;
141                 }
142         }
143         return 0;
144 }
145
146 static int parse_options(char *options, struct super_block *sb, s64 *newLVSize)
147 {
148         void *nls_map = NULL;
149         char *this_char;
150         char *value;
151         struct jfs_sb_info *sbi = JFS_SBI(sb);
152
153         *newLVSize = 0;
154
155         if (!options)
156                 return 1;
157         while ((this_char = strsep(&options, ",")) != NULL) {
158                 if (!*this_char)
159                         continue;
160                 if ((value = strchr(this_char, '=')) != NULL)
161                         *value++ = 0;
162                 if (!strcmp(this_char, "iocharset")) {
163                         if (!value || !*value)
164                                 goto needs_arg;
165                         if (nls_map)    /* specified iocharset twice! */
166                                 unload_nls(nls_map);
167                         nls_map = load_nls(value);
168                         if (!nls_map) {
169                                 printk(KERN_ERR "JFS: charset not found\n");
170                                 goto cleanup;
171                         }
172                 } else if (!strcmp(this_char, "resize")) {
173                         if (!value || !*value) {
174                                 *newLVSize = jfs_get_volume_size(sb);
175                                 if (*newLVSize == 0)
176                                         printk(KERN_ERR
177                                          "JFS: Cannot determine volume size\n");
178                         } else
179                                 *newLVSize = simple_strtoull(value, &value, 0);
180
181                         /* Silently ignore the quota options */
182                 } else if (!strcmp(this_char, "grpquota")
183                            || !strcmp(this_char, "noquota")
184                            || !strcmp(this_char, "quota")
185                            || !strcmp(this_char, "usrquota"))
186                         /* Don't do anything ;-) */ ;
187                 else {
188                         printk("jfs: Unrecognized mount option %s\n",
189                                this_char);
190                         goto cleanup;
191                 }
192         }
193         if (nls_map) {
194                 /* Discard old (if remount) */
195                 if (sbi->nls_tab)
196                         unload_nls(sbi->nls_tab);
197                 sbi->nls_tab = nls_map;
198         }
199         return 1;
200 needs_arg:
201         printk(KERN_ERR "JFS: %s needs an argument\n", this_char);
202 cleanup:
203         if (nls_map)
204                 unload_nls(nls_map);
205         return 0;
206 }
207
208 int jfs_remount(struct super_block *sb, int *flags, char *data)
209 {
210         s64 newLVSize = 0;
211         int rc = 0;
212
213         if (!parse_options(data, sb, &newLVSize)) {
214                 return -EINVAL;
215         }
216         if (newLVSize) {
217                 if (sb->s_flags & MS_RDONLY) {
218                         printk(KERN_ERR
219                   "JFS: resize requires volume to be mounted read-write\n");
220                         return -EROFS;
221                 }
222                 rc = jfs_extendfs(sb, newLVSize, 0);
223                 if (rc)
224                         return rc;
225         }
226
227         if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY))
228                 return jfs_mount_rw(sb, 1);
229         else if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY))
230                 return jfs_umount_rw(sb);
231
232         return 0;
233 }
234
235 static struct super_block *jfs_read_super(struct super_block *sb,
236                                           void *data, int silent)
237 {
238         struct jfs_sb_info *sbi;
239         struct inode *inode;
240         int rc;
241         s64 newLVSize = 0;
242
243         jFYI(1,
244              ("In jfs_read_super s_dev=0x%x s_flags=0x%lx\n", sb->s_dev,
245               sb->s_flags));
246
247         sbi = kmalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
248         if (!sbi)
249                 return NULL;
250         memset(sbi, 0, sizeof (struct jfs_sb_info));
251         sb->u.generic_sbp = sbi;
252
253         if (!parse_options((char *) data, sb, &newLVSize)) {
254                 kfree(sbi);
255                 return NULL;
256         }
257
258         if (newLVSize) {
259                 printk(KERN_ERR "resize option for remount only\n");
260                 return NULL;
261         }
262
263         /*
264          * Initialize blocksize to 4K.
265          */
266         sb_set_blocksize(sb, PSIZE);
267
268         /*
269          * Set method vectors.
270          */
271         sb->s_op = &jfs_super_operations;
272
273         rc = jfs_mount(sb);
274         if (rc) {
275                 if (!silent) {
276                         jERROR(1,
277                                ("jfs_mount failed w/return code = %d\n", rc));
278                 }
279                 goto out_kfree;
280         }
281         if (sb->s_flags & MS_RDONLY)
282                 sbi->log = 0;
283         else {
284                 rc = jfs_mount_rw(sb, 0);
285                 if (rc) {
286                         if (!silent) {
287                                 jERROR(1,
288                                        ("jfs_mount_rw failed w/return code = %d\n",
289                                         rc));
290                         }
291                         goto out_no_rw;
292                 }
293         }
294
295         sb->s_magic = JFS_SUPER_MAGIC;
296
297         inode = iget(sb, ROOT_I);
298         if (!inode || is_bad_inode(inode))
299                 goto out_no_root;
300         sb->s_root = d_alloc_root(inode);
301         if (!sb->s_root)
302                 goto out_no_root;
303
304         if (!sbi->nls_tab)
305                 sbi->nls_tab = load_nls_default();
306
307         /* logical blocks are represented by 40 bits in pxd_t, etc. */
308         sb->s_maxbytes = ((u64) sb->s_blocksize) << 40;
309 #if BITS_PER_LONG == 32
310         /*
311          * Page cache is indexed by long.
312          * I would use MAX_LFS_FILESIZE, but it's only half as big
313          */
314         sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes);
315 #endif
316
317         return sb;
318
319 out_no_root:
320         jEVENT(1, ("jfs_read_super: get root inode failed\n"));
321         if (inode)
322                 iput(inode);
323
324 out_no_rw:
325         rc = jfs_umount(sb);
326         if (rc) {
327                 jERROR(1, ("jfs_umount failed with return code %d\n", rc));
328         }
329 out_kfree:
330         if (sbi->nls_tab)
331                 unload_nls(sbi->nls_tab);
332         kfree(sbi);
333         return NULL;
334 }
335
336 static void jfs_write_super_lockfs(struct super_block *sb)
337 {
338         struct jfs_sb_info *sbi = JFS_SBI(sb);
339         struct jfs_log *log = sbi->log;
340
341         if (!(sb->s_flags & MS_RDONLY)) {
342                 txQuiesce(sb);
343                 lmLogShutdown(log);
344         }
345 }
346
347 static void jfs_unlockfs(struct super_block *sb)
348 {
349         struct jfs_sb_info *sbi = JFS_SBI(sb);
350         struct jfs_log *log = sbi->log;
351         int rc = 0;
352
353         if (!(sb->s_flags & MS_RDONLY)) {
354                 if ((rc = lmLogInit(log)))
355                         jERROR(1,
356                                ("jfs_unlock failed with return code %d\n", rc));
357                 else
358                         txResume(sb);
359         }
360 }
361
362
363 static int jfs_sync_fs(struct super_block *sb)
364 {
365         struct jfs_log *log = JFS_SBI(sb)->log;
366
367         /* log == NULL indicates read-only mount */
368         if (log)
369                 jfs_flush_journal(log, 1);
370
371         return 0;
372 }
373
374 static struct super_operations jfs_super_operations = {
375         .read_inode     = jfs_read_inode,
376         .dirty_inode    = jfs_dirty_inode,
377         .write_inode    = jfs_write_inode,
378         .clear_inode    = jfs_clear_inode,
379         .delete_inode   = jfs_delete_inode,
380         .put_super      = jfs_put_super,
381         .sync_fs        = jfs_sync_fs,
382         .write_super_lockfs = jfs_write_super_lockfs,
383         .unlockfs       = jfs_unlockfs,
384         .statfs         = jfs_statfs,
385         .remount_fs     = jfs_remount,
386 };
387
388 static struct file_system_type jfs_fs_type = {
389         .owner          = THIS_MODULE,
390         .name           = "jfs",
391         .read_super     = jfs_read_super,
392         .fs_flags       = FS_REQUIRES_DEV,
393 };
394
395 extern int metapage_init(void);
396 extern int txInit(void);
397 extern void txExit(void);
398 extern void metapage_exit(void);
399
400 static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
401 {
402         struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
403
404         if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
405             SLAB_CTOR_CONSTRUCTOR) {
406                 INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
407                 init_rwsem(&jfs_ip->rdwrlock);
408                 init_MUTEX(&jfs_ip->commit_sem);
409                 jfs_ip->atlhead = 0;
410                 jfs_ip->active_ag = -1;
411         }
412 }
413
414 static int __init init_jfs_fs(void)
415 {
416         int rc;
417
418         jfs_inode_cachep =
419             kmem_cache_create("jfs_ip", sizeof (struct jfs_inode_info), 0, 0,
420                               init_once, NULL);
421         if (jfs_inode_cachep == NULL)
422                 return -ENOMEM;
423
424         /*
425          * Metapage initialization
426          */
427         rc = metapage_init();
428         if (rc) {
429                 jERROR(1, ("metapage_init failed w/rc = %d\n", rc));
430                 goto free_slab;
431         }
432
433         /*
434          * Transaction Manager initialization
435          */
436         rc = txInit();
437         if (rc) {
438                 jERROR(1, ("txInit failed w/rc = %d\n", rc));
439                 goto free_metapage;
440         }
441
442         /*
443          * I/O completion thread (endio)
444          */
445         jfsIOthread = kernel_thread(jfsIOWait, 0,
446                                     CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
447         if (jfsIOthread < 0) {
448                 jERROR(1,
449                        ("init_jfs_fs: fork failed w/rc = %d\n", jfsIOthread));
450                 goto end_txmngr;
451         }
452         wait_for_completion(&jfsIOwait);        /* Wait until thread starts */
453
454         jfsCommitThread = kernel_thread(jfs_lazycommit, 0,
455                                         CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
456         if (jfsCommitThread < 0) {
457                 jERROR(1,
458                        ("init_jfs_fs: fork failed w/rc = %d\n",
459                         jfsCommitThread));
460                 goto kill_iotask;
461         }
462         wait_for_completion(&jfsIOwait);        /* Wait until thread starts */
463
464         jfsSyncThread = kernel_thread(jfs_sync, 0,
465                                       CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
466         if (jfsSyncThread < 0) {
467                 jERROR(1,
468                        ("init_jfs_fs: fork failed w/rc = %d\n", jfsSyncThread));
469                 goto kill_committask;
470         }
471         wait_for_completion(&jfsIOwait);        /* Wait until thread starts */
472
473 #ifdef PROC_FS_JFS
474         jfs_proc_init();
475 #endif
476
477         return register_filesystem(&jfs_fs_type);
478
479 kill_committask:
480         jfs_stop_threads = 1;
481         wake_up(&jfs_commit_thread_wait);
482         wait_for_completion(&jfsIOwait);        /* Wait for thread exit */
483 kill_iotask:
484         jfs_stop_threads = 1;
485         wake_up(&jfs_IO_thread_wait);
486         wait_for_completion(&jfsIOwait);        /* Wait for thread exit */
487 end_txmngr:
488         txExit();
489 free_metapage:
490         metapage_exit();
491 free_slab:
492         kmem_cache_destroy(jfs_inode_cachep);
493         return -rc;
494 }
495
496 static void __exit exit_jfs_fs(void)
497 {
498         jFYI(1, ("exit_jfs_fs called\n"));
499
500         jfs_stop_threads = 1;
501         txExit();
502         metapage_exit();
503         wake_up(&jfs_IO_thread_wait);
504         wait_for_completion(&jfsIOwait);        /* Wait for IO thread exit */
505         wake_up(&jfs_commit_thread_wait);
506         wait_for_completion(&jfsIOwait);        /* Wait for Commit thread exit */
507         wake_up(&jfs_sync_thread_wait);
508         wait_for_completion(&jfsIOwait);        /* Wait for Sync thread exit */
509 #ifdef PROC_FS_JFS
510         jfs_proc_clean();
511 #endif
512         unregister_filesystem(&jfs_fs_type);
513         kmem_cache_destroy(jfs_inode_cachep);
514 }
515
516 EXPORT_NO_SYMBOLS;
517
518 module_init(init_jfs_fs)
519 module_exit(exit_jfs_fs)