On 19/03/2019 17:53, Andrew Price wrote:
On 19/03/2019 17:05, David Howells wrote:

Can you use vfs_get_block_super()?

It might be possible if we can rearrange things so that this can be done outside of the function:

         if (args->ar_meta)
                 fc->root = dget(sdp->sd_master_dir);
         else
                 fc->root = dget(sdp->sd_root_dir);

but we can't do that in our fill_super() because it needs to be selected whether we have an existing mount or not.

Would this fly?

diff --git a/fs/super.c b/fs/super.c
index 6d8dbf309241..0cdeaf28126f 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1232,11 +1232,12 @@ static int test_bdev_super_fc(struct super_block *s, struct fs_context *fc)
  * @fill_super: Helper to initialise a new superblock
  */
 int vfs_get_block_super(struct fs_context *fc,
-                       int (*fill_super)(struct super_block *,
-                                         struct fs_context *))
+      int (*fill_super)(struct super_block *, struct fs_context *),
+ struct dentry* (*select_root)(struct fs_context *, struct super_block *))
 {
        struct block_device *bdev;
        struct super_block *s;
+       struct dentry *root;
        int error = 0;

        fc->bdev_mode = FMODE_READ | FMODE_EXCL;
@@ -1302,7 +1303,11 @@ int vfs_get_block_super(struct fs_context *fc,
        }

        BUG_ON(fc->root);
-       fc->root = dget(s->s_root);
+       if (select_root)
+               root = select_root(fc, s);
+       else
+               root = s->s_root;
+       fc->root = dget(root);
        return 0;

 error_sb:
diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h
index 8233c873af73..c2e9dc5826ce 100644
--- a/include/linux/fs_context.h
+++ b/include/linux/fs_context.h
@@ -145,8 +145,8 @@ extern int vfs_get_super(struct fs_context *fc,
                                           struct fs_context *fc));

 extern int vfs_get_block_super(struct fs_context *fc,
-                              int (*fill_super)(struct super_block *sb,
-                                                struct fs_context *fc));
+      int (*fill_super)(struct super_block *, struct fs_context *),
+ struct dentry* (*select_root)(struct fs_context *, struct super_block *));

 extern const struct file_operations fscontext_fops;

Reply via email to