Skip to content

Commit fcee216

Browse files
XanClicMiklos Szeredi
authored andcommitted
fuse: split fuse_mount off of fuse_conn
We want to allow submounts for the same fuse_conn, but with different superblocks so that each of the submounts has its own device ID. To do so, we need to split all mount-specific information off of fuse_conn into a new fuse_mount structure, so that multiple mounts can share a single fuse_conn. We need to take care only to perform connection-level actions once (i.e. when the fuse_conn and thus the first fuse_mount are established, or when the last fuse_mount and thus the fuse_conn are destroyed). For example, fuse_sb_destroy() must invoke fuse_send_destroy() until the last superblock is released. To do so, we keep track of which fuse_mount is the root mount and perform all fuse_conn-level actions only when this fuse_mount is involved. Signed-off-by: Max Reitz <[email protected]> Reviewed-by: Stefan Hajnoczi <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 8f622e9 commit fcee216

File tree

11 files changed

+526
-358
lines changed

11 files changed

+526
-358
lines changed

fs/fuse/control.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file,
164164
{
165165
unsigned val;
166166
struct fuse_conn *fc;
167+
struct fuse_mount *fm;
167168
ssize_t ret;
168169

169170
ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
@@ -174,18 +175,27 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file,
174175
if (!fc)
175176
goto out;
176177

178+
down_read(&fc->killsb);
177179
spin_lock(&fc->bg_lock);
178180
fc->congestion_threshold = val;
179-
if (fc->sb) {
181+
182+
/*
183+
* Get any fuse_mount belonging to this fuse_conn; s_bdi is
184+
* shared between all of them
185+
*/
186+
187+
if (!list_empty(&fc->mounts)) {
188+
fm = list_first_entry(&fc->mounts, struct fuse_mount, fc_entry);
180189
if (fc->num_background < fc->congestion_threshold) {
181-
clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC);
182-
clear_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC);
190+
clear_bdi_congested(fm->sb->s_bdi, BLK_RW_SYNC);
191+
clear_bdi_congested(fm->sb->s_bdi, BLK_RW_ASYNC);
183192
} else {
184-
set_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC);
185-
set_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC);
193+
set_bdi_congested(fm->sb->s_bdi, BLK_RW_SYNC);
194+
set_bdi_congested(fm->sb->s_bdi, BLK_RW_ASYNC);
186195
}
187196
}
188197
spin_unlock(&fc->bg_lock);
198+
up_read(&fc->killsb);
189199
fuse_conn_put(fc);
190200
out:
191201
return ret;

fs/fuse/cuse.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757

