Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1894586imu; Tue, 6 Nov 2018 06:05:27 -0800 (PST) X-Google-Smtp-Source: AJdET5cXjl0q+f1ldGWatUwP9qHKibRdcjzp8jOLqR/+5E9Zi2Mb2cRH9xr+GiYOQaKyM6R9gDlf X-Received: by 2002:a63:5d14:: with SMTP id r20mr23956323pgb.329.1541513127171; Tue, 06 Nov 2018 06:05:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1541513127; cv=none; d=google.com; s=arc-20160816; b=oecvcYYMgbJ4oq7mn9JeVZlo6tWwbF5WliaPEhHkBdZyRrieDIcU1rkRm1ZUwGO5lk Ttc4ZTdl9Sg8aidnC9pF1T926+5w74FXYxsbHoL/9Vs4YaICTuJQn4eNWll9C73uWRrd IiQbMW15AM4jDHVtOuH6WgZInRUxcj849N7oo9tL9LOoTi6z2+JrXmQWucie5qnYuTBU M2hFVsMl/y4VWvW/ay5RSFzUBByzXgFi3q/vBEQA8Ygx14m6KxGI+jW/rGa0rOGJ9uw5 Xep/0TdMTdZlzi4aHYhfmgTLol2w/kkOoT5hhgNT0n+XndOmW0mXCY4UouGvFSwimjju Q2sg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:message-id:date:to:from:subject; bh=QS27tBPIpi9P6jmoULqpDq/KLJNeewmAi+K4ep5r8vw=; b=QxYHbqnqtegsBDFSmbRaj+yRF5w6xQYMo64W/+Q7HTU3A/pTw9wEU6T13EbBVAFTUr rnxivNLi4zvsQyLUXRLot57Iyoa42ZKGBswe3tNjtLtIAY+SbK86Mfy61VgMOw/vaPjo KEwxqq1A7UHHQhE/CHHP3HZTuCkg7X9arlFFSkOEnKyyKwEcIUS50CSkhztIb8tVXUY0 UoYwP0fzIA6yIIqOAB0HFnrcoD1ZM48/RSPuVmRyAPSC3xatTOF+8i74QND5ShYDc9iP D5Vq6GL8DBIc9hDOaoEbsq65mfO/HyWRLjaEXOYp4PjQetVovH4QDB2fIvz5EML/ftMA /MRA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=virtuozzo.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c10si4641066pgj.416.2018.11.06.06.05.02; Tue, 06 Nov 2018 06:05:27 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=virtuozzo.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388601AbeKFX2X (ORCPT + 99 others); Tue, 6 Nov 2018 18:28:23 -0500 Received: from relay.sw.ru ([185.231.240.75]:41724 "EHLO relay.sw.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388509AbeKFX2X (ORCPT ); Tue, 6 Nov 2018 18:28:23 -0500 Received: from [172.16.25.169] (helo=localhost.localdomain) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1gK1wY-00053v-3B; Tue, 06 Nov 2018 17:02:58 +0300 Subject: [PATCH RFC] fuse: Prevent background write requests increase inode size From: Kirill Tkhai To: miklos@szeredi.hu, ktkhai@virtuozzo.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Date: Tue, 06 Nov 2018 17:02:57 +0300 Message-ID: <154151286725.17550.12307253489084032792.stgit@localhost.localdomain> User-Agent: StGit/0.18 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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) { /*