Skip to content

Commit 8e4f3e1

Browse files
committed
Merge tag 'fuse-update-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse updates from Miklos Szeredi: - Fixes for virtiofs submounts - Misc fixes and cleanups * tag 'fuse-update-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: virtiofs: Fix spelling mistakes fuse: use DIV_ROUND_UP helper macro for calculations fuse: fix illegal access to inode with reused nodeid fuse: allow fallocate(FALLOC_FL_ZERO_RANGE) fuse: Make fuse_fill_super_submount() static fuse: Switch to fc_mount() for submounts fuse: Call vfs_get_tree() for submounts fuse: add dedicated filesystem context ops for submounts virtiofs: propagate sync() to file server fuse: reject internal errno fuse: check connected before queueing on fpq->io fuse: ignore PG_workingset after stealing fuse: Fix infinite loop in sget_fc() fuse: Fix crash if superblock of submount gets killed early fuse: Fix crash in fuse_dentry_automount() error path
2 parents 729437e + c4e0cd4 commit 8e4f3e1

File tree

9 files changed

+161
-81
lines changed

9 files changed

+161
-81
lines changed

fs/fuse/dax.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ static int fuse_setup_one_mapping(struct inode *inode, unsigned long start_idx,
213213
dmap->writable = writable;
214214
if (!upgrade) {
215215
/*
216-
* We don't take a refernce on inode. inode is valid right now
216+
* We don't take a reference on inode. inode is valid right now
217217
* and when inode is going away, cleanup logic should first
218218
* cleanup dmap entries.
219219
*/
@@ -622,7 +622,7 @@ static int fuse_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
622622
}
623623

624624
/*
625-
* If read beyond end of file happnes, fs code seems to return
625+
* If read beyond end of file happens, fs code seems to return
626626
* it as hole
627627
*/
628628
iomap_hole:
@@ -1207,7 +1207,7 @@ static void fuse_dax_free_mem_worker(struct work_struct *work)
12071207
ret);
12081208
}
12091209

1210-
/* If number of free ranges are still below threhold, requeue */
1210+
/* If number of free ranges are still below threshold, requeue */
12111211
kick_dmap_free_worker(fcd, 1);
12121212
}
12131213

fs/fuse/dev.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static void fuse_drop_waiting(struct fuse_conn *fc)
9191
{
9292
/*
9393
* lockess check of fc->connected is okay, because atomic_dec_and_test()
94-
* provides a memory barrier mached with the one in fuse_wait_aborted()
94+
* provides a memory barrier matched with the one in fuse_wait_aborted()
9595
* to ensure no wake-up is missed.
9696
*/
9797
if (atomic_dec_and_test(&fc->num_waiting) &&
@@ -783,6 +783,7 @@ static int fuse_check_page(struct page *page)
783783
1 << PG_uptodate |
784784
1 << PG_lru |
785785
1 << PG_active |
786+
1 << PG_workingset |
786787
1 << PG_reclaim |
787788
1 << PG_waiters))) {
788789
dump_page(page, "fuse: trying to steal weird page");
@@ -1271,6 +1272,15 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
12711272
goto restart;
12721273
}
12731274
spin_lock(&fpq->lock);
1275+
/*
1276+
* Must not put request on fpq->io queue after having been shut down by
1277+
* fuse_abort_conn()
1278+
*/
1279+
if (!fpq->connected) {
1280+
req->out.h.error = err = -ECONNABORTED;
1281+
goto out_end;
1282+
1283+
}
12741284
list_add(&req->list, &fpq->io);
12751285
spin_unlock(&fpq->lock);
12761286
cs->req = req;
@@ -1857,7 +1867,7 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
18571867
}
18581868

18591869
err = -EINVAL;
1860-
if (oh.error <= -1000 || oh.error > 0)
1870+
if (oh.error <= -512 || oh.error > 0)
18611871
goto copy_finish;
18621872

18631873
spin_lock(&fpq->lock);

fs/fuse/dir.c

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
252252
if (ret == -ENOMEM)
253253
goto out;
254254
if (ret || fuse_invalid_attr(&outarg.attr) ||
255-
inode_wrong_type(inode, outarg.attr.mode))
255+
fuse_stale_inode(inode, outarg.generation, &outarg.attr))
256256
goto invalid;
257257

