2014-04-17 21:09:49

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 00/17] NFS: Create a common path used by reads and writes

I noticed that much of the read and write code was almost identical, with
only minor differences in argument types and names. These patches seek to
unify these two codepaths wherever possible in order to make future changes
easier.

Table of contents:
Patches 01 - 05: Set up common data structures.
Patches 06 - 10: Set up a shared rpc_call_ops struct.
Patches 11 - 15: Set up a shared nfs_pageio_ops struct.

Some of the commit setup was moved into common code, but I'm willing to
move this back into write.c if this looks to be a problem.

Future work:
I have rough pNFS patches that don't currently apply. They need
more testing, and I figured this was enough code churn already.

Testing:
I tested every version of NFS using the cthon and xfs tests without
hitting anything new. Any extra testing would be great seeing how
the read and write paths are vitally important.

Questions? Comments? Death threats?

Anna


Anna Schumaker (17):
NFS: Create a common argument structure for reads and writes
NFS: Create a common results structure for reads and writes
NFS: Create a common read and write data struct
NFS: Create a common read and write header struct
NFS: Move the write verifier into the nfs_pgio_header
NFS: Create a common pgio_alloc and pgio_release function
NFS: Create a common rw_header_alloc and rw_header_free function
NFS: Create a common pgio_rpc_prepare function
NFS: Create a common nfs_pgio_result_common function
NFS: Create a common pgio_common_ops struct
NFS: Create a common rpcsetup function for reads and writes
NFS: Create a common pgio_error function
NFS: Create a generic_pgio function
NFS: Create a common initiate_pgio() function
NFS: Create a common multiple_pgios() function
NFS: Create a common generic_pg_pgios()
NFS: Create a common nfs_pageio_ops instance

fs/nfs/Makefile | 2 +-
fs/nfs/blocklayout/blocklayout.c | 22 +-
fs/nfs/direct.c | 4 +-
fs/nfs/internal.h | 31 ++-
fs/nfs/nfs2xdr.c | 14 +-
fs/nfs/nfs3proc.c | 19 +-
fs/nfs/nfs3xdr.c | 16 +-
fs/nfs/nfs4_fs.h | 4 +-
fs/nfs/nfs4filelayout.c | 40 ++--
fs/nfs/nfs4proc.c | 52 ++---
fs/nfs/nfs4trace.h | 8 +-
fs/nfs/nfs4xdr.c | 19 +-
fs/nfs/objlayout/objio_osd.c | 6 +-
fs/nfs/objlayout/objlayout.c | 16 +-
fs/nfs/objlayout/objlayout.h | 8 +-
fs/nfs/pageio.c | 386 +++++++++++++++++++++++++++++++++++
fs/nfs/pagelist.c | 2 +
fs/nfs/pnfs.c | 46 ++---
fs/nfs/pnfs.h | 10 +-
fs/nfs/proc.c | 19 +-
fs/nfs/read.c | 348 +++-----------------------------
fs/nfs/write.c | 425 +++++----------------------------------
include/linux/nfs_fs.h | 3 +-
include/linux/nfs_page.h | 13 ++
include/linux/nfs_xdr.h | 94 +++------
25 files changed, 661 insertions(+), 946 deletions(-)
create mode 100644 fs/nfs/pageio.c

--
1.9.2



2014-04-21 13:09:30

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 00/17] NFS: Create a common path used by reads and writes

On Mon, Apr 21, 2014 at 08:46:49AM -0400, Anna Schumaker wrote:
> On 04/21/2014 02:42 AM, Christoph Hellwig wrote:
> > On Thu, Apr 17, 2014 at 05:09:24PM -0400, Anna Schumaker wrote:
> >> Questions? Comments? Death threats?
> > Can you say what tree this is based on or even better publish a git
> > tree? I tried to apply the series to various trees so that I can get a
> > better picture for further reviews, but git-am always bailed out
> > somewhere.
> Oops, sorry! This is based on Trond's testing branch. I can work on putting out a git tree later today!

Played around a bit more, and it seems like it's Trond's testing branch
+ my two pgio cleanups. With that I managed to apply your patches.


2014-04-17 21:10:31

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 14/17] NFS: Create a common initiate_pgio() function

From: Anna Schumaker <[email protected]>

Most of this code is the same for both the read and write paths, so
combine everything and use the rw_ops when necessary.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 9 ++------
fs/nfs/nfs4filelayout.c | 6 +++---
fs/nfs/pageio.c | 47 +++++++++++++++++++++++++++++++++++++++++
fs/nfs/read.c | 42 ++++++------------------------------
fs/nfs/write.c | 55 ++++++------------------------------------------
include/linux/nfs_page.h | 2 ++
6 files changed, 67 insertions(+), 94 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 6422b9d..027d72c 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -400,14 +400,13 @@ extern struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
extern void nfs_rw_header_free(struct nfs_pgio_header *);
extern void nfs_pgio_data_release(struct nfs_pgio_data *);
extern int nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_header *);
+extern int nfs_initiate_pgio(struct rpc_clnt *, struct nfs_pgio_data *,
+ const struct rpc_call_ops *, int, int);

/* read.c */
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
struct inode *inode, bool force_mds,
const struct nfs_pgio_completion_ops *compl_ops);
-extern int nfs_initiate_read(struct rpc_clnt *clnt,
- struct nfs_pgio_data *data,
- const struct rpc_call_ops *call_ops, int flags);
extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);

@@ -428,10 +427,6 @@ 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);
-extern int nfs_initiate_write(struct rpc_clnt *clnt,
- struct nfs_pgio_data *data,
- const struct rpc_call_ops *call_ops,
- int how, int flags);
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/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index e693614..7954e16 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -568,8 +568,8 @@ filelayout_read_pagelist(struct nfs_pgio_data *data)
data->mds_offset = offset;

/* Perform an asynchronous read to ds */
- nfs_initiate_read(ds_clnt, data,
- &filelayout_read_call_ops, RPC_TASK_SOFTCONN);
+ nfs_initiate_pgio(ds_clnt, data,
+ &filelayout_read_call_ops, 0, RPC_TASK_SOFTCONN);
return PNFS_ATTEMPTED;
}

@@ -613,7 +613,7 @@ filelayout_write_pagelist(struct nfs_pgio_data *data, int sync)
data->args.offset = filelayout_get_dserver_offset(lseg, offset);

/* Perform an asynchronous write */
- nfs_initiate_write(ds_clnt, data,
+ nfs_initiate_pgio(ds_clnt, data,
&filelayout_write_call_ops, sync,
RPC_TASK_SOFTCONN);
return PNFS_ATTEMPTED;
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index 093cb1d..c80e611 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -126,6 +126,53 @@ static void nfs_pgio_rpcsetup(struct nfs_pgio_data *data,
nfs_fattr_init(&data->fattr);
}

+int nfs_initiate_pgio(struct rpc_clnt *clnt, struct nfs_pgio_data *data,
+ const struct rpc_call_ops *call_ops, int how, int flags)
+{
+ struct inode *inode = data->header->inode;
+ struct rpc_task *task;
+ struct rpc_message msg = {
+ .rpc_argp = &data->args,
+ .rpc_resp = &data->res,
+ .rpc_cred = data->header->cred,
+ };
+ struct rpc_task_setup task_setup_data = {
+ .rpc_client = clnt,
+ .task = &data->task,
+ .rpc_message = &msg,
+ .callback_ops = call_ops,
+ .callback_data = data,
+ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC | flags,
+ };
+ int ret = 0;
+
+ data->header->rw_ops->rw_initiate(data, &msg, &task_setup_data, how);
+
+ dprintk("NFS: %5u initiated pgio call "
+ "(req %s/%llu, %u bytes @ offset %llu)\n",
+ data->task.tk_pid,
+ inode->i_sb->s_id,
+ (unsigned long long)NFS_FILEID(inode),
+ data->args.count,
+ (unsigned long long)data->args.offset);
+
+ task = rpc_run_task(&task_setup_data);
+ if (IS_ERR(task)) {
+ ret = PTR_ERR(task);
+ goto out;
+ }
+ if (how & FLUSH_SYNC) {
+ ret = rpc_wait_for_completion_task(task);
+ if (ret == 0)
+ ret = task->tk_status;
+ }
+ rpc_put_task(task);
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nfs_initiate_pgio);
+
static int nfs_pgio_error(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr)
{
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 07c21bd..ebea335 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -151,53 +151,22 @@ out:
hdr->release(hdr);
}

-int nfs_initiate_read(struct rpc_clnt *clnt,
- struct nfs_pgio_data *data,
- const struct rpc_call_ops *call_ops, int flags)
+static void nfs_initiate_read(struct nfs_pgio_data *data, struct rpc_message *msg,
+ struct rpc_task_setup *task_setup_data, int how)
{
struct inode *inode = data->header->inode;
int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0;
- struct rpc_task *task;
- struct rpc_message msg = {
- .rpc_argp = &data->args,
- .rpc_resp = &data->res,
- .rpc_cred = data->header->cred,
- };
- struct rpc_task_setup task_setup_data = {
- .task = &data->task,
- .rpc_client = clnt,
- .rpc_message = &msg,
- .callback_ops = call_ops,
- .callback_data = data,
- .workqueue = nfsiod_workqueue,
- .flags = RPC_TASK_ASYNC | swap_flags | flags,
- };

- /* Set up the initial task struct. */
- NFS_PROTO(inode)->read_setup(data, &msg);
-
- dprintk("NFS: %5u initiated read call (req %s/%llu, %u bytes @ "
- "offset %llu)\n",
- data->task.tk_pid,
- inode->i_sb->s_id,
- (unsigned long long)NFS_FILEID(inode),
- data->args.count,
- (unsigned long long)data->args.offset);
-
- task = rpc_run_task(&task_setup_data);
- if (IS_ERR(task))
- return PTR_ERR(task);
- rpc_put_task(task);
- return 0;
+ task_setup_data->flags |= swap_flags;
+ NFS_PROTO(inode)->read_setup(data, msg);
}
-EXPORT_SYMBOL_GPL(nfs_initiate_read);

static int nfs_do_read(struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops)
{
struct inode *inode = data->header->inode;

- return nfs_initiate_read(NFS_CLIENT(inode), data, call_ops, 0);
+ return nfs_initiate_pgio(NFS_CLIENT(inode), data, call_ops, 0, 0);
}

static int
@@ -491,4 +460,5 @@ static const struct nfs_rw_ops nfs_rw_read_ops = {
.rw_free_header = nfs_readhdr_free,
.rw_result = nfs_readpage_result,
.rw_result_common = nfs_readpage_result_common,
+ .rw_initiate = nfs_initiate_read,
};
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 8929e33..4279f80 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -932,60 +932,18 @@ static int flush_task_priority(int how)
return RPC_PRIORITY_NORMAL;
}

-int nfs_initiate_write(struct rpc_clnt *clnt,
- struct nfs_pgio_data *data,
- const struct rpc_call_ops *call_ops,
- int how, int flags)
+static void nfs_initiate_write(struct nfs_pgio_data *data, struct rpc_message *msg,
+ struct rpc_task_setup *task_setup_data, int how)
{
struct inode *inode = data->header->inode;
int priority = flush_task_priority(how);
- struct rpc_task *task;
- struct rpc_message msg = {
- .rpc_argp = &data->args,
- .rpc_resp = &data->res,
- .rpc_cred = data->header->cred,
- };
- struct rpc_task_setup task_setup_data = {
- .rpc_client = clnt,
- .task = &data->task,
- .rpc_message = &msg,
- .callback_ops = call_ops,
- .callback_data = data,
- .workqueue = nfsiod_workqueue,
- .flags = RPC_TASK_ASYNC | flags,
- .priority = priority,
- };
- int ret = 0;

- /* Set up the initial task struct. */
- NFS_PROTO(inode)->write_setup(data, &msg);
-
- dprintk("NFS: %5u initiated write call "
- "(req %s/%llu, %u bytes @ offset %llu)\n",
- data->task.tk_pid,
- inode->i_sb->s_id,
- (unsigned long long)NFS_FILEID(inode),
- data->args.count,
- (unsigned long long)data->args.offset);
+ task_setup_data->priority = priority;
+ NFS_PROTO(inode)->write_setup(data, msg);

nfs4_state_protect_write(NFS_SERVER(inode)->nfs_client,
- &task_setup_data.rpc_client, &msg, data);
-
- task = rpc_run_task(&task_setup_data);
- if (IS_ERR(task)) {
- ret = PTR_ERR(task);
- goto out;
- }
- if (how & FLUSH_SYNC) {
- ret = rpc_wait_for_completion_task(task);
- if (ret == 0)
- ret = task->tk_status;
- }
- rpc_put_task(task);
-out:
- return ret;
+ &task_setup_data->rpc_client, msg, data);
}
-EXPORT_SYMBOL_GPL(nfs_initiate_write);

static int nfs_do_write(struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops,
@@ -993,7 +951,7 @@ static int nfs_do_write(struct nfs_pgio_data *data,
{
struct inode *inode = data->header->inode;

- return nfs_initiate_write(NFS_CLIENT(inode), data, call_ops, how, 0);
+ return nfs_initiate_pgio(NFS_CLIENT(inode), data, call_ops, how, 0);
}

static int nfs_do_multiple_writes(struct list_head *head,
@@ -1743,4 +1701,5 @@ static const struct nfs_rw_ops nfs_rw_write_ops = {
.rw_release = nfs_writeback_release_common,
.rw_result = nfs_writeback_result,
.rw_result_common = nfs_writeback_result_common,
+ .rw_initiate = nfs_initiate_write,
};
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 9477d7a..dc5e71c 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -59,6 +59,8 @@ struct nfs_rw_ops {
void (*rw_release)(struct nfs_pgio_data *);
int (*rw_result)(struct rpc_task *, struct nfs_pgio_data *, struct inode *);
void (*rw_result_common)(struct rpc_task *, struct nfs_pgio_data *);
+ void (*rw_initiate)(struct nfs_pgio_data *, struct rpc_message *,
+ struct rpc_task_setup *, int);
};

struct nfs_pageio_descriptor {
--
1.9.2


2014-04-23 13:15:13

by Boaz Harrosh

[permalink] [raw]
Subject: Re: [PATCH 00/17] NFS: Create a common path used by reads and writes

On 04/23/2014 03:55 PM, Boaz Harrosh wrote:
> On 04/18/2014 12:09 AM, Anna Schumaker wrote:
<>
> yes please keep
> it on a public tree for quick testing. Perhaps ask Trond to keep
> it on his tree in a branch. (So to get some coverage under the linux-next
> tree mongers from Intel)
>

BTW: anyone tested how much this conflicts with dros's 17 patches?
(Noticed how it is always 17 patches)
If a brave sole can have both these merged on the same tree it
would be easier for the testing.

Thanks
Boaz


2014-04-17 21:10:03

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 06/17] NFS: Create a common pgio_alloc and pgio_release function

From: Anna Schumaker <[email protected]>

These functions are identical for the read and write paths, so combine
them in a shared file.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/internal.h | 7 +++++--
fs/nfs/pageio.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/pnfs.c | 4 ++--
fs/nfs/read.c | 54 ++++-------------------------------------------
fs/nfs/write.c | 54 ++++-------------------------------------------
6 files changed, 79 insertions(+), 105 deletions(-)
create mode 100644 fs/nfs/pageio.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 03192a6..551d82a 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_NFS_FS) += nfs.o
CFLAGS_nfstrace.o += -I$(src)
nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
direct.o pagelist.o read.o symlink.o unlink.o \
- write.o namespace.o mount_clnt.o nfstrace.o
+ write.o namespace.o mount_clnt.o nfstrace.o pageio.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b0e7a41..7f9d3c4 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -394,6 +394,11 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool
#endif

struct nfs_pgio_completion_ops;
+
+/* pageio.c */
+extern struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
+extern void nfs_pgio_data_release(struct nfs_pgio_data *);
+
/* read.c */
extern struct nfs_rw_header *nfs_readhdr_alloc(void);
extern void nfs_readhdr_free(struct nfs_pgio_header *hdr);
@@ -407,7 +412,6 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr);
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
-extern void nfs_readdata_release(struct nfs_pgio_data *rdata);

/* super.c */
void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
@@ -429,7 +433,6 @@ extern void nfs_writehdr_free(struct nfs_pgio_header *hdr);
extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr);
extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
-extern void nfs_writedata_release(struct nfs_pgio_data *wdata);
extern void nfs_commit_free(struct nfs_commit_data *p);
extern int nfs_initiate_write(struct rpc_clnt *clnt,
struct nfs_pgio_data *data,
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
new file mode 100644
index 0000000..4b267b2
--- /dev/null
+++ b/fs/nfs/pageio.c
@@ -0,0 +1,63 @@
+/*
+ * linux/fs/nfs/pageio.c
+ *
+ * Generic pageio functions shared by read and write paths
+ *
+ * Copyright (c) 2014 Anna Schumaker <[email protected]>
+ */
+#include <linux/nfs_fs.h>
+#include <linux/nfs_xdr.h>
+
+#include "internal.h"
+
+
+static inline struct nfs_rw_header *NFS_RW_HEADER(struct nfs_pgio_header *hdr)
+{
+ return container_of(hdr, struct nfs_rw_header, header);
+}
+
+struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *hdr,
+ unsigned int pagecount)
+{
+ struct nfs_pgio_data *data, *prealloc;
+
+ prealloc = &NFS_RW_HEADER(hdr)->rpc_data;
+ if (prealloc->header == NULL)
+ data = prealloc;
+ else
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ goto out;
+
+ if (nfs_pgarray_set(&data->pages, pagecount)) {
+ data->header = hdr;
+ atomic_inc(&hdr->refcnt);
+ } else {
+ if (data != prealloc)
+ kfree(data);
+ data = NULL;
+ }
+out:
+ return data;
+}
+
+void nfs_pgio_data_release(struct nfs_pgio_data *data)
+{
+ struct nfs_pgio_header *hdr = data->header;
+ struct nfs_rw_header *pageio_header = NFS_RW_HEADER(hdr);
+
+ put_nfs_open_context(data->args.context);
+ if (data->pages.pagevec != data->pages.page_array)
+ kfree(data->pages.pagevec);
+ if (data == &pageio_header->rpc_data) {
+ data->header = NULL;
+ data = NULL;
+ }
+ if (atomic_dec_and_test(&hdr->refcnt))
+ hdr->completion_ops->completion(hdr);
+ /* Note: we only free the rpc_task after callbacks are done.
+ * See the comment in rpc_free_task() for why
+ */
+ kfree(data);
+}
+EXPORT_SYMBOL_GPL(nfs_pgio_data_release);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 43cfe11..e192ba6 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1536,7 +1536,7 @@ pnfs_write_through_mds(struct nfs_pageio_descriptor *desc,
nfs_pageio_reset_write_mds(desc);
desc->pg_recoalesce = 1;
}
- nfs_writedata_release(data);
+ nfs_pgio_data_release(data);
}

static enum pnfs_try_status
@@ -1691,7 +1691,7 @@ pnfs_read_through_mds(struct nfs_pageio_descriptor *desc,
nfs_pageio_reset_read_mds(desc);
desc->pg_recoalesce = 1;
}
- nfs_readdata_release(data);
+ nfs_pgio_data_release(data);
}

/*
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index d29ca36..ab4c1a5 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -51,31 +51,6 @@ struct nfs_rw_header *nfs_readhdr_alloc(void)
}
EXPORT_SYMBOL_GPL(nfs_readhdr_alloc);

-static struct nfs_pgio_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr,
- unsigned int pagecount)
-{
- struct nfs_pgio_data *data, *prealloc;
-
- prealloc = &container_of(hdr, struct nfs_rw_header, header)->rpc_data;
- if (prealloc->header == NULL)
- data = prealloc;
- else
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data)
- goto out;
-
- if (nfs_pgarray_set(&data->pages, pagecount)) {
- data->header = hdr;
- atomic_inc(&hdr->refcnt);
- } else {
- if (data != prealloc)
- kfree(data);
- data = NULL;
- }
-out:
- return data;
-}
-
void nfs_readhdr_free(struct nfs_pgio_header *hdr)
{
struct nfs_rw_header *rhdr = container_of(hdr, struct nfs_rw_header, header);
@@ -84,27 +59,6 @@ void nfs_readhdr_free(struct nfs_pgio_header *hdr)
}
EXPORT_SYMBOL_GPL(nfs_readhdr_free);

-void nfs_readdata_release(struct nfs_pgio_data *rdata)
-{
- struct nfs_pgio_header *hdr = rdata->header;
- struct nfs_rw_header *read_header = container_of(hdr, struct nfs_rw_header, header);
-
- put_nfs_open_context(rdata->args.context);
- if (rdata->pages.pagevec != rdata->pages.page_array)
- kfree(rdata->pages.pagevec);
- if (rdata == &read_header->rpc_data) {
- rdata->header = NULL;
- rdata = NULL;
- }
- if (atomic_dec_and_test(&hdr->refcnt))
- hdr->completion_ops->completion(hdr);
- /* Note: we only free the rpc_task after callbacks are done.
- * See the comment in rpc_free_task() for why
- */
- kfree(rdata);
-}
-EXPORT_SYMBOL_GPL(nfs_readdata_release);
-
static
int nfs_return_empty_page(struct page *page)
{
@@ -327,7 +281,7 @@ static void nfs_pagein_error(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_data *data = list_first_entry(&hdr->rpc_list,
struct nfs_pgio_data, list);
list_del(&data->list);
- nfs_readdata_release(data);
+ nfs_pgio_data_release(data);
}
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
}
@@ -359,7 +313,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc,
do {
size_t len = min(nbytes,rsize);

- data = nfs_readdata_alloc(hdr, 1);
+ data = nfs_pgio_data_alloc(hdr, 1);
if (!data) {
nfs_pagein_error(desc, hdr);
return -ENOMEM;
@@ -385,7 +339,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_data *data;
struct list_head *head = &desc->pg_list;

- data = nfs_readdata_alloc(hdr, nfs_page_array_len(desc->pg_base,
+ data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base,
desc->pg_count));
if (!data) {
nfs_pagein_error(desc, hdr);
@@ -515,7 +469,7 @@ static void nfs_readpage_result_common(struct rpc_task *task, void *calldata)

static void nfs_readpage_release_common(void *calldata)
{
- nfs_readdata_release(calldata);
+ nfs_pgio_data_release(calldata);
}

void nfs_read_prepare(struct rpc_task *task, void *calldata)
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 321a791..0dc4d6a 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -87,31 +87,6 @@ struct nfs_rw_header *nfs_writehdr_alloc(void)
}
EXPORT_SYMBOL_GPL(nfs_writehdr_alloc);

-static struct nfs_pgio_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr,
- unsigned int pagecount)
-{
- struct nfs_pgio_data *data, *prealloc;
-
- prealloc = &container_of(hdr, struct nfs_rw_header, header)->rpc_data;
- if (prealloc->header == NULL)
- data = prealloc;
- else
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data)
- goto out;
-
- if (nfs_pgarray_set(&data->pages, pagecount)) {
- data->header = hdr;
- atomic_inc(&hdr->refcnt);
- } else {
- if (data != prealloc)
- kfree(data);
- data = NULL;
- }
-out:
- return data;
-}
-
void nfs_writehdr_free(struct nfs_pgio_header *hdr)
{
struct nfs_rw_header *whdr = container_of(hdr, struct nfs_rw_header, header);
@@ -119,27 +94,6 @@ void nfs_writehdr_free(struct nfs_pgio_header *hdr)
}
EXPORT_SYMBOL_GPL(nfs_writehdr_free);

