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>
This commit is contained in:
parent
f79d06f544
commit
00bfa30abe
|
@ -231,13 +231,15 @@ extern void nfs_destroy_writepagecache(void);
|
||||||
|
|
||||||
extern int __init nfs_init_directcache(void);
|
extern int __init nfs_init_directcache(void);
|
||||||
extern void nfs_destroy_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,
|
extern void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
|
||||||
struct nfs_pgio_header *hdr,
|
struct nfs_pgio_header *hdr,
|
||||||
void (*release)(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);
|
void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos);
|
||||||
int nfs_iocounter_wait(struct nfs_io_counter *c);
|
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)
|
static inline void nfs_iocounter_init(struct nfs_io_counter *c)
|
||||||
{
|
{
|
||||||
c->flags = 0;
|
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,
|
extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
|
||||||
struct nfs_pgio_header *hdr);
|
struct nfs_pgio_header *hdr);
|
||||||
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
|
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
|
||||||
extern void nfs_readdata_release(struct nfs_pgio_data *rdata);
|
|
||||||
|
|
||||||
/* super.c */
|
/* super.c */
|
||||||
void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
|
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,
|
extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
|
||||||
struct nfs_pgio_header *hdr);
|
struct nfs_pgio_header *hdr);
|
||||||
extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
|
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 void nfs_commit_free(struct nfs_commit_data *p);
|
||||||
extern int nfs_initiate_write(struct rpc_clnt *clnt,
|
extern int nfs_initiate_write(struct rpc_clnt *clnt,
|
||||||
struct nfs_pgio_data *data,
|
struct nfs_pgio_data *data,
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
static struct kmem_cache *nfs_page_cachep;
|
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;
|
p->npages = pagecount;
|
||||||
if (pagecount <= ARRAY_SIZE(p->page_array))
|
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);
|
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
|
* nfs_pageio_init - initialise a page io descriptor
|
||||||
* @desc: pointer to descriptor
|
* @desc: pointer to descriptor
|
||||||
|
|
|
@ -1536,7 +1536,7 @@ pnfs_write_through_mds(struct nfs_pageio_descriptor *desc,
|
||||||
nfs_pageio_reset_write_mds(desc);
|
nfs_pageio_reset_write_mds(desc);
|
||||||
desc->pg_recoalesce = 1;
|
desc->pg_recoalesce = 1;
|
||||||
}
|
}
|
||||||
nfs_writedata_release(data);
|
nfs_pgio_data_release(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum pnfs_try_status
|
static enum pnfs_try_status
|
||||||
|
@ -1691,7 +1691,7 @@ pnfs_read_through_mds(struct nfs_pageio_descriptor *desc,
|
||||||
nfs_pageio_reset_read_mds(desc);
|
nfs_pageio_reset_read_mds(desc);
|
||||||
desc->pg_recoalesce = 1;
|
desc->pg_recoalesce = 1;
|
||||||
}
|
}
|
||||||
nfs_readdata_release(data);
|
nfs_pgio_data_release(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -51,31 +51,6 @@ struct nfs_rw_header *nfs_readhdr_alloc(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nfs_readhdr_alloc);
|
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)
|
void nfs_readhdr_free(struct nfs_pgio_header *hdr)
|
||||||
{
|
{
|
||||||
struct nfs_rw_header *rhdr = container_of(hdr, struct nfs_rw_header, header);
|
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);
|
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
|
static
|
||||||
int nfs_return_empty_page(struct page *page)
|
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 *data = list_first_entry(&hdr->rpc_list,
|
||||||
struct nfs_pgio_data, list);
|
struct nfs_pgio_data, list);
|
||||||
list_del(&data->list);
|
list_del(&data->list);
|
||||||
nfs_readdata_release(data);
|
nfs_pgio_data_release(data);
|
||||||
}
|
}
|
||||||
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
|
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
|
||||||
}
|
}
|
||||||
|
@ -359,7 +313,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc,
|
||||||
do {
|
do {
|
||||||
size_t len = min(nbytes,rsize);
|
size_t len = min(nbytes,rsize);
|
||||||
|
|
||||||
data = nfs_readdata_alloc(hdr, 1);
|
data = nfs_pgio_data_alloc(hdr, 1);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
nfs_pagein_error(desc, hdr);
|
nfs_pagein_error(desc, hdr);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -385,7 +339,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,
|
||||||
struct nfs_pgio_data *data;
|
struct nfs_pgio_data *data;
|
||||||
struct list_head *head = &desc->pg_list;
|
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));
|
desc->pg_count));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
nfs_pagein_error(desc, hdr);
|
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)
|
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)
|
void nfs_read_prepare(struct rpc_task *task, void *calldata)
|
||||||
|
|
|
@ -87,31 +87,6 @@ struct nfs_rw_header *nfs_writehdr_alloc(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nfs_writehdr_alloc);
|
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)
|
void nfs_writehdr_free(struct nfs_pgio_header *hdr)
|
||||||
{
|
{
|
||||||
struct nfs_rw_header *whdr = container_of(hdr, struct nfs_rw_header, header);
|
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);
|
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)
|
static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
|
||||||
{
|
{
|
||||||
ctx->error = 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 *data = list_first_entry(&hdr->rpc_list,
|
||||||
struct nfs_pgio_data, list);
|
struct nfs_pgio_data, list);
|
||||||
list_del(&data->list);
|
list_del(&data->list);
|
||||||
nfs_writedata_release(data);
|
nfs_pgio_data_release(data);
|
||||||
}
|
}
|
||||||
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
|
desc->pg_completion_ops->error_cleanup(&desc->pg_list);
|
||||||
}
|
}
|
||||||
|
@ -1179,7 +1133,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc,
|
||||||
do {
|
do {
|
||||||
size_t len = min(nbytes, wsize);
|
size_t len = min(nbytes, wsize);
|
||||||
|
|
||||||
data = nfs_writedata_alloc(hdr, 1);
|
data = nfs_pgio_data_alloc(hdr, 1);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
nfs_flush_error(desc, hdr);
|
nfs_flush_error(desc, hdr);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1214,7 +1168,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
|
||||||
struct list_head *head = &desc->pg_list;
|
struct list_head *head = &desc->pg_list;
|
||||||
struct nfs_commit_info cinfo;
|
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));
|
desc->pg_count));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
nfs_flush_error(desc, hdr);
|
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);
|
set_bit(NFS_IOHDR_NEED_RESCHED, &hdr->flags);
|
||||||
spin_unlock(&hdr->lock);
|
spin_unlock(&hdr->lock);
|
||||||
}
|
}
|
||||||
nfs_writedata_release(data);
|
nfs_pgio_data_release(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct rpc_call_ops nfs_write_common_ops = {
|
static const struct rpc_call_ops nfs_write_common_ops = {
|
||||||
|
|
Loading…
Reference in New Issue