258258
forget_all_cached_acls(inode);
@@ -309,68 +309,23 @@ static int fuse_dentry_delete(const struct dentry *dentry)
309309
static struct vfsmount *fuse_dentry_automount(struct path *path)
310310
{
311311
struct fs_context *fsc;
312-
struct fuse_mount *parent_fm = get_fuse_mount_super(path->mnt->mnt_sb);
313-
struct fuse_conn *fc = parent_fm->fc;
314-
struct fuse_mount *fm;
315312
struct vfsmount *mnt;
316313
struct fuse_inode *mp_fi = get_fuse_inode(d_inode(path->dentry));
317-
struct super_block *sb;
318-
int err;
319314

320315
fsc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry);
321-
if (IS_ERR(fsc)) {
322-
err = PTR_ERR(fsc);
323-
goto out;
324-
}
325-
326-
err = -ENOMEM;
327-
fm = kzalloc(sizeof(struct fuse_mount), GFP_KERNEL);
328-
if (!fm)
329-
goto out_put_fsc;
330-
331-
fsc->s_fs_info = fm;
332-
sb = sget_fc(fsc, NULL, set_anon_super_fc);
333-
if (IS_ERR(sb)) {
334-
err = PTR_ERR(sb);
335-
kfree(fm);
336-
goto out_put_fsc;
337-
}
338-
fm->fc = fuse_conn_get(fc);
339-
340-
/* Initialize superblock, making @mp_fi its root */
341-
err = fuse_fill_super_submount(sb, mp_fi);
342-
if (err)
343-
goto out_put_sb;
316+
if (IS_ERR(fsc))
317+
return ERR_CAST(fsc);
344318

345-
sb->s_flags |= SB_ACTIVE;
346-
fsc->root = dget(sb->s_root);
347-
/* We are done configuring the superblock, so unlock it */
348-
up_write(&sb->s_umount);
349-
350-
down_write(&fc->killsb);
351-
list_add_tail(&fm->fc_entry, &fc->mounts);
352-
up_write(&fc->killsb);
319+
/* Pass the FUSE inode of the mount for fuse_get_tree_submount() */
320+
fsc->fs_private = mp_fi;
353321

354322
/* Create the submount */
355-
mnt = vfs_create_mount(fsc);
356-
if (IS_ERR(mnt)) {
357-
err = PTR_ERR(mnt);
358-
goto out_put_fsc;
359-
}
360-
mntget(mnt);
361-
put_fs_context(fsc);
362-
return mnt;
323+
mnt = fc_mount(fsc);
324+
if (!IS_ERR(mnt))
325+
mntget(mnt);
363326

364-
out_put_sb:
365-
/*
366-
* Only jump here when fsc->root is NULL and sb is still locked
367-
* (otherwise put_fs_context() will put the superblock)
368-
*/
369-
deactivate_locked_super(sb);
370-
out_put_fsc:
371327
put_fs_context(fsc);
372-
out:
373-
return ERR_PTR(err);
328+
return mnt;
374329
}
375330

376331
const struct dentry_operations fuse_dentry_operations = {

fs/fuse/file.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io)
645645
* == bytes_transferred or rw == WRITE, the caller sets 'pos' to -1.
646646
*
647647
* An example:
648-
* User requested DIO read of 64K. It was splitted into two 32K fuse requests,
648+
* User requested DIO read of 64K. It was split into two 32K fuse requests,
649649
* both submitted asynchronously. The first of them was ACKed by userspace as
650650
* fully completed (req->out.args[0].size == 32K) resulting in pos == -1. The
651651
* second request was ACKed as short, e.g. only 1K was read, resulting in
@@ -1403,7 +1403,7 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
14031403
nbytes += ret;
14041404

14051405
ret += start;
1406-
npages = (ret + PAGE_SIZE - 1) / PAGE_SIZE;
1406+
npages = DIV_ROUND_UP(ret, PAGE_SIZE);
14071407

14081408
ap->descs[ap->num_pages].offset = start;
14091409
fuse_page_descs_length_init(ap->descs, ap->num_pages, npages);
@@ -2905,11 +2905,13 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
29052905
};
29062906
int err;
29072907
bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) ||
2908-
(mode & FALLOC_FL_PUNCH_HOLE);
2908+
(mode & (FALLOC_FL_PUNCH_HOLE |
2909+
FALLOC_FL_ZERO_RANGE));
29092910