-void nfs_writedata_release(struct nfs_pgio_data *wdata)
-{
- struct nfs_pgio_header *hdr = wdata->header;
- struct nfs_rw_header *write_header = container_of(hdr, struct nfs_rw_header, header);
-
- put_nfs_open_context(wdata->args.context);
- if (wdata->pages.pagevec != wdata->pages.page_array)
- kfree(wdata->pages.pagevec);
- if (wdata == &write_header->rpc_data) {
- wdata->header = NULL;
- wdata = NULL;
- }
- if (atomic_dec_and_test(&hdr->refcnt))
- hdr->completion_ops->completion(hdr);
- /* Note: we only free the rpc_task after callbacks are done.
- * See the comment in rpc_free_task() for why
- */
- kfree(wdata);
-}
-EXPORT_SYMBOL_GPL(nfs_writedata_release);
-
static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
{
ctx->error = error;
@@ -1146,7 +1100,7 @@ static void nfs_flush_error(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_data *data = list_first_entry(&hdr->rpc_list,
struct nfs_pgio_data, list);
list_del(&data->list);
- nfs_writedata_release(data);
+ nfs_pgio_data_release(data);
}
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
}
@@ -1179,7 +1133,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc,
do {
size_t len = min(nbytes, wsize);

- data = nfs_writedata_alloc(hdr, 1);
+ data = nfs_pgio_data_alloc(hdr, 1);
if (!data) {
nfs_flush_error(desc, hdr);
return -ENOMEM;
@@ -1214,7 +1168,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
struct list_head *head = &desc->pg_list;
struct nfs_commit_info cinfo;

- data = nfs_writedata_alloc(hdr, nfs_page_array_len(desc->pg_base,
+ data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base,
desc->pg_count));
if (!data) {
nfs_flush_error(desc, hdr);
@@ -1348,7 +1302,7 @@ static void nfs_writeback_release_common(void *calldata)
set_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags);
spin_unlock(&hdr->lock);
}
- nfs_writedata_release(data);
+ nfs_pgio_data_release(data);
}

static const struct rpc_call_ops nfs_write_common_ops = {
--
1.9.2


2014-04-18 14:00:41

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 03/17] NFS: Create a common read and write data struct

On Thu, Apr 17, 2014 at 05:09:27PM -0400, Anna Schumaker wrote:
> From: Anna Schumaker <[email protected]>
>
> At this point, the only difference between nfs_read_data and
> nfs_write_data is the write verifier.

Looks good,

Reviewed-by: Christoph Hellwig <[email protected]>

2014-04-17 21:10:01

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 05/17] NFS: Move the write verifier into the nfs_pgio_header

From: Anna Schumaker <[email protected]>

The header had a pointer to the verifier that was set from the old write
data struct. We don't need to keep the pointer around now that we have
shared structures.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/direct.c | 4 ++--
fs/nfs/write.c | 7 +++----
include/linux/nfs_xdr.h | 3 +--
3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index bbe688e..164b016 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -813,12 +813,12 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES)
bit = NFS_IOHDR_NEED_RESCHED;
else if (dreq->flags == 0) {
- memcpy(&dreq->verf, hdr->verf,
+ memcpy(&dreq->verf, &hdr->verf,
sizeof(dreq->verf));
bit = NFS_IOHDR_NEED_COMMIT;
dreq->flags = NFS_ODIRECT_DO_COMMIT;
} else if (dreq->flags == NFS_ODIRECT_DO_COMMIT) {
- if (memcmp(&dreq->verf, hdr->verf, sizeof(dreq->verf))) {
+ if (memcmp(&dreq->verf, &hdr->verf, sizeof(dreq->verf))) {
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
bit = NFS_IOHDR_NEED_RESCHED;
} else
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 37c4c98..321a791 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -82,7 +82,6 @@ struct nfs_rw_header *nfs_writehdr_alloc(void)
INIT_LIST_HEAD(&hdr->rpc_list);
spin_lock_init(&hdr->lock);
atomic_set(&hdr->refcnt, 0);
- hdr->verf = &p->verf;
}
return p;
}
@@ -644,7 +643,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
goto next;
}
if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) {
- memcpy(&req->wb_verf, &hdr->verf->verifier, sizeof(req->wb_verf));
+ memcpy(&req->wb_verf, &hdr->verf.verifier, sizeof(req->wb_verf));
nfs_mark_request_commit(req, hdr->lseg, &cinfo);
goto next;
}
@@ -1344,8 +1343,8 @@ static void nfs_writeback_release_common(void *calldata)
if (test_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags))
; /* Do nothing */
else if (!test_and_set_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags))
- memcpy(hdr->verf, &data->verf, sizeof(*hdr->verf));
- else if (memcmp(hdr->verf, &data->verf, sizeof(*hdr->verf)))
+ memcpy(&hdr->verf, &data->verf, sizeof(hdr->verf));
+ else if (memcmp(&hdr->verf, &data->verf, sizeof(hdr->verf)))
set_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags);
spin_unlock(&hdr->lock);
}
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index ff09384..4bbd6ad 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1262,7 +1262,7 @@ struct nfs_pgio_header {
struct list_head rpc_list;
atomic_t refcnt;
struct nfs_page *req;
- struct nfs_writeverf *verf;
+ struct nfs_writeverf verf; /* Used for writes */
struct pnfs_layout_segment *lseg;
loff_t io_start;
const struct rpc_call_ops *mds_ops;
@@ -1296,7 +1296,6 @@ struct nfs_pgio_data {
struct nfs_rw_header {
struct nfs_pgio_header header;
struct nfs_pgio_data rpc_data;
- struct nfs_writeverf verf;
};

struct nfs_mds_commit_info {
--
1.9.2


2014-04-18 14:02:20

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 05/17] NFS: Move the write verifier into the nfs_pgio_header

On Thu, Apr 17, 2014 at 05:09:29PM -0400, Anna Schumaker wrote:
> From: Anna Schumaker <[email protected]>
>
> The header had a pointer to the verifier that was set from the old write
> data struct. We don't need to keep the pointer around now that we have
> shared structures.

Looks good,

Reviewed-by: Christoph Hellwig <[email protected]>


2014-04-21 13:52:54

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH 07/17] NFS: Create a common rw_header_alloc and rw_header_free function

On 04/21/2014 09:32 AM, Christoph Hellwig wrote:
> On Thu, Apr 17, 2014 at 05:09:31PM -0400, Anna Schumaker wrote:
>> From: Anna Schumaker <[email protected]>
>>
>> I create a new struct nfs_rw_ops to decide the differences between reads
>> and writes. This struct will be set when initializing a new
>> nfs_pgio_descriptor, and then passed on to the nfs_rw_header when a new
>> header is allocated.
> To me it seems like adding this new vector confuses things. From a look
> at your whole tree it seems like all methods added to it could as well
> be added to nfs_pageio_ops. In that case we'd still keep separate
> instances of nfs_pageio_ops for reads and writes, but most methods would
> be that same. I'm also defintively curious what you have on your
> sleeves for pnfs.
Okay. I'll rework everything into the pageio_ops and see how it looks! Maybe I'll see what I can do about updating the pnfs patches while I'm at it.

Thanks for reviewing all of these!

Anna

> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html


2014-04-21 13:32:53

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 07/17] NFS: Create a common rw_header_alloc and rw_header_free function

On Thu, Apr 17, 2014 at 05:09:31PM -0400, Anna Schumaker wrote:
> From: Anna Schumaker <[email protected]>
>
> I create a new struct nfs_rw_ops to decide the differences between reads
> and writes. This struct will be set when initializing a new
> nfs_pgio_descriptor, and then passed on to the nfs_rw_header when a new
> header is allocated.

To me it seems like adding this new vector confuses things. From a look
at your whole tree it seems like all methods added to it could as well
be added to nfs_pageio_ops. In that case we'd still keep separate
instances of nfs_pageio_ops for reads and writes, but most methods would
be that same. I'm also defintively curious what you have on your
sleeves for pnfs.

2014-04-23 12:55:17

by Boaz Harrosh

[permalink] [raw]
Subject: Re: [PATCH 00/17] NFS: Create a common path used by reads and writes

On 04/18/2014 12:09 AM, Anna Schumaker wrote:
> I noticed that much of the read and write code was almost identical, with
> only minor differences in argument types and names. These patches seek to
> unify these two codepaths wherever possible in order to make future changes
> easier.
>
> Table of contents:
> Patches 01 - 05: Set up common data structures.
> Patches 06 - 10: Set up a shared rpc_call_ops struct.
> Patches 11 - 15: Set up a shared nfs_pageio_ops struct.
>
> Some of the commit setup was moved into common code, but I'm willing to
> move this back into write.c if this looks to be a problem.
>
> Future work:
> I have rough pNFS patches that don't currently apply. They need
> more testing, and I figured this was enough code churn already.
>
> Testing:
> I tested every version of NFS using the cthon and xfs tests without
> hitting anything new. Any extra testing would be great seeing how
> the read and write paths are vitally important.
>
> Questions? Comments? Death threats?
>
> Anna

Good god. Anna did I already tell you that I like you a lot.

This "Identical code but the name" bothered me so much, to no end,
for so long. I envy you that you got to do it finally and so simple
it is.

After you are done there is bunch of code coalescing to do at
pnfs-objects as well. which will be real fun.

Thanks for doing this. Looks very good so far, yes please keep
it on a public tree for quick testing. Perhaps ask Trond to keep
it on his tree in a branch. (So to get some coverage under the linux-next
tree mongers from Intel)

real real cool, spring day
Boaz


2014-04-18 13:57:26

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 02/17] NFS: Create a common results structure for reads and writes

> +struct nfs_pgio_res {
> + struct nfs4_sequence_res seq_res;
> + struct nfs_fattr * fattr;
> + struct nfs_writeverf * verf; /* used by write */
> + const struct nfs_server *server; /* used by write */
> + __u32 count;
> + int eof; /* used by read */

Same comment as for the previous patch applies here. Also maybe
this should use a union to overlay the read/write only fields?


2014-04-25 12:12:05

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 07/17] NFS: Create a common rw_header_alloc and rw_header_free function

On Mon, Apr 21, 2014 at 12:24:23PM -0400, Anna Schumaker wrote:
> > Okay. I'll rework everything into the pageio_ops and see how it looks! Maybe I'll see what I can do about updating the pnfs patches while I'm at it.
> I remember my issue with adding to the nfs_pageio_ops now. The file, object and block layouts along with the generic pnfs code all have their own read and write pageio_ops. Changing all of these seemed more tedious than adding a new struct only in the read and write code.

Indeed, there's more instances in the pnfs code. I was hoping your
pending pnfs patches were addressing that, and the general code
duplication between the pnfs and "classic" I/O code.

I guess it's best to put in your patches as-is for now, and maybe in the
future we can get rid of the pageio_ops once more code is shared with
the pnfs path.

2014-04-17 21:10:01

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 03/17] NFS: Create a common read and write data struct

From: Anna Schumaker <[email protected]>

At this point, the only difference between nfs_read_data and
nfs_write_data is the write verifier.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/blocklayout/blocklayout.c | 22 ++++++++++----------
fs/nfs/internal.h | 10 ++++-----
fs/nfs/nfs3proc.c | 12 +++++------
fs/nfs/nfs4_fs.h | 4 ++--
fs/nfs/nfs4filelayout.c | 34 +++++++++++++++----------------
fs/nfs/nfs4proc.c | 30 +++++++++++++--------------
fs/nfs/nfs4trace.h | 8 ++++----
fs/nfs/objlayout/objio_osd.c | 6 +++---
fs/nfs/objlayout/objlayout.c | 16 +++++++--------
fs/nfs/objlayout/objlayout.h | 8 ++++----
fs/nfs/pnfs.c | 26 ++++++++++++------------
fs/nfs/pnfs.h | 10 ++++-----
fs/nfs/proc.c | 12 +++++------
fs/nfs/read.c | 32 ++++++++++++++---------------
fs/nfs/write.c | 36 ++++++++++++++++----------------
include/linux/nfs_fs.h | 4 ++--
include/linux/nfs_xdr.h | 44 ++++++++++++++--------------------------
17 files changed, 150 insertions(+), 164 deletions(-)

diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index 65d849b..206cc68 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -210,7 +210,7 @@ static void bl_end_io_read(struct bio *bio, int err)
SetPageUptodate(bvec->bv_page);

if (err) {
- struct nfs_read_data *rdata = par->data;
+ struct nfs_pgio_data *rdata = par->data;
struct nfs_pgio_header *header = rdata->header;

if (!header->pnfs_error)
@@ -224,17 +224,17 @@ static void bl_end_io_read(struct bio *bio, int err)
static void bl_read_cleanup(struct work_struct *work)
{
struct rpc_task *task;
- struct nfs_read_data *rdata;
+ struct nfs_pgio_data *rdata;
dprintk("%s enter\n", __func__);
task = container_of(work, struct rpc_task, u.tk_work);
- rdata = container_of(task, struct nfs_read_data, task);
+ rdata = container_of(task, struct nfs_pgio_data, task);
pnfs_ld_read_done(rdata);
}

static void
bl_end_par_io_read(void *data, int unused)
{
- struct nfs_read_data *rdata = data;
+ struct nfs_pgio_data *rdata = data;

rdata->task.tk_status = rdata->header->pnfs_error;
INIT_WORK(&rdata->task.u.tk_work, bl_read_cleanup);
@@ -242,7 +242,7 @@ bl_end_par_io_read(void *data, int unused)
}

static enum pnfs_try_status
-bl_read_pagelist(struct nfs_read_data *rdata)
+bl_read_pagelist(struct nfs_pgio_data *rdata)
{
struct nfs_pgio_header *header = rdata->header;
int i, hole;
@@ -390,7 +390,7 @@ static void bl_end_io_write_zero(struct bio *bio, int err)
}

if (unlikely(err)) {
- struct nfs_write_data *data = par->data;
+ struct nfs_pgio_data *data = par->data;
struct nfs_pgio_header *header = data->header;

if (!header->pnfs_error)
@@ -405,7 +405,7 @@ static void bl_end_io_write(struct bio *bio, int err)
{
struct parallel_io *par = bio->bi_private;
const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
- struct nfs_write_data *data = par->data;
+ struct nfs_pgio_data *data = par->data;
struct nfs_pgio_header *header = data->header;

if (!uptodate) {
@@ -423,10 +423,10 @@ static void bl_end_io_write(struct bio *bio, int err)
static void bl_write_cleanup(struct work_struct *work)
{
struct rpc_task *task;
- struct nfs_write_data *wdata;
+ struct nfs_pgio_data *wdata;
dprintk("%s enter\n", __func__);
task = container_of(work, struct rpc_task, u.tk_work);
- wdata = container_of(task, struct nfs_write_data, task);
+ wdata = container_of(task, struct nfs_pgio_data, task);
if (likely(!wdata->header->pnfs_error)) {
/* Marks for LAYOUTCOMMIT */
mark_extents_written(BLK_LSEG2EXT(wdata->header->lseg),
@@ -438,7 +438,7 @@ static void bl_write_cleanup(struct work_struct *work)
/* Called when last of bios associated with a bl_write_pagelist call finishes */
static void bl_end_par_io_write(void *data, int num_se)
{
- struct nfs_write_data *wdata = data;
+ struct nfs_pgio_data *wdata = data;

if (unlikely(wdata->header->pnfs_error)) {
bl_free_short_extents(&BLK_LSEG2EXT(wdata->header->lseg)->bl_inval,
@@ -673,7 +673,7 @@ check_page:
}

static enum pnfs_try_status
-bl_write_pagelist(struct nfs_write_data *wdata, int sync)
+bl_write_pagelist(struct nfs_pgio_data *wdata, int sync)
{
struct nfs_pgio_header *header = wdata->header;
int i, ret, npg_zero, pg_index, last = 0;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 98fe618..af01b80 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -401,13 +401,13 @@ extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
struct inode *inode, bool force_mds,
const struct nfs_pgio_completion_ops *compl_ops);
extern int nfs_initiate_read(struct rpc_clnt *clnt,
- struct nfs_read_data *data,
+ struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops, int flags);
extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr);
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
-extern void nfs_readdata_release(struct nfs_read_data *rdata);
+extern void nfs_readdata_release(struct nfs_pgio_data *rdata);

/* super.c */
void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
@@ -429,10 +429,10 @@ extern void nfs_writehdr_free(struct nfs_pgio_header *hdr);
extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr);
extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
-extern void nfs_writedata_release(struct nfs_write_data *wdata);
+extern void nfs_writedata_release(struct nfs_pgio_data *wdata);
extern void nfs_commit_free(struct nfs_commit_data *p);
extern int nfs_initiate_write(struct rpc_clnt *clnt,
- struct nfs_write_data *data,
+ struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops,
int how, int flags);
extern void nfs_write_prepare(struct rpc_task *task, void *calldata);
@@ -492,7 +492,7 @@ static inline void nfs_inode_dio_wait(struct inode *inode)
extern ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq);

/* nfs4proc.c */
-extern void __nfs4_read_done_cb(struct nfs_read_data *);
+extern void __nfs4_read_done_cb(struct nfs_pgio_data *);
extern struct nfs_client *nfs4_init_client(struct nfs_client *clp,
const struct rpc_timeout *timeparms,
const char *ip_addr);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index d873241..d235369 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -795,7 +795,7 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
return status;
}

-static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
+static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_data *data)
{
struct inode *inode = data->header->inode;

@@ -807,18 +807,18 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
return 0;
}

-static void nfs3_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
+static void nfs3_proc_read_setup(struct nfs_pgio_data *data, struct rpc_message *msg)
{
msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ];
}

-static int nfs3_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data)
+static int nfs3_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
{
rpc_call_start(task);
return 0;
}

-static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
+static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_data *data)
{
struct inode *inode = data->header->inode;

@@ -829,12 +829,12 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
return 0;
}

-static void nfs3_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg)
+static void nfs3_proc_write_setup(struct nfs_pgio_data *data, struct rpc_message *msg)
{
msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE];
}

-static int nfs3_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data)
+static int nfs3_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
{
rpc_call_start(task);
return 0;
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index e1d1bad..f63cb87 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -337,7 +337,7 @@ nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode,
*/
static inline void
nfs4_state_protect_write(struct nfs_client *clp, struct rpc_clnt **clntp,
- struct rpc_message *msg, struct nfs_write_data *wdata)
+ struct rpc_message *msg, struct nfs_pgio_data *wdata)
{
if (_nfs4_state_protect(clp, NFS_SP4_MACH_CRED_WRITE, clntp, msg) &&
!test_bit(NFS_SP4_MACH_CRED_COMMIT, &clp->cl_sp4_flags))
@@ -369,7 +369,7 @@ nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_flags,

static inline void
nfs4_state_protect_write(struct nfs_client *clp, struct rpc_clnt **clntp,
- struct rpc_message *msg, struct nfs_write_data *wdata)
+ struct rpc_message *msg, struct nfs_pgio_data *wdata)
{
}
#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index b9a35c0..e693614 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -84,7 +84,7 @@ filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset)
BUG();
}

-static void filelayout_reset_write(struct nfs_write_data *data)
+static void filelayout_reset_write(struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;
struct rpc_task *task = &data->task;
@@ -105,7 +105,7 @@ static void filelayout_reset_write(struct nfs_write_data *data)
}
}

