All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kirill Tkhai <ktkhai@virtuozzo.com>
To: miklos@szeredi.hu, ktkhai@virtuozzo.com,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH RFC] fuse: Prevent background write requests increase inode size
Date: Tue, 06 Nov 2018 17:02:57 +0300	[thread overview]
Message-ID: <154151286725.17550.12307253489084032792.stgit@localhost.localdomain> (raw)

Hi, Miklos,

this is not a well-tested patch, this is a concept,
showing the places, where it looks we have a problem.

Commit 7879c4e58b7c made io->async careless about inode size,
and this is wrong. Asyncronuos background requests may be sent
to userspace after inode becomes unlocked, when background
queue is throttled. In this case we execute a write request
extending inode size without any protection, and this ruines
everything. Fix that.

Also, some write background requests do not increment fi->writectr,
e.g.:
	fuse_direct_IO()
	  fuse_direct_io()
	    fuse_send_write()
	      fuse_async_req_send()
	        fuse_request_send_background()

This is a reason fuse_sync_writes() does not work as expected.
Fix that too.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 fs/fuse/file.c |   20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index cc2121b37bf5..0b71a3c96168 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -610,6 +610,9 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos)
 static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_req *req)
 {
 	struct fuse_io_priv *io = req->io;
+	struct kiocb *iocb = io->iocb;
+	struct file *file = iocb->ki_filp;
+	struct fuse_inode *fi = get_fuse_inode(file_inode(file));
 	ssize_t pos = -1;
 
 	fuse_release_user_pages(req, io->should_dirty);
@@ -625,6 +628,12 @@ static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_req *req)
 	}
 
 	fuse_aio_complete(io, req->out.h.error, pos);
+
+	if (io->write) {
+		spin_lock(&fc->lock);
+		fi->writectr--;
+		spin_unlock(&fc->lock);
+	}
 }
 
 static size_t fuse_async_req_send(struct fuse_conn *fc, struct fuse_req *req,
@@ -966,6 +975,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io,
 {
 	struct kiocb *iocb = io->iocb;
 	struct file *file = iocb->ki_filp;
+	struct fuse_inode *fi = get_fuse_inode(file_inode(file));
 	struct fuse_file *ff = file->private_data;
 	struct fuse_conn *fc = ff->fc;
 	struct fuse_write_in *inarg = &req->misc.write.in;
@@ -981,8 +991,12 @@ static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io,
 		inarg->lock_owner = fuse_lock_owner_id(fc, owner);
 	}
 
-	if (io->async)
+	if (io->async) {
+		spin_lock(&fc->lock);
+		fi->writectr++;
+		spin_unlock(&fc->lock);
 		return fuse_async_req_send(fc, req, count, io);
+	}
 
 	fuse_request_send(fc, req);
 	return req->misc.write.out.size;
@@ -2904,8 +2918,10 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 	 * We cannot asynchronously extend the size of a file.
 	 * In such case the aio will behave exactly like sync io.
 	 */
-	if ((offset + count > i_size) && iov_iter_rw(iter) == WRITE)
+	if ((offset + count > i_size) && iov_iter_rw(iter) == WRITE) {
 		io->blocking = true;
+		io->async = false;
+	}
 
 	if (io->async && io->blocking) {
 		/*


             reply	other threads:[~2018-11-06 14:03 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-06 14:02 Kirill Tkhai [this message]
2019-01-15 16:20 ` [PATCH RFC] fuse: Prevent background write requests increase inode size Kirill Tkhai
2019-01-23  9:37 ` Miklos Szeredi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=154151286725.17550.12307253489084032792.stgit@localhost.localdomain \
    --to=ktkhai@virtuozzo.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.