Message ID | 1437467876-22106-5-git-send-email-yangds.fnst@cn.fujitsu.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue 21-07-15 16:37:35, Dongsheng Yang wrote: > As we have cdev in super block now, we can provide get_super_cdev > to get super_block by a cdev reference, similar with get_super > which is working only for block_device. > > Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> Instead of duplicating the superblock searching functions, can you please create common __get_super() function like: struct super_block *__get_super( int (*compare)(struct super_block *, void *), void *key) And it will use the compare function to check whether the sb is the right one or not. You will then have one comparion functions for searching by bdev used by get_super() and one comparison function for searching by cdev used by get_super_cdev(). Similarly you can create __get_super_thawed() to avoid the duplication there. Honza > --- > fs/super.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ > include/linux/fs.h | 2 ++ > 2 files changed, 47 insertions(+) > > diff --git a/fs/super.c b/fs/super.c > index 928c20f..4a9031a 100644 > --- a/fs/super.c > +++ b/fs/super.c > @@ -605,6 +605,37 @@ rescan: > > EXPORT_SYMBOL(get_super); > > +struct super_block *get_super_cdev(struct cdev *cdev) > +{ > + struct super_block *sb; > + > + if (!cdev) > + return NULL; > + > + spin_lock(&sb_lock); > +rescan: > + list_for_each_entry(sb, &super_blocks, s_list) { > + if (hlist_unhashed(&sb->s_instances)) > + continue; > + if (sb->s_cdev == cdev) { > + sb->s_count++; > + spin_unlock(&sb_lock); > + down_read(&sb->s_umount); > + /* still alive? */ > + if (sb->s_root && (sb->s_flags & MS_BORN)) > + return sb; > + up_read(&sb->s_umount); > + /* nope, got unmounted */ > + spin_lock(&sb_lock); > + __put_super(sb); > + goto rescan; > + } > + } > + spin_unlock(&sb_lock); > + return NULL; > +} > +EXPORT_SYMBOL(get_super_cdev); > + > /** > * get_super_thawed - get thawed superblock of a device > * @bdev: device to get the superblock for > @@ -628,6 +659,20 @@ struct super_block *get_super_thawed(struct block_device *bdev) > } > EXPORT_SYMBOL(get_super_thawed); > > +struct super_block *get_super_cdev_thawed(struct cdev *cdev) > +{ > + while (1) { > + struct super_block *s = get_super_cdev(cdev); > + if (!s || s->s_writers.frozen == SB_UNFROZEN) > + return s; > + up_read(&s->s_umount); > + wait_event(s->s_writers.wait_unfrozen, > + s->s_writers.frozen == SB_UNFROZEN); > + put_super(s); > + } > +} > +EXPORT_SYMBOL(get_super_cdev_thawed); > + > /** > * get_active_super - get an active reference to the superblock of a device > * @bdev: device to get the superblock for > diff --git a/include/linux/fs.h b/include/linux/fs.h > index 2f1d9499..5c7d789 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -2744,7 +2744,9 @@ extern void get_filesystem(struct file_system_type *fs); > extern void put_filesystem(struct file_system_type *fs); > extern struct file_system_type *get_fs_type(const char *name); > extern struct super_block *get_super(struct block_device *); > +extern struct super_block *get_super_cdev(struct cdev *); > extern struct super_block *get_super_thawed(struct block_device *); > +extern struct super_block *get_super_cdev_thawed(struct cdev *); > extern struct super_block *get_active_super(struct block_device *bdev); > extern void drop_super(struct super_block *sb); > extern void iterate_supers(void (*)(struct super_block *, void *), void *); > -- > 1.8.4.2 > >
On 07/21/2015 05:04 PM, Jan Kara wrote: > On Tue 21-07-15 16:37:35, Dongsheng Yang wrote: >> As we have cdev in super block now, we can provide get_super_cdev >> to get super_block by a cdev reference, similar with get_super >> which is working only for block_device. >> >> Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> > > Instead of duplicating the superblock searching functions, can you please > create common __get_super() function like: > > struct super_block *__get_super( > int (*compare)(struct super_block *, void *), void *key) > > And it will use the compare function to check whether the sb is the right > one or not. You will then have one comparion functions for searching by > bdev used by get_super() and one comparison function for searching by cdev > used by get_super_cdev(). > > Similarly you can create __get_super_thawed() to avoid the duplication > there. Haha, that's what I wanted to do, but forgive my lazy, I will update it in next version. Yang > > Honza > >> --- >> fs/super.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ >> include/linux/fs.h | 2 ++ >> 2 files changed, 47 insertions(+) >> >> diff --git a/fs/super.c b/fs/super.c >> index 928c20f..4a9031a 100644 >> --- a/fs/super.c >> +++ b/fs/super.c >> @@ -605,6 +605,37 @@ rescan: >> >> EXPORT_SYMBOL(get_super); >> >> +struct super_block *get_super_cdev(struct cdev *cdev) >> +{ >> + struct super_block *sb; >> + >> + if (!cdev) >> + return NULL; >> + >> + spin_lock(&sb_lock); >> +rescan: >> + list_for_each_entry(sb, &super_blocks, s_list) { >> + if (hlist_unhashed(&sb->s_instances)) >> + continue; >> + if (sb->s_cdev == cdev) { >> + sb->s_count++; >> + spin_unlock(&sb_lock); >> + down_read(&sb->s_umount); >> + /* still alive? */ >> + if (sb->s_root && (sb->s_flags & MS_BORN)) >> + return sb; >> + up_read(&sb->s_umount); >> + /* nope, got unmounted */ >> + spin_lock(&sb_lock); >> + __put_super(sb); >> + goto rescan; >> + } >> + } >> + spin_unlock(&sb_lock); >> + return NULL; >> +} >> +EXPORT_SYMBOL(get_super_cdev); >> + >> /** >> * get_super_thawed - get thawed superblock of a device >> * @bdev: device to get the superblock for >> @@ -628,6 +659,20 @@ struct super_block *get_super_thawed(struct block_device *bdev) >> } >> EXPORT_SYMBOL(get_super_thawed); >> >> +struct super_block *get_super_cdev_thawed(struct cdev *cdev) >> +{ >> + while (1) { >> + struct super_block *s = get_super_cdev(cdev); >> + if (!s || s->s_writers.frozen == SB_UNFROZEN) >> + return s; >> + up_read(&s->s_umount); >> + wait_event(s->s_writers.wait_unfrozen, >> + s->s_writers.frozen == SB_UNFROZEN); >> + put_super(s); >> + } >> +} >> +EXPORT_SYMBOL(get_super_cdev_thawed); >> + >> /** >> * get_active_super - get an active reference to the superblock of a device >> * @bdev: device to get the superblock for >> diff --git a/include/linux/fs.h b/include/linux/fs.h >> index 2f1d9499..5c7d789 100644 >> --- a/include/linux/fs.h >> +++ b/include/linux/fs.h >> @@ -2744,7 +2744,9 @@ extern void get_filesystem(struct file_system_type *fs); >> extern void put_filesystem(struct file_system_type *fs); >> extern struct file_system_type *get_fs_type(const char *name); >> extern struct super_block *get_super(struct block_device *); >> +extern struct super_block *get_super_cdev(struct cdev *); >> extern struct super_block *get_super_thawed(struct block_device *); >> +extern struct super_block *get_super_cdev_thawed(struct cdev *); >> extern struct super_block *get_active_super(struct block_device *bdev); >> extern void drop_super(struct super_block *sb); >> extern void iterate_supers(void (*)(struct super_block *, void *), void *); >> -- >> 1.8.4.2 >> >> -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/super.c b/fs/super.c index 928c20f..4a9031a 100644 --- a/fs/super.c +++ b/fs/super.c @@ -605,6 +605,37 @@ rescan: EXPORT_SYMBOL(get_super); +struct super_block *get_super_cdev(struct cdev *cdev) +{ + struct super_block *sb; + + if (!cdev) + return NULL; + + spin_lock(&sb_lock); +rescan: + list_for_each_entry(sb, &super_blocks, s_list) { + if (hlist_unhashed(&sb->s_instances)) + continue; + if (sb->s_cdev == cdev) { + sb->s_count++; + spin_unlock(&sb_lock); + down_read(&sb->s_umount); + /* still alive? */ + if (sb->s_root && (sb->s_flags & MS_BORN)) + return sb; + up_read(&sb->s_umount); + /* nope, got unmounted */ + spin_lock(&sb_lock); + __put_super(sb); + goto rescan; + } + } + spin_unlock(&sb_lock); + return NULL; +} +EXPORT_SYMBOL(get_super_cdev); + /** * get_super_thawed - get thawed superblock of a device * @bdev: device to get the superblock for @@ -628,6 +659,20 @@ struct super_block *get_super_thawed(struct block_device *bdev) } EXPORT_SYMBOL(get_super_thawed); +struct super_block *get_super_cdev_thawed(struct cdev *cdev) +{ + while (1) { + struct super_block *s = get_super_cdev(cdev); + if (!s || s->s_writers.frozen == SB_UNFROZEN) + return s; + up_read(&s->s_umount); + wait_event(s->s_writers.wait_unfrozen, + s->s_writers.frozen == SB_UNFROZEN); + put_super(s); + } +} +EXPORT_SYMBOL(get_super_cdev_thawed); + /** * get_active_super - get an active reference to the superblock of a device * @bdev: device to get the superblock for diff --git a/include/linux/fs.h b/include/linux/fs.h index 2f1d9499..5c7d789 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2744,7 +2744,9 @@ extern void get_filesystem(struct file_system_type *fs); extern void put_filesystem(struct file_system_type *fs); extern struct file_system_type *get_fs_type(const char *name); extern struct super_block *get_super(struct block_device *); +extern struct super_block *get_super_cdev(struct cdev *); extern struct super_block *get_super_thawed(struct block_device *); +extern struct super_block *get_super_cdev_thawed(struct cdev *); extern struct super_block *get_active_super(struct block_device *bdev); extern void drop_super(struct super_block *sb); extern void iterate_supers(void (*)(struct super_block *, void *), void *);
As we have cdev in super block now, we can provide get_super_cdev to get super_block by a cdev reference, similar with get_super which is working only for block_device. Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> --- fs/super.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 2 ++ 2 files changed, 47 insertions(+)