X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fjfs%2Fsuper.c;h=2d6c03d6dc7e20564a436b9180dc21ff452b6601;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=72ae53817dfd5984c85ec5bf0c397954562ed3c9;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 72ae53817..2d6c03d6d 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -23,10 +23,16 @@ #include #include #include +#include +#include +#include +#include #include +#include #include "jfs_incore.h" #include "jfs_filsys.h" +#include "jfs_inode.h" #include "jfs_metapage.h" #include "jfs_superblock.h" #include "jfs_dmap.h" @@ -44,47 +50,21 @@ static struct super_operations jfs_super_operations; static struct export_operations jfs_export_operations; static struct file_system_type jfs_fs_type; -int jfs_stop_threads; -static pid_t jfsIOthread; -static pid_t jfsCommitThread; -static pid_t jfsSyncThread; -DECLARE_COMPLETION(jfsIOwait); +#define MAX_COMMIT_THREADS 64 +static int commit_threads = 0; +module_param(commit_threads, int, 0); +MODULE_PARM_DESC(commit_threads, "Number of commit threads"); + +static struct task_struct *jfsCommitThread[MAX_COMMIT_THREADS]; +struct task_struct *jfsIOthread; +struct task_struct *jfsSyncThread; #ifdef CONFIG_JFS_DEBUG int jfsloglevel = JFS_LOGLEVEL_WARN; -MODULE_PARM(jfsloglevel, "i"); +module_param(jfsloglevel, int, 0644); MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)"); #endif -/* - * External declarations - */ -extern int jfs_mount(struct super_block *); -extern int jfs_mount_rw(struct super_block *, int); -extern int jfs_umount(struct super_block *); -extern int jfs_umount_rw(struct super_block *); - -extern int jfsIOWait(void *); -extern int jfs_lazycommit(void *); -extern int jfs_sync(void *); - -extern void jfs_read_inode(struct inode *inode); -extern void jfs_dirty_inode(struct inode *inode); -extern void jfs_delete_inode(struct inode *inode); -extern void jfs_write_inode(struct inode *inode, int wait); - -extern struct dentry *jfs_get_parent(struct dentry *dentry); -extern int jfs_extendfs(struct super_block *, s64, int); - -#ifdef PROC_FS_JFS /* see jfs_debug.h */ -extern void jfs_proc_init(void); -extern void jfs_proc_clean(void); -#endif - -extern wait_queue_head_t jfs_IO_thread_wait; -extern wait_queue_head_t jfs_commit_thread_wait; -extern wait_queue_head_t jfs_sync_thread_wait; - static void jfs_handle_error(struct super_block *sb) { struct jfs_sb_info *sbi = JFS_SBI(sb); @@ -135,10 +115,15 @@ static void jfs_destroy_inode(struct inode *inode) { struct jfs_inode_info *ji = JFS_IP(inode); + BUG_ON(!list_empty(&ji->anon_inode_list)); + + spin_lock_irq(&ji->ag_lock); if (ji->active_ag != -1) { struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap; atomic_dec(&bmap->db_active[ji->active_ag]); + ji->active_ag = -1; } + spin_unlock_irq(&ji->ag_lock); #ifdef CONFIG_JFS_POSIX_ACL if (ji->i_acl != JFS_ACL_NOT_CACHED) { @@ -199,12 +184,18 @@ static void jfs_put_super(struct super_block *sb) unload_nls(sbi->nls_tab); sbi->nls_tab = NULL; + truncate_inode_pages(sbi->direct_inode->i_mapping, 0); + iput(sbi->direct_inode); + sbi->direct_inode = NULL; + kfree(sbi); } enum { Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize, - Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, + Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota, + Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask, + Opt_tagxid }; static match_table_t tokens = { @@ -214,17 +205,21 @@ static match_table_t tokens = { {Opt_resize, "resize=%u"}, {Opt_resize_nosize, "resize"}, {Opt_errors, "errors=%s"}, + {Opt_tagxid, "tagxid"}, {Opt_ignore, "noquota"}, {Opt_ignore, "quota"}, - {Opt_ignore, "usrquota"}, - {Opt_ignore, "grpquota"}, + {Opt_usrquota, "usrquota"}, + {Opt_grpquota, "grpquota"}, + {Opt_uid, "uid=%u"}, + {Opt_gid, "gid=%u"}, + {Opt_umask, "umask=%u"}, {Opt_err, NULL} }; static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, int *flag) { - void *nls_map = NULL; + void *nls_map = (void *)-1; /* -1: no change; NULL: none */ char *p; struct jfs_sb_info *sbi = JFS_SBI(sb); @@ -252,12 +247,17 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, /* Don't do anything ;-) */ break; case Opt_iocharset: - if (nls_map) /* specified iocharset twice! */ + if (nls_map && nls_map != (void *) -1) unload_nls(nls_map); - nls_map = load_nls(args[0].from); - if (!nls_map) { - printk(KERN_ERR "JFS: charset not found\n"); - goto cleanup; + if (!strcmp(args[0].from, "none")) + nls_map = NULL; + else { + nls_map = load_nls(args[0].from); + if (!nls_map) { + printk(KERN_ERR + "JFS: charset not found\n"); + goto cleanup; + } } break; case Opt_resize: @@ -300,6 +300,51 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, } break; } + +#if defined(CONFIG_QUOTA) + case Opt_quota: + case Opt_usrquota: + *flag |= JFS_USRQUOTA; + break; + case Opt_grpquota: + *flag |= JFS_GRPQUOTA; + break; +#else + case Opt_usrquota: + case Opt_grpquota: + case Opt_quota: + printk(KERN_ERR + "JFS: quota operations not supported\n"); + break; +#endif + case Opt_uid: + { + char *uid = args[0].from; + sbi->uid = simple_strtoul(uid, &uid, 0); + break; + } + case Opt_gid: + { + char *gid = args[0].from; + sbi->gid = simple_strtoul(gid, &gid, 0); + break; + } + case Opt_umask: + { + char *umask = args[0].from; + sbi->umask = simple_strtoul(umask, &umask, 8); + if (sbi->umask & ~0777) { + printk(KERN_ERR + "JFS: Invalid value of umask\n"); + goto cleanup; + } + break; + } +#ifndef CONFIG_TAGGING_NONE + case Opt_tagxid: + *flag |= JFS_TAGXID; + break; +#endif default: printk("jfs: Unrecognized mount option \"%s\" " " or missing value\n", p); @@ -307,7 +352,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, } } - if (nls_map) { + if (nls_map != (void *) -1) { /* Discard old (if remount) */ if (sbi->nls_tab) unload_nls(sbi->nls_tab); @@ -316,7 +361,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, return 1; cleanup: - if (nls_map) + if (nls_map && nls_map != (void *) -1) unload_nls(nls_map); return 0; } @@ -330,6 +375,13 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data) if (!parse_options(data, sb, &newLVSize, &flag)) { return -EINVAL; } + + if ((flag & JFS_TAGXID) && !(sb->s_flags & MS_TAGXID)) { + printk(KERN_ERR "JFS: %s: tagxid not permitted on remount.\n", + sb->s_id); + return -EINVAL; + } + if (newLVSize) { if (sb->s_flags & MS_RDONLY) { printk(KERN_ERR @@ -342,6 +394,12 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data) } if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { + /* + * Invalidate any previously read metadata. fsck may have + * changed the on-disk data since we mounted r/o + */ + truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0); + JFS_SBI(sb)->flag = flag; return jfs_mount_rw(sb, 1); } @@ -376,12 +434,12 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) if (!new_valid_dev(sb->s_bdev->bd_dev)) return -EOVERFLOW; - sbi = kmalloc(sizeof (struct jfs_sb_info), GFP_KERNEL); + sbi = kzalloc(sizeof (struct jfs_sb_info), GFP_KERNEL); if (!sbi) return -ENOSPC; - memset(sbi, 0, sizeof (struct jfs_sb_info)); sb->s_fs_info = sbi; sbi->sb = sb; + sbi->uid = sbi->gid = sbi->umask = -1; /* initialize the mount flag and determine the default error handler */ flag = JFS_ERR_REMOUNT_RO; @@ -392,6 +450,13 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) } sbi->flag = flag; +#ifdef CONFIG_JFS_POSIX_ACL + sb->s_flags |= MS_POSIXACL; +#endif + /* map mount option tagxid */ + if (sbi->flag & JFS_TAGXID) + sb->s_flags |= MS_TAGXID; + if (newLVSize) { printk(KERN_ERR "resize option for remount only\n"); return -EINVAL; @@ -408,15 +473,30 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_op = &jfs_super_operations; sb->s_export_op = &jfs_export_operations; + /* + * Initialize direct-mapping inode/address-space + */ + inode = new_inode(sb); + if (inode == NULL) + goto out_kfree; + inode->i_ino = 0; + inode->i_nlink = 1; + inode->i_size = sb->s_bdev->bd_inode->i_size; + inode->i_mapping->a_ops = &jfs_metapage_aops; + insert_inode_hash(inode); + mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); + + sbi->direct_inode = inode; + rc = jfs_mount(sb); if (rc) { if (!silent) { jfs_err("jfs_mount failed w/return code = %d", rc); } - goto out_kfree; + goto out_mount_failed; } if (sb->s_flags & MS_RDONLY) - sbi->log = 0; + sbi->log = NULL; else { rc = jfs_mount_rw(sb, 0); if (rc) { @@ -437,6 +517,9 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) if (!sb->s_root) goto out_no_root; + if (sbi->mntflag & JFS_OS2) + sb->s_root->d_op = &jfs_ci_dentry_operations; + /* logical blocks are represented by 40 bits in pxd_t, etc. */ sb->s_maxbytes = ((u64) sb->s_blocksize) << 40; #if BITS_PER_LONG == 32 @@ -446,7 +529,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) */ sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes); #endif - + sb->s_time_gran = 1; return 0; out_no_root: @@ -459,6 +542,12 @@ out_no_rw: if (rc) { jfs_err("jfs_umount failed with return code %d", rc); } +out_mount_failed: + filemap_write_and_wait(sbi->direct_inode->i_mapping); + truncate_inode_pages(sbi->direct_inode->i_mapping, 0); + make_bad_inode(sbi->direct_inode); + iput(sbi->direct_inode); + sbi->direct_inode = NULL; out_kfree: if (sbi->nls_tab) unload_nls(sbi->nls_tab); @@ -504,8 +593,34 @@ static int jfs_sync_fs(struct super_block *sb, int wait) struct jfs_log *log = JFS_SBI(sb)->log; /* log == NULL indicates read-only mount */ - if (log) + if (log) { jfs_flush_journal(log, wait); + jfs_syncpt(log, 0); + } + + return 0; +} + +static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) +{ + struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb); + + if (sbi->uid != -1) + seq_printf(seq, ",uid=%d", sbi->uid); + if (sbi->gid != -1) + seq_printf(seq, ",gid=%d", sbi->gid); + if (sbi->umask != -1) + seq_printf(seq, ",umask=%03o", sbi->umask); + if (sbi->flag & JFS_NOINTEGRITY) + seq_puts(seq, ",nointegrity"); + +#if defined(CONFIG_QUOTA) + if (sbi->flag & JFS_USRQUOTA) + seq_puts(seq, ",usrquota"); + + if (sbi->flag & JFS_GRPQUOTA) + seq_puts(seq, ",grpquota"); +#endif return 0; } @@ -523,6 +638,7 @@ static struct super_operations jfs_super_operations = { .unlockfs = jfs_unlockfs, .statfs = jfs_statfs, .remount_fs = jfs_remount, + .show_options = jfs_show_options }; static struct export_operations jfs_export_operations = { @@ -537,11 +653,6 @@ static struct file_system_type jfs_fs_type = { .fs_flags = FS_REQUIRES_DEV, }; -extern int metapage_init(void); -extern int txInit(void); -extern void txExit(void); -extern void metapage_exit(void); - static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) { struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; @@ -551,8 +662,9 @@ static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) memset(jfs_ip, 0, sizeof(struct jfs_inode_info)); INIT_LIST_HEAD(&jfs_ip->anon_inode_list); init_rwsem(&jfs_ip->rdwrlock); - init_MUTEX(&jfs_ip->commit_sem); + mutex_init(&jfs_ip->commit_mutex); init_rwsem(&jfs_ip->xattr_sem); + spin_lock_init(&jfs_ip->ag_lock); jfs_ip->active_ag = -1; #ifdef CONFIG_JFS_POSIX_ACL jfs_ip->i_acl = JFS_ACL_NOT_CACHED; @@ -564,11 +676,13 @@ static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) static int __init init_jfs_fs(void) { + int i; int rc; jfs_inode_cachep = kmem_cache_create("jfs_ip", sizeof(struct jfs_inode_info), 0, - SLAB_RECLAIM_ACCOUNT, init_once, NULL); + SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, + init_once, NULL); if (jfs_inode_cachep == NULL) return -ENOMEM; @@ -593,26 +707,34 @@ static int __init init_jfs_fs(void) /* * I/O completion thread (endio) */ - jfsIOthread = kernel_thread(jfsIOWait, 0, CLONE_KERNEL); - if (jfsIOthread < 0) { - jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsIOthread); + jfsIOthread = kthread_run(jfsIOWait, NULL, "jfsIO"); + if (IS_ERR(jfsIOthread)) { + rc = PTR_ERR(jfsIOthread); + jfs_err("init_jfs_fs: fork failed w/rc = %d", rc); goto end_txmngr; } - wait_for_completion(&jfsIOwait); /* Wait until thread starts */ - jfsCommitThread = kernel_thread(jfs_lazycommit, 0, CLONE_KERNEL); - if (jfsCommitThread < 0) { - jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsCommitThread); - goto kill_iotask; + if (commit_threads < 1) + commit_threads = num_online_cpus(); + if (commit_threads > MAX_COMMIT_THREADS) + commit_threads = MAX_COMMIT_THREADS; + + for (i = 0; i < commit_threads; i++) { + jfsCommitThread[i] = kthread_run(jfs_lazycommit, NULL, "jfsCommit"); + if (IS_ERR(jfsCommitThread[i])) { + rc = PTR_ERR(jfsCommitThread[i]); + jfs_err("init_jfs_fs: fork failed w/rc = %d", rc); + commit_threads = i; + goto kill_committask; + } } - wait_for_completion(&jfsIOwait); /* Wait until thread starts */ - jfsSyncThread = kernel_thread(jfs_sync, 0, CLONE_KERNEL); - if (jfsSyncThread < 0) { - jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsSyncThread); + jfsSyncThread = kthread_run(jfs_sync, NULL, "jfsSync"); + if (IS_ERR(jfsSyncThread)) { + rc = PTR_ERR(jfsSyncThread); + jfs_err("init_jfs_fs: fork failed w/rc = %d", rc); goto kill_committask; } - wait_for_completion(&jfsIOwait); /* Wait until thread starts */ #ifdef PROC_FS_JFS jfs_proc_init(); @@ -621,13 +743,9 @@ static int __init init_jfs_fs(void) return register_filesystem(&jfs_fs_type); kill_committask: - jfs_stop_threads = 1; - wake_up(&jfs_commit_thread_wait); - wait_for_completion(&jfsIOwait); /* Wait for thread exit */ -kill_iotask: - jfs_stop_threads = 1; - wake_up(&jfs_IO_thread_wait); - wait_for_completion(&jfsIOwait); /* Wait for thread exit */ + for (i = 0; i < commit_threads; i++) + kthread_stop(jfsCommitThread[i]); + kthread_stop(jfsIOthread); end_txmngr: txExit(); free_metapage: @@ -639,17 +757,17 @@ free_slab: static void __exit exit_jfs_fs(void) { + int i; + jfs_info("exit_jfs_fs called"); - jfs_stop_threads = 1; txExit(); metapage_exit(); - wake_up(&jfs_IO_thread_wait); - wait_for_completion(&jfsIOwait); /* Wait until IO thread exits */ - wake_up(&jfs_commit_thread_wait); - wait_for_completion(&jfsIOwait); /* Wait until Commit thread exits */ - wake_up(&jfs_sync_thread_wait); - wait_for_completion(&jfsIOwait); /* Wait until Sync thread exits */ + + kthread_stop(jfsIOthread); + for (i = 0; i < commit_threads; i++) + kthread_stop(jfsCommitThread[i]); + kthread_stop(jfsSyncThread); #ifdef PROC_FS_JFS jfs_proc_clean(); #endif