Commit 6dd4740662405a68bb229ac2b9e0aeaaf2188bf2

Authored by Ryusuke Konishi
Committed by Al Viro
1 parent 3f82ff5516

nilfs2: simplify remaining sget() use

This simplifies the test function passed on the remaining sget()
callsite in nilfs.

Instead of checking mount type (i.e. ro-mount/rw-mount/snapshot mount)
in the test function passed to sget(), this patch first looks up the
nilfs_sb_info struct which the given mount type matches, and then
acquires the super block instance holding the nilfs_sb_info.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 4 changed files with 75 additions and 25 deletions Side-by-side Diff

... ... @@ -60,6 +60,7 @@
60 60 struct super_block *s_super; /* reverse pointer to super_block */
61 61 struct the_nilfs *s_nilfs;
62 62 struct list_head s_list; /* list head for nilfs->ns_supers */
  63 + atomic_t s_count; /* reference count */
63 64  
64 65 /* Segment constructor */
65 66 struct list_head s_dirty_files; /* dirty files list */
... ... @@ -336,7 +336,7 @@
336 336 put_nilfs(sbi->s_nilfs);
337 337 sbi->s_super = NULL;
338 338 sb->s_fs_info = NULL;
339   - kfree(sbi);
  339 + nilfs_put_sbinfo(sbi);
340 340  
341 341 unlock_kernel();
342 342 }
... ... @@ -785,6 +785,7 @@
785 785 get_nilfs(nilfs);
786 786 sbi->s_nilfs = nilfs;
787 787 sbi->s_super = sb;
  788 + atomic_set(&sbi->s_count, 1);
788 789  
789 790 err = init_nilfs(nilfs, sbi, (char *)data);
790 791 if (err)
... ... @@ -902,7 +903,7 @@
902 903 failed_sbi:
903 904 put_nilfs(nilfs);
904 905 sb->s_fs_info = NULL;
905   - kfree(sbi);
  906 + nilfs_put_sbinfo(sbi);
906 907 return err;
907 908 }
908 909  
... ... @@ -1014,6 +1015,7 @@
1014 1015  
1015 1016 struct nilfs_super_data {
1016 1017 struct block_device *bdev;
  1018 + struct nilfs_sb_info *sbi;
1017 1019 __u64 cno;
1018 1020 int flags;
1019 1021 };
1020 1022  
... ... @@ -1071,27 +1073,8 @@
1071 1073 static int nilfs_test_bdev_super(struct super_block *s, void *data)
1072 1074 {
1073 1075 struct nilfs_super_data *sd = data;
1074   - int ret;
1075 1076  
1076   - if (s->s_bdev != sd->bdev)
1077   - return 0;
1078   -
1079   - if (!((s->s_flags | sd->flags) & MS_RDONLY))
1080   - return 1; /* Reuse an old R/W-mode super_block */
1081   -
1082   - if (s->s_flags & sd->flags & MS_RDONLY) {
1083   - if (down_read_trylock(&s->s_umount)) {
1084   - ret = s->s_root &&
1085   - (sd->cno == NILFS_SB(s)->s_snapshot_cno);
1086   - up_read(&s->s_umount);
1087   - /*
1088   - * This path is locked with sb_lock by sget().
1089   - * So, drop_super() causes deadlock.
1090   - */
1091   - return ret;
1092   - }
1093   - }
1094   - return 0;
  1077 + return sd->sbi && s->s_fs_info == (void *)sd->sbi;
1095 1078 }
1096 1079  
1097 1080 static int
... ... @@ -1112,7 +1095,6 @@
1112 1095 * much more information than normal filesystems to identify mount
1113 1096 * instance. For snapshot mounts, not only a mount type (ro-mount
1114 1097 * or rw-mount) but also a checkpoint number is required.
1115   - * The results are passed in sget() using nilfs_super_data.
1116 1098 */
1117 1099 sd.cno = 0;
1118 1100 sd.flags = flags;
1119 1101  
1120 1102  
1121 1103  
... ... @@ -1148,13 +1130,23 @@
1148 1130 }
1149 1131  
1150 1132 /*
1151   - * Search specified snapshot or R/W mode super_block
  1133 + * Find existing nilfs_sb_info struct
1152 1134 */
  1135 + sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno);
  1136 +