-static void filelayout_reset_read(struct nfs_read_data *data)
+static void filelayout_reset_read(struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;
struct rpc_task *task = &data->task;
@@ -243,7 +243,7 @@ wait_on_recovery:
/* NFS_PROTO call done callback routines */

static int filelayout_read_done_cb(struct rpc_task *task,
- struct nfs_read_data *data)
+ struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;
int err;
@@ -270,7 +270,7 @@ static int filelayout_read_done_cb(struct rpc_task *task,
* rfc5661 is not clear about which credential should be used.
*/
static void
-filelayout_set_layoutcommit(struct nfs_write_data *wdata)
+filelayout_set_layoutcommit(struct nfs_pgio_data *wdata)
{
struct nfs_pgio_header *hdr = wdata->header;

@@ -305,7 +305,7 @@ filelayout_reset_to_mds(struct pnfs_layout_segment *lseg)
*/
static void filelayout_read_prepare(struct rpc_task *task, void *data)
{
- struct nfs_read_data *rdata = data;
+ struct nfs_pgio_data *rdata = data;

if (unlikely(test_bit(NFS_CONTEXT_BAD, &rdata->args.context->flags))) {
rpc_exit(task, -EIO);
@@ -317,7 +317,7 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
rpc_exit(task, 0);
return;
}
- rdata->read_done_cb = filelayout_read_done_cb;
+ rdata->pgio_done_cb = filelayout_read_done_cb;

if (nfs41_setup_sequence(rdata->ds_clp->cl_session,
&rdata->args.seq_args,
@@ -331,7 +331,7 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)

static void filelayout_read_call_done(struct rpc_task *task, void *data)
{
- struct nfs_read_data *rdata = data;
+ struct nfs_pgio_data *rdata = data;

dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status);

@@ -347,14 +347,14 @@ static void filelayout_read_call_done(struct rpc_task *task, void *data)

static void filelayout_read_count_stats(struct rpc_task *task, void *data)
{
- struct nfs_read_data *rdata = data;
+ struct nfs_pgio_data *rdata = data;

rpc_count_iostats(task, NFS_SERVER(rdata->header->inode)->client->cl_metrics);
}

static void filelayout_read_release(void *data)
{
- struct nfs_read_data *rdata = data;
+ struct nfs_pgio_data *rdata = data;
struct pnfs_layout_hdr *lo = rdata->header->lseg->pls_layout;

filelayout_fenceme(lo->plh_inode, lo);
@@ -363,7 +363,7 @@ static void filelayout_read_release(void *data)
}

static int filelayout_write_done_cb(struct rpc_task *task,
- struct nfs_write_data *data)
+ struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;
int err;
@@ -419,7 +419,7 @@ static int filelayout_commit_done_cb(struct rpc_task *task,

static void filelayout_write_prepare(struct rpc_task *task, void *data)
{
- struct nfs_write_data *wdata = data;
+ struct nfs_pgio_data *wdata = data;

if (unlikely(test_bit(NFS_CONTEXT_BAD, &wdata->args.context->flags))) {
rpc_exit(task, -EIO);
@@ -443,7 +443,7 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data)

static void filelayout_write_call_done(struct rpc_task *task, void *data)
{
- struct nfs_write_data *wdata = data;
+ struct nfs_pgio_data *wdata = data;

if (test_bit(NFS_IOHDR_REDO, &wdata->header->flags) &&
task->tk_status == 0) {
@@ -457,14 +457,14 @@ static void filelayout_write_call_done(struct rpc_task *task, void *data)

static void filelayout_write_count_stats(struct rpc_task *task, void *data)
{
- struct nfs_write_data *wdata = data;
+ struct nfs_pgio_data *wdata = data;

rpc_count_iostats(task, NFS_SERVER(wdata->header->inode)->client->cl_metrics);
}

static void filelayout_write_release(void *data)
{
- struct nfs_write_data *wdata = data;
+ struct nfs_pgio_data *wdata = data;
struct pnfs_layout_hdr *lo = wdata->header->lseg->pls_layout;

filelayout_fenceme(lo->plh_inode, lo);
@@ -529,7 +529,7 @@ static const struct rpc_call_ops filelayout_commit_call_ops = {
};

static enum pnfs_try_status
-filelayout_read_pagelist(struct nfs_read_data *data)
+filelayout_read_pagelist(struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;
struct pnfs_layout_segment *lseg = hdr->lseg;
@@ -575,7 +575,7 @@ filelayout_read_pagelist(struct nfs_read_data *data)

/* Perform async writes. */
static enum pnfs_try_status
-filelayout_write_pagelist(struct nfs_write_data *data, int sync)
+filelayout_write_pagelist(struct nfs_pgio_data *data, int sync)
{
struct nfs_pgio_header *hdr = data->header;
struct pnfs_layout_segment *lseg = hdr->lseg;
@@ -600,7 +600,7 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
__func__, hdr->inode->i_ino, sync, (size_t) data->args.count,
offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count));

- data->write_done_cb = filelayout_write_done_cb;
+ data->pgio_done_cb = filelayout_write_done_cb;
atomic_inc(&ds->ds_clp->cl_count);
data->ds_clp = ds->ds_clp;
fh = nfs4_fl_select_ds_fh(lseg, j);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4794ca6..e793aa9 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4033,12 +4033,12 @@ static bool nfs4_error_stateid_expired(int err)
return false;
}

-void __nfs4_read_done_cb(struct nfs_read_data *data)
+void __nfs4_read_done_cb(struct nfs_pgio_data *data)
{
nfs_invalidate_atime(data->header->inode);
}

-static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data)
+static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_pgio_data *data)
{
struct nfs_server *server = NFS_SERVER(data->header->inode);

@@ -4068,7 +4068,7 @@ static bool nfs4_read_stateid_changed(struct rpc_task *task,
return true;
}

-static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
+static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_data *data)
{

dprintk("--> %s\n", __func__);
@@ -4077,19 +4077,19 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
return -EAGAIN;
if (nfs4_read_stateid_changed(task, &data->args))
return -EAGAIN;
- return data->read_done_cb ? data->read_done_cb(task, data) :
+ return data->pgio_done_cb ? data->pgio_done_cb(task, data) :
nfs4_read_done_cb(task, data);
}

-static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
+static void nfs4_proc_read_setup(struct nfs_pgio_data *data, struct rpc_message *msg)
{
data->timestamp = jiffies;
- data->read_done_cb = nfs4_read_done_cb;
+ data->pgio_done_cb = nfs4_read_done_cb;
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
}

-static int nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data)
+static int nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
{
if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
&data->args.seq_args,
@@ -4104,7 +4104,7 @@ static int nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_dat
return 0;
}

-static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data)
+static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_pgio_data *data)
{
struct inode *inode = data->header->inode;

@@ -4134,18 +4134,18 @@ static bool nfs4_write_stateid_changed(struct rpc_task *task,
return true;
}

-static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
+static int nfs4_write_done(struct rpc_task *task, struct nfs_pgio_data *data)
{
if (!nfs4_sequence_done(task, &data->res.seq_res))
return -EAGAIN;
if (nfs4_write_stateid_changed(task, &data->args))
return -EAGAIN;
- return data->write_done_cb ? data->write_done_cb(task, data) :
+ return data->pgio_done_cb ? data->pgio_done_cb(task, data) :
nfs4_write_done_cb(task, data);
}

static
-bool nfs4_write_need_cache_consistency_data(const struct nfs_write_data *data)
+bool nfs4_write_need_cache_consistency_data(const struct nfs_pgio_data *data)
{
const struct nfs_pgio_header *hdr = data->header;

@@ -4158,7 +4158,7 @@ bool nfs4_write_need_cache_consistency_data(const struct nfs_write_data *data)
return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
}

-static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg)
+static void nfs4_proc_write_setup(struct nfs_pgio_data *data, struct rpc_message *msg)
{
struct nfs_server *server = NFS_SERVER(data->header->inode);

@@ -4168,8 +4168,8 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
} else
data->args.bitmask = server->cache_consistency_bitmask;

- if (!data->write_done_cb)
- data->write_done_cb = nfs4_write_done_cb;
+ if (!data->pgio_done_cb)
+ data->pgio_done_cb = nfs4_write_done_cb;
data->res.server = server;
data->timestamp = jiffies;

@@ -4177,7 +4177,7 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
}

-static int nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data)
+static int nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
{
if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
&data->args.seq_args,
diff --git a/fs/nfs/nfs4trace.h b/fs/nfs/nfs4trace.h
index 849cf14..0a744f3 100644
--- a/fs/nfs/nfs4trace.h
+++ b/fs/nfs/nfs4trace.h
@@ -932,7 +932,7 @@ DEFINE_NFS4_IDMAP_EVENT(nfs4_map_gid_to_group);

DECLARE_EVENT_CLASS(nfs4_read_event,
TP_PROTO(
- const struct nfs_read_data *data,
+ const struct nfs_pgio_data *data,
int error
),

@@ -972,7 +972,7 @@ DECLARE_EVENT_CLASS(nfs4_read_event,
#define DEFINE_NFS4_READ_EVENT(name) \
DEFINE_EVENT(nfs4_read_event, name, \
TP_PROTO( \
- const struct nfs_read_data *data, \
+ const struct nfs_pgio_data *data, \
int error \
), \
TP_ARGS(data, error))
@@ -983,7 +983,7 @@ DEFINE_NFS4_READ_EVENT(nfs4_pnfs_read);

DECLARE_EVENT_CLASS(nfs4_write_event,
TP_PROTO(
- const struct nfs_write_data *data,
+ const struct nfs_pgio_data *data,
int error
),

@@ -1024,7 +1024,7 @@ DECLARE_EVENT_CLASS(nfs4_write_event,
#define DEFINE_NFS4_WRITE_EVENT(name) \
DEFINE_EVENT(nfs4_write_event, name, \
TP_PROTO( \
- const struct nfs_write_data *data, \
+ const struct nfs_pgio_data *data, \
int error \
), \
TP_ARGS(data, error))
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
index 5457745..426b366 100644
--- a/fs/nfs/objlayout/objio_osd.c
+++ b/fs/nfs/objlayout/objio_osd.c
@@ -439,7 +439,7 @@ static void _read_done(struct ore_io_state *ios, void *private)
objlayout_read_done(&objios->oir, status, objios->sync);
}

-int objio_read_pagelist(struct nfs_read_data *rdata)
+int objio_read_pagelist(struct nfs_pgio_data *rdata)
{
struct nfs_pgio_header *hdr = rdata->header;
struct objio_state *objios;
@@ -487,7 +487,7 @@ static void _write_done(struct ore_io_state *ios, void *private)
static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
{
struct objio_state *objios = priv;
- struct nfs_write_data *wdata = objios->oir.rpcdata;
+ struct nfs_pgio_data *wdata = objios->oir.rpcdata;
struct address_space *mapping = wdata->header->inode->i_mapping;
pgoff_t index = offset / PAGE_SIZE;
struct page *page;
@@ -531,7 +531,7 @@ static const struct _ore_r4w_op _r4w_op = {
.put_page = &__r4w_put_page,
};

-int objio_write_pagelist(struct nfs_write_data *wdata, int how)
+int objio_write_pagelist(struct nfs_pgio_data *wdata, int how)
{
struct nfs_pgio_header *hdr = wdata->header;
struct objio_state *objios;
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c
index e4f9cbf..2f955f6 100644
--- a/fs/nfs/objlayout/objlayout.c
+++ b/fs/nfs/objlayout/objlayout.c
@@ -229,11 +229,11 @@ objlayout_io_set_result(struct objlayout_io_res *oir, unsigned index,
static void _rpc_read_complete(struct work_struct *work)
{
struct rpc_task *task;
- struct nfs_read_data *rdata;
+ struct nfs_pgio_data *rdata;

dprintk("%s enter\n", __func__);
task = container_of(work, struct rpc_task, u.tk_work);
- rdata = container_of(task, struct nfs_read_data, task);
+ rdata = container_of(task, struct nfs_pgio_data, task);

pnfs_ld_read_done(rdata);
}
@@ -241,7 +241,7 @@ static void _rpc_read_complete(struct work_struct *work)
void
objlayout_read_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
{
- struct nfs_read_data *rdata = oir->rpcdata;
+ struct nfs_pgio_data *rdata = oir->rpcdata;

oir->status = rdata->task.tk_status = status;
if (status >= 0)
@@ -266,7 +266,7 @@ objlayout_read_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
* Perform sync or async reads.
*/
enum pnfs_try_status
-objlayout_read_pagelist(struct nfs_read_data *rdata)
+objlayout_read_pagelist(struct nfs_pgio_data *rdata)
{
struct nfs_pgio_header *hdr = rdata->header;
struct inode *inode = hdr->inode;
@@ -312,11 +312,11 @@ objlayout_read_pagelist(struct nfs_read_data *rdata)
static void _rpc_write_complete(struct work_struct *work)
{
struct rpc_task *task;
- struct nfs_write_data *wdata;
+ struct nfs_pgio_data *wdata;

dprintk("%s enter\n", __func__);
task = container_of(work, struct rpc_task, u.tk_work);
- wdata = container_of(task, struct nfs_write_data, task);
+ wdata = container_of(task, struct nfs_pgio_data, task);

pnfs_ld_write_done(wdata);
}
@@ -324,7 +324,7 @@ static void _rpc_write_complete(struct work_struct *work)
void
objlayout_write_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
{
- struct nfs_write_data *wdata = oir->rpcdata;
+ struct nfs_pgio_data *wdata = oir->rpcdata;

oir->status = wdata->task.tk_status = status;
if (status >= 0) {
@@ -351,7 +351,7 @@ objlayout_write_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
* Perform sync or async writes.
*/
enum pnfs_try_status
-objlayout_write_pagelist(struct nfs_write_data *wdata,
+objlayout_write_pagelist(struct nfs_pgio_data *wdata,
int how)
{
struct nfs_pgio_header *hdr = wdata->header;
diff --git a/fs/nfs/objlayout/objlayout.h b/fs/nfs/objlayout/objlayout.h
index 87aa1de..01e0410 100644
--- a/fs/nfs/objlayout/objlayout.h
+++ b/fs/nfs/objlayout/objlayout.h
@@ -119,8 +119,8 @@ extern void objio_free_lseg(struct pnfs_layout_segment *lseg);
*/
extern void objio_free_result(struct objlayout_io_res *oir);

-extern int objio_read_pagelist(struct nfs_read_data *rdata);
-extern int objio_write_pagelist(struct nfs_write_data *wdata, int how);
+extern int objio_read_pagelist(struct nfs_pgio_data *rdata);
+extern int objio_write_pagelist(struct nfs_pgio_data *wdata, int how);

/*
* callback API
@@ -168,10 +168,10 @@ extern struct pnfs_layout_segment *objlayout_alloc_lseg(
extern void objlayout_free_lseg(struct pnfs_layout_segment *);

extern enum pnfs_try_status objlayout_read_pagelist(
- struct nfs_read_data *);
+ struct nfs_pgio_data *);

extern enum pnfs_try_status objlayout_write_pagelist(
- struct nfs_write_data *,
+ struct nfs_pgio_data *,
int how);

extern void objlayout_encode_layoutcommit(
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 3d5bc2b..e9cea3a 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1492,7 +1492,7 @@ int pnfs_write_done_resend_to_mds(struct inode *inode,
}
EXPORT_SYMBOL_GPL(pnfs_write_done_resend_to_mds);

-static void pnfs_ld_handle_write_error(struct nfs_write_data *data)
+static void pnfs_ld_handle_write_error(struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;

@@ -1511,7 +1511,7 @@ static void pnfs_ld_handle_write_error(struct nfs_write_data *data)
/*
* Called by non rpc-based layout drivers
*/
-void pnfs_ld_write_done(struct nfs_write_data *data)
+void pnfs_ld_write_done(struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;

@@ -1527,7 +1527,7 @@ EXPORT_SYMBOL_GPL(pnfs_ld_write_done);

static void
pnfs_write_through_mds(struct nfs_pageio_descriptor *desc,
- struct nfs_write_data *data)
+ struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;

@@ -1540,7 +1540,7 @@ pnfs_write_through_mds(struct nfs_pageio_descriptor *desc,
}

static enum pnfs_try_status
-pnfs_try_to_write_data(struct nfs_write_data *wdata,
+pnfs_try_to_write_data(struct nfs_pgio_data *wdata,
const struct rpc_call_ops *call_ops,
struct pnfs_layout_segment *lseg,
int how)
@@ -1564,7 +1564,7 @@ pnfs_try_to_write_data(struct nfs_write_data *wdata,
static void
pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *head, int how)
{
- struct nfs_write_data *data;
+ struct nfs_pgio_data *data;
const struct rpc_call_ops *call_ops = desc->pg_rpc_callops;
struct pnfs_layout_segment *lseg = desc->pg_lseg;

@@ -1572,7 +1572,7 @@ pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *he
while (!list_empty(head)) {
enum pnfs_try_status trypnfs;

- data = list_first_entry(head, struct nfs_write_data, list);
+ data = list_first_entry(head, struct nfs_pgio_data, list);
list_del_init(&data->list);

trypnfs = pnfs_try_to_write_data(data, call_ops, lseg, how);
@@ -1647,7 +1647,7 @@ int pnfs_read_done_resend_to_mds(struct inode *inode,
}
EXPORT_SYMBOL_GPL(pnfs_read_done_resend_to_mds);

-static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
+static void pnfs_ld_handle_read_error(struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;

@@ -1666,7 +1666,7 @@ static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
/*
* Called by non rpc-based layout drivers
*/
-void pnfs_ld_read_done(struct nfs_read_data *data)
+void pnfs_ld_read_done(struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;

@@ -1682,7 +1682,7 @@ EXPORT_SYMBOL_GPL(pnfs_ld_read_done);

static void
pnfs_read_through_mds(struct nfs_pageio_descriptor *desc,
- struct nfs_read_data *data)
+ struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;

@@ -1698,7 +1698,7 @@ pnfs_read_through_mds(struct nfs_pageio_descriptor *desc,
* Call the appropriate parallel I/O subsystem read function.
*/
static enum pnfs_try_status
-pnfs_try_to_read_data(struct nfs_read_data *rdata,
+pnfs_try_to_read_data(struct nfs_pgio_data *rdata,
const struct rpc_call_ops *call_ops,
struct pnfs_layout_segment *lseg)
{
@@ -1722,7 +1722,7 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata,
static void
pnfs_do_multiple_reads(struct nfs_pageio_descriptor *desc, struct list_head *head)
{
- struct nfs_read_data *data;
+ struct nfs_pgio_data *data;
const struct rpc_call_ops *call_ops = desc->pg_rpc_callops;
struct pnfs_layout_segment *lseg = desc->pg_lseg;

@@ -1730,7 +1730,7 @@ pnfs_do_multiple_reads(struct nfs_pageio_descriptor *desc, struct list_head *hea
while (!list_empty(head)) {
enum pnfs_try_status trypnfs;

- data = list_first_entry(head, struct nfs_read_data, list);
+ data = list_first_entry(head, struct nfs_pgio_data, list);
list_del_init(&data->list);

trypnfs = pnfs_try_to_read_data(data, call_ops, lseg);
@@ -1821,7 +1821,7 @@ void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg)
EXPORT_SYMBOL_GPL(pnfs_set_lo_fail);

void
-pnfs_set_layoutcommit(struct nfs_write_data *wdata)
+pnfs_set_layoutcommit(struct nfs_pgio_data *wdata)
{
struct nfs_pgio_header *hdr = wdata->header;
struct inode *inode = hdr->inode;
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 94a9a18..0031267 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -113,8 +113,8 @@ struct pnfs_layoutdriver_type {
* Return PNFS_ATTEMPTED to indicate the layout code has attempted
* I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS
*/
- enum pnfs_try_status (*read_pagelist) (struct nfs_read_data *nfs_data);
- enum pnfs_try_status (*write_pagelist) (struct nfs_write_data *nfs_data, int how);
+ enum pnfs_try_status (*read_pagelist) (struct nfs_pgio_data *nfs_data);
+ enum pnfs_try_status (*write_pagelist) (struct nfs_pgio_data *nfs_data, int how);

void (*free_deviceid_node) (struct nfs4_deviceid_node *);

@@ -212,13 +212,13 @@ bool pnfs_roc(struct inode *ino);
void pnfs_roc_release(struct inode *ino);
void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);
bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task);
-void pnfs_set_layoutcommit(struct nfs_write_data *wdata);
+void pnfs_set_layoutcommit(struct nfs_pgio_data *wdata);
void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data);
int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
int _pnfs_return_layout(struct inode *);
int pnfs_commit_and_return_layout(struct inode *);
-void pnfs_ld_write_done(struct nfs_write_data *);
-void pnfs_ld_read_done(struct nfs_read_data *);
+void pnfs_ld_write_done(struct nfs_pgio_data *);
+void pnfs_ld_read_done(struct nfs_pgio_data *);
struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
struct nfs_open_context *ctx,
loff_t pos,
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 8cc227f..c54829e 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -578,7 +578,7 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
return 0;
}

-static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
+static int nfs_read_done(struct rpc_task *task, struct nfs_pgio_data *data)
{
struct inode *inode = data->header->inode;

@@ -594,18 +594,18 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
return 0;
}

-static void nfs_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
+static void nfs_proc_read_setup(struct nfs_pgio_data *data, struct rpc_message *msg)
{
msg->rpc_proc = &nfs_procedures[NFSPROC_READ];
}

-static int nfs_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data)
+static int nfs_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
{
rpc_call_start(task);
return 0;
}

-static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
+static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_data *data)
{
struct inode *inode = data->header->inode;

@@ -614,14 +614,14 @@ static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
return 0;
}

-static void nfs_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg)
+static void nfs_proc_write_setup(struct nfs_pgio_data *data, struct rpc_message *msg)
{
/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
data->args.stable = NFS_FILE_SYNC;
msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE];
}

-static int nfs_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data)
+static int nfs_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
{
rpc_call_start(task);
return 0;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 473bba3..9e426cc 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -51,10 +51,10 @@ struct nfs_read_header *nfs_readhdr_alloc(void)
}
EXPORT_SYMBOL_GPL(nfs_readhdr_alloc);

-static struct nfs_read_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr,
+static struct nfs_pgio_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr,
unsigned int pagecount)
{
- struct nfs_read_data *data, *prealloc;
+ struct nfs_pgio_data *data, *prealloc;

prealloc = &container_of(hdr, struct nfs_read_header, header)->rpc_data;
if (prealloc->header == NULL)
@@ -84,7 +84,7 @@ void nfs_readhdr_free(struct nfs_pgio_header *hdr)
}
EXPORT_SYMBOL_GPL(nfs_readhdr_free);

-void nfs_readdata_release(struct nfs_read_data *rdata)
+void nfs_readdata_release(struct nfs_pgio_data *rdata)
{
struct nfs_pgio_header *hdr = rdata->header;
struct nfs_read_header *read_header = container_of(hdr, struct nfs_read_header, header);
@@ -212,7 +212,7 @@ out:
}

int nfs_initiate_read(struct rpc_clnt *clnt,
- struct nfs_read_data *data,
+ struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops, int flags)
{
struct inode *inode = data->header->inode;
@@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(nfs_initiate_read);
/*
* Set up the NFS read request struct
*/
-static void nfs_read_rpcsetup(struct nfs_read_data *data,
+static void nfs_read_rpcsetup(struct nfs_pgio_data *data,
unsigned int count, unsigned int offset)
{
struct nfs_page *req = data->header->req;
@@ -274,7 +274,7 @@ static void nfs_read_rpcsetup(struct nfs_read_data *data,
nfs_fattr_init(&data->fattr);
}

-static int nfs_do_read(struct nfs_read_data *data,
+static int nfs_do_read(struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops)
{
struct inode *inode = data->header->inode;
@@ -286,13 +286,13 @@ static int
nfs_do_multiple_reads(struct list_head *head,
const struct rpc_call_ops *call_ops)
{
- struct nfs_read_data *data;
+ struct nfs_pgio_data *data;
int ret = 0;

while (!list_empty(head)) {
int ret2;

- data = list_first_entry(head, struct nfs_read_data, list);
+ data = list_first_entry(head, struct nfs_pgio_data, list);
list_del_init(&data->list);

ret2 = nfs_do_read(data, call_ops);
@@ -324,8 +324,8 @@ static void nfs_pagein_error(struct nfs_pageio_descriptor *desc,
{
set_bit(NFS_IOHDR_REDO, &hdr->flags);
while (!list_empty(&hdr->rpc_list)) {
- struct nfs_read_data *data = list_first_entry(&hdr->rpc_list,
- struct nfs_read_data, list);
+ struct nfs_pgio_data *data = list_first_entry(&hdr->rpc_list,
+ struct nfs_pgio_data, list);
list_del(&data->list);
nfs_readdata_release(data);
}
@@ -350,7 +350,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc,
{
struct nfs_page *req = hdr->req;
struct page *page = req->wb_page;
- struct nfs_read_data *data;
+ struct nfs_pgio_data *data;
size_t rsize = desc->pg_bsize, nbytes;
unsigned int offset;

@@ -382,7 +382,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,
{
struct nfs_page *req;
struct page **pages;
- struct nfs_read_data *data;
+ struct nfs_pgio_data *data;
struct list_head *head = &desc->pg_list;

data = nfs_readdata_alloc(hdr, nfs_page_array_len(desc->pg_base,
@@ -447,7 +447,7 @@ static const struct nfs_pageio_ops nfs_pageio_read_ops = {
* This is the callback from RPC telling us whether a reply was
* received or some error occurred (timeout or socket shutdown).
*/
-int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
+int nfs_readpage_result(struct rpc_task *task, struct nfs_pgio_data *data)
{
struct inode *inode = data->header->inode;
int status;
@@ -468,7 +468,7 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
return 0;
}

-static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
+static void nfs_readpage_retry(struct rpc_task *task, struct nfs_pgio_data *data)
{
struct nfs_pgio_args *argp = &data->args;
struct nfs_pgio_res *resp = &data->res;
@@ -490,7 +490,7 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data

static void nfs_readpage_result_common(struct rpc_task *task, void *calldata)
{
- struct nfs_read_data *data = calldata;
+ struct nfs_pgio_data *data = calldata;
struct nfs_pgio_header *hdr = data->header;

/* Note the only returns of nfs_readpage_result are 0 and -EAGAIN */
@@ -520,7 +520,7 @@ static void nfs_readpage_release_common(void *calldata)

void nfs_read_prepare(struct rpc_task *task, void *calldata)
{
- struct nfs_read_data *data = calldata;
+ struct nfs_pgio_data *data = calldata;
int err;
err = NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data);
if (err)
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index d392a70..3a2fc5c 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -88,10 +88,10 @@ struct nfs_write_header *nfs_writehdr_alloc(void)
}
EXPORT_SYMBOL_GPL(nfs_writehdr_alloc);

-static struct nfs_write_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr,
+static struct nfs_pgio_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr,
unsigned int pagecount)
{
- struct nfs_write_data *data, *prealloc;
+ struct nfs_pgio_data *data, *prealloc;

prealloc = &container_of(hdr, struct nfs_write_header, header)->rpc_data;
if (prealloc->header == NULL)
@@ -120,7 +120,7 @@ void nfs_writehdr_free(struct nfs_pgio_header *hdr)
}
EXPORT_SYMBOL_GPL(nfs_writehdr_free);

-void nfs_writedata_release(struct nfs_write_data *wdata)
+void nfs_writedata_release(struct nfs_pgio_data *wdata)
{
struct nfs_pgio_header *hdr = wdata->header;
struct nfs_write_header *write_header = container_of(hdr, struct nfs_write_header, header);
@@ -582,7 +582,7 @@ nfs_clear_request_commit(struct nfs_page *req)
}

static inline
-int nfs_write_need_commit(struct nfs_write_data *data)
+int nfs_write_need_commit(struct nfs_pgio_data *data)
{
if (data->verf.committed == NFS_DATA_SYNC)
return data->header->lseg == NULL;
@@ -613,7 +613,7 @@ nfs_clear_request_commit(struct nfs_page *req)
}

static inline
-int nfs_write_need_commit(struct nfs_write_data *data)
+int nfs_write_need_commit(struct nfs_pgio_data *data)
{
return 0;
}
@@ -990,7 +990,7 @@ static int flush_task_priority(int how)
}

int nfs_initiate_write(struct rpc_clnt *clnt,
- struct nfs_write_data *data,
+ struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops,
int how, int flags)
{
@@ -1047,7 +1047,7 @@ EXPORT_SYMBOL_GPL(nfs_initiate_write);
/*
* Set up the argument/result storage required for the RPC call.
*/
-static void nfs_write_rpcsetup(struct nfs_write_data *data,
+static void nfs_write_rpcsetup(struct nfs_pgio_data *data,
unsigned int count, unsigned int offset,
int how, struct nfs_commit_info *cinfo)
{
@@ -1082,7 +1082,7 @@ static void nfs_write_rpcsetup(struct nfs_write_data *data,
nfs_fattr_init(&data->fattr);
}

-static int nfs_do_write(struct nfs_write_data *data,
+static int nfs_do_write(struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops,
int how)
{
@@ -1095,13 +1095,13 @@ static int nfs_do_multiple_writes(struct list_head *head,
const struct rpc_call_ops *call_ops,
int how)
{
- struct nfs_write_data *data;
+ struct nfs_pgio_data *data;
int ret = 0;

while (!list_empty(head)) {
int ret2;

- data = list_first_entry(head, struct nfs_write_data, list);
+ data = list_first_entry(head, struct nfs_pgio_data, list);
list_del_init(&data->list);

ret2 = nfs_do_write(data, call_ops, how);
@@ -1144,8 +1144,8 @@ static void nfs_flush_error(struct nfs_pageio_descriptor *desc,
{
set_bit(NFS_IOHDR_REDO, &hdr->flags);
while (!list_empty(&hdr->rpc_list)) {
- struct nfs_write_data *data = list_first_entry(&hdr->rpc_list,
- struct nfs_write_data, list);
+ struct nfs_pgio_data *data = list_first_entry(&hdr->rpc_list,
+ struct nfs_pgio_data, list);
list_del(&data->list);
nfs_writedata_release(data);
}
@@ -1161,7 +1161,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc,
{
struct nfs_page *req = hdr->req;
struct page *page = req->wb_page;
- struct nfs_write_data *data;
+ struct nfs_pgio_data *data;
size_t wsize = desc->pg_bsize, nbytes;
unsigned int offset;
int requests = 0;
@@ -1211,7 +1211,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
{
struct nfs_page *req;
struct page **pages;
- struct nfs_write_data *data;
+ struct nfs_pgio_data *data;
struct list_head *head = &desc->pg_list;
struct nfs_commit_info cinfo;

@@ -1305,7 +1305,7 @@ EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds);

void nfs_write_prepare(struct rpc_task *task, void *calldata)
{
- struct nfs_write_data *data = calldata;
+ struct nfs_pgio_data *data = calldata;
int err;
err = NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data);
if (err)
@@ -1328,14 +1328,14 @@ void nfs_commit_prepare(struct rpc_task *task, void *calldata)
*/
static void nfs_writeback_done_common(struct rpc_task *task, void *calldata)
{
- struct nfs_write_data *data = calldata;
+ struct nfs_pgio_data *data = calldata;

nfs_writeback_done(task, data);
}

static void nfs_writeback_release_common(void *calldata)
{
- struct nfs_write_data *data = calldata;
+ struct nfs_pgio_data *data = calldata;
struct nfs_pgio_header *hdr = data->header;
int status = data->task.tk_status;

@@ -1386,7 +1386,7 @@ static int nfs_should_remove_suid(const struct inode *inode)
/*
* This function is called when the WRITE call is complete.
*/
-void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
+void nfs_writeback_done(struct rpc_task *task, struct nfs_pgio_data *data)
{
struct nfs_pgio_args *argp = &data->args;
struct nfs_pgio_res *resp = &data->res;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index fa6918b..7e0db56 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -520,7 +520,7 @@ extern int nfs_writepage(struct page *page, struct writeback_control *wbc);
extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
-extern void nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
+extern void nfs_writeback_done(struct rpc_task *, struct nfs_pgio_data *);

/*
* Try to write back everything synchronously (but check the
@@ -553,7 +553,7 @@ nfs_have_writebacks(struct inode *inode)
extern int nfs_readpage(struct file *, struct page *);
extern int nfs_readpages(struct file *, struct address_space *,
struct list_head *, unsigned);
-extern int nfs_readpage_result(struct rpc_task *, struct nfs_read_data *);
+extern int nfs_readpage_result(struct rpc_task *, struct nfs_pgio_data *);
extern int nfs_readpage_async(struct nfs_open_context *, struct inode *,
struct page *);

diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 64c0fd2..e7d934a 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1246,20 +1246,6 @@ struct nfs_page_array {
struct page *page_array[NFS_PAGEVEC_SIZE];
};

-struct nfs_read_data {
- struct nfs_pgio_header *header;
- struct list_head list;
- struct rpc_task task;
- struct nfs_fattr fattr; /* fattr storage */
- struct nfs_pgio_args args;
- struct nfs_pgio_res res;
- unsigned long timestamp; /* For lease renewal */
- int (*read_done_cb) (struct rpc_task *task, struct nfs_read_data *data);
- __u64 mds_offset;
- struct nfs_page_array pages;
- struct nfs_client *ds_clp; /* pNFS data server */
-};
-
/* used as flag bits in nfs_pgio_header */
enum {
NFS_IOHDR_ERROR = 0,
@@ -1292,29 +1278,29 @@ struct nfs_pgio_header {
unsigned long flags;
};

-struct nfs_read_header {
- struct nfs_pgio_header header;
- struct nfs_read_data rpc_data;
-};
-
-struct nfs_write_data {
+struct nfs_pgio_data {
struct nfs_pgio_header *header;
struct list_head list;
struct rpc_task task;
struct nfs_fattr fattr;
- struct nfs_writeverf verf;
+ struct nfs_writeverf verf; /* Used for writes */
struct nfs_pgio_args args; /* argument struct */
struct nfs_pgio_res res; /* result struct */
unsigned long timestamp; /* For lease renewal */
- int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data);
+ int (*pgio_done_cb) (struct rpc_task *task, struct nfs_pgio_data *data);
__u64 mds_offset; /* Filelayout dense stripe */
struct nfs_page_array pages;
struct nfs_client *ds_clp; /* pNFS data server */
};

+struct nfs_read_header {
+ struct nfs_pgio_header header;
+ struct nfs_pgio_data rpc_data;
+};
+
struct nfs_write_header {
struct nfs_pgio_header header;
- struct nfs_write_data rpc_data;
+ struct nfs_pgio_data rpc_data;
struct nfs_writeverf verf;
};

@@ -1447,12 +1433,12 @@ struct nfs_rpc_ops {
struct nfs_pathconf *);
int (*set_capabilities)(struct nfs_server *, struct nfs_fh *);
int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, int);
- void (*read_setup) (struct nfs_read_data *, struct rpc_message *);
- int (*read_rpc_prepare)(struct rpc_task *, struct nfs_read_data *);
- int (*read_done) (struct rpc_task *, struct nfs_read_data *);
- void (*write_setup) (struct nfs_write_data *, struct rpc_message *);
- int (*write_rpc_prepare)(struct rpc_task *, struct nfs_write_data *);
- int (*write_done) (struct rpc_task *, struct nfs_write_data *);
+ void (*read_setup) (struct nfs_pgio_data *, struct rpc_message *);
+ int (*read_rpc_prepare)(struct rpc_task *, struct nfs_pgio_data *);
+ int (*read_done) (struct rpc_task *, struct nfs_pgio_data *);
+ void (*write_setup) (struct nfs_pgio_data *, struct rpc_message *);
+ int (*write_rpc_prepare)(struct rpc_task *, struct nfs_pgio_data *);
+ int (*write_done) (struct rpc_task *, struct nfs_pgio_data *);
void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *);
void (*commit_rpc_prepare)(struct rpc_task *, struct nfs_commit_data *);
int (*commit_done) (struct rpc_task *, struct nfs_commit_data *);
--
1.9.2


2014-04-17 21:10:25

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 10/17] NFS: Create a common rpc_call_ops struct

From: Anna Schumaker <[email protected]>

The read and write paths set up this struct in exactly the same way, so
create a single shared struct.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 4 +---
fs/nfs/pageio.c | 10 ++++++++--
fs/nfs/read.c | 11 ++---------
fs/nfs/write.c | 11 ++---------
4 files changed, 13 insertions(+), 23 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b18cca4..798eb47 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -396,13 +396,11 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool
struct nfs_pgio_completion_ops;

/* pageio.c */
+extern const struct rpc_call_ops nfs_pgio_common_ops;
extern struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
extern void nfs_rw_header_free(struct nfs_pgio_header *);
extern struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
extern void nfs_pgio_data_release(struct nfs_pgio_data *);
-extern void nfs_pgio_prepare(struct rpc_task *, void *);
-extern void nfs_pgio_release_common(void *);
-extern void nfs_pgio_result_common(struct rpc_task *, void *);

/* read.c */
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index efbcc44..f64fd70 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -87,7 +87,7 @@ void nfs_pgio_data_release(struct nfs_pgio_data *data)
}
EXPORT_SYMBOL_GPL(nfs_pgio_data_release);

-void nfs_pgio_prepare(struct rpc_task *task, void *calldata)
+static void nfs_pgio_prepare(struct rpc_task *task, void *calldata)
{
struct nfs_pgio_data *data = calldata;
int err;
@@ -114,7 +114,7 @@ static int nfs_pgio_result(struct rpc_task *task, struct nfs_pgio_data *data)
return data->header->rw_ops->rw_result(task, data, inode);
}

-void nfs_pgio_result_common(struct rpc_task *task, void *calldata)
+static void nfs_pgio_result_common(struct rpc_task *task, void *calldata)
{
struct nfs_pgio_data *data = calldata;

@@ -125,3 +125,9 @@ void nfs_pgio_result_common(struct rpc_task *task, void *calldata)
else
data->header->rw_ops->rw_result_common(task, data);
}
+
+const struct rpc_call_ops nfs_pgio_common_ops = {
+ .rpc_call_prepare = nfs_pgio_prepare,
+ .rpc_call_done = nfs_pgio_result_common,
+ .rpc_release = nfs_pgio_release_common,
+};
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 4f49507..98373ba 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -29,7 +29,6 @@
#define NFSDBG_FACILITY NFSDBG_PAGECACHE

static const struct nfs_pageio_ops nfs_pageio_read_ops;
-static const struct rpc_call_ops nfs_read_common_ops;
static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops;
static const struct nfs_rw_ops nfs_rw_read_ops;

@@ -314,7 +313,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc,

nfs_list_remove_request(req);
nfs_list_add_request(req, &hdr->pages);
- desc->pg_rpc_callops = &nfs_read_common_ops;
+ desc->pg_rpc_callops = &nfs_pgio_common_ops;
return 0;
}

@@ -343,7 +342,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,

nfs_read_rpcsetup(data, desc->pg_count, 0);
list_add(&data->list, &hdr->rpc_list);
- desc->pg_rpc_callops = &nfs_read_common_ops;
+ desc->pg_rpc_callops = &nfs_pgio_common_ops;
return 0;
}

@@ -443,12 +442,6 @@ static void nfs_readpage_result_common(struct rpc_task *task, struct nfs_pgio_da
nfs_readpage_retry(task, data);
}

-static const struct rpc_call_ops nfs_read_common_ops = {
- .rpc_call_prepare = nfs_pgio_prepare,
- .rpc_call_done = nfs_pgio_result_common,
- .rpc_release = nfs_pgio_release_common,
-};
-
/*
* Read a page over NFS.
* We read the page synchronously in the following case:
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index d2351a1..e492537 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -42,7 +42,6 @@
* Local function declarations
*/
static void nfs_redirty_request(struct nfs_page *req);
-static const struct rpc_call_ops nfs_write_common_ops;
static const struct rpc_call_ops nfs_commit_ops;
static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
@@ -1138,7 +1137,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc,
} while (nbytes != 0);
nfs_list_remove_request(req);
nfs_list_add_request(req, &hdr->pages);
- desc->pg_rpc_callops = &nfs_write_common_ops;
+ desc->pg_rpc_callops = &nfs_pgio_common_ops;
return 0;
}

@@ -1182,7 +1181,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
/* Set up the argument struct */
nfs_write_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo);
list_add(&data->list, &hdr->rpc_list);
- desc->pg_rpc_callops = &nfs_write_common_ops;
+ desc->pg_rpc_callops = &nfs_pgio_common_ops;
return 0;
}

@@ -1272,12 +1271,6 @@ static void nfs_writeback_release_common(struct nfs_pgio_data *data)
}
}

-static const struct rpc_call_ops nfs_write_common_ops = {
- .rpc_call_prepare = nfs_pgio_prepare,
- .rpc_call_done = nfs_pgio_result_common,
- .rpc_release = nfs_pgio_release_common,
-};
-
/*
* Special version of should_remove_suid() that ignores capabilities.
*/
--
1.9.2


2014-04-18 14:01:24

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 04/17] NFS: Create a common read and write header struct

On Thu, Apr 17, 2014 at 05:09:28PM -0400, Anna Schumaker wrote:
> From: Anna Schumaker <[email protected]>
>
> The only difference is the write verifier field, so I leave a comment
> saying that it's not used for reads.

Looks good.

Reviewed-by: Christoph Hellwig <[email protected]>

2014-04-23 13:51:19

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH 00/17] NFS: Create a common path used by reads and writes

We'll make sure it works! I'm about to look through Dros' patches, so I'll know more soon!

Anna

On 04/23/2014 09:42 AM, Weston Andros Adamson wrote:
> Yeah there are bound to be some conflicts between these two patchsets, but
> I don?t think it should be too nasty.
>
> Anna and I can work together to get both sets into a branch once we get things
> reviewed.
>
> The good news is that we can combine testing efforts - both of these patchsets
> change the read and write path for all versions of NFS, so we really need to
> make sure we didn?t break anything. Not that pnfs isn?t important ;)
>
> -dros
>
> On Apr 23, 2014, at 9:15 AM, Boaz Harrosh <[email protected]> wrote:
>
>> On 04/23/2014 03:55 PM, Boaz Harrosh wrote:
>>> On 04/18/2014 12:09 AM, Anna Schumaker wrote:
>> <>
>>> yes please keep
>>> it on a public tree for quick testing. Perhaps ask Trond to keep
>>> it on his tree in a branch. (So to get some coverage under the linux-next
>>> tree mongers from Intel)
>>>
>>
>> BTW: anyone tested how much this conflicts with dros's 17 patches?
>> (Noticed how it is always 17 patches)
>> If a brave sole can have both these merged on the same tree it
>> would be easier for the testing.
>>
>> Thanks
>> Boaz
>>
>


2014-04-17 21:10:30

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 13/17] NFS: Create a generic_pgio function

From: Anna Schumaker <[email protected]>

These functions are almost identical on both the read and write side.
FLUSH_COND_STABLE will never be set for the read path, so leaving it in
the generic code won't hurt anything.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 10 +----
fs/nfs/pageio.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++---
fs/nfs/pnfs.c | 4 +-
fs/nfs/read.c | 81 +---------------------------------------
fs/nfs/write.c | 97 +-----------------------------------------------
5 files changed, 108 insertions(+), 192 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 383175e..6422b9d 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -396,14 +396,10 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool
struct nfs_pgio_completion_ops;

/* pageio.c */
-extern const struct rpc_call_ops nfs_pgio_common_ops;
extern struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
extern void nfs_rw_header_free(struct nfs_pgio_header *);
-extern struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
extern void nfs_pgio_data_release(struct nfs_pgio_data *);
-extern int nfs_pgio_error(struct nfs_pageio_descriptor *, struct nfs_pgio_header *);
-extern void nfs_pgio_rpcsetup(struct nfs_pgio_data *, unsigned int,
- unsigned int, int, struct nfs_commit_info *);
+extern int nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_header *);

/* read.c */
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
@@ -413,8 +409,6 @@ extern int nfs_initiate_read(struct rpc_clnt *clnt,
struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops, int flags);
extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
-extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr);
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);

/* super.c */
@@ -432,8 +426,6 @@ int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags, bool force_mds,
const struct nfs_pgio_completion_ops *compl_ops);
-extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr);
extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
extern void nfs_commit_free(struct nfs_commit_data *p);
extern int nfs_initiate_write(struct rpc_clnt *clnt,
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index 86f6f4d..093cb1d 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -13,6 +13,9 @@

#define NFSDBG_FACILITY NFSDBG_PAGECACHE

+static const struct rpc_call_ops nfs_pgio_common_ops;
+
+
static inline struct nfs_rw_header *NFS_RW_HEADER(struct nfs_pgio_header *hdr)
{
return container_of(hdr, struct nfs_rw_header, header);
@@ -41,8 +44,8 @@ void nfs_rw_header_free(struct nfs_pgio_header *hdr)
}
EXPORT_SYMBOL_GPL(nfs_rw_header_free);

-struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *hdr,
- unsigned int pagecount)
+static struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *hdr,
+ unsigned int pagecount)
{
struct nfs_pgio_data *data, *prealloc;

@@ -87,7 +90,7 @@ void nfs_pgio_data_release(struct nfs_pgio_data *data)
}
EXPORT_SYMBOL_GPL(nfs_pgio_data_release);

-void nfs_pgio_rpcsetup(struct nfs_pgio_data *data,
+static void nfs_pgio_rpcsetup(struct nfs_pgio_data *data,
unsigned int count, unsigned int offset,
int how, struct nfs_commit_info *cinfo)
{
@@ -123,7 +126,7 @@ void nfs_pgio_rpcsetup(struct nfs_pgio_data *data,
nfs_fattr_init(&data->fattr);
}

-int nfs_pgio_error(struct nfs_pageio_descriptor *desc,
+static int nfs_pgio_error(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr)
{
struct nfs_pgio_data *data;
@@ -138,6 +141,101 @@ int nfs_pgio_error(struct nfs_pageio_descriptor *desc,
return -ENOMEM;
}

+/*
+ * Generate multiple small requests to read or write a single
+ * contiguous dirty on one page.
+ */
+static int nfs_pgio_multi(struct nfs_pageio_descriptor *desc,
+ struct nfs_pgio_header *hdr)
+{
+ struct nfs_page *req = hdr->req;
+ struct page *page = req->wb_page;
+ struct nfs_pgio_data *data;
+ size_t wsize = desc->pg_bsize, nbytes;
+ unsigned int offset;
+ int requests = 0;
+ struct nfs_commit_info cinfo;
+
+ nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq);
+
+ if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
+ (desc->pg_moreio || nfs_reqs_to_commit(&cinfo) ||
+ desc->pg_count > wsize))
+ desc->pg_ioflags &= ~FLUSH_COND_STABLE;
+
+ offset = 0;
+ nbytes = desc->pg_count;
+ do {
+ size_t len = min(nbytes, wsize);
+
+ data = nfs_pgio_data_alloc(hdr, 1);
+ if (!data)
+ return nfs_pgio_error(desc, hdr);
+ data->pages.pagevec[0] = page;
+ nfs_pgio_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo);
+ list_add(&data->list, &hdr->rpc_list);
+ requests++;
+ nbytes -= len;
+ offset += len;
+ } while (nbytes != 0);
+
+ nfs_list_remove_request(req);
+ nfs_list_add_request(req, &hdr->pages);
+ desc->pg_rpc_callops = &nfs_pgio_common_ops;
+ return 0;
+}
+
+/*
+ * Create an RPC task for the given write request and kick it.
+ * The page must have been locked by the caller.
+ *
+ * It may happen that the page we're passed is not marked dirty.
+ * This is the case if nfs_updatepage detects a conflicting request
+ * that has been written but not committed.
+ */
+static int nfs_pgio_one(struct nfs_pageio_descriptor *desc,
+ struct nfs_pgio_header *hdr)
+{
+ struct nfs_page *req;
+ struct page **pages;
+ struct nfs_pgio_data *data;
+ struct list_head *head = &desc->pg_list;
+ struct nfs_commit_info cinfo;
+
+ data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base,
+ desc->pg_count));
+ if (!data)
+ return nfs_pgio_error(desc, hdr);
+
+ nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq);
+ pages = data->pages.pagevec;
+ while (!list_empty(head)) {
+ req = nfs_list_entry(head->next);
+ nfs_list_remove_request(req);
+ nfs_list_add_request(req, &hdr->pages);
+ *pages++ = req->wb_page;
+ }
+
+ if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
+ (desc->pg_moreio || nfs_reqs_to_commit(&cinfo)))
+ desc->pg_ioflags &= ~FLUSH_COND_STABLE;
+
+ /* Set up the argument struct */
+ nfs_pgio_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo);
+ list_add(&data->list, &hdr->rpc_list);
+ desc->pg_rpc_callops = &nfs_pgio_common_ops;
+ return 0;
+}
+
+int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
+ struct nfs_pgio_header *hdr)
+{
+ if (desc->pg_bsize < PAGE_CACHE_SIZE)
+ return nfs_pgio_multi(desc, hdr);
+ return nfs_pgio_one(desc, hdr);
+}
+EXPORT_SYMBOL_GPL(nfs_generic_pgio);
+
static void nfs_pgio_prepare(struct rpc_task *task, void *calldata)
{
struct nfs_pgio_data *data = calldata;
@@ -177,7 +275,7 @@ static void nfs_pgio_result_common(struct rpc_task *task, void *calldata)
data->header->rw_ops->rw_result_common(task, data);
}

-const struct rpc_call_ops nfs_pgio_common_ops = {
+static const struct rpc_call_ops nfs_pgio_common_ops = {
.rpc_call_prepare = nfs_pgio_prepare,
.rpc_call_done = nfs_pgio_result_common,
.rpc_release = nfs_pgio_release_common,
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 54c84c1..0fe6701 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1607,7 +1607,7 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
nfs_pgheader_init(desc, hdr, pnfs_writehdr_free);
hdr->lseg = pnfs_get_lseg(desc->pg_lseg);
atomic_inc(&hdr->refcnt);
- ret = nfs_generic_flush(desc, hdr);
+ ret = nfs_generic_pgio(desc, hdr);
if (ret != 0) {
pnfs_put_lseg(desc->pg_lseg);
desc->pg_lseg = NULL;
@@ -1766,7 +1766,7 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
nfs_pgheader_init(desc, hdr, pnfs_readhdr_free);
hdr->lseg = pnfs_get_lseg(desc->pg_lseg);
atomic_inc(&hdr->refcnt);
- ret = nfs_generic_pagein(desc, hdr);
+ ret = nfs_generic_pgio(desc, hdr);
if (ret != 0) {
pnfs_put_lseg(desc->pg_lseg);
desc->pg_lseg = NULL;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index c623671..07c21bd 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -237,85 +237,6 @@ static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops = {
.completion = nfs_read_completion,
};

-/*
- * Generate multiple requests to fill a single page.
- *
- * We optimize to reduce the number of read operations on the wire. If we
- * detect that we're reading a page, or an area of a page, that is past the
- * end of file, we do not generate NFS read operations but just clear the
- * parts of the page that would have come back zero from the server anyway.
- *
- * We rely on the cached value of i_size to make this determination; another
- * client can fill pages on the server past our cached end-of-file, but we
- * won't see the new data until our attribute cache is updated. This is more
- * or less conventional NFS client behavior.
- */
-static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr)
-{
- struct nfs_page *req = hdr->req;
- struct page *page = req->wb_page;
- struct nfs_pgio_data *data;
- size_t rsize = desc->pg_bsize, nbytes;
- unsigned int offset;
-
- offset = 0;
- nbytes = desc->pg_count;
- do {
- size_t len = min(nbytes,rsize);
-
- data = nfs_pgio_data_alloc(hdr, 1);
- if (!data)
- return nfs_pgio_error(desc, hdr);
- data->pages.pagevec[0] = page;
- nfs_pgio_rpcsetup(data, len, offset, 0, NULL);
- list_add(&data->list, &hdr->rpc_list);
- nbytes -= len;
- offset += len;
- } while (nbytes != 0);
-
- nfs_list_remove_request(req);
- nfs_list_add_request(req, &hdr->pages);
- desc->pg_rpc_callops = &nfs_pgio_common_ops;
- return 0;
-}
-
-static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr)
-{
- struct nfs_page *req;
- struct page **pages;
- struct nfs_pgio_data *data;
- struct list_head *head = &desc->pg_list;
-
- data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base,
- desc->pg_count));
- if (!data)
- return nfs_pgio_error(desc, hdr);
-
- pages = data->pages.pagevec;
- while (!list_empty(head)) {
- req = nfs_list_entry(head->next);
- nfs_list_remove_request(req);
- nfs_list_add_request(req, &hdr->pages);
- *pages++ = req->wb_page;
- }
-
- nfs_pgio_rpcsetup(data, desc->pg_count, 0, 0, NULL);
- list_add(&data->list, &hdr->rpc_list);
- desc->pg_rpc_callops = &nfs_pgio_common_ops;
- return 0;
-}
-
-int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr)
-{
- if (desc->pg_bsize < PAGE_CACHE_SIZE)
- return nfs_pagein_multi(desc, hdr);
- return nfs_pagein_one(desc, hdr);
-}
-EXPORT_SYMBOL_GPL(nfs_generic_pagein);
-
static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
{
struct nfs_rw_header *rhdr;
@@ -330,7 +251,7 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
hdr = &rhdr->header;
nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
atomic_inc(&hdr->refcnt);
- ret = nfs_generic_pagein(desc, hdr);
+ ret = nfs_generic_pgio(desc, hdr);
if (ret == 0)
ret = nfs_do_multiple_reads(&hdr->rpc_list,
desc->pg_rpc_callops);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 1f98f31..8929e33 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1044,101 +1044,6 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = {
.completion = nfs_write_completion,
};

-/*
- * Generate multiple small requests to write out a single
- * contiguous dirty area on one page.
- */
-static int nfs_flush_multi(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr)
-{
- struct nfs_page *req = hdr->req;
- struct page *page = req->wb_page;
- struct nfs_pgio_data *data;
- size_t wsize = desc->pg_bsize, nbytes;
- unsigned int offset;
- int requests = 0;
- struct nfs_commit_info cinfo;
-
- nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq);
-
- if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
- (desc->pg_moreio || nfs_reqs_to_commit(&cinfo) ||
- desc->pg_count > wsize))
- desc->pg_ioflags &= ~FLUSH_COND_STABLE;
-
-
- offset = 0;
- nbytes = desc->pg_count;
- do {
- size_t len = min(nbytes, wsize);
-
- data = nfs_pgio_data_alloc(hdr, 1);
- if (!data)
- return nfs_pgio_error(desc, hdr);
- data->pages.pagevec[0] = page;
- nfs_pgio_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo);
- list_add(&data->list, &hdr->rpc_list);
- requests++;
- nbytes -= len;
- offset += len;
- } while (nbytes != 0);
- nfs_list_remove_request(req);
- nfs_list_add_request(req, &hdr->pages);
- desc->pg_rpc_callops = &nfs_pgio_common_ops;
- return 0;
-}
-
-/*
- * Create an RPC task for the given write request and kick it.
- * The page must have been locked by the caller.
- *
- * It may happen that the page we're passed is not marked dirty.
- * This is the case if nfs_updatepage detects a conflicting request
- * that has been written but not committed.
- */
-static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr)
-{
- struct nfs_page *req;
- struct page **pages;
- struct nfs_pgio_data *data;
- struct list_head *head = &desc->pg_list;
- struct nfs_commit_info cinfo;
-
- data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base,
- desc->pg_count));
- if (!data)
- return nfs_pgio_error(desc, hdr);
-
- nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq);
- pages = data->pages.pagevec;
- while (!list_empty(head)) {
- req = nfs_list_entry(head->next);
- nfs_list_remove_request(req);
- nfs_list_add_request(req, &hdr->pages);
- *pages++ = req->wb_page;
- }
-
- if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
- (desc->pg_moreio || nfs_reqs_to_commit(&cinfo)))
- desc->pg_ioflags &= ~FLUSH_COND_STABLE;
-
- /* Set up the argument struct */
- nfs_pgio_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo);
- list_add(&data->list, &hdr->rpc_list);
- desc->pg_rpc_callops = &nfs_pgio_common_ops;
- return 0;
-}
-
-int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr)
-{
- if (desc->pg_bsize < PAGE_CACHE_SIZE)
- return nfs_flush_multi(desc, hdr);
- return nfs_flush_one(desc, hdr);
-}
-EXPORT_SYMBOL_GPL(nfs_generic_flush);
-
static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
{
struct nfs_rw_header *whdr;
@@ -1153,7 +1058,7 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
hdr = &whdr->header;
nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
atomic_inc(&hdr->refcnt);
- ret = nfs_generic_flush(desc, hdr);
+ ret = nfs_generic_pgio(desc, hdr);
if (ret == 0)
ret = nfs_do_multiple_writes(&hdr->rpc_list,
desc->pg_rpc_callops,
--
1.9.2


2014-04-17 21:10:50

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 16/17] NFS: Create a common generic_pg_pgios()

From: Anna Schumaker <[email protected]>

What we have here is two functions that look identical. Let's share
some more code!

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 1 +
fs/nfs/pageio.c | 23 +++++++++++++++++++++++
fs/nfs/read.c | 25 +------------------------
fs/nfs/write.c | 26 +-------------------------
4 files changed, 26 insertions(+), 49 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 81c314c..0243825 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -403,6 +403,7 @@ extern int nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_head
extern int nfs_initiate_pgio(struct rpc_clnt *, struct nfs_pgio_data *,
const struct rpc_call_ops *, int, int);
extern int nfs_do_multiple_pgios(struct list_head *, const struct rpc_call_ops *, int);
+extern int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *);

/* read.c */
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index 4a98d54..da01458 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -312,6 +312,29 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
}
EXPORT_SYMBOL_GPL(nfs_generic_pgio);

+int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc)
+{
+ struct nfs_rw_header *rw_hdr;
+ struct nfs_pgio_header *hdr;
+ int ret;
+
+ rw_hdr = nfs_rw_header_alloc(desc->pg_rw_ops);
+ if (!rw_hdr) {
+ desc->pg_completion_ops->error_cleanup(&desc->pg_list);
+ return -ENOMEM;
+ }
+ hdr = &rw_hdr->header;
+ nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
+ atomic_inc(&hdr->refcnt);
+ ret = nfs_generic_pgio(desc, hdr);
+ if (ret == 0)
+ ret = nfs_do_multiple_pgios(&hdr->rpc_list,
+ desc->pg_rpc_callops, 0);
+ if (atomic_dec_and_test(&hdr->refcnt))
+ hdr->completion_ops->completion(hdr);
+ return ret;
+}
+
static void nfs_pgio_prepare(struct rpc_task *task, void *calldata)
{
struct nfs_pgio_data *data = calldata;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 9dd1aeb..8460795 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -178,32 +178,9 @@ static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops = {
.completion = nfs_read_completion,
};

-static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
-{
- struct nfs_rw_header *rhdr;
- struct nfs_pgio_header *hdr;
- int ret;
-
- rhdr = nfs_rw_header_alloc(desc->pg_rw_ops);
- if (!rhdr) {
- desc->pg_completion_ops->error_cleanup(&desc->pg_list);
- return -ENOMEM;
- }
- hdr = &rhdr->header;
- nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
- atomic_inc(&hdr->refcnt);
- ret = nfs_generic_pgio(desc, hdr);
- if (ret == 0)
- ret = nfs_do_multiple_pgios(&hdr->rpc_list,
- desc->pg_rpc_callops, 0);
- if (atomic_dec_and_test(&hdr->refcnt))
- hdr->completion_ops->completion(hdr);
- return ret;
-}
-
static const struct nfs_pageio_ops nfs_pageio_read_ops = {
.pg_test = nfs_generic_pg_test,
- .pg_doio = nfs_generic_pg_readpages,
+ .pg_doio = nfs_generic_pg_pgios,
};

/*
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 28fdde2..ebbb663 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -973,33 +973,9 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = {
.completion = nfs_write_completion,
};

-static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
-{
- struct nfs_rw_header *whdr;
- struct nfs_pgio_header *hdr;
- int ret;
-
- whdr = nfs_rw_header_alloc(desc->pg_rw_ops);
- if (!whdr) {
- desc->pg_completion_ops->error_cleanup(&desc->pg_list);
- return -ENOMEM;
- }
- hdr = &whdr->header;
- nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
- atomic_inc(&hdr->refcnt);
- ret = nfs_generic_pgio(desc, hdr);
- if (ret == 0)
- ret = nfs_do_multiple_pgios(&hdr->rpc_list,
- desc->pg_rpc_callops,
- desc->pg_ioflags);
- if (atomic_dec_and_test(&hdr->refcnt))
- hdr->completion_ops->completion(hdr);
- return ret;
-}
-
static const struct nfs_pageio_ops nfs_pageio_write_ops = {
.pg_test = nfs_generic_pg_test,
- .pg_doio = nfs_generic_pg_writepages,
+ .pg_doio = nfs_generic_pg_pgios,
};

void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
--
1.9.2


2014-04-21 12:46:53

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH 00/17] NFS: Create a common path used by reads and writes

On 04/21/2014 02:42 AM, Christoph Hellwig wrote:
> On Thu, Apr 17, 2014 at 05:09:24PM -0400, Anna Schumaker wrote:
>> Questions? Comments? Death threats?
> Can you say what tree this is based on or even better publish a git
> tree? I tried to apply the series to various trees so that I can get a
> better picture for further reviews, but git-am always bailed out
> somewhere.
Oops, sorry! This is based on Trond's testing branch. I can work on putting out a git tree later today!

>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html


2014-04-17 21:10:00

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 04/17] NFS: Create a common read and write header struct

From: Anna Schumaker <[email protected]>

The only difference is the write verifier field, so I leave a comment
saying that it's not used for reads.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 4 ++--
fs/nfs/pnfs.c | 4 ++--
fs/nfs/read.c | 14 +++++++-------
fs/nfs/write.c | 14 +++++++-------
include/linux/nfs_xdr.h | 7 +------
5 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index af01b80..b0e7a41 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -395,7 +395,7 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool

struct nfs_pgio_completion_ops;
/* read.c */
-extern struct nfs_read_header *nfs_readhdr_alloc(void);
+extern struct nfs_rw_header *nfs_readhdr_alloc(void);
extern void nfs_readhdr_free(struct nfs_pgio_header *hdr);
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
struct inode *inode, bool force_mds,
@@ -424,7 +424,7 @@ int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags, bool force_mds,
const struct nfs_pgio_completion_ops *compl_ops);
-extern struct nfs_write_header *nfs_writehdr_alloc(void);
+extern struct nfs_rw_header *nfs_writehdr_alloc(void);
extern void nfs_writehdr_free(struct nfs_pgio_header *hdr);
extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index e9cea3a..43cfe11 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1592,7 +1592,7 @@ EXPORT_SYMBOL_GPL(pnfs_writehdr_free);
int
pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
{
- struct nfs_write_header *whdr;
+ struct nfs_rw_header *whdr;
struct nfs_pgio_header *hdr;
int ret;

@@ -1750,7 +1750,7 @@ EXPORT_SYMBOL_GPL(pnfs_readhdr_free);
int
pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
{
- struct nfs_read_header *rhdr;
+ struct nfs_rw_header *rhdr;
struct nfs_pgio_header *hdr;
int ret;

diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 9e426cc..d29ca36 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -34,9 +34,9 @@ static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops;

static struct kmem_cache *nfs_rdata_cachep;

-struct nfs_read_header *nfs_readhdr_alloc(void)
+struct nfs_rw_header *nfs_readhdr_alloc(void)
{
- struct nfs_read_header *rhdr;
+ struct nfs_rw_header *rhdr;

rhdr = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
if (rhdr) {
@@ -56,7 +56,7 @@ static struct nfs_pgio_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr,
{
struct nfs_pgio_data *data, *prealloc;

- prealloc = &container_of(hdr, struct nfs_read_header, header)->rpc_data;
+ prealloc = &container_of(hdr, struct nfs_rw_header, header)->rpc_data;
if (prealloc->header == NULL)
data = prealloc;
else
@@ -78,7 +78,7 @@ out:

void nfs_readhdr_free(struct nfs_pgio_header *hdr)
{
- struct nfs_read_header *rhdr = container_of(hdr, struct nfs_read_header, header);
+ struct nfs_rw_header *rhdr = container_of(hdr, struct nfs_rw_header, header);

kmem_cache_free(nfs_rdata_cachep, rhdr);
}
@@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(nfs_readhdr_free);
void nfs_readdata_release(struct nfs_pgio_data *rdata)
{
struct nfs_pgio_header *hdr = rdata->header;
- struct nfs_read_header *read_header = container_of(hdr, struct nfs_read_header, header);
+ struct nfs_rw_header *read_header = container_of(hdr, struct nfs_rw_header, header);

put_nfs_open_context(rdata->args.context);
if (rdata->pages.pagevec != rdata->pages.page_array)
@@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(nfs_generic_pagein);

static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
{
- struct nfs_read_header *rhdr;
+ struct nfs_rw_header *rhdr;
struct nfs_pgio_header *hdr;
int ret;

@@ -680,7 +680,7 @@ out:
int __init nfs_init_readpagecache(void)
{
nfs_rdata_cachep = kmem_cache_create("nfs_read_data",
- sizeof(struct nfs_read_header),
+ sizeof(struct nfs_rw_header),
0, SLAB_HWCACHE_ALIGN,
NULL);
if (nfs_rdata_cachep == NULL)
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 3a2fc5c..37c4c98 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -70,9 +70,9 @@ void nfs_commit_free(struct nfs_commit_data *p)
}
EXPORT_SYMBOL_GPL(nfs_commit_free);

-struct nfs_write_header *nfs_writehdr_alloc(void)
+struct nfs_rw_header *nfs_writehdr_alloc(void)
{
- struct nfs_write_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOIO);
+ struct nfs_rw_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOIO);

if (p) {
struct nfs_pgio_header *hdr = &p->header;
@@ -93,7 +93,7 @@ static struct nfs_pgio_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr,
{
struct nfs_pgio_data *data, *prealloc;

- prealloc = &container_of(hdr, struct nfs_write_header, header)->rpc_data;
+ prealloc = &container_of(hdr, struct nfs_rw_header, header)->rpc_data;
if (prealloc->header == NULL)
data = prealloc;
else
@@ -115,7 +115,7 @@ out:

void nfs_writehdr_free(struct nfs_pgio_header *hdr)
{
- struct nfs_write_header *whdr = container_of(hdr, struct nfs_write_header, header);
+ struct nfs_rw_header *whdr = container_of(hdr, struct nfs_rw_header, header);
mempool_free(whdr, nfs_wdata_mempool);
}
EXPORT_SYMBOL_GPL(nfs_writehdr_free);
@@ -123,7 +123,7 @@ EXPORT_SYMBOL_GPL(nfs_writehdr_free);
void nfs_writedata_release(struct nfs_pgio_data *wdata)
{
struct nfs_pgio_header *hdr = wdata->header;
- struct nfs_write_header *write_header = container_of(hdr, struct nfs_write_header, header);
+ struct nfs_rw_header *write_header = container_of(hdr, struct nfs_rw_header, header);

put_nfs_open_context(wdata->args.context);
if (wdata->pages.pagevec != wdata->pages.page_array)
@@ -1253,7 +1253,7 @@ EXPORT_SYMBOL_GPL(nfs_generic_flush);

static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
{
- struct nfs_write_header *whdr;
+ struct nfs_rw_header *whdr;
struct nfs_pgio_header *hdr;
int ret;

@@ -1910,7 +1910,7 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
int __init nfs_init_writepagecache(void)
{
nfs_wdata_cachep = kmem_cache_create("nfs_write_data",
- sizeof(struct nfs_write_header),
+ sizeof(struct nfs_rw_header),
0, SLAB_HWCACHE_ALIGN,
NULL);
if (nfs_wdata_cachep == NULL)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index e7d934a..ff09384 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1293,12 +1293,7 @@ struct nfs_pgio_data {
struct nfs_client *ds_clp; /* pNFS data server */
};

-struct nfs_read_header {
- struct nfs_pgio_header header;
- struct nfs_pgio_data rpc_data;
-};
-
-struct nfs_write_header {
+struct nfs_rw_header {
struct nfs_pgio_header header;
struct nfs_pgio_data rpc_data;
struct nfs_writeverf verf;
--
1.9.2


2014-04-17 21:10:11

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 09/17] NFS: Create a common nfs_pgio_result_common function

From: Anna Schumaker <[email protected]>

Combining these functions will let me make a single nfs_rw_common_ops
struct (see the next patch).

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 1 +
fs/nfs/pageio.c | 23 ++++++++++++++++++++++
fs/nfs/read.c | 25 ++++++++----------------
fs/nfs/write.c | 51 +++++++++++++++++++-----------------------------
include/linux/nfs_fs.h | 1 -
include/linux/nfs_page.h | 2 ++
6 files changed, 54 insertions(+), 49 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 105e2b5..b18cca4 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -402,6 +402,7 @@ extern struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsig
extern void nfs_pgio_data_release(struct nfs_pgio_data *);
extern void nfs_pgio_prepare(struct rpc_task *, void *);
extern void nfs_pgio_release_common(void *);
+extern void nfs_pgio_result_common(struct rpc_task *, void *);

/* read.c */
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index 864d2f7..efbcc44 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -11,6 +11,7 @@

#include "internal.h"

+#define NFSDBG_FACILITY NFSDBG_PAGECACHE

static inline struct nfs_rw_header *NFS_RW_HEADER(struct nfs_pgio_header *hdr)
{
@@ -102,3 +103,25 @@ void nfs_pgio_release_common(void *calldata)
data->header->rw_ops->rw_release(data);
nfs_pgio_data_release(data);
}
+
+static int nfs_pgio_result(struct rpc_task *task, struct nfs_pgio_data *data)
+{
+ struct inode *inode = data->header->inode;
+
+ dprintk("NFS: %s: %5u, (status %d)\n", __func__, task->tk_pid,
+ task->tk_status);
+
+ return data->header->rw_ops->rw_result(task, data, inode);
+}
+
+void nfs_pgio_result_common(struct rpc_task *task, void *calldata)
+{
+ struct nfs_pgio_data *data = calldata;
+
+ if (nfs_pgio_result(task, data) != 0)
+ return;
+ if (task->tk_status < 0)
+ nfs_set_pgio_error(data->header, task->tk_status, data->args.offset);
+ else
+ data->header->rw_ops->rw_result_common(task, data);
+}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 313835b..4f49507 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -388,15 +388,10 @@ static const struct nfs_pageio_ops nfs_pageio_read_ops = {
* This is the callback from RPC telling us whether a reply was
* received or some error occurred (timeout or socket shutdown).
*/
-int nfs_readpage_result(struct rpc_task *task, struct nfs_pgio_data *data)
+static int nfs_readpage_result(struct rpc_task *task, struct nfs_pgio_data *data,
+ struct inode *inode)
{
- struct inode *inode = data->header->inode;
- int status;
-
- dprintk("NFS: %s: %5u, (status %d)\n", __func__, task->tk_pid,
- task->tk_status);
-
- status = NFS_PROTO(inode)->read_done(task, data);
+ int status = NFS_PROTO(inode)->read_done(task, data);
if (status != 0)
return status;

@@ -429,17 +424,11 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_pgio_data *data
rpc_restart_call_prepare(task);
}

-static void nfs_readpage_result_common(struct rpc_task *task, void *calldata)
+static void nfs_readpage_result_common(struct rpc_task *task, struct nfs_pgio_data *data)
{
- struct nfs_pgio_data *data = calldata;
struct nfs_pgio_header *hdr = data->header;

- /* Note the only returns of nfs_readpage_result are 0 and -EAGAIN */
- if (nfs_readpage_result(task, data) != 0)
- return;
- if (task->tk_status < 0)
- nfs_set_pgio_error(hdr, task->tk_status, data->args.offset);
- else if (data->res.eof) {
+ if (data->res.eof) {
loff_t bound;

bound = data->args.offset + data->res.count;
@@ -456,7 +445,7 @@ static void nfs_readpage_result_common(struct rpc_task *task, void *calldata)

static const struct rpc_call_ops nfs_read_common_ops = {
.rpc_call_prepare = nfs_pgio_prepare,
- .rpc_call_done = nfs_readpage_result_common,
+ .rpc_call_done = nfs_pgio_result_common,
.rpc_release = nfs_pgio_release_common,
};

@@ -625,4 +614,6 @@ static const struct nfs_rw_ops nfs_rw_read_ops = {
.rw_mode = FMODE_READ,
.rw_alloc_header = nfs_readhdr_alloc,
.rw_free_header = nfs_readhdr_free,
+ .rw_result = nfs_readpage_result,
+ .rw_result_common = nfs_readpage_result_common,
};
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index b08fb7d..d2351a1 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1255,20 +1255,6 @@ void nfs_commit_prepare(struct rpc_task *task, void *calldata)
NFS_PROTO(data->inode)->commit_rpc_prepare(task, data);
}

-/*
- * Handle a write reply that flushes a whole page.
- *
- * FIXME: There is an inherent race with invalidate_inode_pages and
- * writebacks since the page->count is kept > 1 for as long
- * as the page has a write request pending.
- */
-static void nfs_writeback_done_common(struct rpc_task *task, void *calldata)
-{
- struct nfs_pgio_data *data = calldata;
-
- nfs_writeback_done(task, data);
-}
-
static void nfs_writeback_release_common(struct nfs_pgio_data *data)
{
struct nfs_pgio_header *hdr = data->header;
@@ -1288,7 +1274,7 @@ static void nfs_writeback_release_common(struct nfs_pgio_data *data)

static const struct rpc_call_ops nfs_write_common_ops = {
.rpc_call_prepare = nfs_pgio_prepare,
- .rpc_call_done = nfs_writeback_done_common,
+ .rpc_call_done = nfs_pgio_result_common,
.rpc_release = nfs_pgio_release_common,
};

@@ -1320,16 +1306,11 @@ static int nfs_should_remove_suid(const struct inode *inode)
/*
* This function is called when the WRITE call is complete.
*/
-void nfs_writeback_done(struct rpc_task *task, struct nfs_pgio_data *data)
+static int nfs_writeback_result(struct rpc_task *task, struct nfs_pgio_data *data,
+ struct inode *inode)
{
- struct nfs_pgio_args *argp = &data->args;
- struct nfs_pgio_res *resp = &data->res;
- struct inode *inode = data->header->inode;
int status;

- dprintk("NFS: %5u nfs_writeback_done (status %d)\n",
- task->tk_pid, task->tk_status);
-
/*
* ->write_done will attempt to use post-op attributes to detect
* conflicting writes by other clients. A strict interpretation
@@ -1339,11 +1320,11 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_pgio_data *data)
*/
status = NFS_PROTO(inode)->write_done(task, data);
if (status != 0)
- return;
- nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, resp->count);
+ return status;
+ nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, data->res.count);

#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
- if (resp->verf->committed < argp->stable && task->tk_status >= 0) {
+ if (data->res.verf->committed < data->args.stable && task->tk_status >= 0) {
/* We tried a write call, but the server did not
* commit data to stable storage even though we
* requested it.
@@ -1359,25 +1340,31 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_pgio_data *data)
dprintk("NFS: faulty NFS server %s:"
" (committed = %d) != (stable = %d)\n",
NFS_SERVER(inode)->nfs_client->cl_hostname,
- resp->verf->committed, argp->stable);
+ data->res.verf->committed, data->args.stable);
complain = jiffies + 300 * HZ;
}
}
#endif
- if (task->tk_status < 0) {
- nfs_set_pgio_error(data->header, task->tk_status, argp->offset);
- return;
- }

/* Deal with the suid/sgid bit corner case */
if (nfs_should_remove_suid(inode))
nfs_mark_for_revalidate(inode);
+ return 0;
+}
+
+/*
+ * This function is called when the WRITE call is complete.
+ */
+static void nfs_writeback_result_common(struct rpc_task *task, struct nfs_pgio_data *data)
+{
+ struct nfs_pgio_args *argp = &data->args;
+ struct nfs_pgio_res *resp = &data->res;

if (resp->count < argp->count) {
static unsigned long complain;

/* This a short write! */
- nfs_inc_stats(inode, NFSIOS_SHORTWRITE);
+ nfs_inc_stats(data->header->inode, NFSIOS_SHORTWRITE);

/* Has the server at least made some progress? */
if (resp->count == 0) {
@@ -1911,4 +1898,6 @@ static const struct nfs_rw_ops nfs_rw_write_ops = {
.rw_alloc_header = nfs_writehdr_alloc,
.rw_free_header = nfs_writehdr_free,
.rw_release = nfs_writeback_release_common,
+ .rw_result = nfs_writeback_result,
+ .rw_result_common = nfs_writeback_result_common,
};
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 7e0db56..e12a1d6 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -553,7 +553,6 @@ nfs_have_writebacks(struct inode *inode)
extern int nfs_readpage(struct file *, struct page *);
extern int nfs_readpages(struct file *, struct address_space *,
struct list_head *, unsigned);
-extern int nfs_readpage_result(struct rpc_task *, struct nfs_pgio_data *);
extern int nfs_readpage_async(struct nfs_open_context *, struct inode *,
struct page *);

diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index da00a4d..9477d7a 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -57,6 +57,8 @@ struct nfs_rw_ops {
struct nfs_rw_header *(*rw_alloc_header)(void);
void (*rw_free_header)(struct nfs_rw_header *);
void (*rw_release)(struct nfs_pgio_data *);
+ int (*rw_result)(struct rpc_task *, struct nfs_pgio_data *, struct inode *);
+ void (*rw_result_common)(struct rpc_task *, struct nfs_pgio_data *);
};

struct nfs_pageio_descriptor {
--
1.9.2


2014-04-18 13:56:16

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 01/17] NFS: Create a common argument structure for reads and writes

> /*
> + * Arguments shared by the read and write call.
> + */
> +struct nfs_pgio_args {
> + struct nfs4_sequence_args seq_args;
> + struct nfs_fh * fh;
> + struct nfs_open_context *context;
> + struct nfs_lock_context *lock_context;
> + nfs4_stateid stateid;
> + __u64 offset;
> + __u32 count;
> + enum nfs3_stable_how stable; /* used by write */
> + unsigned int pgbase;
> + struct page ** pages;
> + const u32 * bitmask; /* used by write */
> +};

It might make sense to keep the arguments only used for writes together
at the end of the structure.

Otherwise looks good,

Reviewed-by: Christoph Hellwig <[email protected]>

2014-04-17 21:10:29

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 12/17] NFS: Create a common pgio_error function

From: Anna Schumaker <[email protected]>

At this point, the read and write versions of this function look
identical so both should use the same function.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 1 +
fs/nfs/pageio.c | 15 +++++++++++++++
fs/nfs/read.c | 25 ++++---------------------
fs/nfs/write.c | 25 ++++---------------------
4 files changed, 24 insertions(+), 42 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 7bc36ee..383175e 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -401,6 +401,7 @@ extern struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
extern void nfs_rw_header_free(struct nfs_pgio_header *);
extern struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
extern void nfs_pgio_data_release(struct nfs_pgio_data *);
+extern int nfs_pgio_error(struct nfs_pageio_descriptor *, struct nfs_pgio_header *);
extern void nfs_pgio_rpcsetup(struct nfs_pgio_data *, unsigned int,
unsigned int, int, struct nfs_commit_info *);

diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index fddb3e3..86f6f4d 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -123,6 +123,21 @@ void nfs_pgio_rpcsetup(struct nfs_pgio_data *data,
nfs_fattr_init(&data->fattr);
}

+int nfs_pgio_error(struct nfs_pageio_descriptor *desc,
+ struct nfs_pgio_header *hdr)
+{
+ struct nfs_pgio_data *data;
+
+ set_bit(NFS_IOHDR_REDO, &hdr->flags);
+ while (!list_empty(&hdr->rpc_list)) {
+ data = list_first_entry(&hdr->rpc_list, struct nfs_pgio_data, list);
+ list_del(&data->list);
+ nfs_pgio_data_release(data);
+ }
+ desc->pg_completion_ops->error_cleanup(&desc->pg_list);
+ return -ENOMEM;
+}
+
static void nfs_pgio_prepare(struct rpc_task *task, void *calldata)
{
struct nfs_pgio_data *data = calldata;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 2c33fc3..c623671 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -237,19 +237,6 @@ static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops = {
.completion = nfs_read_completion,
};

-static void nfs_pagein_error(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr)
-{
- set_bit(NFS_IOHDR_REDO, &hdr->flags);
- while (!list_empty(&hdr->rpc_list)) {
- struct nfs_pgio_data *data = list_first_entry(&hdr->rpc_list,
- struct nfs_pgio_data, list);
- list_del(&data->list);
- nfs_pgio_data_release(data);
- }
- desc->pg_completion_ops->error_cleanup(&desc->pg_list);
-}
-
/*
* Generate multiple requests to fill a single page.
*
@@ -278,10 +265,8 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc,
size_t len = min(nbytes,rsize);

data = nfs_pgio_data_alloc(hdr, 1);
- if (!data) {
- nfs_pagein_error(desc, hdr);
- return -ENOMEM;
- }
+ if (!data)
+ return nfs_pgio_error(desc, hdr);
data->pages.pagevec[0] = page;
nfs_pgio_rpcsetup(data, len, offset, 0, NULL);
list_add(&data->list, &hdr->rpc_list);
@@ -305,10 +290,8 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,

data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base,
desc->pg_count));
- if (!data) {
- nfs_pagein_error(desc, hdr);
- return -ENOMEM;
- }
+ if (!data)
+ return nfs_pgio_error(desc, hdr);

pages = data->pages.pagevec;
while (!list_empty(head)) {
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 15f2ffc..1f98f31 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1044,19 +1044,6 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = {
.completion = nfs_write_completion,
};

-static void nfs_flush_error(struct nfs_pageio_descriptor *desc,
- struct nfs_pgio_header *hdr)
-{
- set_bit(NFS_IOHDR_REDO, &hdr->flags);
- while (!list_empty(&hdr->rpc_list)) {
- struct nfs_pgio_data *data = list_first_entry(&hdr->rpc_list,
- struct nfs_pgio_data, list);
- list_del(&data->list);
- nfs_pgio_data_release(data);
- }
- desc->pg_completion_ops->error_cleanup(&desc->pg_list);
-}
-
/*
* Generate multiple small requests to write out a single
* contiguous dirty area on one page.
@@ -1086,10 +1073,8 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc,
size_t len = min(nbytes, wsize);

data = nfs_pgio_data_alloc(hdr, 1);
- if (!data) {
- nfs_flush_error(desc, hdr);
- return -ENOMEM;
- }
+ if (!data)
+ return nfs_pgio_error(desc, hdr);
data->pages.pagevec[0] = page;
nfs_pgio_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo);
list_add(&data->list, &hdr->rpc_list);
@@ -1122,10 +1107,8 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,

data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base,
desc->pg_count));
- if (!data) {
- nfs_flush_error(desc, hdr);
- return -ENOMEM;
- }
+ if (!data)
+ return nfs_pgio_error(desc, hdr);

nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq);
pages = data->pages.pagevec;
--
1.9.2


2014-04-23 14:00:00

by Boaz Harrosh

[permalink] [raw]
Subject: Re: [PATCH 00/17] NFS: Create a common path used by reads and writes

Thanks guys. once you have some combined tree I'll run some tests to help
you out on the pnfs end. I'd test each one separately but if you are going
to do this soon I can lazily just wait ;-)

Thanks
Boaz

On 04/23/2014 04:51 PM, Anna Schumaker wrote:
> We'll make sure it works! I'm about to look through Dros' patches, so I'll know more soon!
>
> Anna
>
> On 04/23/2014 09:42 AM, Weston Andros Adamson wrote:
>> Yeah there are bound to be some conflicts between these two patchsets, but
>> I don’t think it should be too nasty.
>>
>> Anna and I can work together to get both sets into a branch once we get things
>> reviewed.
>>
>> The good news is that we can combine testing efforts - both of these patchsets
>> change the read and write path for all versions of NFS, so we really need to
>> make sure we didn’t break anything. Not that pnfs isn’t important ;)
>>
>> -dros
>>
>> On Apr 23, 2014, at 9:15 AM, Boaz Harrosh <[email protected]> wrote:
>>
>>> On 04/23/2014 03:55 PM, Boaz Harrosh wrote:
>>>> On 04/18/2014 12:09 AM, Anna Schumaker wrote:
>>> <>
>>>> yes please keep
>>>> it on a public tree for quick testing. Perhaps ask Trond to keep
>>>> it on his tree in a branch. (So to get some coverage under the linux-next
>>>> tree mongers from Intel)
>>>>
>>>
>>> BTW: anyone tested how much this conflicts with dros's 17 patches?
>>> (Noticed how it is always 17 patches)
>>> If a brave sole can have both these merged on the same tree it
>>> would be easier for the testing.
>>>
>>> Thanks
>>> Boaz
>>>
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>


2014-04-25 13:02:42

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH 07/17] NFS: Create a common rw_header_alloc and rw_header_free function

On 04/25/2014 08:12 AM, Christoph Hellwig wrote:
> On Mon, Apr 21, 2014 at 12:24:23PM -0400, Anna Schumaker wrote:
>>> Okay. I'll rework everything into the pageio_ops and see how it looks! Maybe I'll see what I can do about updating the pnfs patches while I'm at it.
>> I remember my issue with adding to the nfs_pageio_ops now. The file, object and block layouts along with the generic pnfs code all have their own read and write pageio_ops. Changing all of these seemed more tedious than adding a new struct only in the read and write code.
>
> Indeed, there's more instances in the pnfs code. I was hoping your
> pending pnfs patches were addressing that, and the general code
> duplication between the pnfs and "classic" I/O code.

Sorry, my pnfs patches only touch pnfs.c. I'm hoping to get help from people who know more about each layout driver once they can take a look at what I did here. My new plan is to put them on top of Dros' work.

>
> I guess it's best to put in your patches as-is for now, and maybe in the
> future we can get rid of the pageio_ops once more code is shared with
> the pnfs path.
>

Sure. I'll post a v2 later today that addresses rearranging variables in the combined structs.

Anna

2014-04-17 21:09:50

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 01/17] NFS: Create a common argument structure for reads and writes

From: Anna Schumaker <[email protected]>

Reads and writes have very similar arguments. This patch combines them
together and documents the few fields used only by write.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/nfs2xdr.c | 8 ++++----
fs/nfs/nfs3xdr.c | 8 ++++----
fs/nfs/nfs4proc.c | 4 ++--
fs/nfs/nfs4xdr.c | 10 ++++++----
fs/nfs/read.c | 2 +-
fs/nfs/write.c | 2 +-
include/linux/nfs_xdr.h | 47 +++++++++++++++++++----------------------------
7 files changed, 37 insertions(+), 44 deletions(-)

diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 62db136..461cd8b 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -613,7 +613,7 @@ static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
* };
*/
static void encode_readargs(struct xdr_stream *xdr,
- const struct nfs_readargs *args)
+ const struct nfs_pgio_args *args)
{
u32 offset = args->offset;
u32 count = args->count;
@@ -629,7 +629,7 @@ static void encode_readargs(struct xdr_stream *xdr,

static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
- const struct nfs_readargs *args)
+ const struct nfs_pgio_args *args)
{
encode_readargs(xdr, args);
prepare_reply_buffer(req, args->pages, args->pgbase,
@@ -649,7 +649,7 @@ static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
* };
*/
static void encode_writeargs(struct xdr_stream *xdr,
- const struct nfs_writeargs *args)
+ const struct nfs_pgio_args *args)
{
u32 offset = args->offset;
u32 count = args->count;
@@ -669,7 +669,7 @@ static void encode_writeargs(struct xdr_stream *xdr,

static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
- const struct nfs_writeargs *args)
+ const struct nfs_pgio_args *args)
{
encode_writeargs(xdr, args);
xdr->buf->flags |= XDRBUF_WRITE;
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index fa6d721..02f16c2 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -953,7 +953,7 @@ static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req,
* };
*/
static void encode_read3args(struct xdr_stream *xdr,
- const struct nfs_readargs *args)
+ const struct nfs_pgio_args *args)
{
__be32 *p;

@@ -966,7 +966,7 @@ static void encode_read3args(struct xdr_stream *xdr,

static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
struct xdr_stream *xdr,
- const struct nfs_readargs *args)
+ const struct nfs_pgio_args *args)
{
encode_read3args(xdr, args);
prepare_reply_buffer(req, args->pages, args->pgbase,
@@ -992,7 +992,7 @@ static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
* };
*/
static void encode_write3args(struct xdr_stream *xdr,
- const struct nfs_writeargs *args)
+ const struct nfs_pgio_args *args)
{
__be32 *p;

@@ -1008,7 +1008,7 @@ static void encode_write3args(struct xdr_stream *xdr,

static void nfs3_xdr_enc_write3args(struct rpc_rqst *req,
struct xdr_stream *xdr,
- const struct nfs_writeargs *args)
+ const struct nfs_pgio_args *args)
{
encode_write3args(xdr, args);
xdr->buf->flags |= XDRBUF_WRITE;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 21cd1f2..4794ca6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4055,7 +4055,7 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data)
}

static bool nfs4_read_stateid_changed(struct rpc_task *task,
- struct nfs_readargs *args)
+ struct nfs_pgio_args *args)
{

if (!nfs4_error_stateid_expired(task->tk_status) ||
@@ -4121,7 +4121,7 @@ static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data
}

static bool nfs4_write_stateid_changed(struct rpc_task *task,
- struct nfs_writeargs *args)
+ struct nfs_pgio_args *args)
{

if (!nfs4_error_stateid_expired(task->tk_status) ||
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 73ce8d4..032159c 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1556,7 +1556,8 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr);
}

-static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr)
+static void encode_read(struct xdr_stream *xdr, const struct nfs_pgio_args *args,
+ struct compound_hdr *hdr)
{
__be32 *p;

@@ -1701,7 +1702,8 @@ static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4
encode_nfs4_verifier(xdr, &arg->confirm);
}

-static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
+static void encode_write(struct xdr_stream *xdr, const struct nfs_pgio_args *args,
+ struct compound_hdr *hdr)
{
__be32 *p;

@@ -2451,7 +2453,7 @@ static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr,
* Encode a READ request
*/
static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr,
- struct nfs_readargs *args)
+ struct nfs_pgio_args *args)
{
struct compound_hdr hdr = {
.minorversion = nfs4_xdr_minorversion(&args->seq_args),
@@ -2513,7 +2515,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
* Encode a WRITE request
*/
static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr,
- struct nfs_writeargs *args)
+ struct nfs_pgio_args *args)
{
struct compound_hdr hdr = {
.minorversion = nfs4_xdr_minorversion(&args->seq_args),
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 7f87461..46d5552 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -470,7 +470,7 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)

static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
{
- struct nfs_readargs *argp = &data->args;
+ struct nfs_pgio_args *argp = &data->args;
struct nfs_readres *resp = &data->res;

/* This is a short read! */
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ee6d46f..25ba383 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1388,7 +1388,7 @@ static int nfs_should_remove_suid(const struct inode *inode)
*/
void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
{
- struct nfs_writeargs *argp = &data->args;
+ struct nfs_pgio_args *argp = &data->args;
struct nfs_writeres *resp = &data->res;
struct inode *inode = data->header->inode;
int status;
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 3e8fc1f..9ce2a48 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -491,18 +491,6 @@ struct nfs4_delegreturnres {
/*
* Arguments to the read call.
*/
-struct nfs_readargs {
- struct nfs4_sequence_args seq_args;
- struct nfs_fh * fh;
- struct nfs_open_context *context;
- struct nfs_lock_context *lock_context;
- nfs4_stateid stateid;
- __u64 offset;
- __u32 count;
- unsigned int pgbase;
- struct page ** pages;
-};
-
struct nfs_readres {
struct nfs4_sequence_res seq_res;
struct nfs_fattr * fattr;
@@ -513,20 +501,6 @@ struct nfs_readres {
/*
* Arguments to the write call.
*/
-struct nfs_writeargs {
- struct nfs4_sequence_args seq_args;
- struct nfs_fh * fh;
- struct nfs_open_context *context;
- struct nfs_lock_context *lock_context;
- nfs4_stateid stateid;
- __u64 offset;
- __u32 count;
- enum nfs3_stable_how stable;
- unsigned int pgbase;
- struct page ** pages;
- const u32 * bitmask;
-};
-
struct nfs_write_verifier {
char data[8];
};
@@ -545,6 +519,23 @@ struct nfs_writeres {
};

/*
+ * Arguments shared by the read and write call.
+ */
+struct nfs_pgio_args {
+ struct nfs4_sequence_args seq_args;
+ struct nfs_fh * fh;
+ struct nfs_open_context *context;
+ struct nfs_lock_context *lock_context;
+ nfs4_stateid stateid;
+ __u64 offset;
+ __u32 count;
+ enum nfs3_stable_how stable; /* used by write */
+ unsigned int pgbase;
+ struct page ** pages;
+ const u32 * bitmask; /* used by write */
+};
+
+/*
* Arguments to the commit call.
*/
struct nfs_commitargs {
@@ -1269,7 +1260,7 @@ struct nfs_read_data {
struct list_head list;
struct rpc_task task;
struct nfs_fattr fattr; /* fattr storage */
- struct nfs_readargs args;
+ struct nfs_pgio_args args;
struct nfs_readres res;
unsigned long timestamp; /* For lease renewal */
int (*read_done_cb) (struct rpc_task *task, struct nfs_read_data *data);
@@ -1321,7 +1312,7 @@ struct nfs_write_data {
struct rpc_task task;
struct nfs_fattr fattr;
struct nfs_writeverf verf;
- struct nfs_writeargs args; /* argument struct */
+ struct nfs_pgio_args args; /* argument struct */
struct nfs_writeres res; /* result struct */
unsigned long timestamp; /* For lease renewal */
int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data);
--
1.9.2


2014-04-21 16:24:26

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH 07/17] NFS: Create a common rw_header_alloc and rw_header_free function

On 04/21/2014 09:52 AM, Anna Schumaker wrote:
> On 04/21/2014 09:32 AM, Christoph Hellwig wrote:
>> On Thu, Apr 17, 2014 at 05:09:31PM -0400, Anna Schumaker wrote:
>>> From: Anna Schumaker <[email protected]>
>>>
>>> I create a new struct nfs_rw_ops to decide the differences between reads
>>> and writes. This struct will be set when initializing a new
>>> nfs_pgio_descriptor, and then passed on to the nfs_rw_header when a new
>>> header is allocated.
>> To me it seems like adding this new vector confuses things. From a look
>> at your whole tree it seems like all methods added to it could as well
>> be added to nfs_pageio_ops. In that case we'd still keep separate
>> instances of nfs_pageio_ops for reads and writes, but most methods would
>> be that same. I'm also defintively curious what you have on your
>> sleeves for pnfs.
> Okay. I'll rework everything into the pageio_ops and see how it looks! Maybe I'll see what I can do about updating the pnfs patches while I'm at it.
I remember my issue with adding to the nfs_pageio_ops now. The file, object and block layouts along with the generic pnfs code all have their own read and write pageio_ops. Changing all of these seemed more tedious than adding a new struct only in the read and write code.

>
> Thanks for reviewing all of these!
>
> Anna
>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html


2014-04-17 21:10:09

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 08/17] NFS: Create a common pgio_rpc_prepare function

From: Anna Schumaker <[email protected]>

The read and write paths do exactly the same thing for the rpc_prepare
rpc_op. This patch combines them together into a single function.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 2 ++
fs/nfs/nfs3proc.c | 11 ++---------
fs/nfs/nfs4proc.c | 22 +++-------------------
fs/nfs/pageio.c | 17 +++++++++++++++++
fs/nfs/proc.c | 11 ++---------
fs/nfs/read.c | 19 +++----------------
fs/nfs/write.c | 19 +++++--------------
include/linux/nfs_page.h | 2 ++
include/linux/nfs_xdr.h | 3 +--
9 files changed, 37 insertions(+), 69 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 7e8d311..105e2b5 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -400,6 +400,8 @@ extern struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
extern void nfs_rw_header_free(struct nfs_pgio_header *);
extern struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
extern void nfs_pgio_data_release(struct nfs_pgio_data *);
+extern void nfs_pgio_prepare(struct rpc_task *, void *);
+extern void nfs_pgio_release_common(void *);

/* read.c */
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index d235369..e7daa42 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -812,7 +812,7 @@ static void nfs3_proc_read_setup(struct nfs_pgio_data *data, struct rpc_message
msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ];
}

-static int nfs3_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
+static int nfs3_proc_pgio_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
{
rpc_call_start(task);
return 0;
@@ -834,12 +834,6 @@ static void nfs3_proc_write_setup(struct nfs_pgio_data *data, struct rpc_message
msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE];
}

-static int nfs3_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
-{
- rpc_call_start(task);
- return 0;
-}
-
static void nfs3_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
{
rpc_call_start(task);
@@ -946,11 +940,10 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.fsinfo = nfs3_proc_fsinfo,
.pathconf = nfs3_proc_pathconf,
.decode_dirent = nfs3_decode_dirent,
+ .pgio_rpc_prepare = nfs3_proc_pgio_rpc_prepare,
.read_setup = nfs3_proc_read_setup,
- .read_rpc_prepare = nfs3_proc_read_rpc_prepare,
.read_done = nfs3_read_done,
.write_setup = nfs3_proc_write_setup,
- .write_rpc_prepare = nfs3_proc_write_rpc_prepare,
.write_done = nfs3_write_done,
.commit_setup = nfs3_proc_commit_setup,
.commit_rpc_prepare = nfs3_proc_commit_rpc_prepare,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e793aa9..44fb93a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4089,7 +4089,7 @@ static void nfs4_proc_read_setup(struct nfs_pgio_data *data, struct rpc_message
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
}

-static int nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
+static int nfs4_proc_pgio_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
{
if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
&data->args.seq_args,
@@ -4097,7 +4097,7 @@ static int nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_pgio_dat
task))
return 0;
if (nfs4_set_rw_stateid(&data->args.stateid, data->args.context,
- data->args.lock_context, FMODE_READ) == -EIO)
+ data->args.lock_context, data->header->rw_ops->rw_mode) == -EIO)
return -EIO;
if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags)))
return -EIO;
@@ -4177,21 +4177,6 @@ static void nfs4_proc_write_setup(struct nfs_pgio_data *data, struct rpc_message
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
}

-static int nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
-{
- if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
- &data->args.seq_args,
- &data->res.seq_res,
- task))
- return 0;
- if (nfs4_set_rw_stateid(&data->args.stateid, data->args.context,
- data->args.lock_context, FMODE_WRITE) == -EIO)
- return -EIO;
- if (unlikely(test_bit(NFS_CONTEXT_BAD, &data->args.context->flags)))
- return -EIO;
- return 0;
-}
-
static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
{
nfs4_setup_sequence(NFS_SERVER(data->inode),
@@ -8432,11 +8417,10 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.pathconf = nfs4_proc_pathconf,
.set_capabilities = nfs4_server_capabilities,
.decode_dirent = nfs4_decode_dirent,
+ .pgio_rpc_prepare = nfs4_proc_pgio_rpc_prepare,
.read_setup = nfs4_proc_read_setup,
- .read_rpc_prepare = nfs4_proc_read_rpc_prepare,
.read_done = nfs4_read_done,
.write_setup = nfs4_proc_write_setup,
- .write_rpc_prepare = nfs4_proc_write_rpc_prepare,
.write_done = nfs4_write_done,
.commit_setup = nfs4_proc_commit_setup,
.commit_rpc_prepare = nfs4_proc_commit_rpc_prepare,
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index 05e3500..864d2f7 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -85,3 +85,20 @@ void nfs_pgio_data_release(struct nfs_pgio_data *data)
kfree(data);
}
EXPORT_SYMBOL_GPL(nfs_pgio_data_release);
+
+void nfs_pgio_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs_pgio_data *data = calldata;
+ int err;
+ err = NFS_PROTO(data->header->inode)->pgio_rpc_prepare(task, data);
+ if (err)
+ rpc_exit(task, err);
+}
+
+void nfs_pgio_release_common(void *calldata)
+{
+ struct nfs_pgio_data *data = calldata;
+ if (data->header->rw_ops->rw_release)
+ data->header->rw_ops->rw_release(data);
+ nfs_pgio_data_release(data);
+}
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index c54829e..c171ce1 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -599,7 +599,7 @@ static void nfs_proc_read_setup(struct nfs_pgio_data *data, struct rpc_message *
msg->rpc_proc = &nfs_procedures[NFSPROC_READ];
}

-static int nfs_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
+static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
{
rpc_call_start(task);
return 0;
@@ -621,12 +621,6 @@ static void nfs_proc_write_setup(struct nfs_pgio_data *data, struct rpc_message
msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE];
}

-static int nfs_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_pgio_data *data)
-{
- rpc_call_start(task);
- return 0;
-}
-
static void nfs_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
{
BUG();
@@ -734,11 +728,10 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.fsinfo = nfs_proc_fsinfo,
.pathconf = nfs_proc_pathconf,
.decode_dirent = nfs2_decode_dirent,
+ .pgio_rpc_prepare = nfs_proc_pgio_rpc_prepare,
.read_setup = nfs_proc_read_setup,
- .read_rpc_prepare = nfs_proc_read_rpc_prepare,
.read_done = nfs_read_done,
.write_setup = nfs_proc_write_setup,
- .write_rpc_prepare = nfs_proc_write_rpc_prepare,
.write_done = nfs_write_done,
.commit_setup = nfs_proc_commit_setup,
.commit_rpc_prepare = nfs_proc_commit_rpc_prepare,
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 4cf3577..313835b 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -454,24 +454,10 @@ static void nfs_readpage_result_common(struct rpc_task *task, void *calldata)
nfs_readpage_retry(task, data);
}

-static void nfs_readpage_release_common(void *calldata)
-{
- nfs_pgio_data_release(calldata);
-}
-
-void nfs_read_prepare(struct rpc_task *task, void *calldata)
-{
- struct nfs_pgio_data *data = calldata;
- int err;
- err = NFS_PROTO(data->header->inode)->read_rpc_prepare(task, data);
- if (err)
- rpc_exit(task, err);
-}
-
static const struct rpc_call_ops nfs_read_common_ops = {
- .rpc_call_prepare = nfs_read_prepare,
+ .rpc_call_prepare = nfs_pgio_prepare,
.rpc_call_done = nfs_readpage_result_common,
- .rpc_release = nfs_readpage_release_common,
+ .rpc_release = nfs_pgio_release_common,
};

/*
@@ -636,6 +622,7 @@ void nfs_destroy_readpagecache(void)
}

static const struct nfs_rw_ops nfs_rw_read_ops = {
+ .rw_mode = FMODE_READ,
.rw_alloc_header = nfs_readhdr_alloc,
.rw_free_header = nfs_readhdr_free,
};
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9c5cde3..b08fb7d 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1248,15 +1248,6 @@ void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds);


-void nfs_write_prepare(struct rpc_task *task, void *calldata)
-{
- struct nfs_pgio_data *data = calldata;
- int err;
- err = NFS_PROTO(data->header->inode)->write_rpc_prepare(task, data);
- if (err)
- rpc_exit(task, err);
-}
-
void nfs_commit_prepare(struct rpc_task *task, void *calldata)
{
struct nfs_commit_data *data = calldata;
@@ -1278,9 +1269,8 @@ static void nfs_writeback_done_common(struct rpc_task *task, void *calldata)
nfs_writeback_done(task, data);
}

-static void nfs_writeback_release_common(void *calldata)
+static void nfs_writeback_release_common(struct nfs_pgio_data *data)
{
- struct nfs_pgio_data *data = calldata;
struct nfs_pgio_header *hdr = data->header;
int status = data->task.tk_status;

@@ -1294,13 +1284,12 @@ static void nfs_writeback_release_common(void *calldata)
set_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags);
spin_unlock(&hdr->lock);
}
- nfs_pgio_data_release(data);
}

static const struct rpc_call_ops nfs_write_common_ops = {
- .rpc_call_prepare = nfs_write_prepare,
+ .rpc_call_prepare = nfs_pgio_prepare,
.rpc_call_done = nfs_writeback_done_common,
- .rpc_release = nfs_writeback_release_common,
+ .rpc_release = nfs_pgio_release_common,
};

/*
@@ -1918,6 +1907,8 @@ void nfs_destroy_writepagecache(void)
}

static const struct nfs_rw_ops nfs_rw_write_ops = {
+ .rw_mode = FMODE_WRITE,
.rw_alloc_header = nfs_writehdr_alloc,
.rw_free_header = nfs_writehdr_free,
+ .rw_release = nfs_writeback_release_common,
};
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 5948125..da00a4d 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -53,8 +53,10 @@ struct nfs_pageio_ops {
};

struct nfs_rw_ops {
+ const fmode_t rw_mode;
struct nfs_rw_header *(*rw_alloc_header)(void);
void (*rw_free_header)(struct nfs_rw_header *);
+ void (*rw_release)(struct nfs_pgio_data *);
};

struct nfs_pageio_descriptor {
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index f846507..dacd240 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1428,11 +1428,10 @@ struct nfs_rpc_ops {
struct nfs_pathconf *);
int (*set_capabilities)(struct nfs_server *, struct nfs_fh *);
int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, int);
+ int (*pgio_rpc_prepare)(struct rpc_task *, struct nfs_pgio_data *);
void (*read_setup) (struct nfs_pgio_data *, struct rpc_message *);
- int (*read_rpc_prepare)(struct rpc_task *, struct nfs_pgio_data *);
int (*read_done) (struct rpc_task *, struct nfs_pgio_data *);
void (*write_setup) (struct nfs_pgio_data *, struct rpc_message *);
- int (*write_rpc_prepare)(struct rpc_task *, struct nfs_pgio_data *);
int (*write_done) (struct rpc_task *, struct nfs_pgio_data *);
void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *);
void (*commit_rpc_prepare)(struct rpc_task *, struct nfs_commit_data *);
--
1.9.2


2014-04-21 06:42:07

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 00/17] NFS: Create a common path used by reads and writes

On Thu, Apr 17, 2014 at 05:09:24PM -0400, Anna Schumaker wrote:
> Questions? Comments? Death threats?

Can you say what tree this is based on or even better publish a git
tree? I tried to apply the series to various trees so that I can get a
better picture for further reviews, but git-am always bailed out
somewhere.


2014-04-18 14:03:45

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 06/17] NFS: Create a common pgio_alloc and pgio_release function

On Thu, Apr 17, 2014 at 05:09:30PM -0400, Anna Schumaker wrote:
> From: Anna Schumaker <[email protected]>
>
> These functions are identical for the read and write paths, so combine
> them in a shared file.

Looks good,

Reviewed-by: Christoph Hellwig <[email protected]>

2014-04-21 12:45:34

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH 02/17] NFS: Create a common results structure for reads and writes

On 04/18/2014 09:57 AM, Christoph Hellwig wrote:
>> +struct nfs_pgio_res {
>> + struct nfs4_sequence_res seq_res;
>> + struct nfs_fattr * fattr;
>> + struct nfs_writeverf * verf; /* used by write */
>> + const struct nfs_server *server; /* used by write */
>> + __u32 count;
>> + int eof; /* used by read */
> Same comment as for the previous patch applies here. Also maybe
> this should use a union to overlay the read/write only fields?
I thought about a union, but I didn't know if it was worth it for only one or two differing variables. I can put one in that would make more sense, though. Thanks!

>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html


2014-04-23 13:42:13

by Weston Andros Adamson

[permalink] [raw]
Subject: Re: [PATCH 00/17] NFS: Create a common path used by reads and writes

Yeah there are bound to be some conflicts between these two patchsets, but
I don?t think it should be too nasty.

Anna and I can work together to get both sets into a branch once we get things
reviewed.

The good news is that we can combine testing efforts - both of these patchsets
change the read and write path for all versions of NFS, so we really need to
make sure we didn?t break anything. Not that pnfs isn?t important ;)

-dros

On Apr 23, 2014, at 9:15 AM, Boaz Harrosh <[email protected]> wrote:

> On 04/23/2014 03:55 PM, Boaz Harrosh wrote:
>> On 04/18/2014 12:09 AM, Anna Schumaker wrote:
> <>
>> yes please keep
>> it on a public tree for quick testing. Perhaps ask Trond to keep
>> it on his tree in a branch. (So to get some coverage under the linux-next
>> tree mongers from Intel)
>>
>
> BTW: anyone tested how much this conflicts with dros's 17 patches?
> (Noticed how it is always 17 patches)
> If a brave sole can have both these merged on the same tree it
> would be easier for the testing.
>
> Thanks
> Boaz
>


2014-04-17 21:10:50

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 15/17] NFS: Create a common multiple_pgios() function

From: Anna Schumaker <[email protected]>

Once again, these two functions look identical in the read and write
case. Time to combine them together!

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 1 +
fs/nfs/pageio.c | 29 +++++++++++++++++++++++++++++
fs/nfs/read.c | 32 ++------------------------------
fs/nfs/write.c | 31 +------------------------------
4 files changed, 33 insertions(+), 60 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 027d72c..81c314c 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -402,6 +402,7 @@ extern void nfs_pgio_data_release(struct nfs_pgio_data *);
extern int nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_header *);
extern int nfs_initiate_pgio(struct rpc_clnt *, struct nfs_pgio_data *,
const struct rpc_call_ops *, int, int);
+extern int nfs_do_multiple_pgios(struct list_head *, const struct rpc_call_ops *, int);

/* read.c */
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index c80e611..4a98d54 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -173,6 +173,35 @@ out:
}
EXPORT_SYMBOL_GPL(nfs_initiate_pgio);

+static int nfs_do_pgio(struct nfs_pgio_data *data,
+ const struct rpc_call_ops *call_ops,
+ int how)
+{
+ struct inode *inode = data->header->inode;
+
+ return nfs_initiate_pgio(NFS_CLIENT(inode), data, call_ops, how, 0);
+}
+
+int nfs_do_multiple_pgios(struct list_head *head,
+ const struct rpc_call_ops *call_ops,
+ int how)
+{
+ struct nfs_pgio_data *data;
+ int ret = 0;
+
+ while (!list_empty(head)) {
+ int ret2;
+
+ data = list_first_entry(head, struct nfs_pgio_data, list);
+ list_del_init(&data->list);
+
+ ret2 = nfs_do_pgio(data, call_ops, how);
+ if (ret == 0)
+ ret = ret2;
+ }
+ return ret;
+}
+
static int nfs_pgio_error(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr)
{
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index ebea335..9dd1aeb 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -161,34 +161,6 @@ static void nfs_initiate_read(struct nfs_pgio_data *data, struct rpc_message *ms
NFS_PROTO(inode)->read_setup(data, msg);
}

-static int nfs_do_read(struct nfs_pgio_data *data,
- const struct rpc_call_ops *call_ops)
-{
- struct inode *inode = data->header->inode;
-
- return nfs_initiate_pgio(NFS_CLIENT(inode), data, call_ops, 0, 0);
-}
-
-static int
-nfs_do_multiple_reads(struct list_head *head,
- const struct rpc_call_ops *call_ops)
-{
- struct nfs_pgio_data *data;
- int ret = 0;
-
- while (!list_empty(head)) {
- int ret2;
-
- data = list_first_entry(head, struct nfs_pgio_data, list);
- list_del_init(&data->list);
-
- ret2 = nfs_do_read(data, call_ops);
- if (ret == 0)
- ret = ret2;
- }
- return ret;
-}
-
static void
nfs_async_read_error(struct list_head *head)
{
@@ -222,8 +194,8 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
atomic_inc(&hdr->refcnt);
ret = nfs_generic_pgio(desc, hdr);
if (ret == 0)
- ret = nfs_do_multiple_reads(&hdr->rpc_list,
- desc->pg_rpc_callops);
+ ret = nfs_do_multiple_pgios(&hdr->rpc_list,
+ desc->pg_rpc_callops, 0);
if (atomic_dec_and_test(&hdr->refcnt))
hdr->completion_ops->completion(hdr);
return ret;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 4279f80..28fdde2 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -945,35 +945,6 @@ static void nfs_initiate_write(struct nfs_pgio_data *data, struct rpc_message *m
&task_setup_data->rpc_client, msg, data);
}

-static int nfs_do_write(struct nfs_pgio_data *data,
- const struct rpc_call_ops *call_ops,
- int how)
-{
- struct inode *inode = data->header->inode;
-
- return nfs_initiate_pgio(NFS_CLIENT(inode), data, call_ops, how, 0);
-}
-
-static int nfs_do_multiple_writes(struct list_head *head,
- const struct rpc_call_ops *call_ops,
- int how)
-{
- struct nfs_pgio_data *data;
- int ret = 0;
-
- while (!list_empty(head)) {
- int ret2;
-
- data = list_first_entry(head, struct nfs_pgio_data, list);
- list_del_init(&data->list);
-
- ret2 = nfs_do_write(data, call_ops, how);
- if (ret == 0)
- ret = ret2;
- }
- return ret;
-}
-
/* If a nfs_flush_* function fails, it should remove reqs from @head and
* call this on each, which will prepare them to be retried on next
* writeback using standard nfs.
@@ -1018,7 +989,7 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
atomic_inc(&hdr->refcnt);
ret = nfs_generic_pgio(desc, hdr);
if (ret == 0)
- ret = nfs_do_multiple_writes(&hdr->rpc_list,
+ ret = nfs_do_multiple_pgios(&hdr->rpc_list,
desc->pg_rpc_callops,
desc->pg_ioflags);
if (atomic_dec_and_test(&hdr->refcnt))
--
1.9.2


2014-04-17 21:10:33

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 11/17] NFS: Create a common rpcsetup function for reads and writes

From: Anna Schumaker <[email protected]>

Write adds a little bit of code dealing with flush flags, but since
"how" will always be 0 when reading we can share the code.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 3 +++
fs/nfs/pageio.c | 36 ++++++++++++++++++++++++++++++++++++
fs/nfs/read.c | 26 ++------------------------
fs/nfs/write.c | 46 ++++------------------------------------------
4 files changed, 45 insertions(+), 66 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 798eb47..7bc36ee 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -401,6 +401,8 @@ extern struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
extern void nfs_rw_header_free(struct nfs_pgio_header *);
extern struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
extern void nfs_pgio_data_release(struct nfs_pgio_data *);
+extern void nfs_pgio_rpcsetup(struct nfs_pgio_data *, unsigned int,
+ unsigned int, int, struct nfs_commit_info *);

/* read.c */
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
@@ -449,6 +451,7 @@ extern void nfs_init_commit(struct nfs_commit_data *data,
struct nfs_commit_info *cinfo);
int nfs_scan_commit_list(struct list_head *src, struct list_head *dst,
struct nfs_commit_info *cinfo, int max);
+unsigned long nfs_reqs_to_commit(struct nfs_commit_info *);
int nfs_scan_commit(struct inode *inode, struct list_head *dst,
struct nfs_commit_info *cinfo);
void nfs_mark_request_commit(struct nfs_page *req,
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index f64fd70..fddb3e3 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -87,6 +87,42 @@ void nfs_pgio_data_release(struct nfs_pgio_data *data)
}
EXPORT_SYMBOL_GPL(nfs_pgio_data_release);

+void nfs_pgio_rpcsetup(struct nfs_pgio_data *data,
+ unsigned int count, unsigned int offset,
+ int how, struct nfs_commit_info *cinfo)
+{
+ struct nfs_page *req = data->header->req;
+
+ /* Set up the RPC argument and reply structs
+ * NB: take care not to mess about with data->commit et al. */
+
+ data->args.fh = NFS_FH(data->header->inode);
+ data->args.offset = req_offset(req) + offset;
+ /* pnfs_set_layoutcommit needs this */
+ data->mds_offset = data->args.offset;
+ data->args.pgbase = req->wb_pgbase + offset;
+ data->args.pages = data->pages.pagevec;
+ data->args.count = count;
+ data->args.context = get_nfs_open_context(req->wb_context);
+ data->args.lock_context = req->wb_lock_context;
+ data->args.stable = NFS_UNSTABLE;
+ switch (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) {
+ case 0:
+ break;
+ case FLUSH_COND_STABLE:
+ if (nfs_reqs_to_commit(cinfo))
+ break;
+ default:
+ data->args.stable = NFS_FILE_SYNC;
+ }
+
+ data->res.fattr = &data->fattr;
+ data->res.count = count;
+ data->res.eof = 0;
+ data->res.verf = &data->verf;
+ nfs_fattr_init(&data->fattr);
+}
+
static void nfs_pgio_prepare(struct rpc_task *task, void *calldata)
{
struct nfs_pgio_data *data = calldata;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 98373ba..2c33fc3 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -192,28 +192,6 @@ int nfs_initiate_read(struct rpc_clnt *clnt,
}
EXPORT_SYMBOL_GPL(nfs_initiate_read);

-/*
- * Set up the NFS read request struct
- */
-static void nfs_read_rpcsetup(struct nfs_pgio_data *data,
- unsigned int count, unsigned int offset)
-{
- struct nfs_page *req = data->header->req;
-
- data->args.fh = NFS_FH(data->header->inode);
- data->args.offset = req_offset(req) + offset;
- data->args.pgbase = req->wb_pgbase + offset;
- data->args.pages = data->pages.pagevec;
- data->args.count = count;
- data->args.context = get_nfs_open_context(req->wb_context);
- data->args.lock_context = req->wb_lock_context;
-
- data->res.fattr = &data->fattr;
- data->res.count = count;
- data->res.eof = 0;
- nfs_fattr_init(&data->fattr);
-}
-
static int nfs_do_read(struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops)
{
@@ -305,7 +283,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc,
return -ENOMEM;
}
data->pages.pagevec[0] = page;
- nfs_read_rpcsetup(data, len, offset);
+ nfs_pgio_rpcsetup(data, len, offset, 0, NULL);
list_add(&data->list, &hdr->rpc_list);
nbytes -= len;
offset += len;
@@ -340,7 +318,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,
*pages++ = req->wb_page;
}

- nfs_read_rpcsetup(data, desc->pg_count, 0);
+ nfs_pgio_rpcsetup(data, desc->pg_count, 0, 0, NULL);
list_add(&data->list, &hdr->rpc_list);
desc->pg_rpc_callops = &nfs_pgio_common_ops;
return 0;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e492537..15f2ffc 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -603,7 +603,7 @@ out:
}

#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
-static unsigned long
+unsigned long
nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
{
return cinfo->mds->ncommit;
@@ -660,7 +660,7 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst,
}

#else
-static unsigned long nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
+unsigned long nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
{
return 0;
}
@@ -987,44 +987,6 @@ out:
}
EXPORT_SYMBOL_GPL(nfs_initiate_write);

-/*
- * Set up the argument/result storage required for the RPC call.
- */
-static void nfs_write_rpcsetup(struct nfs_pgio_data *data,
- unsigned int count, unsigned int offset,
- int how, struct nfs_commit_info *cinfo)
-{
- struct nfs_page *req = data->header->req;
-
- /* Set up the RPC argument and reply structs
- * NB: take care not to mess about with data->commit et al. */
-
- data->args.fh = NFS_FH(data->header->inode);
- data->args.offset = req_offset(req) + offset;
- /* pnfs_set_layoutcommit needs this */
- data->mds_offset = data->args.offset;
- data->args.pgbase = req->wb_pgbase + offset;
- data->args.pages = data->pages.pagevec;
- data->args.count = count;
- data->args.context = get_nfs_open_context(req->wb_context);
- data->args.lock_context = req->wb_lock_context;
- data->args.stable = NFS_UNSTABLE;
- switch (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) {
- case 0:
- break;
- case FLUSH_COND_STABLE:
- if (nfs_reqs_to_commit(cinfo))
- break;
- default:
- data->args.stable = NFS_FILE_SYNC;
- }
-
- data->res.fattr = &data->fattr;
- data->res.count = count;
- data->res.verf = &data->verf;
- nfs_fattr_init(&data->fattr);
-}
-
static int nfs_do_write(struct nfs_pgio_data *data,
const struct rpc_call_ops *call_ops,
int how)
@@ -1129,7 +1091,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc,
return -ENOMEM;
}
data->pages.pagevec[0] = page;
- nfs_write_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo);
+ nfs_pgio_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo);
list_add(&data->list, &hdr->rpc_list);
requests++;
nbytes -= len;
@@ -1179,7 +1141,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
desc->pg_ioflags &= ~FLUSH_COND_STABLE;

/* Set up the argument struct */
- nfs_write_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo);
+ nfs_pgio_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo);
list_add(&data->list, &hdr->rpc_list);
desc->pg_rpc_callops = &nfs_pgio_common_ops;
return 0;
--
1.9.2


2014-04-17 21:10:34

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 17/17] NFS: Create a common nfs_pageio_ops struct

At this point the read and write structures look identical, so combine
them into something shared by both.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 2 +-
fs/nfs/pageio.c | 7 ++++++-
fs/nfs/read.c | 10 ++--------
fs/nfs/write.c | 9 ++-------
4 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 0243825..0c22142 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -396,6 +396,7 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool
struct nfs_pgio_completion_ops;

/* pageio.c */
+extern const struct nfs_pageio_ops nfs_pgio_rw_ops;
extern struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
extern void nfs_rw_header_free(struct nfs_pgio_header *);
extern void nfs_pgio_data_release(struct nfs_pgio_data *);
@@ -403,7 +404,6 @@ extern int nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_head
extern int nfs_initiate_pgio(struct rpc_clnt *, struct nfs_pgio_data *,
const struct rpc_call_ops *, int, int);
extern int nfs_do_multiple_pgios(struct list_head *, const struct rpc_call_ops *, int);
-extern int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *);

/* read.c */
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index da01458..b9d06c8 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -312,7 +312,7 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
}
EXPORT_SYMBOL_GPL(nfs_generic_pgio);

-int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc)
+static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc)
{
struct nfs_rw_header *rw_hdr;
struct nfs_pgio_header *hdr;
@@ -379,3 +379,8 @@ static const struct rpc_call_ops nfs_pgio_common_ops = {
.rpc_call_done = nfs_pgio_result_common,
.rpc_release = nfs_pgio_release_common,
};
+
+const struct nfs_pageio_ops nfs_pgio_rw_ops = {
+ .pg_test = nfs_generic_pg_test,
+ .pg_doio = nfs_generic_pg_pgios,
+};
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 8460795..d7e9460 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -28,7 +28,6 @@

#define NFSDBG_FACILITY NFSDBG_PAGECACHE

-static const struct nfs_pageio_ops nfs_pageio_read_ops;
static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops;
static const struct nfs_rw_ops nfs_rw_read_ops;

@@ -58,7 +57,7 @@ void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
const struct nfs_pgio_completion_ops *compl_ops)
{
struct nfs_server *server = NFS_SERVER(inode);
- const struct nfs_pageio_ops *pg_ops = &nfs_pageio_read_ops;
+ const struct nfs_pageio_ops *pg_ops = &nfs_pgio_rw_ops;

#ifdef CONFIG_NFS_V4_1
if (server->pnfs_curr_ld && !force_mds)
@@ -71,7 +70,7 @@ EXPORT_SYMBOL_GPL(nfs_pageio_init_read);

void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
{
- pgio->pg_ops = &nfs_pageio_read_ops;
+ pgio->pg_ops = &nfs_pgio_rw_ops;
pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->rsize;
}
EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds);
@@ -178,11 +177,6 @@ static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops = {
.completion = nfs_read_completion,
};

-static const struct nfs_pageio_ops nfs_pageio_read_ops = {
- .pg_test = nfs_generic_pg_test,
- .pg_doio = nfs_generic_pg_pgios,
-};
-
/*
* This is the callback from RPC telling us whether a reply was
* received or some error occurred (timeout or socket shutdown).
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ebbb663..3483dd4 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -973,17 +973,12 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = {
.completion = nfs_write_completion,
};

-static const struct nfs_pageio_ops nfs_pageio_write_ops = {
- .pg_test = nfs_generic_pg_test,
- .pg_doio = nfs_generic_pg_pgios,
-};
-
void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags, bool force_mds,
const struct nfs_pgio_completion_ops *compl_ops)
{
struct nfs_server *server = NFS_SERVER(inode);
- const struct nfs_pageio_ops *pg_ops = &nfs_pageio_write_ops;
+ const struct nfs_pageio_ops *pg_ops = &nfs_pgio_rw_ops;

#ifdef CONFIG_NFS_V4_1
if (server->pnfs_curr_ld && !force_mds)
@@ -996,7 +991,7 @@ EXPORT_SYMBOL_GPL(nfs_pageio_init_write);

void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
{
- pgio->pg_ops = &nfs_pageio_write_ops;
+ pgio->pg_ops = &nfs_pgio_rw_ops;
pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->wsize;
}
EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds);
--
1.9.2


2014-04-21 12:44:05

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH 01/17] NFS: Create a common argument structure for reads and writes

On 04/18/2014 09:56 AM, Christoph Hellwig wrote:
>> /*
>> + * Arguments shared by the read and write call.
>> + */
>> +struct nfs_pgio_args {
>> + struct nfs4_sequence_args seq_args;
>> + struct nfs_fh * fh;
>> + struct nfs_open_context *context;
>> + struct nfs_lock_context *lock_context;
>> + nfs4_stateid stateid;
>> + __u64 offset;
>> + __u32 count;
>> + enum nfs3_stable_how stable; /* used by write */
>> + unsigned int pgbase;
>> + struct page ** pages;
>> + const u32 * bitmask; /* used by write */
>> +};
> It might make sense to keep the arguments only used for writes together
> at the end of the structure.

Makes sense. I'll fix that up, thanks!

Anna

>
> Otherwise looks good,
>
> Reviewed-by: Christoph Hellwig <[email protected]>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html


2014-04-17 21:09:53

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 02/17] NFS: Create a common results structure for reads and writes

