Skip to content

Commit 8975f89

Browse files
committed
Merge tag 'fuse-update-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse updates from Miklos Szeredi: - Fix a regression introduced in 5.15 - Extend the size of the FUSE_INIT request to accommodate for more flags. There's a slight possibility of a regression for obscure fuse servers; if this happens, then more complexity will need to be added to the protocol - Allow the DAX property to be controlled by the server on a per-inode basis in virtiofs - Allow sending security context to the server when creating a file or directory * tag 'fuse-update-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: Documentation/filesystem/dax: DAX on virtiofs fuse: mark inode DONT_CACHE when per inode DAX hint changes fuse: negotiate per inode DAX in FUSE_INIT fuse: enable per inode DAX fuse: support per inode DAX in fuse protocol fuse: make DAX mount option a tri-state fuse: add fuse_should_enable_dax() helper fuse: Pass correct lend value to filemap_write_and_wait_range() fuse: send security context of inode on file fuse: extend init flags
2 parents 1fb38c9 + 073c3ab commit 8975f89

File tree

8 files changed

+294
-52
lines changed

8 files changed

+294
-52
lines changed

Documentation/filesystems/dax.rst

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ on it as usual. The `DAX` code currently only supports files with a block
2323
size equal to your kernel's `PAGE_SIZE`, so you may need to specify a block
2424
size when creating the filesystem.
2525

26-
Currently 3 filesystems support `DAX`: ext2, ext4 and xfs. Enabling `DAX` on them
27-
is different.
26+
Currently 4 filesystems support `DAX`: ext2, ext4, xfs and virtiofs.
27+
Enabling `DAX` on them is different.
2828

2929
Enabling DAX on ext2
3030
--------------------
@@ -168,6 +168,22 @@ if the underlying media does not support dax and/or the filesystem is
168168
overridden with a mount option.
169169

170170

171+
Enabling DAX on virtiofs
172+
----------------------------
173+
The semantic of DAX on virtiofs is basically equal to that on ext4 and xfs,
174+
except that when '-o dax=inode' is specified, virtiofs client derives the hint
175+
whether DAX shall be enabled or not from virtiofs server through FUSE protocol,
176+
rather than the persistent `FS_XFLAG_DAX` flag. That is, whether DAX shall be
177+
enabled or not is completely determined by virtiofs server, while virtiofs
178+
server itself may deploy various algorithm making this decision, e.g. depending
179+
on the persistent `FS_XFLAG_DAX` flag on the host.
180+
181+
It is still supported to set or clear persistent `FS_XFLAG_DAX` flag inside
182+
guest, but it is not guaranteed that DAX will be enabled or disabled for
183+
corresponding file then. Users inside guest still need to call statx(2) and
184+
check the statx flag `STATX_ATTR_DAX` to see if DAX is enabled for this file.
185+
186+
171187
Implementation Tips for Block Driver Writers
172188
--------------------------------------------
173189

fs/fuse/dax.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,11 +1279,14 @@ static int fuse_dax_mem_range_init(struct fuse_conn_dax *fcd)
12791279
return ret;
12801280
}
12811281