29102911
bool block_faults = FUSE_IS_DAX(inode) && lock_inode;
29112912

2912-
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
2913+
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
2914+
FALLOC_FL_ZERO_RANGE))
29132915
return -EOPNOTSUPP;
29142916

29152917
if (fm->fc->no_fallocate)
@@ -2924,7 +2926,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
29242926
goto out;
29252927
}
29262928

2927-
if (mode & FALLOC_FL_PUNCH_HOLE) {
2929+
if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) {
29282930
loff_t endbyte = offset + length - 1;
29292931

29302932
err = fuse_writeback_range(inode, offset, endbyte);
@@ -2964,7 +2966,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
29642966
file_update_time(file);
29652967
}
29662968

2967-
if (mode & FALLOC_FL_PUNCH_HOLE)
2969+
if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE))
29682970
truncate_pagecache_range(inode, offset, offset + length - 1);
29692971

29702972
fuse_invalidate_attr(inode);

fs/fuse/fuse_i.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,9 @@ struct fuse_conn {
761761
/* Auto-mount submounts announced by the server */
762762
unsigned int auto_submounts:1;
763763

764+
/* Propagate syncfs() to server */
765+
unsigned int sync_fs:1;
766+
764767
/** The number of requests waiting for completion */
765768
atomic_t num_waiting;
766769

@@ -867,6 +870,13 @@ static inline u64 fuse_get_attr_version(struct fuse_conn *fc)
867870
return atomic64_read(&fc->attr_version);
868871
}
869872

873+
static inline bool fuse_stale_inode(const struct inode *inode, int generation,
874+
struct fuse_attr *attr)
875+
{
876+
return inode->i_generation != generation ||
877+
inode_wrong_type(inode, attr->mode);
878+
}
879+
870880
static inline void fuse_make_bad(struct inode *inode)
871881
{
872882
remove_inode_hash(inode);
@@ -1081,22 +1091,18 @@ void fuse_send_init(struct fuse_mount *fm);
10811091
*/
10821092
int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx);
10831093

1084-
/*
1085-
* Fill in superblock for submounts
1086-
* @sb: partially-initialized superblock to fill in
1087-
* @parent_fi: The fuse_inode of the parent filesystem where this submount is
1088-
* mounted
1089-
*/
1090-
int fuse_fill_super_submount(struct super_block *sb,
1091-
struct fuse_inode *parent_fi);
1092-
10931094
/*
10941095
* Remove the mount from the connection
10951096
*
10961097
* Returns whether this was the last mount
10971098
*/
10981099
bool fuse_mount_remove(struct fuse_mount *fm);
10991100

1101+
/*
1102+
* Setup context ops for submounts
1103+
*/
1104+
int fuse_init_fs_context_submount(struct fs_context *fsc);
1105+
11001106
/*
11011107
* Shut down the connection (possibly sending DESTROY request).
11021108
*/

fs/fuse/inode.c

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,8 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
350350
inode->i_generation = generation;
351351
fuse_init_inode(inode, attr);
352352
unlock_new_inode(inode);
353-
} else if (inode_wrong_type(inode, attr->mode)) {
354-
/* Inode has changed type, any I/O on the old should fail */
353+
} else if (fuse_stale_inode(inode, generation, attr)) {
354+
/* nodeid was reused, any I/O on the old inode should fail */
355355
fuse_make_bad(inode);
356356
iput(inode);
357357
goto retry;
@@ -506,6 +506,45 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
506506
return err;
507507
}
508508