From: Anna Schumaker <[email protected]>

Reads and writes have very similar results. This patch combines the two
structs together with comments to show where the differing fields are
used.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/nfs2xdr.c | 6 +++---
fs/nfs/nfs3xdr.c | 8 ++++----
fs/nfs/nfs4xdr.c | 9 +++++----
fs/nfs/read.c | 2 +-
fs/nfs/write.c | 2 +-
include/linux/nfs_xdr.h | 31 +++++++++++--------------------
6 files changed, 25 insertions(+), 33 deletions(-)

diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 461cd8b..5f61b83 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -103,7 +103,7 @@ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
/*
* typedef opaque nfsdata<>;
*/
-static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result)
+static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_pgio_res *result)
{
u32 recvd, count;
__be32 *p;
@@ -857,7 +857,7 @@ out_default:
* };
*/
static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr,
- struct nfs_readres *result)
+ struct nfs_pgio_res *result)
{
enum nfs_stat status;
int error;
@@ -878,7 +878,7 @@ out_default:
}

static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
- struct nfs_writeres *result)
+ struct nfs_pgio_res *result)
{
/* All NFSv2 writes are "file sync" writes */
result->verf->committed = NFS_FILE_SYNC;
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 02f16c2..8f4cbe7 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -1589,7 +1589,7 @@ out_default:
* };
*/
static int decode_read3resok(struct xdr_stream *xdr,
- struct nfs_readres *result)
+ struct nfs_pgio_res *result)
{
u32 eof, count, ocount, recvd;
__be32 *p;
@@ -1625,7 +1625,7 @@ out_overflow:
}