1282-
int fuse_dax_conn_alloc(struct fuse_conn *fc, struct dax_device *dax_dev)
1282+
int fuse_dax_conn_alloc(struct fuse_conn *fc, enum fuse_dax_mode dax_mode,
1283+
struct dax_device *dax_dev)
12831284
{
12841285
struct fuse_conn_dax *fcd;
12851286
int err;
12861287

1288+
fc->dax_mode = dax_mode;
1289+
12871290
if (!dax_dev)
12881291
return 0;
12891292

@@ -1327,17 +1330,46 @@ static const struct address_space_operations fuse_dax_file_aops = {
13271330
.invalidatepage = noop_invalidatepage,
13281331
};
13291332

1330-
void fuse_dax_inode_init(struct inode *inode)
1333+
static bool fuse_should_enable_dax(struct inode *inode, unsigned int flags)
13311334
{
13321335
struct fuse_conn *fc = get_fuse_conn(inode);
1336+
enum fuse_dax_mode dax_mode = fc->dax_mode;
1337+
1338+
if (dax_mode == FUSE_DAX_NEVER)
1339+
return false;
13331340

1341+
/*
1342+
* fc->dax may be NULL in 'inode' mode when filesystem device doesn't
1343+
* support DAX, in which case it will silently fallback to 'never' mode.
1344+
*/
13341345
if (!fc->dax)
1346+
return false;
1347+
1348+
if (dax_mode == FUSE_DAX_ALWAYS)
1349+
return true;
1350+
1351+
/* dax_mode is FUSE_DAX_INODE* */
1352+
return fc->inode_dax && (flags & FUSE_ATTR_DAX);
1353+
}
1354+
1355+
void fuse_dax_inode_init(struct inode *inode, unsigned int flags)
1356+
{
1357+
if (!fuse_should_enable_dax(inode, flags))
13351358
return;
13361359

13371360
inode->i_flags |= S_DAX;
13381361
inode->i_data.a_ops = &fuse_dax_file_aops;
13391362
}
13401363

1364+
void fuse_dax_dontcache(struct inode *inode, unsigned int flags)
1365+
{
1366+
struct fuse_conn *fc = get_fuse_conn(inode);
1367+
1368+
if (fuse_is_inode_dax_mode(fc->dax_mode) &&
1369+
((bool) IS_DAX(inode) != (bool) (flags & FUSE_ATTR_DAX)))
1370+
d_mark_dontcache(inode);
1371+
}
1372+
13411373
bool fuse_dax_check_alignment(struct fuse_conn *fc, unsigned int map_alignment)
13421374
{
13431375
if (fc->dax && (map_alignment > FUSE_DAX_SHIFT)) {

fs/fuse/dir.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include <linux/xattr.h>
1818
#include <linux/iversion.h>
1919
#include <linux/posix_acl.h>
20+
#include <linux/security.h>
21+
#include <linux/types.h>
22+
#include <linux/kernel.h>
2023

2124
static void fuse_advise_use_readdirplus(struct inode *dir)
2225
{
@@ -456,6 +459,62 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
456459
return ERR_PTR(err);
457460
}
458461

462+
static int get_security_context(struct dentry *entry, umode_t mode,
463+
void **security_ctx, u32 *security_ctxlen)
464+
{
465+
struct fuse_secctx *fctx;
466+
struct fuse_secctx_header *header;
467+
void *ctx = NULL, *ptr;
468+
u32 ctxlen, total_len = sizeof(*header);
469+
int err, nr_ctx = 0;
470+
const char *name;
471+
size_t namelen;
472+
473+
err = security_dentry_init_security(entry, mode, &entry->d_name,
474+
&name, &ctx, &ctxlen);
475+
if (err) {
476+
if (err != -EOPNOTSUPP)
477+
goto out_err;
478+
/* No LSM is supporting this security hook. Ignore error */
479+
ctxlen = 0;
480+
ctx = NULL;
481+
}
482+
483+
if (ctxlen) {
484+
nr_ctx = 1;
485+
namelen = strlen(name) + 1;
486+
err = -EIO;
487+
if (WARN_ON(namelen > XATTR_NAME_MAX + 1 || ctxlen > S32_MAX))
488+
goto out_err;
489+
total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen + ctxlen);
490+
}
491+
492+
err = -ENOMEM;
493+
header = ptr = kzalloc(total_len, GFP_KERNEL);
494+
if (!ptr)
495+
goto out_err;
496+
497+
header->nr_secctx = nr_ctx;
498+
header->size = total_len;
499+
ptr += sizeof(*header);
500+
if (nr_ctx) {
501+
fctx = ptr;
502+
fctx->size = ctxlen;
503+
ptr += sizeof(*fctx);
504+
505+
strcpy(ptr, name);
506+
ptr += namelen;
507+
508+
memcpy(ptr, ctx, ctxlen);
509+
}
510+
*security_ctxlen = total_len;
511+
*security_ctx = header;
512+
err = 0;
513+
out_err:
514+
kfree(ctx);
515+
return err;
516+
}
517+
459518
/*
460519
* Atomic create+open operation
461520
*
@@ -476,6 +535,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
476535
struct fuse_entry_out outentry;
477536
struct fuse_inode *fi;
478537
struct fuse_file *ff;
538+
void *security_ctx = NULL;
539+
u32 security_ctxlen;
479540

480541
/* Userspace expects S_IFREG in create mode */
481542
BUG_ON((mode & S_IFMT) != S_IFREG);
@@ -517,7 +578,20 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
517578
args.out_args[0].value = &outentry;
518579
args.out_args[1].size = sizeof(outopen);
519580
args.out_args[1].value = &outopen;
581+
582+
if (fm->fc->init_security) {
583+
err = get_security_context(entry, mode, &security_ctx,
584+
&security_ctxlen);
585+
if (err)
586+
goto out_put_forget_req;
587+
588+
args.in_numargs = 3;
589+
args.in_args[2].size = security_ctxlen;
590+
args.in_args[2].value = security_ctx;
591+
}
592+
520593
err = fuse_simple_request(fm, &args);
594+
kfree(security_ctx);
521595
if (err)
522596
goto out_free_ff;
523597

@@ -620,6 +694,8 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
620694
struct dentry *d;
621695
int err;
622696
struct fuse_forget_link *forget;
697+
void *security_ctx = NULL;
698+
u32 security_ctxlen;
623699

624700
if (fuse_is_bad(dir))
625701
return -EIO;
@@ -633,7 +709,22 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
633709
args->out_numargs = 1;
634710
args->out_args[0].size = sizeof(outarg);
635711
args->out_args[0].value = &outarg;
712+
713+
if (fm->fc->init_security && args->opcode != FUSE_LINK) {
714+
err = get_security_context(entry, mode, &security_ctx,
715+
&security_ctxlen);
716+
if (err)
717+
goto out_put_forget_req;
718+
719+
BUG_ON(args->in_numargs != 2);
720+
721+
args->in_numargs = 3;
722+
args->in_args[2].size = security_ctxlen;
723+
args->in_args[2].value = security_ctx;
724+
}
725+
636726
err = fuse_simple_request(fm, args);
727+
kfree(security_ctx);
637728
if (err)
638729
goto out_put_forget_req;
639730

fs/fuse/file.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2910,7 +2910,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
29102910

29112911
static int fuse_writeback_range(struct inode *inode, loff_t start, loff_t end)
29122912
{
2913-
int err = filemap_write_and_wait_range(inode->i_mapping, start, -1);
2913+
int err = filemap_write_and_wait_range(inode->i_mapping, start, LLONG_MAX);
29142914

29152915
if (!err)
29162916
fuse_sync_writes(inode);
@@ -3169,7 +3169,7 @@ static const struct address_space_operations fuse_file_aops = {
31693169
.write_end = fuse_write_end,
31703170
};
31713171

3172-
void fuse_init_file_inode(struct inode *inode)
3172+
void fuse_init_file_inode(struct inode *inode, unsigned int flags)
31733173
{
31743174
struct fuse_inode *fi = get_fuse_inode(inode);
31753175

@@ -3183,5 +3183,5 @@ void fuse_init_file_inode(struct inode *inode)
31833183
fi->writepages = RB_ROOT;
31843184

31853185
if (IS_ENABLED(CONFIG_FUSE_DAX))
3186-
fuse_dax_inode_init(inode);
3186+
fuse_dax_inode_init(inode, flags);
31873187
}

fs/fuse/fuse_i.h

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,18 @@ struct fuse_dev {
480480
struct list_head entry;
481481
};
482482

483+
enum fuse_dax_mode {
484+
FUSE_DAX_INODE_DEFAULT, /* default */
485+
FUSE_DAX_ALWAYS, /* "-o dax=always" */
486+
FUSE_DAX_NEVER, /* "-o dax=never" */
487+
FUSE_DAX_INODE_USER, /* "-o dax=inode" */
488+
};
489+
490+
static inline bool fuse_is_inode_dax_mode(enum fuse_dax_mode mode)
491+
{
492+
return mode == FUSE_DAX_INODE_DEFAULT || mode == FUSE_DAX_INODE_USER;
493+
}
494+
483495
struct fuse_fs_context {
484496
int fd;
485497
struct file *file;
@@ -497,7 +509,7 @@ struct fuse_fs_context {
497509
bool no_control:1;
498510
bool no_force_umount:1;
499511
bool legacy_opts_show:1;
500-
bool dax:1;
512+
enum fuse_dax_mode dax_mode;
501513
unsigned int max_read;
502514
unsigned int blksize;
503515
const char *subtype;
@@ -765,6 +777,12 @@ struct fuse_conn {
765777
/* Propagate syncfs() to server */
766778
unsigned int sync_fs:1;
767779

780+
/* Initialize security xattrs when creating a new inode */
781+
unsigned int init_security:1;
782+
783+
/* Does the filesystem support per inode DAX? */
784+
unsigned int inode_dax:1;
785+
768786
/** The number of requests waiting for completion */
769787
atomic_t num_waiting;
770788

@@ -802,6 +820,9 @@ struct fuse_conn {
802820
struct list_head devices;
803821

804822
#ifdef CONFIG_FUSE_DAX
823+
/* Dax mode */
824+
enum fuse_dax_mode dax_mode;
825+
805826
/* Dax specific conn data, non-NULL if DAX is enabled */
806827
struct fuse_conn_dax *dax;
807828
#endif
@@ -1007,7 +1028,7 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc,
10071028
/**
10081029
* Initialize file operations on a regular file
10091030
*/
1010-
void fuse_init_file_inode(struct inode *inode);
1031+
void fuse_init_file_inode(struct inode *inode, unsigned int flags);
10111032

10121033
/**
10131034
* Initialize inode operations on regular files and special files
@@ -1269,11 +1290,13 @@ ssize_t fuse_dax_read_iter(struct kiocb *iocb, struct iov_iter *to);
12691290
ssize_t fuse_dax_write_iter(struct kiocb *iocb, struct iov_iter *from);
12701291
int fuse_dax_mmap(struct file *file, struct vm_area_struct *vma);
12711292
int fuse_dax_break_layouts(struct inode *inode, u64 dmap_start, u64 dmap_end);
1272-
int fuse_dax_conn_alloc(struct fuse_conn *fc, struct dax_device *dax_dev);
1293+
int fuse_dax_conn_alloc(struct fuse_conn *fc, enum fuse_dax_mode mode,
1294+
struct dax_device *dax_dev);
12731295
void fuse_dax_conn_free(struct fuse_conn *fc);
12741296
bool fuse_dax_inode_alloc(struct super_block *sb, struct fuse_inode *fi);
1275-
void fuse_dax_inode_init(struct inode *inode);
1297+
void fuse_dax_inode_init(struct inode *inode, unsigned int flags);
12761298
void fuse_dax_inode_cleanup(struct inode *inode);
1299+
void fuse_dax_dontcache(struct inode *inode, unsigned int flags);
12771300
bool fuse_dax_check_alignment(struct fuse_conn *fc, unsigned int map_alignment);
12781301
void fuse_dax_cancel_work(struct fuse_conn *fc);
12791302

0 commit comments

Comments
 (0)