1153 1137 if (!sd.cno)
1154 1138 /* trying to get the latest checkpoint. */
1155 1139 sd.cno = nilfs_last_cno(nilfs);
1156 1140  
  1141 + /*
  1142 + * Get super block instance holding the nilfs_sb_info struct.
  1143 + * A new instance is allocated if no existing mount is present or
  1144 + * existing instance has been unmounted.
  1145 + */
1157 1146 s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd);
  1147 + if (sd.sbi)
  1148 + nilfs_put_sbinfo(sd.sbi);
  1149 +
1158 1150 if (IS_ERR(s)) {
1159 1151 err = PTR_ERR(s);
1160 1152 goto failed_unlock;
fs/nilfs2/the_nilfs.c
... ... @@ -664,6 +664,56 @@
664 664 return ret;
665 665 }
666 666  
  667 +/**
  668 + * nilfs_find_sbinfo - find existing nilfs_sb_info structure
  669 + * @nilfs: nilfs object
  670 + * @rw_mount: mount type (non-zero value for read/write mount)
  671 + * @cno: checkpoint number (zero for read-only mount)
  672 + *
  673 + * nilfs_find_sbinfo() returns the nilfs_sb_info structure which
  674 + * @rw_mount and @cno (in case of snapshots) matched. If no instance
  675 + * was found, NULL is returned. Although the super block instance can
  676 + * be unmounted after this function returns, the nilfs_sb_info struct
  677 + * is kept on memory until nilfs_put_sbinfo() is called.
  678 + */
  679 +struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *nilfs,
  680 + int rw_mount, __u64 cno)
  681 +{
  682 + struct nilfs_sb_info *sbi;
  683 +
  684 + down_read(&nilfs->ns_sem);
  685 + /*
  686 + * The SNAPSHOT flag and sb->s_flags are supposed to be
  687 + * protected with nilfs->ns_sem.
  688 + */
  689 + sbi = nilfs->ns_current;
  690 + if (rw_mount) {
  691 + if (sbi && !(sbi->s_super->s_flags & MS_RDONLY))
  692 + goto found; /* read/write mount */
  693 + else
  694 + goto out;
  695 + } else if (cno == 0) {
  696 + if (sbi && (sbi->s_super->s_flags & MS_RDONLY))
  697 + goto found; /* read-only mount */
  698 + else
  699 + goto out;
  700 + }
  701 +
  702 + list_for_each_entry(sbi, &nilfs->ns_supers, s_list) {
  703 + if (nilfs_test_opt(sbi, SNAPSHOT) &&
  704 + sbi->s_snapshot_cno == cno)
  705 + goto found; /* snapshot mount */
  706 + }
  707 + out:
  708 + up_read(&nilfs->ns_sem);
  709 + return NULL;
  710 +
  711 + found:
  712 + atomic_inc(&sbi->s_count);
  713 + up_read(&nilfs->ns_sem);
  714 + return sbi;
  715 +}
  716 +
667 717 int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno,
668 718 int snapshot_mount)
669 719 {
fs/nilfs2/the_nilfs.h
... ... @@ -201,6 +201,7 @@
201 201 int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
202 202 int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
203 203 int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
  204 +struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
204 205 int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
205 206 int nilfs_near_disk_full(struct the_nilfs *);
206 207 void nilfs_fall_back_super_block(struct the_nilfs *);
... ... @@ -241,6 +242,12 @@
241 242 if (sbi == nilfs->ns_writer)
242 243 nilfs->ns_writer = NULL;
243 244 mutex_unlock(&nilfs->ns_writer_mutex);
  245 +}
  246 +
  247 +static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi)
  248 +{
  249 + if (!atomic_dec_and_test(&sbi->s_count))
  250 + kfree(sbi);
244 251 }
245 252  
246 253 static inline void