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;