static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
- struct nfs_readres *result)
+ struct nfs_pgio_res *result)
{
enum nfs_stat status;
int error;
@@ -1673,7 +1673,7 @@ out_status:
* };
*/
static int decode_write3resok(struct xdr_stream *xdr,
- struct nfs_writeres *result)
+ struct nfs_pgio_res *result)
{
__be32 *p;

@@ -1697,7 +1697,7 @@ out_eio:
}

static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr,
- struct nfs_writeres *result)
+ struct nfs_pgio_res *result)
{
enum nfs_stat status;
int error;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 032159c..939ae60 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -5087,7 +5087,8 @@ static int decode_putrootfh(struct xdr_stream *xdr)
return decode_op_hdr(xdr, OP_PUTROOTFH);
}

-static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res)
+static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req,
+ struct nfs_pgio_res *res)
{
__be32 *p;
uint32_t count, eof, recvd;
@@ -5341,7 +5342,7 @@ static int decode_setclientid_confirm(struct xdr_stream *xdr)
return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM);
}

-static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
+static int decode_write(struct xdr_stream *xdr, struct nfs_pgio_res *res)
{
__be32 *p;
int status;
@@ -6638,7 +6639,7 @@ out:
* Decode Read response
*/
static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
- struct nfs_readres *res)
+ struct nfs_pgio_res *res)
{
struct compound_hdr hdr;
int status;
@@ -6663,7 +6664,7 @@ out:
* Decode WRITE response
*/
static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
- struct nfs_writeres *res)
+ struct nfs_pgio_res *res)
{
struct compound_hdr hdr;
int status;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 46d5552..473bba3 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -471,7 +471,7 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
{
struct nfs_pgio_args *argp = &data->args;
- struct nfs_readres *resp = &data->res;
+ struct nfs_pgio_res *resp = &data->res;

/* This is a short read! */
nfs_inc_stats(data->header->inode, NFSIOS_SHORTREAD);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 25ba383..d392a70 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1389,7 +1389,7 @@ static int nfs_should_remove_suid(const struct inode *inode)
void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct nfs_pgio_args *argp = &data->args;
- struct nfs_writeres *resp = &data->res;
+ struct nfs_pgio_res *resp = &data->res;
struct inode *inode = data->header->inode;
int status;

diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9ce2a48..64c0fd2 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -489,16 +489,6 @@ struct nfs4_delegreturnres {
};

/*
- * Arguments to the read call.
- */
-struct nfs_readres {
- struct nfs4_sequence_res seq_res;
- struct nfs_fattr * fattr;
- __u32 count;
- int eof;
-};
-
-/*
* Arguments to the write call.
*/
struct nfs_write_verifier {
@@ -510,14 +500,6 @@ struct nfs_writeverf {
enum nfs3_stable_how committed;
};

-struct nfs_writeres {
- struct nfs4_sequence_res seq_res;
- struct nfs_fattr * fattr;
- struct nfs_writeverf * verf;
- __u32 count;
- const struct nfs_server *server;
-};
-
/*
* Arguments shared by the read and write call.
*/
@@ -535,6 +517,15 @@ struct nfs_pgio_args {
const u32 * bitmask; /* used by write */
};

+struct nfs_pgio_res {
+ struct nfs4_sequence_res seq_res;
+ struct nfs_fattr * fattr;
+ struct nfs_writeverf * verf; /* used by write */
+ const struct nfs_server *server; /* used by write */
+ __u32 count;
+ int eof; /* used by read */
+};
+
/*
* Arguments to the commit call.
*/
@@ -1261,7 +1252,7 @@ struct nfs_read_data {
struct rpc_task task;
struct nfs_fattr fattr; /* fattr storage */
struct nfs_pgio_args args;
- struct nfs_readres res;
+ struct nfs_pgio_res res;
unsigned long timestamp; /* For lease renewal */
int (*read_done_cb) (struct rpc_task *task, struct nfs_read_data *data);
__u64 mds_offset;
@@ -1313,7 +1304,7 @@ struct nfs_write_data {
struct nfs_fattr fattr;
struct nfs_writeverf verf;
struct nfs_pgio_args args; /* argument struct */
- struct nfs_writeres res; /* result struct */
+ struct nfs_pgio_res res; /* result struct */
unsigned long timestamp; /* For lease renewal */
int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data);
__u64 mds_offset; /* Filelayout dense stripe */
--
1.9.2


2014-04-17 21:10:07

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH 07/17] NFS: Create a common rw_header_alloc and rw_header_free function

From: Anna Schumaker <[email protected]>

I create a new struct nfs_rw_ops to decide the differences between reads
and writes. This struct will be set when initializing a new
nfs_pgio_descriptor, and then passed on to the nfs_rw_header when a new
header is allocated.

Signed-off-by: Anna Schumaker <[email protected]>
---
fs/nfs/internal.h | 6 ++----
fs/nfs/pageio.c | 24 ++++++++++++++++++++++++
fs/nfs/pagelist.c | 2 ++
fs/nfs/pnfs.c | 8 ++++----
fs/nfs/read.c | 34 +++++++++++++---------------------
fs/nfs/write.c | 28 ++++++++++++----------------
include/linux/nfs_page.h | 7 +++++++
include/linux/nfs_xdr.h | 1 +
8 files changed, 65 insertions(+), 45 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 7f9d3c4..7e8d311 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -396,12 +396,12 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool
struct nfs_pgio_completion_ops;

/* pageio.c */
+extern struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
+extern void nfs_rw_header_free(struct nfs_pgio_header *);
extern struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
extern void nfs_pgio_data_release(struct nfs_pgio_data *);

/* read.c */
-extern struct nfs_rw_header *nfs_readhdr_alloc(void);
-extern void nfs_readhdr_free(struct nfs_pgio_header *hdr);
extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
struct inode *inode, bool force_mds,
const struct nfs_pgio_completion_ops *compl_ops);
@@ -428,8 +428,6 @@ int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags, bool force_mds,
const struct nfs_pgio_completion_ops *compl_ops);
-extern struct nfs_rw_header *nfs_writehdr_alloc(void);
-extern void nfs_writehdr_free(struct nfs_pgio_header *hdr);
extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr);
extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
diff --git a/fs/nfs/pageio.c b/fs/nfs/pageio.c
index 4b267b2..05e3500 100644
--- a/fs/nfs/pageio.c
+++ b/fs/nfs/pageio.c
@@ -6,6 +6,7 @@
* Copyright (c) 2014 Anna Schumaker <[email protected]>
*/
#include <linux/nfs_fs.h>
+#include <linux/nfs_page.h>
#include <linux/nfs_xdr.h>

