Skip to content

Commit 1866d77

Browse files
XanClicMiklos Szeredi
authored andcommitted
fuse: Allow fuse_fill_super_common() for submounts
Submounts have their own superblock, which needs to be initialized. However, they do not have a fuse_fs_context associated with them, and the root node's attributes should be taken from the mountpoint's node. Extend fuse_fill_super_common() to work for submounts by making the @ctx parameter optional, and by adding a @submount_finode parameter. (There is a plain "unsigned" in an existing code block that is being indented by this commit. Extend it to "unsigned int" so checkpatch does not complain.) Signed-off-by: Max Reitz <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent fcee216 commit 1866d77

File tree

2 files changed

+96
-21
lines changed

2 files changed

+96
-21
lines changed

fs/fuse/fuse_i.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,14 @@ void fuse_send_init(struct fuse_mount *fm);
10441044
*/
10451045
int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx);
10461046

1047+
/*
1048+
* Fill in superblock for submounts
1049+
* @sb: partially-initialized superblock to fill in
1050+
* @parent_fi: The fuse_inode of the parent filesystem where this submount is
1051+
* mounted
1052+
*/
1053+
int fuse_fill_super_submount(struct super_block *sb,
1054+
struct fuse_inode *parent_fi);
10471055

10481056
/*
10491057
* Remove the mount from the connection

fs/fuse/inode.c

Lines changed: 88 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,11 @@ static void fuse_evict_inode(struct inode *inode)
126126

127127
if (FUSE_IS_DAX(inode))
128128
fuse_dax_inode_cleanup(inode);
129-
fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup);
130-
fi->forget = NULL;
129+
if (fi->nlookup) {
130+
fuse_queue_forget(fc, fi->forget, fi->nodeid,
131+
fi->nlookup);
132+
fi->forget = NULL;
133+
}
131134
}
132135
if (S_ISREG(inode->i_mode) && !is_bad_inode(inode)) {
133136
WARN_ON(!list_empty(&fi->write_files));
@@ -1207,6 +1210,87 @@ void fuse_dev_free(struct fuse_dev *fud)
12071210
}
12081211
EXPORT_SYMBOL_GPL(fuse_dev_free);
12091212

1213+
static void fuse_fill_attr_from_inode(struct fuse_attr *attr,
1214+
const struct fuse_inode *fi)
1215+
{
1216+
*attr = (struct fuse_attr){
1217+
.ino = fi->inode.i_ino,
1218+
.size = fi->inode.i_size,
1219+
.blocks = fi->inode.i_blocks,
1220+
.atime = fi->inode.i_atime.tv_sec,
1221+
.mtime = fi->inode.i_mtime.tv_sec,
1222+
.ctime = fi->inode.i_ctime.tv_sec,
1223+
.atimensec = fi->inode.i_atime.tv_nsec,
1224+
.mtimensec = fi->inode.i_mtime.tv_nsec,
1225+
.ctimensec = fi->inode.i_ctime.tv_nsec,
1226+
.mode = fi->inode.i_mode,
1227+
.nlink = fi->inode.i_nlink,
1228+
.uid = fi->inode.i_uid.val,
1229+
.gid = fi->inode.i_gid.val,
1230+
.rdev = fi->inode.i_rdev,
1231+
.blksize = 1u << fi->inode.i_blkbits,
1232+
};
1233+
}
1234+
1235+
static void fuse_sb_defaults(struct super_block *sb)
1236+
{
1237+
sb->s_magic = FUSE_SUPER_MAGIC;
1238+
sb->s_op = &fuse_super_operations;
1239+
sb->s_xattr = fuse_xattr_handlers;
1240+
sb->s_maxbytes = MAX_LFS_FILESIZE;
1241+
sb->s_time_gran = 1;
1242+
sb->s_export_op = &fuse_export_operations;
1243+
sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE;
1244+
if (sb->s_user_ns != &init_user_ns)
1245+
sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
1246+
sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
1247+
1248+
/*
1249+
* If we are not in the initial user namespace posix
1250+
* acls must be translated.
1251+
*/
1252+
if (sb->s_user_ns != &init_user_ns)
1253+
sb->s_xattr = fuse_no_acl_xattr_handlers;
1254+
}
1255+
1256+
int fuse_fill_super_submount(struct super_block *sb,
1257+
struct fuse_inode *parent_fi)
1258+
{
1259+
struct fuse_mount *fm = get_fuse_mount_super(sb);
1260+
struct super_block *parent_sb = parent_fi->inode.i_sb;
1261+
struct fuse_attr root_attr;
1262+
struct inode *root;
1263+
1264+
fuse_sb_defaults(sb);
1265+
fm->sb = sb;
1266+
1267+
WARN_ON(sb->s_bdi != &noop_backing_dev_info);
1268+
sb->s_bdi = bdi_get(parent_sb->s_bdi);
1269+
1270+
sb->s_xattr = parent_sb->s_xattr;
1271+
sb->s_time_gran = parent_sb->s_time_gran;
1272+
sb->s_blocksize = parent_sb->s_blocksize;
1273+
sb->s_blocksize_bits = parent_sb->s_blocksize_bits;
1274+
sb->s_subtype = kstrdup(parent_sb->s_subtype, GFP_KERNEL);
1275+
if (parent_sb->s_subtype && !sb->s_subtype)
1276+
return -ENOMEM;
1277+
1278+
fuse_fill_attr_from_inode(&root_attr, parent_fi);
1279+
root = fuse_iget(sb, parent_fi->nodeid, 0, &root_attr, 0, 0);
1280+
/*
1281+
* This inode is just a duplicate, so it is not looked up and
1282+
* its nlookup should not be incremented. fuse_iget() does
1283+
* that, though, so undo it here.
1284+
*/
1285+
get_fuse_inode(root)->nlookup--;
1286+
sb->s_d_op = &fuse_dentry_operations;
1287+
sb->s_root = d_make_root(root);
1288+
if (!sb->s_root)
1289+
return -ENOMEM;
1290+
1291+
return 0;
1292+
}
1293+
12101294
int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
12111295
{
12121296
struct fuse_dev *fud = NULL;
@@ -1220,7 +1304,7 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
12201304
if (sb->s_flags & SB_MANDLOCK)
12211305
goto err;
12221306

1223-
sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
1307+
fuse_sb_defaults(sb);
12241308

12251309
if (ctx->is_bdev) {
12261310
#ifdef CONFIG_BLOCK
@@ -1235,23 +1319,6 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
12351319

12361320
sb->s_subtype = ctx->subtype;
12371321
ctx->subtype = NULL;
1238-
sb->s_magic = FUSE_SUPER_MAGIC;
1239-
sb->s_op = &fuse_super_operations;
1240-
sb->s_xattr = fuse_xattr_handlers;
1241-
sb->s_maxbytes = MAX_LFS_FILESIZE;
1242-
sb->s_time_gran = 1;
1243-
sb->s_export_op = &fuse_export_operations;
1244-
sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE;
1245-
if (sb->s_user_ns != &init_user_ns)
1246-
sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
1247-
1248-
/*
1249-
* If we are not in the initial user namespace posix
1250-
* acls must be translated.
1251-
*/
1252-
if (sb->s_user_ns != &init_user_ns)
1253-
sb->s_xattr = fuse_no_acl_xattr_handlers;
1254-
12551322
if (IS_ENABLED(CONFIG_FUSE_DAX)) {
12561323
err = fuse_dax_conn_alloc(fc, ctx->dax_dev);
12571324
if (err)
@@ -1281,7 +1348,7 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
12811348
fc->user_id = ctx->user_id;
12821349
fc->group_id = ctx->group_id;
12831350
fc->legacy_opts_show = ctx->legacy_opts_show;
1284-
fc->max_read = max_t(unsigned, 4096, ctx->max_read);
1351+
fc->max_read = max_t(unsigned int, 4096, ctx->max_read);
12851352
fc->destroy = ctx->destroy;
12861353
fc->no_control = ctx->no_control;
12871354
fc->no_force_umount = ctx->no_force_umount;

0 commit comments

Comments
 (0)