2018-03-07 20:58:40

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 1/2] NFS: Fix an incorrect type in struct nfs_direct_req

The start offset needs to be of type loff_t.

Fixed: 5fadeb47dcc5c ("nfs: count DIO good bytes correctly with mirroring")
Cc: [email protected] # v4.0+
Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/direct.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 8c10b0562e75..621c517b325c 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -86,10 +86,10 @@ struct nfs_direct_req {
struct nfs_direct_mirror mirrors[NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX];
int mirror_count;

+ loff_t io_start; /* Start offset for I/O */
ssize_t count, /* bytes actually processed */
max_count, /* max expected count */
bytes_left, /* bytes left to be sent */
- io_start, /* start of IO */
error; /* any reported error */
struct completion completion; /* wait for i/o completion */

--
2.14.3



2018-03-07 20:58:41

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 2/2] NFS: Record file size changes when doing O_DIRECT writes

Ensure that we do update the file size when doing O_DIRECT writes
rather than relying on attribute updates. Those may not be
immediately forthcoming if this is a delegated file and/or we
are doing pNFS.

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/direct.c | 1 +
fs/nfs/internal.h | 1 +
fs/nfs/write.c | 14 +++++---------
3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 621c517b325c..aae35f87d4d0 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -938,6 +938,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
return result < 0 ? result : -EIO;
}

+ nfs_grow_file(inode, dreq->io_start, requested_bytes);
if (put_dreq(dreq))
nfs_direct_write_complete(dreq);
return requested_bytes;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 8357ff69962f..51ecc634f79a 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -474,6 +474,7 @@ extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
const struct nfs_pgio_completion_ops *compl_ops);
extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
extern void nfs_commit_free(struct nfs_commit_data *p);
+void nfs_grow_file(struct inode *inode, loff_t offset, unsigned int count);
extern void nfs_write_prepare(struct rpc_task *task, void *calldata);
extern void nfs_commit_prepare(struct rpc_task *task, void *calldata);
extern int nfs_initiate_commit(struct rpc_clnt *clnt,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 7428a669d7a7..93460f1cf5a4 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -216,18 +216,13 @@ static struct nfs_page *nfs_page_find_head_request(struct page *page)
}

/* Adjust the file length if we're writing beyond the end */
-static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count)
+void nfs_grow_file(struct inode *inode, loff_t offset, unsigned int count)
{
- struct inode *inode = page_file_mapping(page)->host;
- loff_t end, i_size;
- pgoff_t end_index;
+ loff_t end = offset + count;
+ loff_t i_size;

spin_lock(&inode->i_lock);
i_size = i_size_read(inode);
- end_index = (i_size - 1) >> PAGE_SHIFT;
- if (i_size > 0 && page_index(page) < end_index)
- goto out;
- end = page_file_offset(page) + ((loff_t)offset+count);
if (i_size >= end)
goto out;
i_size_write(inode, end);
@@ -1170,13 +1165,14 @@ static struct nfs_page * nfs_setup_write_request(struct nfs_open_context* ctx,
static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
unsigned int offset, unsigned int count)
{
+ struct inode *inode = page_file_mapping(page)->host;
struct nfs_page *req;

req = nfs_setup_write_request(ctx, page, offset, count);
if (IS_ERR(req))
return PTR_ERR(req);
/* Update file length */
- nfs_grow_file(page, offset, count);
+ nfs_grow_file(inode, req_offset(req), req->wb_bytes);
nfs_mark_uptodate(req);
nfs_mark_request_dirty(req);
nfs_unlock_and_release_request(req);
--
2.14.3