Skip to content

Commit e1c0eec

Browse files
author
Miklos Szeredi
committed
fuse: honor iocb sync flags on write
If the IOCB_DSYNC flag is set a sync is not being performed by fuse_file_write_iter. Honor IOCB_DSYNC/IOCB_SYNC by setting O_DYSNC/O_SYNC respectively in the flags filed of the write request. We don't need to sync data or metadata, since fuse_perform_write() does write-through and the filesystem is responsible for updating file times. Original patch by Vitaly Zolotusky. Reported-by: Nate Clark <[email protected]> Cc: Vitaly Zolotusky <[email protected]>. Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 5d6d3a3 commit e1c0eec

File tree

3 files changed

+28
-22
lines changed

3 files changed

+28
-22
lines changed

fs/fuse/cuse.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,15 @@ static struct list_head *cuse_conntbl_head(dev_t devt)
9090

9191
static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to)
9292
{
93-
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb->ki_filp);
93+
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb);
9494
loff_t pos = 0;
9595

9696
return fuse_direct_io(&io, to, &pos, FUSE_DIO_CUSE);
9797
}
9898

9999
static ssize_t cuse_write_iter(struct kiocb *kiocb, struct iov_iter *from)
100100
{
101-
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb->ki_filp);
101+
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb);
102102
loff_t pos = 0;
103103
/*
104104
* No locking or generic_write_checks(), the server is

fs/fuse/file.c

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ static size_t fuse_async_req_send(struct fuse_conn *fc, struct fuse_req *req,
645645
static size_t fuse_send_read(struct fuse_req *req, struct fuse_io_priv *io,
646646
loff_t pos, size_t count, fl_owner_t owner)
647647
{
648-
struct file *file = io->file;
648+
struct file *file = io->iocb->ki_filp;
649649
struct fuse_file *ff = file->private_data;
650650
struct fuse_conn *fc = ff->fc;
651651

@@ -707,7 +707,8 @@ static void fuse_short_read(struct fuse_req *req, struct inode *inode,
707707

708708
static int fuse_do_readpage(struct file *file, struct page *page)
709709
{
710-
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file);
710+
struct kiocb iocb;
711+
struct fuse_io_priv io;
711712
struct inode *inode = page->mapping->host;
712713
struct fuse_conn *fc = get_fuse_conn(inode);
713714
struct fuse_req *req;
@@ -735,6 +736,8 @@ static int fuse_do_readpage(struct file *file, struct page *page)
735736
req->num_pages = 1;
736737
req->pages[0] = page;
737738
req->page_descs[0].length = count;
739+
init_sync_kiocb(&iocb, file);
740+
io = (struct fuse_io_priv) FUSE_IO_PRIV_SYNC(&iocb);
738741
num_read = fuse_send_read(req, &io, pos, count, NULL);
739742
err = req->out.h.error;
740743

@@ -957,13 +960,18 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
957960
static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io,
958961
loff_t pos, size_t count, fl_owner_t owner)
959962
{
960-
struct file *file = io->file;
963+
struct kiocb *iocb = io->iocb;
964+
struct file *file = iocb->ki_filp;
961965
struct fuse_file *ff = file->private_data;
962966
struct fuse_conn *fc = ff->fc;
963967
struct fuse_write_in *inarg = &req->misc.write.in;
964968

965969
fuse_write_fill(req, ff, pos, count);
966970
inarg->flags = file->f_flags;
971+
if (iocb->ki_flags & IOCB_DSYNC)
972+
inarg->flags |= O_DSYNC;
973+
if (iocb->ki_flags & IOCB_SYNC)
974+
inarg->flags |= O_SYNC;
967975
if (owner != NULL) {
968976
inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
969977
inarg->lock_owner = fuse_lock_owner_id(fc, owner);
@@ -993,14 +1001,14 @@ bool fuse_write_update_size(struct inode *inode, loff_t pos)
9931001
return ret;
9941002
}
9951003

996-
static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
1004+
static size_t fuse_send_write_pages(struct fuse_req *req, struct kiocb *iocb,
9971005
struct inode *inode, loff_t pos,
9981006
size_t count)
9991007
{
10001008
size_t res;
10011009
unsigned offset;
10021010
unsigned i;
1003-
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file);
1011+
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
10041012

10051013
for (i = 0; i < req->num_pages; i++)
10061014
fuse_wait_on_page_writeback(inode, req->pages[i]->index);
@@ -1100,7 +1108,7 @@ static inline unsigned fuse_wr_pages(loff_t pos, size_t len)
11001108
FUSE_MAX_PAGES_PER_REQ);
11011109
}
11021110

1103-
static ssize_t fuse_perform_write(struct file *file,
1111+
static ssize_t fuse_perform_write(struct kiocb *iocb,
11041112
struct address_space *mapping,
11051113
struct iov_iter *ii, loff_t pos)
11061114
{
@@ -1133,7 +1141,7 @@ static ssize_t fuse_perform_write(struct file *file,
11331141
} else {
11341142
size_t num_written;
11351143

1136-
num_written = fuse_send_write_pages(req, file, inode,
1144+
num_written = fuse_send_write_pages(req, iocb, inode,
11371145
pos, count);
11381146
err = req->out.h.error;
11391147
if (!err) {
@@ -1201,7 +1209,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
12011209

12021210
pos += written;
12031211

1204-
written_buffered = fuse_perform_write(file, mapping, from, pos);
1212+
written_buffered = fuse_perform_write(iocb, mapping, from, pos);
12051213
if (written_buffered < 0) {
12061214
err = written_buffered;
12071215
goto out;
@@ -1220,13 +1228,15 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
12201228
written += written_buffered;
12211229
iocb->ki_pos = pos + written_buffered;
12221230
} else {
1223-
written = fuse_perform_write(file, mapping, from, iocb->ki_pos);
1231+
written = fuse_perform_write(iocb, mapping, from, iocb->ki_pos);
12241232
if (written >= 0)
12251233
iocb->ki_pos += written;
12261234
}
12271235
out:
12281236
current->backing_dev_info = NULL;
12291237
inode_unlock(inode);
1238+
if (written > 0)
1239+
written = generic_write_sync(iocb, written);
12301240

12311241
return written ? written : err;
12321242
}
@@ -1317,7 +1327,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
13171327
{
13181328
int write = flags & FUSE_DIO_WRITE;
13191329
int cuse = flags & FUSE_DIO_CUSE;
1320-
struct file *file = io->file;
1330+
struct file *file = io->iocb->ki_filp;
13211331
struct inode *inode = file->f_mapping->host;
13221332
struct fuse_file *ff = file->private_data;
13231333
struct fuse_conn *fc = ff->fc;
@@ -1399,8 +1409,7 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
13991409
loff_t *ppos)
14001410
{
14011411
ssize_t res;
1402-
struct file *file = io->file;
1403-
struct inode *inode = file_inode(file);
1412+
struct inode *inode = file_inode(io->iocb->ki_filp);
14041413

14051414
if (is_bad_inode(inode))
14061415
return -EIO;
@@ -1414,15 +1423,14 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
14141423

14151424
static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
14161425
{
1417-
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb->ki_filp);
1426+
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
14181427
return __fuse_direct_read(&io, to, &iocb->ki_pos);
14191428
}
14201429

14211430
static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
14221431
{
1423-
struct file *file = iocb->ki_filp;
1424-
struct inode *inode = file_inode(file);
1425-
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file);
1432+
struct inode *inode = file_inode(iocb->ki_filp);
1433+
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
14261434
ssize_t res;
14271435

14281436
if (is_bad_inode(inode))
@@ -2871,7 +2879,6 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
28712879
io->offset = offset;
28722880
io->write = (iov_iter_rw(iter) == WRITE);
28732881
io->err = 0;
2874-
io->file = file;
28752882
/*
28762883
* By default, we want to optimize all I/Os with async request
28772884
* submission to the client filesystem if supported.

fs/fuse/fuse_i.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,15 @@ struct fuse_io_priv {
252252
bool should_dirty;
253253
int err;
254254
struct kiocb *iocb;
255-
struct file *file;
256255
struct completion *done;
257256
bool blocking;
258257
};
259258

260-
#define FUSE_IO_PRIV_SYNC(f) \
259+
#define FUSE_IO_PRIV_SYNC(i) \
261260
{ \
262261
.refcnt = KREF_INIT(1), \
263262
.async = 0, \
264-
.file = f, \
263+
.iocb = i, \
265264
}
266265

267266
/**

0 commit comments

Comments
 (0)