Skip to content

Commit 57e1176

Browse files
amir73ilMiklos Szeredi
authored andcommitted
fuse: implement read/write passthrough
Use the backing file read/write helpers to implement read/write passthrough to a backing file. After read/write, we invalidate a/c/mtime/size attributes. Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 4a90451 commit 57e1176

File tree

3 files changed

+84
-6
lines changed

3 files changed

+84
-6
lines changed

fs/fuse/file.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,10 +1693,13 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
16931693
if (FUSE_IS_DAX(inode))
16941694
return fuse_dax_read_iter(iocb, to);
16951695

1696-
if (!(ff->open_flags & FOPEN_DIRECT_IO))
1697-
return fuse_cache_read_iter(iocb, to);
1698-
else
1696+
/* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */
1697+
if (ff->open_flags & FOPEN_DIRECT_IO)
16991698
return fuse_direct_read_iter(iocb, to);
1699+
else if (fuse_file_passthrough(ff))
1700+
return fuse_passthrough_read_iter(iocb, to);
1701+
else
1702+
return fuse_cache_read_iter(iocb, to);
17001703
}
17011704

17021705
static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
@@ -1711,10 +1714,13 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
17111714
if (FUSE_IS_DAX(inode))
17121715
return fuse_dax_write_iter(iocb, from);
17131716

1714-
if (!(ff->open_flags & FOPEN_DIRECT_IO))
1715-
return fuse_cache_write_iter(iocb, from);
1716-
else
1717+
/* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */
1718+
if (ff->open_flags & FOPEN_DIRECT_IO)
17171719
return fuse_direct_write_iter(iocb, from);
1720+
else if (fuse_file_passthrough(ff))
1721+
return fuse_passthrough_write_iter(iocb, from);
1722+
else
1723+
return fuse_cache_write_iter(iocb, from);
17181724
}
17191725

17201726
static void fuse_writepage_free(struct fuse_writepage_args *wpa)

fs/fuse/fuse_i.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,4 +1466,7 @@ static inline struct file *fuse_file_passthrough(struct fuse_file *ff)
14661466
#endif
14671467
}
14681468

1469+
ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *iter);
1470+
ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *iter);
1471+
14691472
#endif /* _FS_FUSE_I_H */

fs/fuse/passthrough.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,75 @@
1010
#include <linux/file.h>
1111
#include <linux/backing-file.h>
1212

13+
static void fuse_file_accessed(struct file *file)
14+
{
15+
struct inode *inode = file_inode(file);
16+
17+
fuse_invalidate_atime(inode);
18+
}
19+
20+
static void fuse_file_modified(struct file *file)
21+
{
22+
struct inode *inode = file_inode(file);
23+
24+
fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE);
25+
}
26+
27+
ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *iter)
28+
{
29+
struct file *file = iocb->ki_filp;
30+
struct fuse_file *ff = file->private_data;
31+
struct file *backing_file = fuse_file_passthrough(ff);
32+
size_t count = iov_iter_count(iter);
33+
ssize_t ret;
34+
struct backing_file_ctx ctx = {
35+
.cred = ff->cred,
36+
.user_file = file,
37+
.accessed = fuse_file_accessed,
38+
};
39+
40+
41+
pr_debug("%s: backing_file=0x%p, pos=%lld, len=%zu\n", __func__,
42+
backing_file, iocb->ki_pos, count);
43+
44+
if (!count)
45+
return 0;
46+
47+
ret = backing_file_read_iter(backing_file, iter, iocb, iocb->ki_flags,
48+
&ctx);
49+
50+
return ret;
51+
}
52+
53+
ssize_t fuse_passthrough_write_iter(struct kiocb *iocb,
54+
struct iov_iter *iter)
55+
{
56+
struct file *file = iocb->ki_filp;
57+
struct inode *inode = file_inode(file);
58+
struct fuse_file *ff = file->private_data;
59+
struct file *backing_file = fuse_file_passthrough(ff);
60+
size_t count = iov_iter_count(iter);
61+
ssize_t ret;
62+
struct backing_file_ctx ctx = {
63+
.cred = ff->cred,
64+
.user_file = file,
65+
.end_write = fuse_file_modified,
66+
};
67+
68+
pr_debug("%s: backing_file=0x%p, pos=%lld, len=%zu\n", __func__,
69+
backing_file, iocb->ki_pos, count);
70+
71+
if (!count)
72+
return 0;
73+
74+
inode_lock(inode);
75+
ret = backing_file_write_iter(backing_file, iter, iocb, iocb->ki_flags,
76+
&ctx);
77+
inode_unlock(inode);
78+
79+
return ret;
80+
}
81+
1382
struct fuse_backing *fuse_backing_get(struct fuse_backing *fb)
1483
{
1584
if (fb && refcount_inc_not_zero(&fb->count))

0 commit comments

Comments
 (0)