509+
static int fuse_sync_fs(struct super_block *sb, int wait)
510+
{
511+
struct fuse_mount *fm = get_fuse_mount_super(sb);
512+
struct fuse_conn *fc = fm->fc;
513+
struct fuse_syncfs_in inarg;
514+
FUSE_ARGS(args);
515+
int err;
516+
517+
/*
518+
* Userspace cannot handle the wait == 0 case. Avoid a
519+
* gratuitous roundtrip.
520+
*/
521+
if (!wait)
522+
return 0;
523+
524+
/* The filesystem is being unmounted. Nothing to do. */
525+
if (!sb->s_root)
526+
return 0;
527+
528+
if (!fc->sync_fs)
529+
return 0;
530+
531+
memset(&inarg, 0, sizeof(inarg));
532+
args.in_numargs = 1;
533+
args.in_args[0].size = sizeof(inarg);
534+
args.in_args[0].value = &inarg;
535+
args.opcode = FUSE_SYNCFS;
536+
args.nodeid = get_node_id(sb->s_root->d_inode);
537+
args.out_numargs = 0;
538+
539+
err = fuse_simple_request(fm, &args);
540+
if (err == -ENOSYS) {
541+
fc->sync_fs = 0;
542+
err = 0;
543+
}
544+
545+
return err;
546+
}
547+
509548
enum {
510549
OPT_SOURCE,
511550
OPT_SUBTYPE,
@@ -909,6 +948,7 @@ static const struct super_operations fuse_super_operations = {
909948
.put_super = fuse_put_super,
910949
.umount_begin = fuse_umount_begin,
911950
.statfs = fuse_statfs,
951+
.sync_fs = fuse_sync_fs,
912952
.show_options = fuse_show_options,
913953
};
914954

@@ -1275,8 +1315,8 @@ static void fuse_sb_defaults(struct super_block *sb)
12751315
sb->s_xattr = fuse_no_acl_xattr_handlers;
12761316
}
12771317

1278-
int fuse_fill_super_submount(struct super_block *sb,
1279-
struct fuse_inode *parent_fi)
1318+
static int fuse_fill_super_submount(struct super_block *sb,
1319+
struct fuse_inode *parent_fi)
12801320
{
12811321
struct fuse_mount *fm = get_fuse_mount_super(sb);
12821322
struct super_block *parent_sb = parent_fi->inode.i_sb;
@@ -1313,6 +1353,58 @@ int fuse_fill_super_submount(struct super_block *sb,
13131353
return 0;
13141354
}
13151355

1356+
/* Filesystem context private data holds the FUSE inode of the mount point */
1357+
static int fuse_get_tree_submount(struct fs_context *fsc)
1358+
{
1359+
struct fuse_mount *fm;
1360+
struct fuse_inode *mp_fi = fsc->fs_private;
1361+
struct fuse_conn *fc = get_fuse_conn(&mp_fi->inode);
1362+
struct super_block *sb;
1363+
int err;
1364+
1365+
fm = kzalloc(sizeof(struct fuse_mount), GFP_KERNEL);
1366+
if (!fm)
1367+
return -ENOMEM;
1368+
1369+
fsc->s_fs_info = fm;
1370+
sb = sget_fc(fsc, NULL, set_anon_super_fc);
1371+
if (IS_ERR(sb)) {
1372+
kfree(fm);
1373+
return PTR_ERR(sb);
1374+
}
1375+
fm->fc = fuse_conn_get(fc);
1376+
1377+
/* Initialize superblock, making @mp_fi its root */
1378+
err = fuse_fill_super_submount(sb, mp_fi);
1379+
if (err) {
1380+
fuse_conn_put(fc);
1381+
kfree(fm);
1382+
sb->s_fs_info = NULL;
1383+
deactivate_locked_super(sb);
1384+
return err;
1385+
}
1386+
1387+
down_write(&fc->killsb);
1388+
list_add_tail(&fm->fc_entry, &fc->mounts);
1389+
up_write(&fc->killsb);
1390+
1391+
sb->s_flags |= SB_ACTIVE;
1392+
fsc->root = dget(sb->s_root);
1393+
1394+
return 0;
1395+
}
1396+
1397+
static const struct fs_context_operations fuse_context_submount_ops = {
1398+
.get_tree = fuse_get_tree_submount,
1399+
};
1400+
1401+
int fuse_init_fs_context_submount(struct fs_context *fsc)
1402+
{
1403+
fsc->ops = &fuse_context_submount_ops;
1404+
return 0;
1405+
}
1406+
EXPORT_SYMBOL_GPL(fuse_init_fs_context_submount);
1407+
13161408
int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
13171409
{
13181410
struct fuse_dev *fud = NULL;

0 commit comments

Comments
 (0)