5858
struct cuse_conn {
5959
struct list_head list; /* linked on cuse_conntbl */
60+
struct fuse_mount fm; /* Dummy mount referencing fc */
6061
struct fuse_conn fc; /* fuse connection */
6162
struct cdev *cdev; /* associated character device */
6263
struct device *dev; /* device representing @cdev */
@@ -134,7 +135,7 @@ static int cuse_open(struct inode *inode, struct file *file)
134135
* Generic permission check is already done against the chrdev
135136
* file, proceed to open.
136137
*/
137-
rc = fuse_do_open(&cc->fc, 0, file, 0);
138+
rc = fuse_do_open(&cc->fm, 0, file, 0);
138139
if (rc)
139140
fuse_conn_put(&cc->fc);
140141
return rc;
@@ -143,10 +144,10 @@ static int cuse_open(struct inode *inode, struct file *file)
143144
static int cuse_release(struct inode *inode, struct file *file)
144145
{
145146
struct fuse_file *ff = file->private_data;
146-
struct fuse_conn *fc = ff->fc;
147+
struct fuse_mount *fm = ff->fm;
147148

148149
fuse_sync_release(NULL, ff, file->f_flags);
149-
fuse_conn_put(fc);
150+
fuse_conn_put(fm->fc);
150151

151152
return 0;
152153
}
@@ -155,7 +156,7 @@ static long cuse_file_ioctl(struct file *file, unsigned int cmd,
155156
unsigned long arg)
156157
{
157158
struct fuse_file *ff = file->private_data;
158-
struct cuse_conn *cc = fc_to_cc(ff->fc);
159+
struct cuse_conn *cc = fc_to_cc(ff->fm->fc);
159160
unsigned int flags = 0;
160161

161162
if (cc->unrestricted_ioctl)
@@ -168,7 +169,7 @@ static long cuse_file_compat_ioctl(struct file *file, unsigned int cmd,
168169
unsigned long arg)
169170
{
170171
struct fuse_file *ff = file->private_data;
171-
struct cuse_conn *cc = fc_to_cc(ff->fc);
172+
struct cuse_conn *cc = fc_to_cc(ff->fm->fc);
172173
unsigned int flags = FUSE_IOCTL_COMPAT;
173174

174175
if (cc->unrestricted_ioctl)
@@ -313,9 +314,10 @@ struct cuse_init_args {
313314
* required data structures for it. Please read the comment at the
314315
* top of this file for high level overview.
315316
*/
316-
static void cuse_process_init_reply(struct fuse_conn *fc,
317+
static void cuse_process_init_reply(struct fuse_mount *fm,
317318
struct fuse_args *args, int error)
318319
{
320+
struct fuse_conn *fc = fm->fc;
319321
struct cuse_init_args *ia = container_of(args, typeof(*ia), ap.args);
320322
struct fuse_args_pages *ap = &ia->ap;
321323
struct cuse_conn *cc = fc_to_cc(fc), *pos;
@@ -424,7 +426,7 @@ static int cuse_send_init(struct cuse_conn *cc)
424426
{
425427
int rc;
426428
struct page *page;
427-
struct fuse_conn *fc = &cc->fc;
429+
struct fuse_mount *fm = &cc->fm;
428430
struct cuse_init_args *ia;
429431
struct fuse_args_pages *ap;
430432

@@ -460,7 +462,7 @@ static int cuse_send_init(struct cuse_conn *cc)
460462
ia->desc.length = ap->args.out_args[1].size;
461463
ap->args.end = cuse_process_init_reply;
462464

463-
rc = fuse_simple_background(fc, &ap->args, GFP_KERNEL);
465+
rc = fuse_simple_background(fm, &ap->args, GFP_KERNEL);
464466
if (rc) {
465467
kfree(ia);
466468
err_free_page:
@@ -506,7 +508,8 @@ static int cuse_channel_open(struct inode *inode, struct file *file)
506508
* Limit the cuse channel to requests that can
507509
* be represented in file->f_cred->user_ns.
508510
*/
509-
fuse_conn_init(&cc->fc, file->f_cred->user_ns, &fuse_dev_fiq_ops, NULL);
511+
fuse_conn_init(&cc->fc, &cc->fm, file->f_cred->user_ns,
512+
&fuse_dev_fiq_ops, NULL);
510513

511514
fud = fuse_dev_alloc_install(&cc->fc);
512515
if (!fud) {

fs/fuse/dax.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ static int fuse_setup_one_mapping(struct inode *inode, unsigned long start_idx,
182182
struct fuse_dax_mapping *dmap, bool writable,
183183
bool upgrade)
184184
{
185-
struct fuse_conn *fc = get_fuse_conn(inode);
186-
struct fuse_conn_dax *fcd = fc->dax;
185+
struct fuse_mount *fm = get_fuse_mount(inode);
186+
struct fuse_conn_dax *fcd = fm->fc->dax;
187187
struct fuse_inode *fi = get_fuse_inode(inode);
188188
struct fuse_setupmapping_in inarg;
189189
loff_t offset = start_idx << FUSE_DAX_SHIFT;
@@ -206,7 +206,7 @@ static int fuse_setup_one_mapping(struct inode *inode, unsigned long start_idx,
206206
args.in_numargs = 1;
207207
args.in_args[0].size = sizeof(inarg);
208208
args.in_args[0].value = &inarg;
209-
err = fuse_simple_request(fc, &args);
209+
err = fuse_simple_request(fm, &args);
210210
if (err < 0)
211211
return err;
212212
dmap->writable = writable;
@@ -234,7 +234,7 @@ static int fuse_send_removemapping(struct inode *inode,
234234
struct fuse_removemapping_one *remove_one)
235235
{
236236
struct fuse_inode *fi = get_fuse_inode(inode);
237-
struct fuse_conn *fc = get_fuse_conn(inode);
237+
struct fuse_mount *fm = get_fuse_mount(inode);
238238
FUSE_ARGS(args);
239239

240240
args.opcode = FUSE_REMOVEMAPPING;
@@ -244,7 +244,7 @@ static int fuse_send_removemapping(struct inode *inode,
244244
args.in_args[0].value = inargp;
245245
args.in_args[1].size = inargp->count * sizeof(*remove_one);
246246
args.in_args[1].value = remove_one;
247-
return fuse_simple_request(fc, &args);
247+
return fuse_simple_request(fm, &args);
248248
}
249249

250250
static int dmap_removemapping_list(struct inode *inode, unsigned int num,

0 commit comments

Comments
 (0)