#include "internal.h"
@@ -16,6 +17,29 @@ static inline struct nfs_rw_header *NFS_RW_HEADER(struct nfs_pgio_header *hdr)
return container_of(hdr, struct nfs_rw_header, header);
}

+struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *ops)
+{
+ struct nfs_rw_header *header = ops->rw_alloc_header();
+
+ if (header) {
+ struct nfs_pgio_header *hdr = &header->header;
+
+ INIT_LIST_HEAD(&hdr->pages);
+ INIT_LIST_HEAD(&hdr->rpc_list);
+ spin_lock_init(&hdr->lock);
+ atomic_set(&hdr->refcnt, 0);
+ hdr->rw_ops = ops;
+ }
+ return header;
+}
+EXPORT_SYMBOL_GPL(nfs_rw_header_alloc);
+
+void nfs_rw_header_free(struct nfs_pgio_header *hdr)
+{
+ hdr->rw_ops->rw_free_header(NFS_RW_HEADER(hdr));
+}
+EXPORT_SYMBOL_GPL(nfs_rw_header_free);
+
struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *hdr,
unsigned int pagecount)
{
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 2ffebf2..8221706 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -307,6 +307,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
struct inode *inode,
const struct nfs_pageio_ops *pg_ops,
const struct nfs_pgio_completion_ops *compl_ops,
+ const struct nfs_rw_ops *rw_ops,
size_t bsize,
int io_flags)
{
@@ -320,6 +321,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
desc->pg_inode = inode;
desc->pg_ops = pg_ops;
desc->pg_completion_ops = compl_ops;
+ desc->pg_rw_ops = rw_ops;
desc->pg_ioflags = io_flags;
desc->pg_error = 0;
desc->pg_lseg = NULL;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index e192ba6..54c84c1 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1585,7 +1585,7 @@ pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *he
static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)
{
pnfs_put_lseg(hdr->lseg);
- nfs_writehdr_free(hdr);
+ nfs_rw_header_free(hdr);
}
EXPORT_SYMBOL_GPL(pnfs_writehdr_free);

