From: andros@netapp.com
To: bhalevy@panasas.com
Cc: linux-nfs@vger.kernel.org, Andy Adamson <andros@netapp.com>
Subject: [PATCH 44/50] pnfs_submit: filelayout commit
Date: Fri, 13 Aug 2010 17:31:56 -0400 [thread overview]
Message-ID: <1281735122-1496-45-git-send-email-andros@netapp.com> (raw)
In-Reply-To: <1281735122-1496-44-git-send-email-andros@netapp.com>
From: The pNFS Team <linux-nfs@vger.kernel.org>
Signed-off-by: Andy Adamson <andros@netapp.com>
---
fs/nfs/inode.c | 2 +
fs/nfs/nfs4filelayout.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/write.c | 30 +++++---
3 files changed, 192 insertions(+), 11 deletions(-)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 0360336..30d9ac6 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -644,6 +644,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
atomic_inc(&ctx->lock_context.count);
return ctx;
}
+EXPORT_SYMBOL(get_nfs_open_context);
static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
{
@@ -996,6 +997,7 @@ void nfs_fattr_init(struct nfs_fattr *fattr)
fattr->time_start = jiffies;
fattr->gencount = nfs_inc_attr_generation_counter();
}
+EXPORT_SYMBOL(nfs_fattr_init);
struct nfs_fattr *nfs_alloc_fattr(void)
{
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 8c5702b..fea1772 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -501,6 +501,176 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg)
_filelayout_free_lseg(lseg);
}
+/* Allocate a new nfs_write_data struct and initialize */
+static struct nfs_write_data *
+filelayout_clone_write_data(struct nfs_write_data *old)
+{
+ static struct nfs_write_data *new;
+
+ new = nfs_commitdata_alloc();
+ if (!new)
+ goto out;
+ kref_init(&new->refcount);
+ new->parent = old;
+ kref_get(&old->refcount);
+ new->inode = old->inode;
+ new->cred = old->cred;
+ new->args.offset = 0;
+ new->args.count = 0;
+ new->res.count = 0;
+ new->res.fattr = &new->fattr;
+ nfs_fattr_init(&new->fattr);
+ new->res.verf = &new->verf;
+ new->args.context = get_nfs_open_context(old->args.context);
+ new->pdata.lseg = NULL;
+ new->pdata.call_ops = old->pdata.call_ops;
+ new->pdata.how = old->pdata.how;
+out:
+ return new;
+}
+
+static void filelayout_commit_call_done(struct rpc_task *task, void *data)
+{
+ struct nfs_write_data *wdata = (struct nfs_write_data *)data;
+
+ wdata->pdata.call_ops->rpc_call_done(task, data);
+}
+
+static struct rpc_call_ops filelayout_commit_call_ops = {
+ .rpc_call_prepare = nfs_write_prepare,
+ .rpc_call_done = filelayout_commit_call_done,
+ .rpc_release = filelayout_write_release,
+};
+
+/*
+ * Execute a COMMIT op to the MDS or to each data server on which a page
+ * in 'pages' exists.
+ * Invoke the pnfs_commit_complete callback.
+ */
+enum pnfs_try_status
+filelayout_commit(struct nfs_write_data *data, int sync)
+{
+ LIST_HEAD(head);
+ struct nfs_page *req;
+ loff_t file_offset = 0;
+ u16 idx, i;
+ struct list_head **ds_page_list = NULL;
+ u16 *indices_used;
+ int num_indices_seen = 0;
+ const struct rpc_call_ops *call_ops;
+ struct rpc_clnt *clnt;
+ struct nfs_write_data **clone_list = NULL;
+ struct nfs_write_data *dsdata;
+ struct nfs4_pnfs_ds *ds;
+
+ dprintk("%s data %p sync %d\n", __func__, data, sync);
+
+ /* Alloc room for both in one go */
+ ds_page_list = kzalloc((NFS4_PNFS_MAX_MULTI_CNT + 1) *
+ (sizeof(u16) + sizeof(struct list_head *)),
+ GFP_KERNEL);
+ if (!ds_page_list)
+ goto mem_error;
+ indices_used = (u16 *) (ds_page_list + NFS4_PNFS_MAX_MULTI_CNT + 1);
+ /*
+ * Sort pages based on which ds to send to.
+ * MDS is given index equal to NFS4_PNFS_MAX_MULTI_CNT.
+ * Note we are assuming there is only a single lseg in play.
+ * When that is not true, we could first sort on lseg, then
+ * sort within each as we do here.
+ */
+ while (!list_empty(&data->pages)) {
+ req = nfs_list_entry(data->pages.next);
+ nfs_list_remove_request(req);
+ if (!req->wb_lseg ||
+ ((struct nfs4_filelayout_segment *)
+ LSEG_LD_DATA(req->wb_lseg))->commit_through_mds)
+ idx = NFS4_PNFS_MAX_MULTI_CNT;
+ else {
+ file_offset = (loff_t)req->wb_index << PAGE_CACHE_SHIFT;
+ idx = nfs4_fl_calc_ds_index(req->wb_lseg, file_offset);
+ }
+ if (ds_page_list[idx]) {
+ /* Already seen this idx */
+ list_add(&req->wb_list, ds_page_list[idx]);
+ } else {
+ /* New idx not seen so far */
+ list_add_tail(&req->wb_list, &head);
+ indices_used[num_indices_seen++] = idx;
+ }
+ ds_page_list[idx] = &req->wb_list;
+ }
+ /* Once created, clone must be released via call_op */
+ clone_list = kzalloc(num_indices_seen *
+ sizeof(struct nfs_write_data *), GFP_KERNEL);
+ if (!clone_list)
+ goto mem_error;
+ for (i = 0; i < num_indices_seen - 1; i++) {
+ clone_list[i] = filelayout_clone_write_data(data);
+ if (!clone_list[i])
+ goto mem_error;
+ }
+ clone_list[i] = data;
+ /*
+ * Now send off the RPCs to each ds. Note that it is important
+ * that any RPC to the MDS be sent last (or at least after all
+ * clones have been made.)
+ */
+ for (i = 0; i < num_indices_seen; i++) {
+ dsdata = clone_list[i];
+ idx = indices_used[i];
+ list_cut_position(&dsdata->pages, &head, ds_page_list[idx]);
+ if (idx == NFS4_PNFS_MAX_MULTI_CNT) {
+ call_ops = data->pdata.call_ops;;
+ clnt = NFS_CLIENT(dsdata->inode);
+ ds = NULL;
+ } else {
+ struct nfs_fh *fh;
+
+ call_ops = &filelayout_commit_call_ops;
+ req = nfs_list_entry(dsdata->pages.next);
+ ds = nfs4_fl_prepare_ds(req->wb_lseg, idx);
+ if (!ds) {
+ /* Trigger retry of this chunk through MDS */
+ dsdata->task.tk_status = -EIO;
+ data->pdata.call_ops->rpc_release(dsdata);
+ continue;
+ }
+ clnt = ds->ds_clp->cl_rpcclient;
+ dsdata->fldata.ds_nfs_client = ds->ds_clp;
+ file_offset = (loff_t)req->wb_index << PAGE_CACHE_SHIFT;
+ fh = nfs4_fl_select_ds_fh(req->wb_lseg, file_offset);
+ if (fh)
+ dsdata->args.fh = fh;
+ }
+ dprintk("%s: Initiating commit: %llu USE DS:\n",
+ __func__, file_offset);
+ print_ds(ds);
+
+ /* Send COMMIT to data server */
+ nfs_initiate_commit(dsdata, clnt, call_ops, sync);
+ }
+ kfree(clone_list);
+ kfree(ds_page_list);
+ return PNFS_ATTEMPTED;
+
+ mem_error:
+ if (clone_list) {
+ for (i = 0; i < num_indices_seen - 1; i++) {
+ if (!clone_list[i])
+ break;
+ data->pdata.call_ops->rpc_release(clone_list[i]);
+ }
+ kfree(clone_list);
+ }
+ kfree(ds_page_list);
+ /* One of these will be empty, but doesn't hurt to do both */
+ nfs_mark_list_commit(&head);
+ nfs_mark_list_commit(&data->pages);
+ data->pdata.call_ops->rpc_release(data);
+ return PNFS_ATTEMPTED;
+}
+
/* Return the stripesize for the specified file */
ssize_t
filelayout_get_stripesize(struct pnfs_layout_type *layoutid)
@@ -534,6 +704,7 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
}
struct layoutdriver_io_operations filelayout_io_operations = {
+ .commit = filelayout_commit,
.read_pagelist = filelayout_read_pagelist,
.write_pagelist = filelayout_write_pagelist,
.alloc_layout = filelayout_alloc_layout,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 668c4c1..2251551 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -60,6 +60,7 @@ struct nfs_write_data *nfs_commitdata_alloc(void)
}
return p;
}
+EXPORT_SYMBOL(nfs_commitdata_alloc);
void nfs_commit_free(struct nfs_write_data *p)
{
@@ -1395,6 +1396,23 @@ static int nfs_commit_rpcsetup(struct list_head *head,
how, pnfs);
}
+/* Handle memory error during commit */
+void nfs_mark_list_commit(struct list_head *head)
+{
+ struct nfs_page *req;
+
+ while (!list_empty(head)) {
+ req = nfs_list_entry(head->next);
+ nfs_list_remove_request(req);
+ nfs_mark_request_commit(req);
+ dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
+ dec_bdi_stat(req->wb_page->mapping->backing_dev_info,
+ BDI_RECLAIMABLE);
+ nfs_clear_page_tag_locked(req);
+ }
+}
+EXPORT_SYMBOL(nfs_mark_list_commit);
+
/*
* Commit dirty pages
*/
@@ -1402,25 +1420,15 @@ static int
nfs_commit_list(struct inode *inode, struct list_head *head, int how, int pnfs)
{
struct nfs_write_data *data;
- struct nfs_page *req;
data = nfs_commitdata_alloc();
-
if (!data)
goto out_bad;
/* Set up the argument struct */
return nfs_commit_rpcsetup(head, data, how, pnfs);
out_bad:
- while (!list_empty(head)) {
- req = nfs_list_entry(head->next);
- nfs_list_remove_request(req);
- nfs_mark_request_commit(req);
- dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
- dec_bdi_stat(req->wb_page->mapping->backing_dev_info,
- BDI_RECLAIMABLE);
- nfs_clear_page_tag_locked(req);
- }
+ nfs_mark_list_commit(head);
nfs_commit_clear_lock(NFS_I(inode));
return -ENOMEM;
}
--
1.6.2.5
next prev parent reply other threads:[~2010-08-13 21:33 UTC|newest]
Thread overview: 69+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-13 21:31 [PATCH 0/50] Squashed and re-organized pnfs-submit tree andros
2010-08-13 21:31 ` [PATCH 01/50] nfs41: prevent exchange_id from sending server-only flag andros
2010-08-13 21:31 ` [PATCH 02/50] sunrpc: define xdr_decode_opaque_fixed andros
2010-08-13 21:31 ` [PATCH 03/50] sunrpc: don't reset buflen twice in xdr_shrink_pagelen andros
2010-08-13 21:31 ` [PATCH 04/50] nfsd: remove duplicate NFS4_STATEID_SIZE declaration andros
2010-08-13 21:31 ` [PATCH 05/50] pnfs_submit: pnfs and nfslayoutdriver kconfig andros
2010-08-13 21:31 ` [PATCH 06/50] pnfs_submit: introduce include/linux/nfs4_pnfs.h andros
2010-08-13 21:31 ` [PATCH 07/50] pnfs_submit: introduce include/linux/pnfs_xdr.h andros
2010-08-13 21:31 ` [PATCH 08/50] pnfs_submit: introduce fs/nfs/pnfs.h andros
2010-08-13 21:31 ` [PATCH 09/50] pnfs_submit: introduce fs/nfs/pnfs.c andros
2010-08-13 21:31 ` [PATCH 10/50] pnfs_submit: register unregister pnfs module andros
2010-08-13 21:31 ` [PATCH 11/50] pnfs_submit: set and unset pnfs layoutdriver modules andros
2010-08-13 21:31 ` [PATCH 12/50] pnfs_submit: generic pnfs deviceid cache andros
2010-08-13 21:31 ` [PATCH 13/50] pnfs_submit: introduce nfs4layoutdriver module andros
2010-08-13 21:31 ` [PATCH 14/50] pnfs_submit: filelayout data server cache andros
2010-08-13 21:31 ` [PATCH 15/50] pnfs_submit: filelayout deviceid cache andros
2010-08-13 21:31 ` [PATCH 16/50] pnfs_submit: generic getdeviceinfo andros
2010-08-13 21:31 ` [PATCH 17/50] pnfs_submit: filelayout getdeviceinfo andros
2010-08-13 21:31 ` [PATCH 18/50] pnfs-submit: change stateid to be a union andros
2010-08-13 21:31 ` [PATCH 19/50] pnfs_submit: layout header alloc,reference, and destroy andros
2010-08-13 21:31 ` [PATCH 20/50] pnfs_submit: filelayout alloc_layout and free_layout andros
2010-08-13 21:31 ` [PATCH 21/50] pnfs_submit: layout segment alloc, reference, destroy andros
2010-08-13 21:31 ` [PATCH 22/50] pnfs_submit: layoutget andros
2010-08-13 21:31 ` [PATCH 23/50] pnfs_submit: layout helper functions andros
2010-08-13 21:31 ` [PATCH 24/50] pnfs_submit: filelayout layout segment alloc and free andros
2010-08-13 21:31 ` [PATCH 25/50] pnfs_submit: layoutcommit helper functions andros
2010-08-13 21:31 ` [PATCH 26/50] pnfs_submit: layoutcommit andros
2010-08-13 21:31 ` [PATCH 27/50] pnfs_submit: layoutreturn helper functions andros
2010-08-13 21:31 ` [PATCH 28/50] pnfs_submit: layoutreturn andros
2010-08-13 21:31 ` [PATCH 29/50] pnfs_submit: add data server session to nfs4_setup_sequence andros
2010-08-13 21:31 ` [PATCH 30/50] pnfs_submit: update nfs4_async_handle_error for data server andros
2010-08-13 21:31 ` [PATCH 31/50] pnfs_submit: update state renewal for data servers andros
2010-08-13 21:31 ` [PATCH 32/50] pnfs_submit-pageio-helpers.patch andros
2010-08-13 21:31 ` [PATCH 33/50] pnfs_submit: associate layout segmennt with nfs_page andros
2010-08-13 21:31 ` [PATCH 34/50] pnfs_submit: filelayout policy operations andros
2010-08-13 21:31 ` [PATCH 35/50] pnfs_submit: filelayout i/o helpers andros
2010-08-13 21:31 ` [PATCH 36/50] pnfs_submit: generic read andros
2010-08-13 21:31 ` [PATCH 37/50] pnfs_submit: filelayout read andros
2010-08-13 21:31 ` [PATCH 38/50] pnfs_submit: generic write andros
2010-08-13 21:31 ` [PATCH 39/50] pnfs_submit: data server write with no getattr andros
2010-08-13 21:31 ` [PATCH 40/50] pnfs_submit: filelayout write andros
2010-08-13 21:31 ` [PATCH 41/50] pnfs_submit: signal layoutdriver commit andros
2010-08-13 21:31 ` [PATCH 42/50] pnfs_submit: generic commit andros
2010-08-13 21:31 ` [PATCH 43/50] pnfs_submit: data server commit with no getattr andros
2010-08-13 21:31 ` andros [this message]
2010-08-13 21:31 ` [PATCH 45/50] pnfs_submit: cb_layoutrecall andros
2010-08-13 21:31 ` [PATCH 46/50] pnfs_submit: increase NFS_MAX_FILE_IO_SIZE andros
2010-08-13 21:31 ` [PATCH 47/50] SQUASHME pnfs_post_submit: direct i/o andros
2010-08-13 21:32 ` [PATCH 48/50] SQUASHME pnfs_post_submit: layout type enum andros
2010-08-13 21:32 ` [PATCH 49/50] SQUASHME pnfs_post_submit: cb notify deviceid declarations andros
2010-08-13 21:32 ` [PATCH 50/50] SQUASHME pnfs_submit: remove this unused code andros
2010-08-19 20:25 ` Benny Halevy
2010-08-31 16:32 ` Boaz Harrosh
2010-08-31 15:52 ` [PATCH 48/50] SQUASHME pnfs_post_submit: layout type enum Boaz Harrosh
2010-08-18 20:31 ` [PATCH 11/50] pnfs_submit: set and unset pnfs layoutdriver modules Christoph Hellwig
2010-08-18 20:46 ` Benny Halevy
2010-08-19 9:43 ` Christoph Hellwig
2010-08-18 20:29 ` [PATCH 10/50] pnfs_submit: register unregister pnfs module Christoph Hellwig
2010-08-18 20:49 ` Benny Halevy
2010-08-18 20:28 ` [PATCH 09/50] pnfs_submit: introduce fs/nfs/pnfs.c Christoph Hellwig
2010-08-19 17:21 ` J. Bruce Fields
2010-08-18 20:27 ` [PATCH 06/50] pnfs_submit: introduce include/linux/nfs4_pnfs.h Christoph Hellwig
2010-08-18 20:48 ` William A. (Andy) Adamson
2010-08-18 20:50 ` Benny Halevy
2010-08-18 20:25 ` [PATCH 05/50] pnfs_submit: pnfs and nfslayoutdriver kconfig Christoph Hellwig
2010-08-18 21:09 ` Benny Halevy
2010-08-19 9:45 ` Christoph Hellwig
2010-08-20 22:13 ` [PATCH 04/50] nfsd: remove duplicate NFS4_STATEID_SIZE declaration J. Bruce Fields
2010-08-19 20:50 ` [PATCH 0/50] Squashed and re-organized pnfs-submit tree Benny Halevy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1281735122-1496-45-git-send-email-andros@netapp.com \
--to=andros@netapp.com \
--cc=bhalevy@panasas.com \
--cc=linux-nfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).