summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Schumaker <Anna.Schumaker@netapp.com>2014-05-06 09:12:29 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-05-28 18:39:55 -0400
commit00bfa30abe86982ce1929e9cabd703e5546106bd (patch)
tree902a6cf951f53be35916332635016ad0378c60b7
parentf79d06f544a797d75cbf5256a5d06c4b3d2759cc (diff)
downloadlwn-00bfa30abe86982ce1929e9cabd703e5546106bd.tar.gz
lwn-00bfa30abe86982ce1929e9cabd703e5546106bd.zip
NFS: Create a common pgio_alloc and pgio_release function
These functions are identical for the read and write paths so they can be combined. Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/internal.h6
-rw-r--r--fs/nfs/pagelist.c62
-rw-r--r--fs/nfs/pnfs.c4
-rw-r--r--fs/nfs/read.c54
-rw-r--r--fs/nfs/write.c54
5 files changed, 74 insertions, 106 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b0e7a41d14a8..5ddc142c5062 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -231,13 +231,15 @@ extern void nfs_destroy_writepagecache(void);
extern int __init nfs_init_directcache(void);
extern void nfs_destroy_directcache(void);
-extern bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount);
extern void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr,
void (*release)(struct nfs_pgio_header *hdr));
void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos);
int nfs_iocounter_wait(struct nfs_io_counter *c);
+struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
+void nfs_pgio_data_release(struct nfs_pgio_data *);
+
static inline void nfs_iocounter_init(struct nfs_io_counter *c)
{
c->flags = 0;
@@ -407,7 +409,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 +430,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/pagelist.c b/fs/nfs/pagelist.c
index 2ffebf2081ce..a98ccf722d7b 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -26,7 +26,7 @@
static struct kmem_cache *nfs_page_cachep;
-bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount)
+static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount)
{
p->npages = pagecount;
if (pagecount <= ARRAY_SIZE(p->page_array))
@@ -295,6 +295,66 @@ bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *pr
}
EXPORT_SYMBOL_GPL(nfs_generic_pg_test);
+static inline struct nfs_rw_header *NFS_RW_HEADER(struct nfs_pgio_header *hdr)
+{
+ return container_of(hdr, struct nfs_rw_header, header);
+}
+
+/**
+ * nfs_pgio_data_alloc - Allocate pageio data
+ * @hdr: The header making a request
+ * @pagecount: Number of pages to create
+ */
+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;
+}
+
+/**
+ * nfs_pgio_data_release - Properly free pageio data
+ * @data: The data to release
+ */
+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);
+
/**
* nfs_pageio_init - initialise a page io descriptor
* @desc: pointer to descriptor
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 43cfe11aa1a4..e192ba69a7d4 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 d29ca3673694..ab4c1a5b5fbd 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 321a791c72bf..0dc4d6a28bd0 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 = {