@@ -1596,7 +1596,7 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
struct nfs_pgio_header *hdr;
int ret;

- whdr = nfs_writehdr_alloc();
+ whdr = nfs_rw_header_alloc(desc->pg_rw_ops);
if (!whdr) {
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
pnfs_put_lseg(desc->pg_lseg);
@@ -1743,7 +1743,7 @@ pnfs_do_multiple_reads(struct nfs_pageio_descriptor *desc, struct list_head *hea
static void pnfs_readhdr_free(struct nfs_pgio_header *hdr)
{
pnfs_put_lseg(hdr->lseg);
- nfs_readhdr_free(hdr);
+ nfs_rw_header_free(hdr);
}
EXPORT_SYMBOL_GPL(pnfs_readhdr_free);

@@ -1754,7 +1754,7 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
struct nfs_pgio_header *hdr;
int ret;

- rhdr = nfs_readhdr_alloc();
+ rhdr = nfs_rw_header_alloc(desc->pg_rw_ops);
if (!rhdr) {
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
ret = -ENOMEM;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index ab4c1a5..4cf3577 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -31,33 +31,19 @@
static const struct nfs_pageio_ops nfs_pageio_read_ops;
static const struct rpc_call_ops nfs_read_common_ops;
static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops;
+static const struct nfs_rw_ops nfs_rw_read_ops;

static struct kmem_cache *nfs_rdata_cachep;

-struct nfs_rw_header *nfs_readhdr_alloc(void)
+static struct nfs_rw_header *nfs_readhdr_alloc(void)
{
- struct nfs_rw_header *rhdr;
-
- rhdr = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
- if (rhdr) {
- struct nfs_pgio_header *hdr = &rhdr->header;
-
- INIT_LIST_HEAD(&hdr->pages);
- INIT_LIST_HEAD(&hdr->rpc_list);
- spin_lock_init(&hdr->lock);
- atomic_set(&hdr->refcnt, 0);
- }
- return rhdr;
+ return kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
}
-EXPORT_SYMBOL_GPL(nfs_readhdr_alloc);

-void nfs_readhdr_free(struct nfs_pgio_header *hdr)
+static void nfs_readhdr_free(struct nfs_rw_header *rhdr)
{
- struct nfs_rw_header *rhdr = container_of(hdr, struct nfs_rw_header, header);
-
kmem_cache_free(nfs_rdata_cachep, rhdr);
}
-EXPORT_SYMBOL_GPL(nfs_readhdr_free);

static
int nfs_return_empty_page(struct page *page)
@@ -79,7 +65,8 @@ void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
if (server->pnfs_curr_ld && !force_mds)
pg_ops = server->pnfs_curr_ld->pg_read_ops;
#endif
- nfs_pageio_init(pgio, inode, pg_ops, compl_ops, server->rsize, 0);
+ nfs_pageio_init(pgio, inode, pg_ops, compl_ops, &nfs_rw_read_ops,
+ server->rsize, 0);
}
EXPORT_SYMBOL_GPL(nfs_pageio_init_read);

@@ -375,13 +362,13 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
struct nfs_pgio_header *hdr;
int ret;

- rhdr = nfs_readhdr_alloc();
+ rhdr = nfs_rw_header_alloc(desc->pg_rw_ops);
if (!rhdr) {
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
return -ENOMEM;
}
hdr = &rhdr->header;
- nfs_pgheader_init(desc, hdr, nfs_readhdr_free);
+ nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
atomic_inc(&hdr->refcnt);
ret = nfs_generic_pagein(desc, hdr);
if (ret == 0)
@@ -647,3 +634,8 @@ void nfs_destroy_readpagecache(void)
{
kmem_cache_destroy(nfs_rdata_cachep);
}
+
+static const struct nfs_rw_ops nfs_rw_read_ops = {
+ .rw_alloc_header = nfs_readhdr_alloc,
+ .rw_free_header = nfs_readhdr_free,
+};
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 0dc4d6a..9c5cde3 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -46,6 +46,7 @@ static const struct rpc_call_ops nfs_write_common_ops;
static const struct rpc_call_ops nfs_commit_ops;
static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
+static const struct nfs_rw_ops nfs_rw_write_ops;

static struct kmem_cache *nfs_wdata_cachep;
static mempool_t *nfs_wdata_mempool;
@@ -70,29 +71,19 @@ void nfs_commit_free(struct nfs_commit_data *p)
}
EXPORT_SYMBOL_GPL(nfs_commit_free);

-struct nfs_rw_header *nfs_writehdr_alloc(void)
+static struct nfs_rw_header *nfs_writehdr_alloc(void)
{
struct nfs_rw_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOIO);

- if (p) {
- struct nfs_pgio_header *hdr = &p->header;
-
+ if (p)
memset(p, 0, sizeof(*p));
- INIT_LIST_HEAD(&hdr->pages);
- INIT_LIST_HEAD(&hdr->rpc_list);
- spin_lock_init(&hdr->lock);
- atomic_set(&hdr->refcnt, 0);
- }
return p;
}
-EXPORT_SYMBOL_GPL(nfs_writehdr_alloc);

