* [PATCHes] fs/super.c stuff
@ 2001-06-11 5:32 Alexander Viro
2001-06-11 5:33 ` [PATCH] fs/super.c stuff (1/10) Alexander Viro
0 siblings, 1 reply; 12+ messages in thread
From: Alexander Viro @ 2001-06-11 5:32 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel
OK. It works here(tm). I'm sending first 10 chunks - about 70% of locking
changes. That's a good intermediate point and I'd rather avoid doing too
large steps.
Contents (patches will go in separate postings):
1, Eliminates mnt_instances and s_mounts. Instead of it we add new field to
struct super_block - s_active. Number of vfsmounts for given superblock,
i.e. number of entries in old s_mounts. Right now all accesses are serialized
by mount_sem, but later we'll need it to be atomic_t.
2. Better handling of s_active. Instead of incrementing it just when we
attach a vfsmount we do that beforehand and decrement if get_sb_... fails.
3. blkdev_put(bdev, BDEV_FS) doesn't touch superblock anymore. Current
callers don't need that (nothing to touch - it's either final kill_super()
or failed read_super()) and having it non-interfering with fs structures
gives us more freedom for get_sb_bdev().
4. pure cosmetics - fs.h contains an extern for function that doesn't exist
(put_super(kdev_t)). Removed.
5. instead of passing sb->s_dev to remove_dquot_ref() and doing get_super()
there we pass sb itself. While we are at it invalidate_dquots() is made
static - nothing outside of dquot.c calls it.
6. drop_super() added. At that stage - empty, we just add calls to balance
those of get_super().
7. First serious part.
* we add a spinlock (sb_lock) that protects super_blocks list.
* we add a reference counter to struct super_block. ->s_count.
At that stage we don't use it - only maintain correct value. Logics is
the same as for mm_struct - each temporary reference contributes 1,
all permanent references (from vfsmounts) are lumped together. It's an
int - all accesses are protected by sb_lock.
At that stage we rely on mount_sem to handle the moments when
we turn a temporary reference into permanent one. That will change,
but we need to kill the "reuse" branch of get_empty_super() to do that.
And that requires s_count already in place.
8. _Now_ we can get to real stuff.
* kill_super() removes dying superblock from the super_blocks list.
* when s_count drops to zero we free the superblock.
9. We are done with "reuse" branch of get_empty_super(). The rest (allocation
of new one) is renamed in alloc_super(). Insertion into the super_blocks
is moved into (the only) caller - read_super().
10. Now we can solve most of the problems with get_super()/umount().
get_super() does down_read(&s->s_umount (and drop_super() - up_read()).
>From that point it's more or less easy ride - we need to reorganize
get_sb_...() to have exclusion between mount() and get_super() callers,
but now we have everything we need for that. I would rather submit that
part separately. All really evil stuff is done - in a sense it's the
nastiest point of sequence. Basically, the rest will consist of cleanups.
I've tried to carve the thing into edible chunks - if you find something
too large, please, tell. Patches themselves will go in followups to this
posting, numbered from 1 to 10. They are incremental to each other, starting
at 2.4.6-pre2.
Cheers,
Al
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] fs/super.c stuff (1/10) 2001-06-11 5:32 [PATCHes] fs/super.c stuff Alexander Viro @ 2001-06-11 5:33 ` Alexander Viro 2001-06-11 5:33 ` [PATCH] fs/super.c stuff (2/10) Alexander Viro 0 siblings, 1 reply; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:33 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2/fs/super.c S6-pre2-mnt_instances/fs/super.c --- S6-pre2/fs/super.c Fri Jun 8 18:29:03 2001 +++ S6-pre2-mnt_instances/fs/super.c Sat Jun 9 19:18:31 2001 @@ -386,19 +386,20 @@ mnt->mnt_parent = mnt; spin_lock(&dcache_lock); - list_add(&mnt->mnt_instances, &sb->s_mounts); list_add(&mnt->mnt_list, vfsmntlist.prev); spin_unlock(&dcache_lock); + atomic_inc(&sb->s_active); if (sb->s_type->fs_flags & FS_SINGLE) get_filesystem(sb->s_type); out: return mnt; } -static struct vfsmount *clone_mnt(struct vfsmount *old_mnt, struct dentry *root) +static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root) { - char *name = old_mnt->mnt_devname; + char *name = old->mnt_devname; struct vfsmount *mnt = alloc_vfsmnt(); + struct super_block *sb = old->mnt_sb; if (!mnt) goto out; @@ -408,14 +409,12 @@ if (mnt->mnt_devname) strcpy(mnt->mnt_devname, name); } - mnt->mnt_sb = old_mnt->mnt_sb; + mnt->mnt_sb = sb; mnt->mnt_root = dget(root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - spin_lock(&dcache_lock); - list_add(&mnt->mnt_instances, &old_mnt->mnt_instances); - spin_unlock(&dcache_lock); + atomic_inc(&sb->s_active); out: return mnt; } @@ -487,9 +486,6 @@ struct super_block *sb = mnt->mnt_sb; dput(mnt->mnt_root); - spin_lock(&dcache_lock); - list_del(&mnt->mnt_instances); - spin_unlock(&dcache_lock); if (mnt->mnt_devname) kfree(mnt->mnt_devname); kmem_cache_free(mnt_cache, mnt); @@ -757,9 +753,9 @@ INIT_LIST_HEAD(&s->s_locked_inodes); list_add (&s->s_list, super_blocks.prev); INIT_LIST_HEAD(&s->s_files); - INIT_LIST_HEAD(&s->s_mounts); init_rwsem(&s->s_umount); sema_init(&s->s_lock, 1); + atomic_set(&s->s_active, 0); sema_init(&s->s_vfs_rename_sem,1); sema_init(&s->s_nfsd_free_path_sem,1); sema_init(&s->s_dquot.dqio_sem, 1); @@ -938,12 +934,9 @@ struct file_system_type *fs = sb->s_type; struct super_operations *sop = sb->s_op; - spin_lock(&dcache_lock); - if (!list_empty(&sb->s_mounts)) { - spin_unlock(&dcache_lock); + atomic_dec(&sb->s_active); + if (atomic_read(&sb->s_active)) return; - } - spin_unlock(&dcache_lock); down_write(&sb->s_umount); lock_kernel(); sb->s_root = NULL; @@ -1045,9 +1038,7 @@ mnt->mnt_root = dget(sb->s_root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - spin_lock(&dcache_lock); - list_add(&mnt->mnt_instances, &sb->s_mounts); - spin_unlock(&dcache_lock); + atomic_inc(&sb->s_active); type->kern_mnt = mnt; return mnt; } @@ -1092,7 +1083,7 @@ spin_lock(&dcache_lock); - if (mnt->mnt_instances.next != mnt->mnt_instances.prev) { + if (atomic_read(&sb->s_active) > 1) { if (atomic_read(&mnt->mnt_count) > 2) { spin_unlock(&dcache_lock); return -EBUSY; @@ -1324,9 +1315,7 @@ mnt->mnt_root = dget(sb->s_root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - spin_lock(&dcache_lock); - list_add(&mnt->mnt_instances, &sb->s_mounts); - spin_unlock(&dcache_lock); + atomic_inc(&sb->s_active); /* Something was mounted here while we slept */ while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) diff -urN S6-pre2/include/linux/fs.h S6-pre2-mnt_instances/include/linux/fs.h --- S6-pre2/include/linux/fs.h Fri Jun 8 18:29:03 2001 +++ S6-pre2-mnt_instances/include/linux/fs.h Sat Jun 9 19:18:31 2001 @@ -679,13 +679,13 @@ struct dentry *s_root; struct rw_semaphore s_umount; struct semaphore s_lock; + atomic_t s_active; struct list_head s_dirty; /* dirty inodes */ struct list_head s_locked_inodes;/* inodes being synced */ struct list_head s_files; struct block_device *s_bdev; - struct list_head s_mounts; /* vfsmount(s) of this one */ struct quota_mount_options s_dquot; /* Diskquota specific options */ union { diff -urN S6-pre2/include/linux/mount.h S6-pre2-mnt_instances/include/linux/mount.h --- S6-pre2/include/linux/mount.h Fri Jun 8 18:29:03 2001 +++ S6-pre2-mnt_instances/include/linux/mount.h Sat Jun 9 19:18:31 2001 @@ -18,7 +18,6 @@ struct vfsmount *mnt_parent; /* fs we are mounted on */ struct dentry *mnt_mountpoint; /* dentry of mountpoint */ struct dentry *mnt_root; /* root of the mounted tree */ - struct list_head mnt_instances; /* other vfsmounts of the same fs */ struct super_block *mnt_sb; /* pointer to superblock */ struct list_head mnt_mounts; /* list of children, anchored here */ struct list_head mnt_child; /* and going through their mnt_child */ ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] fs/super.c stuff (2/10) 2001-06-11 5:33 ` [PATCH] fs/super.c stuff (1/10) Alexander Viro @ 2001-06-11 5:33 ` Alexander Viro 2001-06-11 5:34 ` [PATCH] fs/super.c stuff (3/10) Alexander Viro 2001-06-11 5:34 ` Alexander Viro 0 siblings, 2 replies; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:33 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2-mnt_instances/fs/super.c S6-pre2-s_active/fs/super.c --- S6-pre2-mnt_instances/fs/super.c Sat Jun 9 19:18:31 2001 +++ S6-pre2-s_active/fs/super.c Sun Jun 10 12:07:40 2001 @@ -388,7 +388,6 @@ spin_lock(&dcache_lock); list_add(&mnt->mnt_list, vfsmntlist.prev); spin_unlock(&dcache_lock); - atomic_inc(&sb->s_active); if (sb->s_type->fs_flags & FS_SINGLE) get_filesystem(sb->s_type); out: @@ -740,6 +739,7 @@ s = sb_entry(s->s_list.next)) { if (s->s_dev) continue; + atomic_inc(&s->s_active); return s; } /* Need a new one... */ @@ -755,7 +755,7 @@ INIT_LIST_HEAD(&s->s_files); init_rwsem(&s->s_umount); sema_init(&s->s_lock, 1); - atomic_set(&s->s_active, 0); + atomic_set(&s->s_active, 1); sema_init(&s->s_vfs_rename_sem,1); sema_init(&s->s_nfsd_free_path_sem,1); sema_init(&s->s_dquot.dqio_sem, 1); @@ -794,6 +794,7 @@ s->s_bdev = 0; s->s_type = NULL; unlock_super(s); + atomic_dec(&s->s_active); return NULL; } @@ -860,6 +861,7 @@ if (fs_type == sb->s_type && ((flags ^ sb->s_flags) & MS_RDONLY) == 0) { path_release(&nd); + atomic_inc(&sb->s_active); return sb; } } else { @@ -923,6 +925,7 @@ if (!sb) BUG(); do_remount_sb(sb, flags, data); + atomic_inc(&sb->s_active); return sb; } @@ -1038,7 +1041,6 @@ mnt->mnt_root = dget(sb->s_root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - atomic_inc(&sb->s_active); type->kern_mnt = mnt; return mnt; } @@ -1315,7 +1317,6 @@ mnt->mnt_root = dget(sb->s_root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - atomic_inc(&sb->s_active); /* Something was mounted here while we slept */ while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) @@ -1573,6 +1574,7 @@ sb = get_super(ROOT_DEV); if (sb) { fs_type = sb->s_type; + atomic_inc(&sb->s_active); goto mount_it; } ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] fs/super.c stuff (3/10) 2001-06-11 5:33 ` [PATCH] fs/super.c stuff (2/10) Alexander Viro @ 2001-06-11 5:34 ` Alexander Viro 2001-06-11 5:34 ` Alexander Viro 1 sibling, 0 replies; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:34 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2-s_active/fs/block_dev.c S6-pre2-fsync_no_super/fs/block_dev.c --- S6-pre2-s_active/fs/block_dev.c Fri Jun 8 18:29:02 2001 +++ S6-pre2-fsync_no_super/fs/block_dev.c Sun Jun 10 12:13:03 2001 @@ -678,8 +678,10 @@ down(&bdev->bd_sem); /* syncing will go here */ lock_kernel(); - if (kind == BDEV_FILE || kind == BDEV_FS) + if (kind == BDEV_FILE) fsync_dev(rdev); + else if (kind == BDEV_FS) + fsync_no_super(rdev); if (atomic_dec_and_test(&bdev->bd_openers)) { /* invalidating buffers will go here */ invalidate_buffers(rdev); diff -urN S6-pre2-s_active/fs/buffer.c S6-pre2-fsync_no_super/fs/buffer.c --- S6-pre2-s_active/fs/buffer.c Fri Jun 8 18:29:03 2001 +++ S6-pre2-fsync_no_super/fs/buffer.c Sun Jun 10 12:13:03 2001 @@ -318,6 +318,12 @@ return sync_buffers(dev, 1); } +int fsync_no_super(kdev_t dev) +{ + sync_buffers(dev, 0); + return sync_buffers(dev, 1); +} + int fsync_dev(kdev_t dev) { sync_buffers(dev, 0); diff -urN S6-pre2-s_active/fs/super.c S6-pre2-fsync_no_super/fs/super.c --- S6-pre2-s_active/fs/super.c Sun Jun 10 12:07:40 2001 +++ S6-pre2-fsync_no_super/fs/super.c Sun Jun 10 12:13:04 2001 @@ -971,12 +971,12 @@ sb->s_type = NULL; unlock_super(sb); unlock_kernel(); - up_write(&sb->s_umount); if (bdev) { blkdev_put(bdev, BDEV_FS); bdput(bdev); } else put_unnamed_dev(dev); + up_write(&sb->s_umount); } /* diff -urN S6-pre2-s_active/include/linux/fs.h S6-pre2-fsync_no_super/include/linux/fs.h --- S6-pre2-s_active/include/linux/fs.h Sun Jun 10 11:58:01 2001 +++ S6-pre2-fsync_no_super/include/linux/fs.h Sun Jun 10 12:13:04 2001 @@ -1122,6 +1122,7 @@ extern void sync_dev(kdev_t); extern int fsync_dev(kdev_t); extern int fsync_super(struct super_block *); +extern int fsync_no_super(kdev_t); extern void sync_inodes_sb(struct super_block *); extern int fsync_inode_buffers(struct inode *); extern int osync_inode_buffers(struct inode *); ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] fs/super.c stuff (3/10) 2001-06-11 5:33 ` [PATCH] fs/super.c stuff (2/10) Alexander Viro 2001-06-11 5:34 ` [PATCH] fs/super.c stuff (3/10) Alexander Viro @ 2001-06-11 5:34 ` Alexander Viro 2001-06-11 5:35 ` [PATCH] fs/super.c stuff (5/10) Alexander Viro 2001-06-11 5:36 ` [PATCH] fs/super.c stuff (3/10) Alexander Viro 1 sibling, 2 replies; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:34 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2-fsync_no_super/include/linux/fs.h S6-pre2-put_super/include/linux/fs.h --- S6-pre2-fsync_no_super/include/linux/fs.h Sun Jun 10 18:36:27 2001 +++ S6-pre2-put_super/include/linux/fs.h Sun Jun 10 18:39:04 2001 @@ -1320,7 +1320,6 @@ extern struct file_system_type *get_fs_type(const char *name); extern struct super_block *get_super(kdev_t); -extern void put_super(kdev_t); static inline int is_mounted(kdev_t dev) { struct super_block *sb = get_super(dev); ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] fs/super.c stuff (5/10) 2001-06-11 5:34 ` Alexander Viro @ 2001-06-11 5:35 ` Alexander Viro 2001-06-11 5:37 ` [PATCH] fs/super.c stuff (6/10) Alexander Viro 2001-06-11 5:36 ` [PATCH] fs/super.c stuff (3/10) Alexander Viro 1 sibling, 1 reply; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:35 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2-put_super/fs/dquot.c S6-pre2-dquot/fs/dquot.c --- S6-pre2-put_super/fs/dquot.c Thu May 24 18:26:44 2001 +++ S6-pre2-dquot/fs/dquot.c Sun Jun 10 18:46:54 2001 @@ -325,7 +325,7 @@ memset(&dquot->dq_dqb, 0, sizeof(struct dqblk)); } -void invalidate_dquots(kdev_t dev, short type) +static void invalidate_dquots(kdev_t dev, short type) { struct dquot *dquot, *next; int need_restart; @@ -1388,7 +1388,7 @@ } /* Function in inode.c - remove pointers to dquots in icache */ -extern void remove_dquot_ref(kdev_t, short); +extern void remove_dquot_ref(struct super_block *, short); /* * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) @@ -1413,7 +1413,7 @@ reset_enable_flags(dqopt, cnt); /* Note: these are blocking operations */ - remove_dquot_ref(sb->s_dev, cnt); + remove_dquot_ref(sb, cnt); invalidate_dquots(sb->s_dev, cnt); /* Wait for any pending IO - remove me as soon as invalidate is more polite */ diff -urN S6-pre2-put_super/fs/inode.c S6-pre2-dquot/fs/inode.c --- S6-pre2-put_super/fs/inode.c Fri Jun 8 18:29:03 2001 +++ S6-pre2-dquot/fs/inode.c Sun Jun 10 18:43:02 2001 @@ -1164,14 +1164,13 @@ void put_dquot_list(struct list_head *); int remove_inode_dquot_ref(struct inode *, short, struct list_head *); -void remove_dquot_ref(kdev_t dev, short type) +void remove_dquot_ref(struct super_block *sb, short type) { - struct super_block *sb = get_super(dev); struct inode *inode; struct list_head *act_head; LIST_HEAD(tofree_head); - if (!sb || !sb->dq_op) + if (!sb->dq_op) return; /* nothing to do */ /* We have to be protected against other CPUs */ diff -urN S6-pre2-put_super/include/linux/quotaops.h S6-pre2-dquot/include/linux/quotaops.h --- S6-pre2-put_super/include/linux/quotaops.h Sun Jun 10 13:15:27 2001 +++ S6-pre2-dquot/include/linux/quotaops.h Sun Jun 10 18:46:33 2001 @@ -21,7 +21,6 @@ */ extern void dquot_initialize(struct inode *inode, short type); extern void dquot_drop(struct inode *inode); -extern void invalidate_dquots(kdev_t dev, short type); extern int quota_off(struct super_block *sb, short type); extern int sync_dquots(kdev_t dev, short type); ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] fs/super.c stuff (6/10) 2001-06-11 5:35 ` [PATCH] fs/super.c stuff (5/10) Alexander Viro @ 2001-06-11 5:37 ` Alexander Viro 2001-06-11 5:37 ` [PATCH] fs/super.c stuff (7/10) Alexander Viro 0 siblings, 1 reply; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:37 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2-dquot/arch/parisc/hpux/sys_hpux.c S6-pre2-drop_super/arch/parisc/hpux/sys_hpux.c --- S6-pre2-dquot/arch/parisc/hpux/sys_hpux.c Fri Feb 16 20:46:44 2001 +++ S6-pre2-drop_super/arch/parisc/hpux/sys_hpux.c Sun Jun 10 18:38:23 2001 @@ -109,9 +109,11 @@ lock_kernel(); s = get_super(to_kdev_t(dev)); + unlock_kernel(); if (s == NULL) goto out; err = vfs_statfs(s, &sbuf); + drop_super(s); if (err) goto out; @@ -124,7 +126,6 @@ /* Changed to hpux_ustat: */ err = copy_to_user(ubuf,&tmp,sizeof(struct hpux_ustat)) ? -EFAULT : 0; out: - unlock_kernel(); return err; } diff -urN S6-pre2-dquot/fs/dquot.c S6-pre2-drop_super/fs/dquot.c --- S6-pre2-dquot/fs/dquot.c Sun Jun 10 18:46:54 2001 +++ S6-pre2-drop_super/fs/dquot.c Sun Jun 10 18:38:23 2001 @@ -1602,6 +1602,8 @@ if (sb && sb_has_quota_enabled(sb, type)) ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr); out: + if (sb) + drop_super(sb); unlock_kernel(); return ret; } diff -urN S6-pre2-dquot/fs/inode.c S6-pre2-drop_super/fs/inode.c --- S6-pre2-dquot/fs/inode.c Sun Jun 10 18:43:02 2001 +++ S6-pre2-drop_super/fs/inode.c Sun Jun 10 18:38:23 2001 @@ -605,8 +605,10 @@ fsync_dev(dev); res = 0; - if (sb) + if (sb) { res = invalidate_inodes(sb); + drop_super(sb); + } invalidate_buffers(dev); return res; } diff -urN S6-pre2-dquot/fs/super.c S6-pre2-drop_super/fs/super.c --- S6-pre2-dquot/fs/super.c Sun Jun 10 18:36:27 2001 +++ S6-pre2-drop_super/fs/super.c Sun Jun 10 18:38:23 2001 @@ -491,7 +491,6 @@ kill_super(sb); } - /* Use octal escapes, like mount does, for embedded spaces etc. */ static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' }; @@ -640,6 +639,10 @@ #undef MANGLE #undef FREEROOM } + +void drop_super(struct super_block *sb) +{ +} /* * Note: check the dirty flag before waiting, so we don't @@ -709,6 +712,7 @@ if (s == NULL) goto out; err = vfs_statfs(s, &sbuf); + drop_super(s); if (err) goto out; diff -urN S6-pre2-dquot/include/linux/fs.h S6-pre2-drop_super/include/linux/fs.h --- S6-pre2-dquot/include/linux/fs.h Sun Jun 10 18:39:04 2001 +++ S6-pre2-drop_super/include/linux/fs.h Sun Jun 10 18:38:31 2001 @@ -1320,11 +1320,12 @@ extern struct file_system_type *get_fs_type(const char *name); extern struct super_block *get_super(kdev_t); +extern void drop_super(struct super_block *sb); static inline int is_mounted(kdev_t dev) { struct super_block *sb = get_super(dev); if (sb) { - /* drop_super(sb); will go here */ + drop_super(sb); return 1; } return 0; diff -urN S6-pre2-dquot/kernel/ksyms.c S6-pre2-drop_super/kernel/ksyms.c --- S6-pre2-dquot/kernel/ksyms.c Fri Jun 8 18:29:03 2001 +++ S6-pre2-drop_super/kernel/ksyms.c Sun Jun 10 18:38:23 2001 @@ -129,6 +129,7 @@ EXPORT_SYMBOL(update_atime); EXPORT_SYMBOL(get_fs_type); EXPORT_SYMBOL(get_super); +EXPORT_SYMBOL(drop_super); EXPORT_SYMBOL(getname); EXPORT_SYMBOL(names_cachep); EXPORT_SYMBOL(fput); ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] fs/super.c stuff (7/10) 2001-06-11 5:37 ` [PATCH] fs/super.c stuff (6/10) Alexander Viro @ 2001-06-11 5:37 ` Alexander Viro 2001-06-11 5:38 ` [PATCH] fs/super.c stuff (8/10) Alexander Viro 0 siblings, 1 reply; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:37 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2-put_super/fs/inode.c S6-pre2-s_count/fs/inode.c --- S6-pre2-put_super/fs/inode.c Sun Jun 10 12:25:34 2001 +++ S6-pre2-s_count/fs/inode.c Sun Jun 10 12:29:35 2001 @@ -339,30 +339,48 @@ spin_unlock(&inode_lock); } +/* + * Note: + * We don't need to grab a reference to superblock here. If it has non-empty + * ->s_dirty it's hadn't been killed yet and kill_super() won't proceed + * past sync_inodes_sb() until both ->s_dirty and ->s_locked_inodes are + * empty. Since __sync_one() regains inode_lock before it finally moves + * inode from superblock lists we are OK. + */ + void sync_unlocked_inodes(void) { - struct super_block * sb = sb_entry(super_blocks.next); + struct super_block * sb; + spin_lock(&inode_lock); + spin_lock(&sb_lock); + sb = sb_entry(super_blocks.next); for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { if (!list_empty(&sb->s_dirty)) { - spin_lock(&inode_lock); + spin_unlock(&sb_lock); sync_list(&sb->s_dirty); - spin_unlock(&inode_lock); + spin_lock(&sb_lock); } } + spin_unlock(&sb_lock); + spin_unlock(&inode_lock); } void sync_inodes(kdev_t dev) { - struct super_block * sb = sb_entry(super_blocks.next); + struct super_block * sb; /* * Search the super_blocks array for the device(s) to sync. */ + spin_lock(&sb_lock); + sb = sb_entry(super_blocks.next); for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { if (!sb->s_dev) continue; if (dev && sb->s_dev != dev) continue; + sb->s_count++; + spin_unlock(&sb_lock); down_read(&sb->s_umount); if (sb->s_dev && (sb->s_dev == dev || !dev)) { spin_lock(&inode_lock); @@ -372,9 +390,12 @@ spin_unlock(&inode_lock); } up_read(&sb->s_umount); + spin_lock(&sb_lock); + sb->s_count--; if (dev) break; } + spin_unlock(&sb_lock); } /* @@ -382,13 +403,19 @@ */ static void try_to_sync_unused_inodes(void) { - struct super_block * sb = sb_entry(super_blocks.next); + struct super_block * sb; + + spin_lock(&sb_lock); + sb = sb_entry(super_blocks.next); for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { if (!sb->s_dev) continue; + spin_unlock(&sb_lock); if (!try_to_sync_unused_list(&sb->s_dirty)) break; + spin_lock(&sb_lock); } + spin_unlock(&sb_lock); } /** diff -urN S6-pre2-put_super/fs/super.c S6-pre2-s_count/fs/super.c --- S6-pre2-put_super/fs/super.c Sun Jun 10 12:25:34 2001 +++ S6-pre2-s_count/fs/super.c Sun Jun 10 12:35:54 2001 @@ -62,6 +62,7 @@ int nr_super_blocks; int max_super_blocks = NR_SUPER; LIST_HEAD(super_blocks); +spinlock_t sb_lock = SPIN_LOCK_UNLOCKED; /* * Handling of filesystem drivers list. @@ -640,8 +641,16 @@ #undef FREEROOM } +static inline void __put_super(struct super_block *sb) +{ + spin_lock(&sb_lock); + sb->s_count--; + spin_unlock(&sb_lock); +} + void drop_super(struct super_block *sb) { + __put_super(sb); } /* @@ -653,6 +662,7 @@ { struct super_block * sb; + spin_lock(&sb_lock); for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { @@ -662,12 +672,17 @@ continue; if (!sb->s_dirt) continue; + sb->s_count++; + spin_unlock(&sb_lock); lock_super(sb); if (sb->s_dev && sb->s_dirt && (!dev || dev == sb->s_dev)) if (sb->s_op && sb->s_op->write_super) sb->s_op->write_super(sb); unlock_super(sb); + spin_lock(&sb_lock); + sb->s_count--; } + spin_unlock(&sb_lock); } /** @@ -685,17 +700,23 @@ if (!dev) return NULL; restart: + spin_lock(&sb_lock); s = sb_entry(super_blocks.next); while (s != sb_entry(&super_blocks)) if (s->s_dev == dev) { /* Yes, it sucks. As soon as we get refcounting... */ + /* Almost there */ + s->s_count++; + spin_unlock(&sb_lock); lock_super(s); unlock_super(s); if (s->s_dev == dev) return s; + drop_super(s); goto restart; } else s = sb_entry(s->s_list.next); + spin_unlock(&sb_lock); return NULL; } @@ -738,14 +759,18 @@ { struct super_block *s; + spin_lock(&sb_lock); for (s = sb_entry(super_blocks.next); s != sb_entry(&super_blocks); s = sb_entry(s->s_list.next)) { if (s->s_dev) continue; + s->s_count++; atomic_inc(&s->s_active); + spin_unlock(&sb_lock); return s; } + spin_unlock(&sb_lock); /* Need a new one... */ if (nr_super_blocks >= max_super_blocks) return NULL; @@ -753,6 +778,7 @@ if (s) { nr_super_blocks++; memset(s, 0, sizeof(struct super_block)); + spin_lock(&sb_lock); INIT_LIST_HEAD(&s->s_dirty); INIT_LIST_HEAD(&s->s_locked_inodes); list_add (&s->s_list, super_blocks.prev); @@ -760,10 +786,12 @@ init_rwsem(&s->s_umount); sema_init(&s->s_lock, 1); atomic_set(&s->s_active, 1); + s->s_count = 1; sema_init(&s->s_vfs_rename_sem,1); sema_init(&s->s_nfsd_free_path_sem,1); sema_init(&s->s_dquot.dqio_sem, 1); sema_init(&s->s_dquot.dqoff_sem, 1); + spin_unlock(&sb_lock); } return s; } @@ -799,6 +827,7 @@ s->s_type = NULL; unlock_super(s); atomic_dec(&s->s_active); + __put_super(s); return NULL; } @@ -864,10 +893,24 @@ if (sb) { if (fs_type == sb->s_type && ((flags ^ sb->s_flags) & MS_RDONLY) == 0) { - path_release(&nd); +/* + * We are heavily relying on mount_sem here. We _will_ get rid of that + * ugliness RSN (and then atomicity of ->s_active will play), but first + * we need to get rid of "reuse" branch of get_empty_super() and that + * requires reference counters. Chicken and egg problem, but fortunately + * we can use the fact that right now all accesses to ->s_active are + * under mount_sem. + */ + if (atomic_read(&sb->s_active)) { + spin_lock(&sb_lock); + sb->s_count--; + spin_unlock(&sb_lock); + } atomic_inc(&sb->s_active); + path_release(&nd); return sb; } + __put_super(sb); } else { mode_t mode = FMODE_READ; /* we always need it ;-) */ if (!(flags & MS_RDONLY)) @@ -941,8 +984,7 @@ struct file_system_type *fs = sb->s_type; struct super_operations *sop = sb->s_op; - atomic_dec(&sb->s_active); - if (atomic_read(&sb->s_active)) + if (!atomic_dec_and_test(&sb->s_active)) return; down_write(&sb->s_umount); lock_kernel(); @@ -981,6 +1023,7 @@ } else put_unnamed_dev(dev); up_write(&sb->s_umount); + __put_super(sb); } /* @@ -1240,13 +1283,13 @@ return err; err = -ENOMEM; + down(&mount_sem); mnt = clone_mnt(old_nd.mnt, old_nd.dentry); if (mnt) { - down(&mount_sem); err = graft_tree(mnt, nd); - up(&mount_sem); mntput(mnt); } + up(&mount_sem); path_release(&old_nd); return err; } @@ -1577,6 +1620,7 @@ check_disk_change(ROOT_DEV); sb = get_super(ROOT_DEV); if (sb) { + /* FIXME */ fs_type = sb->s_type; atomic_inc(&sb->s_active); goto mount_it; diff -urN S6-pre2-put_super/include/linux/fs.h S6-pre2-s_count/include/linux/fs.h --- S6-pre2-put_super/include/linux/fs.h Sun Jun 10 12:27:37 2001 +++ S6-pre2-s_count/include/linux/fs.h Sun Jun 10 01:29:52 2001 @@ -662,6 +662,7 @@ #include <linux/usbdev_fs_sb.h> extern struct list_head super_blocks; +extern spinlock_t sb_lock; #define sb_entry(list) list_entry((list), struct super_block, s_list) struct super_block { @@ -679,6 +680,7 @@ struct dentry *s_root; struct rw_semaphore s_umount; struct semaphore s_lock; + int s_count; atomic_t s_active; struct list_head s_dirty; /* dirty inodes */ ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] fs/super.c stuff (8/10) 2001-06-11 5:37 ` [PATCH] fs/super.c stuff (7/10) Alexander Viro @ 2001-06-11 5:38 ` Alexander Viro 2001-06-11 5:39 ` [PATCH] fs/super.c stuff (9/10) Alexander Viro 0 siblings, 1 reply; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:38 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2-s_count/fs/inode.c S6-pre2-freeing/fs/inode.c --- S6-pre2-s_count/fs/inode.c Sun Jun 10 12:45:04 2001 +++ S6-pre2-freeing/fs/inode.c Sun Jun 10 12:45:47 2001 @@ -258,23 +258,6 @@ __sync_one(list_entry(tmp, struct inode, i_list), 0); } -static inline int wait_on_dirty(struct list_head *head) -{ - struct list_head * tmp; - list_for_each(tmp, head) { - struct inode *inode = list_entry(tmp, struct inode, i_list); - if (!inode->i_state & I_DIRTY) - continue; - __iget(inode); - spin_unlock(&inode_lock); - __wait_on_inode(inode); - iput(inode); - spin_lock(&inode_lock); - return 1; - } - return 0; -} - static inline void wait_on_locked(struct list_head *head) { struct list_head * tmp; @@ -319,23 +302,13 @@ return 1; } -/** - * sync_inodes - * @dev: device to sync the inodes from. - * - * sync_inodes goes through the super block's dirty list, - * writes them out, and puts them back on the normal list. - */ - -/* - * caller holds exclusive lock on sb->s_umount - */ - void sync_inodes_sb(struct super_block *sb) { spin_lock(&inode_lock); - sync_list(&sb->s_dirty); - wait_on_locked(&sb->s_locked_inodes); + while (!list_empty(&sb->s_dirty)||!list_empty(&sb->s_locked_inodes)) { + sync_list(&sb->s_dirty); + wait_on_locked(&sb->s_locked_inodes); + } spin_unlock(&inode_lock); } @@ -365,37 +338,75 @@ spin_unlock(&inode_lock); } +/* + * Find a superblock with inodes that need to be synced + */ + +static struct super_block *get_super_to_sync(void) +{ + struct list_head *p; +restart: + spin_lock(&inode_lock); + spin_lock(&sb_lock); + list_for_each(p, &super_blocks) { + struct super_block *s = list_entry(p,struct super_block,s_list); + if (list_empty(&s->s_dirty) && list_empty(&s->s_locked_inodes)) + continue; + s->s_count++; + spin_unlock(&sb_lock); + spin_unlock(&inode_lock); + down_read(&s->s_umount); + if (!s->s_root) { + up_read(&s->s_umount); + spin_lock(&sb_lock); + if (!--s->s_count) + kfree(s); + spin_unlock(&sb_lock); + goto restart; + } + return s; + } + spin_unlock(&sb_lock); + spin_unlock(&inode_lock); + return NULL; +} + +/** + * sync_inodes + * @dev: device to sync the inodes from. + * + * sync_inodes goes through the super block's dirty list, + * writes them out, and puts them back on the normal list. + */ + void sync_inodes(kdev_t dev) { - struct super_block * sb; + struct super_block * s; /* * Search the super_blocks array for the device(s) to sync. */ - spin_lock(&sb_lock); - sb = sb_entry(super_blocks.next); - for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { - if (!sb->s_dev) - continue; - if (dev && sb->s_dev != dev) - continue; - sb->s_count++; - spin_unlock(&sb_lock); - down_read(&sb->s_umount); - if (sb->s_dev && (sb->s_dev == dev || !dev)) { - spin_lock(&inode_lock); - do { - sync_list(&sb->s_dirty); - } while (wait_on_dirty(&sb->s_locked_inodes)); - spin_unlock(&inode_lock); + if (dev) { + if ((s = get_super(dev)) != NULL) { + down_read(&s->s_umount); + if (s->s_root) + sync_inodes_sb(s); + up_read(&s->s_umount); + spin_lock(&sb_lock); + if (!--s->s_count) + kfree(s); + spin_unlock(&sb_lock); + } + } else { + while ((s = get_super_to_sync()) != NULL) { + sync_inodes_sb(s); + up_read(&s->s_umount); + spin_lock(&sb_lock); + if (!--s->s_count) + kfree(s); + spin_unlock(&sb_lock); } - up_read(&sb->s_umount); - spin_lock(&sb_lock); - sb->s_count--; - if (dev) - break; } - spin_unlock(&sb_lock); } /* diff -urN S6-pre2-s_count/fs/super.c S6-pre2-freeing/fs/super.c --- S6-pre2-s_count/fs/super.c Sun Jun 10 12:45:04 2001 +++ S6-pre2-freeing/fs/super.c Sun Jun 10 12:45:47 2001 @@ -644,7 +644,8 @@ static inline void __put_super(struct super_block *sb) { spin_lock(&sb_lock); - sb->s_count--; + if (!--sb->s_count) + kfree(sb); spin_unlock(&sb_lock); } @@ -652,6 +653,21 @@ { __put_super(sb); } + +static void put_super(struct super_block *sb) +{ + up_write(&sb->s_umount); + __put_super(sb); +} + +static inline void write_super(struct super_block *sb) +{ + lock_super(sb); + if (sb->s_root && sb->s_dirt) + if (sb->s_op && sb->s_op->write_super) + sb->s_op->write_super(sb); + unlock_super(sb); +} /* * Note: check the dirty flag before waiting, so we don't @@ -662,26 +678,30 @@ { struct super_block * sb; - spin_lock(&sb_lock); - for (sb = sb_entry(super_blocks.next); - sb != sb_entry(&super_blocks); - sb = sb_entry(sb->s_list.next)) { - if (!sb->s_dev) - continue; - if (dev && sb->s_dev != dev) - continue; - if (!sb->s_dirt) - continue; - sb->s_count++; - spin_unlock(&sb_lock); - lock_super(sb); - if (sb->s_dev && sb->s_dirt && (!dev || dev == sb->s_dev)) - if (sb->s_op && sb->s_op->write_super) - sb->s_op->write_super(sb); - unlock_super(sb); - spin_lock(&sb_lock); - sb->s_count--; + if (dev) { + sb = get_super(dev); + if (sb) { + if (sb->s_dirt) + write_super(sb); + up_read(&sb->s_umount); + __put_super(sb); + } + return; } +restart: + spin_lock(&sb_lock); + sb = sb_entry(super_blocks.next); + while (sb != sb_entry(&super_blocks)) + if (sb->s_dirt) { + sb->s_count++; + spin_unlock(&sb_lock); + down_read(&sb->s_umount); + write_super(sb); + up_read(&sb->s_umount); + __put_super(sb); + goto restart; + } else + sb = sb_entry(sb->s_list.next); spin_unlock(&sb_lock); } @@ -1022,8 +1042,10 @@ bdput(bdev); } else put_unnamed_dev(dev); - up_write(&sb->s_umount); - __put_super(sb); + spin_lock(&sb_lock); + list_del(&sb->s_list); + spin_unlock(&sb_lock); + put_super(sb); } /* ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] fs/super.c stuff (9/10) 2001-06-11 5:38 ` [PATCH] fs/super.c stuff (8/10) Alexander Viro @ 2001-06-11 5:39 ` Alexander Viro 2001-06-11 5:40 ` [PATCH] fs/super.c stuff (10/10) Alexander Viro 0 siblings, 1 reply; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:39 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2-freeing/fs/super.c S6-pre2-current/fs/super.c --- S6-pre2-freeing/fs/super.c Sun Jun 10 12:45:47 2001 +++ S6-pre2-current/fs/super.c Sun Jun 10 12:53:15 2001 @@ -59,8 +59,6 @@ /* this is initialized in init/main.c */ kdev_t ROOT_DEV; -int nr_super_blocks; -int max_super_blocks = NR_SUPER; LIST_HEAD(super_blocks); spinlock_t sb_lock = SPIN_LOCK_UNLOCKED; @@ -775,43 +773,23 @@ * the request. */ -static struct super_block *get_empty_super(void) +static struct super_block *alloc_super(void) { - struct super_block *s; - - spin_lock(&sb_lock); - for (s = sb_entry(super_blocks.next); - s != sb_entry(&super_blocks); - s = sb_entry(s->s_list.next)) { - if (s->s_dev) - continue; - s->s_count++; - atomic_inc(&s->s_active); - spin_unlock(&sb_lock); - return s; - } - spin_unlock(&sb_lock); - /* Need a new one... */ - if (nr_super_blocks >= max_super_blocks) - return NULL; - s = kmalloc(sizeof(struct super_block), GFP_USER); + struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER); if (s) { - nr_super_blocks++; memset(s, 0, sizeof(struct super_block)); - spin_lock(&sb_lock); INIT_LIST_HEAD(&s->s_dirty); INIT_LIST_HEAD(&s->s_locked_inodes); - list_add (&s->s_list, super_blocks.prev); INIT_LIST_HEAD(&s->s_files); init_rwsem(&s->s_umount); sema_init(&s->s_lock, 1); - atomic_set(&s->s_active, 1); s->s_count = 1; + atomic_set(&s->s_active, 1); sema_init(&s->s_vfs_rename_sem,1); sema_init(&s->s_nfsd_free_path_sem,1); sema_init(&s->s_dquot.dqio_sem, 1); sema_init(&s->s_dquot.dqoff_sem, 1); - spin_unlock(&sb_lock); + s->s_maxbytes = MAX_NON_LFS; } return s; } @@ -821,16 +799,16 @@ void *data, int silent) { struct super_block * s; - s = get_empty_super(); + s = alloc_super(); if (!s) goto out; s->s_dev = dev; s->s_bdev = bdev; s->s_flags = flags; - s->s_dirt = 0; s->s_type = type; - s->s_dquot.flags = 0; - s->s_maxbytes = MAX_NON_LFS; + spin_lock(&sb_lock); + list_add (&s->s_list, super_blocks.prev); + spin_unlock(&sb_lock); lock_super(s); if (!type->read_super(s, data, silent)) goto out_fail; @@ -991,8 +969,8 @@ sb = fs_type->kern_mnt->mnt_sb; if (!sb) BUG(); - do_remount_sb(sb, flags, data); atomic_inc(&sb->s_active); + do_remount_sb(sb, flags, data); return sb; } diff -urN S6-pre2-freeing/include/linux/fs.h S6-pre2-current/include/linux/fs.h --- S6-pre2-freeing/include/linux/fs.h Sun Jun 10 12:45:04 2001 +++ S6-pre2-current/include/linux/fs.h Sun Jun 10 06:10:13 2001 @@ -61,7 +61,6 @@ }; extern struct inodes_stat_t inodes_stat; -extern int max_super_blocks, nr_super_blocks; extern int leases_enable, dir_notify_enable, lease_break_time; #define NR_FILE 8192 /* this can well be larger on a larger system */ diff -urN S6-pre2-freeing/kernel/sysctl.c S6-pre2-current/kernel/sysctl.c --- S6-pre2-freeing/kernel/sysctl.c Sat Apr 14 21:41:29 2001 +++ S6-pre2-current/kernel/sysctl.c Sun Jun 10 06:09:56 2001 @@ -286,10 +286,6 @@ 0444, NULL, &proc_dointvec}, {FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int), 0644, NULL, &proc_dointvec}, - {FS_NRSUPER, "super-nr", &nr_super_blocks, sizeof(int), - 0444, NULL, &proc_dointvec}, - {FS_MAXSUPER, "super-max", &max_super_blocks, sizeof(int), - 0644, NULL, &proc_dointvec}, {FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int), 0444, NULL, &proc_dointvec}, {FS_MAXDQUOT, "dquot-max", &max_dquots, sizeof(int), ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] fs/super.c stuff (10/10) 2001-06-11 5:39 ` [PATCH] fs/super.c stuff (9/10) Alexander Viro @ 2001-06-11 5:40 ` Alexander Viro 0 siblings, 0 replies; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:40 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel diff -urN S6-pre2-alloc_super/fs/inode.c S6-pre2-current/fs/inode.c --- S6-pre2-alloc_super/fs/inode.c Sun Jun 10 19:09:35 2001 +++ S6-pre2-current/fs/inode.c Sun Jun 10 19:26:27 2001 @@ -357,11 +357,7 @@ spin_unlock(&inode_lock); down_read(&s->s_umount); if (!s->s_root) { - up_read(&s->s_umount); - spin_lock(&sb_lock); - if (!--s->s_count) - kfree(s); - spin_unlock(&sb_lock); + drop_super(s); goto restart; } return s; @@ -388,23 +384,13 @@ */ if (dev) { if ((s = get_super(dev)) != NULL) { - down_read(&s->s_umount); - if (s->s_root) - sync_inodes_sb(s); - up_read(&s->s_umount); - spin_lock(&sb_lock); - if (!--s->s_count) - kfree(s); - spin_unlock(&sb_lock); + sync_inodes_sb(s); + drop_super(s); } } else { while ((s = get_super_to_sync()) != NULL) { sync_inodes_sb(s); - up_read(&s->s_umount); - spin_lock(&sb_lock); - if (!--s->s_count) - kfree(s); - spin_unlock(&sb_lock); + drop_super(s); } } } @@ -636,13 +622,14 @@ int invalidate_device(kdev_t dev, int do_sync) { - struct super_block *sb = get_super(dev); + struct super_block *sb; int res; if (do_sync) fsync_dev(dev); res = 0; + sb = get_super(dev); if (sb) { res = invalidate_inodes(sb); drop_super(sb); diff -urN S6-pre2-alloc_super/fs/super.c S6-pre2-current/fs/super.c --- S6-pre2-alloc_super/fs/super.c Sun Jun 10 19:09:39 2001 +++ S6-pre2-current/fs/super.c Sun Jun 10 19:36:51 2001 @@ -647,8 +647,23 @@ spin_unlock(&sb_lock); } +static inline struct super_block * find_super(kdev_t dev) +{ + struct list_head *p; + + list_for_each(p, &super_blocks) { + struct super_block * s = sb_entry(p); + if (s->s_dev == dev) { + s->s_count++; + return s; + } + } + return NULL; +} + void drop_super(struct super_block *sb) { + up_read(&sb->s_umount); __put_super(sb); } @@ -681,8 +696,7 @@ if (sb) { if (sb->s_dirt) write_super(sb); - up_read(&sb->s_umount); - __put_super(sb); + drop_super(sb); } return; } @@ -695,8 +709,7 @@ spin_unlock(&sb_lock); down_read(&sb->s_umount); write_super(sb); - up_read(&sb->s_umount); - __put_super(sb); + drop_super(sb); goto restart; } else sb = sb_entry(sb->s_list.next); @@ -719,21 +732,19 @@ return NULL; restart: spin_lock(&sb_lock); - s = sb_entry(super_blocks.next); - while (s != sb_entry(&super_blocks)) - if (s->s_dev == dev) { - /* Yes, it sucks. As soon as we get refcounting... */ - /* Almost there */ - s->s_count++; - spin_unlock(&sb_lock); - lock_super(s); - unlock_super(s); - if (s->s_dev == dev) - return s; - drop_super(s); - goto restart; - } else - s = sb_entry(s->s_list.next); + s = find_super(dev); + if (s) { + spin_unlock(&sb_lock); + /* Yes, it sucks. As soon as we get refcounting... */ + /* Almost there - next two lines will go away RSN */ + lock_super(s); + unlock_super(s); + down_read(&s->s_umount); + if (s->s_root) + return s; + drop_super(s); + goto restart; + } spin_unlock(&sb_lock); return NULL; } @@ -905,10 +916,11 @@ spin_unlock(&sb_lock); } atomic_inc(&sb->s_active); + up_read(&sb->s_umount); path_release(&nd); return sb; } - __put_super(sb); + drop_super(sb); } else { mode_t mode = FMODE_READ; /* we always need it ;-) */ if (!(flags & MS_RDONLY)) @@ -1623,6 +1635,7 @@ /* FIXME */ fs_type = sb->s_type; atomic_inc(&sb->s_active); + up_read(&sb->s_umount); goto mount_it; } ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] fs/super.c stuff (3/10) 2001-06-11 5:34 ` Alexander Viro 2001-06-11 5:35 ` [PATCH] fs/super.c stuff (5/10) Alexander Viro @ 2001-06-11 5:36 ` Alexander Viro 1 sibling, 0 replies; 12+ messages in thread From: Alexander Viro @ 2001-06-11 5:36 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel Grr... 4 of 10, that is. Sorry. On Mon, 11 Jun 2001, Alexander Viro wrote: > diff -urN S6-pre2-fsync_no_super/include/linux/fs.h S6-pre2-put_super/include/linux/fs.h > --- S6-pre2-fsync_no_super/include/linux/fs.h Sun Jun 10 18:36:27 2001 > +++ S6-pre2-put_super/include/linux/fs.h Sun Jun 10 18:39:04 2001 > @@ -1320,7 +1320,6 @@ > > extern struct file_system_type *get_fs_type(const char *name); > extern struct super_block *get_super(kdev_t); > -extern void put_super(kdev_t); > static inline int is_mounted(kdev_t dev) > { > struct super_block *sb = get_super(dev); > > > ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2001-06-11 5:40 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2001-06-11 5:32 [PATCHes] fs/super.c stuff Alexander Viro 2001-06-11 5:33 ` [PATCH] fs/super.c stuff (1/10) Alexander Viro 2001-06-11 5:33 ` [PATCH] fs/super.c stuff (2/10) Alexander Viro 2001-06-11 5:34 ` [PATCH] fs/super.c stuff (3/10) Alexander Viro 2001-06-11 5:34 ` Alexander Viro 2001-06-11 5:35 ` [PATCH] fs/super.c stuff (5/10) Alexander Viro 2001-06-11 5:37 ` [PATCH] fs/super.c stuff (6/10) Alexander Viro 2001-06-11 5:37 ` [PATCH] fs/super.c stuff (7/10) Alexander Viro 2001-06-11 5:38 ` [PATCH] fs/super.c stuff (8/10) Alexander Viro 2001-06-11 5:39 ` [PATCH] fs/super.c stuff (9/10) Alexander Viro 2001-06-11 5:40 ` [PATCH] fs/super.c stuff (10/10) Alexander Viro 2001-06-11 5:36 ` [PATCH] fs/super.c stuff (3/10) Alexander Viro
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).