Skip to content

Commit 9e310ea

Browse files
committed
Merge tag 'fuse-update-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse updates from Miklos Szeredi: - Revert non-waiting FLUSH due to a regression - Fix a lookup counter leak in readdirplus - Add an option to allow shared mmaps in no-cache mode - Add btime support and statx intrastructure to the protocol - Invalidate positive/negative dentry on failed create/delete * tag 'fuse-update-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: fuse: conditionally fill kstat in fuse_do_statx() fuse: invalidate dentry on EEXIST creates or ENOENT deletes fuse: cache btime fuse: implement statx fuse: add ATTR_TIMEOUT macro fuse: add STATX request fuse: handle empty request_mask in statx fuse: write back dirty pages before direct write in direct_io_relax mode fuse: add a new fuse init flag to relax restrictions in no cache mode fuse: invalidate page cache pages before direct write fuse: nlookup missing decrement in fuse_direntplus_link Revert "fuse: in fuse_flush only wait if someone wants the return code"
2 parents 4b3d6e0 + f73016b commit 9e310ea

File tree

6 files changed

+296
-106
lines changed

6 files changed

+296
-106
lines changed

fs/fuse/dir.c

Lines changed: 130 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ static void fuse_dentry_settime(struct dentry *dentry, u64 time)
9292
/*
9393
* Calculate the time in jiffies until a dentry/attributes are valid
9494
*/
95-
static u64 time_to_jiffies(u64 sec, u32 nsec)
95+
u64 fuse_time_to_jiffies(u64 sec, u32 nsec)
9696
{
9797
if (sec || nsec) {
9898
struct timespec64 ts = {
@@ -112,17 +112,7 @@ static u64 time_to_jiffies(u64 sec, u32 nsec)
112112
void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
113113
{
114114
fuse_dentry_settime(entry,
115-
time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
116-
}
117-
118-
static u64 attr_timeout(struct fuse_attr_out *o)
119-
{
120-
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
121-
}
122-
123-
u64 entry_attr_timeout(struct fuse_entry_out *o)
124-
{
125-
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
115+
fuse_time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
126116
}
127117

128118
void fuse_invalidate_attr_mask(struct inode *inode, u32 mask)
@@ -265,8 +255,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
265255
goto invalid;
266256

267257
forget_all_cached_acls(inode);
268-
fuse_change_attributes(inode, &outarg.attr,
269-
entry_attr_timeout(&outarg),
258+
fuse_change_attributes(inode, &outarg.attr, NULL,
259+
ATTR_TIMEOUT(&outarg),
270260
attr_version);
271261
fuse_change_entry_timeout(entry, &outarg);
272262
} else if (inode) {
@@ -360,10 +350,14 @@ int fuse_valid_type(int m)
360350
S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
361351
}
362352

353+
static bool fuse_valid_size(u64 size)
354+
{
355+
return size <= LLONG_MAX;
356+
}
357+
363358
bool fuse_invalid_attr(struct fuse_attr *attr)
364359
{
365-
return !fuse_valid_type(attr->mode) ||
366-
attr->size > LLONG_MAX;
360+
return !fuse_valid_type(attr->mode) || !fuse_valid_size(attr->size);
367361
}
368362

369363
int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
@@ -399,7 +393,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
399393
goto out_put_forget;
400394

401395
*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
402-
&outarg->attr, entry_attr_timeout(outarg),
396+
&outarg->attr, ATTR_TIMEOUT(outarg),
403397
attr_version);
404398
err = -ENOMEM;
405399
if (!*inode) {
@@ -686,7 +680,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
686680
ff->nodeid = outentry.nodeid;
687681
ff->open_flags = outopen.open_flags;
688682
inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
689-
&outentry.attr, entry_attr_timeout(&outentry), 0);
683+
&outentry.attr, ATTR_TIMEOUT(&outentry), 0);
690684
if (!inode) {
691685
flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
692686
fuse_sync_release(NULL, ff, flags);
@@ -755,7 +749,8 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
755749
if (err == -ENOSYS) {
756750
fc->no_create = 1;
757751
goto mknod;
758-
}
752+
} else if (err == -EEXIST)
753+
fuse_invalidate_entry(entry);
759754
out_dput:
760755
dput(res);
761756
return err;
@@ -813,7 +808,7 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
813808
goto out_put_forget_req;
814809

815810
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
816-
&outarg.attr, entry_attr_timeout(&outarg), 0);
811+
&outarg.attr, ATTR_TIMEOUT(&outarg), 0);
817812
if (!inode) {
818813
fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
819814
return -ENOMEM;
@@ -835,6 +830,8 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
835830
return 0;
836831

837832
out_put_forget_req:
833+
if (err == -EEXIST)
834+
fuse_invalidate_entry(entry);
838835
kfree(forget);
839836
return err;
840837
}
@@ -986,7 +983,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
986983
if (!err) {
987984
fuse_dir_changed(dir);
988985
fuse_entry_unlinked(entry);
989-
} else if (err == -EINTR)
986+
} else if (err == -EINTR || err == -ENOENT)
990987
fuse_invalidate_entry(entry);
991988
return err;
992989
}
@@ -1009,7 +1006,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
10091006
if (!err) {
10101007
fuse_dir_changed(dir);
10111008
fuse_entry_unlinked(entry);
1012-
} else if (err == -EINTR)
1009+
} else if (err == -EINTR || err == -ENOENT)
10131010
fuse_invalidate_entry(entry);
10141011
return err;
10151012
}
@@ -1050,7 +1047,7 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
10501047
/* newent will end up negative */
10511048
if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent))
10521049
fuse_entry_unlinked(newent);
1053-
} else if (err == -EINTR) {
1050+
} else if (err == -EINTR || err == -ENOENT) {
10541051
/* If request was interrupted, DEITY only knows if the
10551052
rename actually took place. If the invalidation
10561053
fails (e.g. some process has CWD under the renamed
@@ -1153,6 +1150,87 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
11531150
stat->blksize = 1 << blkbits;
11541151
}
11551152

1153+
static void fuse_statx_to_attr(struct fuse_statx *sx, struct fuse_attr *attr)
1154+
{
1155+
memset(attr, 0, sizeof(*attr));
1156+
attr->ino = sx->ino;
1157+
attr->size = sx->size;
1158+
attr->blocks = sx->blocks;
1159+
attr->atime = sx->atime.tv_sec;
1160+
attr->mtime = sx->mtime.tv_sec;
1161+
attr->ctime = sx->ctime.tv_sec;
1162+
attr->atimensec = sx->atime.tv_nsec;
1163+
attr->mtimensec = sx->mtime.tv_nsec;
1164+
attr->ctimensec = sx->ctime.tv_nsec;
1165+
attr->mode = sx->mode;
1166+
attr->nlink = sx->nlink;
1167+
attr->uid = sx->uid;
1168+
attr->gid = sx->gid;
1169+
attr->rdev = new_encode_dev(MKDEV(sx->rdev_major, sx->rdev_minor));
1170+
attr->blksize = sx->blksize;
1171+
}
1172+
1173+
static int fuse_do_statx(struct inode *inode, struct file *file,
1174+
struct kstat *stat)
1175+
{
1176+
int err;
1177+
struct fuse_attr attr;
1178+
struct fuse_statx *sx;
1179+
struct fuse_statx_in inarg;
1180+
struct fuse_statx_out outarg;
1181+
struct fuse_mount *fm = get_fuse_mount(inode);
1182+
u64 attr_version = fuse_get_attr_version(fm->fc);
1183+
FUSE_ARGS(args);
1184+
1185+
memset(&inarg, 0, sizeof(inarg));
1186+
memset(&outarg, 0, sizeof(outarg));
1187+
/* Directories have separate file-handle space */
1188+
if (file && S_ISREG(inode->i_mode)) {
1189+
struct fuse_file *ff = file->private_data;
1190+
1191+
inarg.getattr_flags |= FUSE_GETATTR_FH;
1192+
inarg.fh = ff->fh;
1193+
}
1194+
/* For now leave sync hints as the default, request all stats. */
1195+
inarg.sx_flags = 0;
1196+
inarg.sx_mask = STATX_BASIC_STATS | STATX_BTIME;
1197+
args.opcode = FUSE_STATX;
1198+
args.nodeid = get_node_id(inode);
1199+
args.in_numargs = 1;
1200+
args.in_args[0].size = sizeof(inarg);
1201+
args.in_args[0].value = &inarg;
1202+
args.out_numargs = 1;
1203+
args.out_args[0].size = sizeof(outarg);
1204+
args.out_args[0].value = &outarg;
1205+
err = fuse_simple_request(fm, &args);
1206+
if (err)
1207+
return err;
1208+
1209+
sx = &outarg.stat;
1210+
if (((sx->mask & STATX_SIZE) && !fuse_valid_size(sx->size)) ||
1211+
((sx->mask & STATX_TYPE) && (!fuse_valid_type(sx->mode) ||
1212+
inode_wrong_type(inode, sx->mode)))) {
1213+
make_bad_inode(inode);
1214+
return -EIO;
1215+
}
1216+
1217+
fuse_statx_to_attr(&outarg.stat, &attr);
1218+
if ((sx->mask & STATX_BASIC_STATS) == STATX_BASIC_STATS) {
1219+
fuse_change_attributes(inode, &attr, &outarg.stat,
1220+
ATTR_TIMEOUT(&outarg), attr_version);
1221+
}
1222+
1223+
if (stat) {
1224+
stat->result_mask = sx->mask & (STATX_BASIC_STATS | STATX_BTIME);
1225+
stat->btime.tv_sec = sx->btime.tv_sec;
1226+
stat->btime.tv_nsec = min_t(u32, sx->btime.tv_nsec, NSEC_PER_SEC - 1);
1227+
fuse_fillattr(inode, &attr, stat);
1228+
stat->result_mask |= STATX_TYPE;
1229+
}
1230+
1231+
return 0;
1232+
}
1233+
11561234
static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
11571235
struct file *file)
11581236
{
@@ -1189,8 +1267,8 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
11891267
fuse_make_bad(inode);
11901268
err = -EIO;
11911269
} else {
1192-
fuse_change_attributes(inode, &outarg.attr,
1193-
attr_timeout(&outarg),
1270+
fuse_change_attributes(inode, &outarg.attr, NULL,
1271+
ATTR_TIMEOUT(&outarg),
11941272
attr_version);
11951273
if (stat)
11961274
fuse_fillattr(inode, &outarg.attr, stat);
@@ -1204,12 +1282,22 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
12041282
unsigned int flags)
12051283
{
12061284
struct fuse_inode *fi = get_fuse_inode(inode);
1285+
struct fuse_conn *fc = get_fuse_conn(inode);
12071286
int err = 0;
12081287
bool sync;
12091288
u32 inval_mask = READ_ONCE(fi->inval_mask);
12101289
u32 cache_mask = fuse_get_cache_mask(inode);
12111290

1212-
if (flags & AT_STATX_FORCE_SYNC)
1291+
1292+
/* FUSE only supports basic stats and possibly btime */
1293+
request_mask &= STATX_BASIC_STATS | STATX_BTIME;
1294+
retry:
1295+
if (fc->no_statx)
1296+
request_mask &= STATX_BASIC_STATS;
1297+
1298+
if (!request_mask)
1299+
sync = false;
1300+
else if (flags & AT_STATX_FORCE_SYNC)
12131301
sync = true;
12141302
else if (flags & AT_STATX_DONT_SYNC)
12151303
sync = false;
@@ -1220,11 +1308,24 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
12201308

12211309
if (sync) {
12221310
forget_all_cached_acls(inode);
1223-
err = fuse_do_getattr(inode, stat, file);
1311+
/* Try statx if BTIME is requested */
1312+
if (!fc->no_statx && (request_mask & ~STATX_BASIC_STATS)) {
1313+
err = fuse_do_statx(inode, file, stat);
1314+
if (err == -ENOSYS) {
1315+
fc->no_statx = 1;
1316+
goto retry;
1317+
}
1318+
} else {
1319+
err = fuse_do_getattr(inode, stat, file);
1320+
}
12241321
} else if (stat) {
12251322
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
12261323
stat->mode = fi->orig_i_mode;
12271324
stat->ino = fi->orig_ino;
1325+
if (test_bit(FUSE_I_BTIME, &fi->state)) {
1326+
stat->btime = fi->i_btime;
1327+
stat->result_mask |= STATX_BTIME;
1328+
}
12281329
}
12291330

12301331
return err;
@@ -1861,8 +1962,8 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
18611962
/* FIXME: clear I_DIRTY_SYNC? */
18621963
}
18631964

1864-
fuse_change_attributes_common(inode, &outarg.attr,
1865-
attr_timeout(&outarg),
1965+
fuse_change_attributes_common(inode, &outarg.attr, NULL,
1966+
ATTR_TIMEOUT(&outarg),
18661967
fuse_get_cache_mask(inode));
18671968
oldsize = inode->i_size;
18681969
/* see the comment in fuse_change_attributes() */

0 commit comments

Comments
 (0)