-void nfs_writehdr_free(struct nfs_pgio_header *hdr)
+static void nfs_writehdr_free(struct nfs_rw_header *whdr)
{
- struct nfs_rw_header *whdr = container_of(hdr, struct nfs_rw_header, header);
mempool_free(whdr, nfs_wdata_mempool);
}
-EXPORT_SYMBOL_GPL(nfs_writehdr_free);

static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
{
@@ -1210,13 +1201,13 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
struct nfs_pgio_header *hdr;
int ret;

- whdr = nfs_writehdr_alloc();
+ whdr = nfs_rw_header_alloc(desc->pg_rw_ops);
if (!whdr) {
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
return -ENOMEM;
}
hdr = &whdr->header;
- nfs_pgheader_init(desc, hdr, nfs_writehdr_free);
+ nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
atomic_inc(&hdr->refcnt);
ret = nfs_generic_flush(desc, hdr);
if (ret == 0)
@@ -1244,7 +1235,8 @@ void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
if (server->pnfs_curr_ld && !force_mds)
pg_ops = server->pnfs_curr_ld->pg_write_ops;
#endif
- nfs_pageio_init(pgio, inode, pg_ops, compl_ops, server->wsize, ioflags);
+ nfs_pageio_init(pgio, inode, pg_ops, compl_ops, &nfs_rw_write_ops,
+ server->wsize, ioflags);
}
EXPORT_SYMBOL_GPL(nfs_pageio_init_write);

@@ -1925,3 +1917,7 @@ void nfs_destroy_writepagecache(void)
kmem_cache_destroy(nfs_wdata_cachep);
}

+static const struct nfs_rw_ops nfs_rw_write_ops = {
+ .rw_alloc_header = nfs_writehdr_alloc,
+ .rw_free_header = nfs_writehdr_free,
+};
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 92ce578..5948125 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -52,6 +52,11 @@ struct nfs_pageio_ops {
int (*pg_doio)(struct nfs_pageio_descriptor *);
};

+struct nfs_rw_ops {
+ struct nfs_rw_header *(*rw_alloc_header)(void);
+ void (*rw_free_header)(struct nfs_rw_header *);
+};
+
struct nfs_pageio_descriptor {
struct list_head pg_list;
unsigned long pg_bytes_written;
@@ -63,6 +68,7 @@ struct nfs_pageio_descriptor {

struct inode *pg_inode;
const struct nfs_pageio_ops *pg_ops;
+ const struct nfs_rw_ops *pg_rw_ops;
int pg_ioflags;
int pg_error;
const struct rpc_call_ops *pg_rpc_callops;
@@ -86,6 +92,7 @@ extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
struct inode *inode,
const struct nfs_pageio_ops *pg_ops,
const struct nfs_pgio_completion_ops *compl_ops,
+ const struct nfs_rw_ops *rw_ops,
size_t bsize,
int how);
extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 4bbd6ad..f846507 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1268,6 +1268,7 @@ struct nfs_pgio_header {
const struct rpc_call_ops *mds_ops;
void (*release) (struct nfs_pgio_header *hdr);
const struct nfs_pgio_completion_ops *completion_ops;
+ const struct nfs_rw_ops *rw_ops;
struct nfs_direct_req *dreq;
void *layout_private;
spinlock_t lock;
--
1.9.2