From: andros@netapp.com
To: bhalevy@panasas.com
Cc: linux-nfs@vger.kernel.org, Andy Adamson <andros@netapp.com>
Subject: [PATCH 42/50] pnfs_submit: generic commit
Date: Fri, 13 Aug 2010 17:31:54 -0400 [thread overview]
Message-ID: <1281735122-1496-43-git-send-email-andros@netapp.com> (raw)
In-Reply-To: <1281735122-1496-42-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/internal.h | 8 ++++
fs/nfs/nfs4proc.c | 14 ++++++-
fs/nfs/pnfs.c | 37 ++++++++++++++++
fs/nfs/pnfs.h | 3 +
fs/nfs/write.c | 99 ++++++++++++++++++++++++++++++++------------
include/linux/nfs4_pnfs.h | 7 +++
include/linux/nfs_iostat.h | 1 +
7 files changed, 141 insertions(+), 28 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 02f0da8..ae8b895 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -276,6 +276,14 @@ extern int pnfs_initiate_write(struct nfs_write_data *data,
struct rpc_clnt *clnt,
const struct rpc_call_ops *call_ops,
int how);
+extern int nfs_initiate_commit(struct nfs_write_data *data,
+ struct rpc_clnt *clnt,
+ const struct rpc_call_ops *call_ops,
+ int how);
+extern int pnfs_initiate_commit(struct nfs_write_data *data,
+ struct rpc_clnt *clnt,
+ const struct rpc_call_ops *call_ops,
+ int how, int pnfs);
extern void nfs_write_prepare(struct rpc_task *task, void *calldata);
extern void nfs_mark_list_commit(struct list_head *head);
#ifdef CONFIG_MIGRATION
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 44ffa33..55aba4c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3233,6 +3233,17 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct inode *inode = data->inode;
+ struct nfs_server *server = NFS_SERVER(data->inode);
+ struct nfs_client *client = server->nfs_client;
+
+#ifdef CONFIG_NFS_V4_1
+ /* Is this a DS session */
+ if (data->fldata.ds_nfs_client) {
+ dprintk("%s DS commit\n", __func__);
+ client = data->fldata.ds_nfs_client;
+ }
+#endif /* CONFIG_NFS_V4_1 */
+
if (!nfs4_sequence_done(task, &data->res.seq_res))
return -EAGAIN;
@@ -3240,7 +3251,8 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
return -EAGAIN;
}
- nfs_refresh_inode(inode, data->res.fattr);
+ if (client == server->nfs_client)
+ nfs_refresh_inode(inode, data->res.fattr);
return 0;
}
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 424efce..393855e 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -260,6 +260,14 @@ pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
return NULL;
}
+ if (!io_ops->read_pagelist || !io_ops->write_pagelist ||
+ !io_ops->commit) {
+ printk(KERN_ERR "%s Layout driver must provide "
+ "read_pagelist, write_pagelist, and commit.\n",
+ __func__);
+ return NULL;
+ }
+
pnfs_mod = kmalloc(sizeof(struct pnfs_module), GFP_KERNEL);
if (pnfs_mod != NULL) {
dprintk("%s Registering id:%u name:%s\n",
@@ -1323,6 +1331,35 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata,
return trypnfs;
}
+enum pnfs_try_status
+pnfs_try_to_commit(struct nfs_write_data *data,
+ const struct rpc_call_ops *call_ops, int sync)
+{
+ struct inode *inode = data->inode;
+ struct nfs_server *nfss = NFS_SERVER(data->inode);
+ enum pnfs_try_status trypnfs;
+
+ dprintk("%s: Begin\n", __func__);
+
+ /* We need to account for possibility that
+ * each nfs_page can point to a different lseg (or be NULL).
+ * For the immediate case of whole-file-only layouts, we at
+ * least know there can be only a single lseg.
+ * We still have to account for the possibility of some being NULL.
+ * This will be done by passing the buck to the layout driver.
+ */
+ data->pdata.call_ops = call_ops;
+ data->pdata.how = sync;
+ data->pdata.lseg = NULL;
+ trypnfs = nfss->pnfs_curr_ld->ld_io_ops->commit(data, sync);
+ if (trypnfs == PNFS_NOT_ATTEMPTED)
+ _pnfs_clear_lseg_from_pages(&data->pages);
+ else
+ nfs_inc_stats(inode, NFSIOS_PNFS_COMMIT);
+ dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs);
+ return trypnfs;
+}
+
/*
* Set up the argument/result storage required for the RPC call.
*/
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index b110f4e..80f67c7 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -50,6 +50,9 @@ void pnfs_layoutcommit_free(struct pnfs_layoutcommit_data *data);
int pnfs_layoutcommit_inode(struct inode *inode, int sync);
void pnfs_update_last_write(struct nfs_inode *nfsi, loff_t offset, size_t extent);
void pnfs_need_layoutcommit(struct nfs_inode *nfsi, struct nfs_open_context *ctx);
+unsigned int pnfs_getiosize(struct nfs_server *server);
+enum pnfs_try_status pnfs_try_to_commit(struct nfs_write_data *,
+ const struct rpc_call_ops *, int);
void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *,
struct nfs_open_context *, struct list_head *);
void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 18926d3..668c4c1 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1311,40 +1311,72 @@ static void nfs_commitdata_release(void *data)
nfs_commit_free(wdata);
}
-/*
- * Set up the argument/result storage required for the RPC call.
- */
-static int nfs_commit_rpcsetup(struct list_head *head,
- struct nfs_write_data *data,
- int how)
+int nfs_initiate_commit(struct nfs_write_data *data,
+ struct rpc_clnt *clnt,
+ const struct rpc_call_ops *call_ops,
+ int how)
{
- struct nfs_page *first = nfs_list_entry(head->next);
- struct inode *inode = first->wb_context->path.dentry->d_inode;
+ struct inode *inode = data->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 = first->wb_context->cred,
+ .rpc_cred = data->cred,
};
struct rpc_task_setup task_setup_data = {
.task = &data->task,
- .rpc_client = NFS_CLIENT(inode),
+ .rpc_client = clnt,
.rpc_message = &msg,
- .callback_ops = &nfs_commit_ops,
+ .callback_ops = call_ops,
.callback_data = data,
.workqueue = nfsiod_workqueue,
.flags = RPC_TASK_ASYNC,
.priority = priority,
};
+ /* Set up the initial task struct. */
+ NFS_PROTO(inode)->commit_setup(data, &msg);
+
+ dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
+
+ task = rpc_run_task(&task_setup_data);
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+ rpc_put_task(task);
+ return 0;
+}
+EXPORT_SYMBOL(nfs_initiate_commit);
+
+
+int pnfs_initiate_commit(struct nfs_write_data *data,
+ struct rpc_clnt *clnt,
+ const struct rpc_call_ops *call_ops,
+ int how, int pnfs)
+{
+ if (pnfs &&
+ (pnfs_try_to_commit(data, &nfs_commit_ops, how) == PNFS_ATTEMPTED))
+ return 0;
+ return nfs_initiate_commit(data, clnt, &nfs_commit_ops, how);
+}
+
+/*
+ * Set up the argument/result storage required for the RPC call.
+ */
+static int nfs_commit_rpcsetup(struct list_head *head,
+ struct nfs_write_data *data,
+ int how, int pnfs)
+{
+ struct nfs_page *first = nfs_list_entry(head->next);
+ struct inode *inode = first->wb_context->path.dentry->d_inode;
+
/* Set up the RPC argument and reply structs
* NB: take care not to mess about with data->commit et al. */
list_splice_init(head, &data->pages);
data->inode = inode;
- data->cred = msg.rpc_cred;
+ data->cred = first->wb_context->cred;
data->args.fh = NFS_FH(data->inode);
/* Note: we always request a commit of the entire inode */
@@ -1355,24 +1387,19 @@ static int nfs_commit_rpcsetup(struct list_head *head,
data->res.fattr = &data->fattr;
data->res.verf = &data->verf;
nfs_fattr_init(&data->fattr);
+ kref_init(&data->refcount);
+ data->parent = NULL;
+ data->args.context = first->wb_context; /* used by commit done */
- /* Set up the initial task struct. */
- NFS_PROTO(inode)->commit_setup(data, &msg);
-
- dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
-
- task = rpc_run_task(&task_setup_data);
- if (IS_ERR(task))
- return PTR_ERR(task);
- rpc_put_task(task);
- return 0;
+ return pnfs_initiate_commit(data, NFS_CLIENT(inode), &nfs_commit_ops,
+ how, pnfs);
}
/*
* Commit dirty pages
*/
static int
-nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+nfs_commit_list(struct inode *inode, struct list_head *head, int how, int pnfs)
{
struct nfs_write_data *data;
struct nfs_page *req;
@@ -1383,7 +1410,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
goto out_bad;
/* Set up the argument struct */
- return nfs_commit_rpcsetup(head, data, how);
+ return nfs_commit_rpcsetup(head, data, how, pnfs);
out_bad:
while (!list_empty(head)) {
req = nfs_list_entry(head->next);
@@ -1413,6 +1440,19 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
return;
}
+static inline void nfs_commit_cleanup(struct kref *kref)
+{
+ struct nfs_write_data *data;
+
+ data = container_of(kref, struct nfs_write_data, refcount);
+ /* Clear lock only when all cloned commits are finished */
+ if (data->parent)
+ kref_put(&data->parent->refcount, nfs_commit_cleanup);
+ else
+ nfs_commit_clear_lock(NFS_I(data->inode));
+ nfs_commitdata_release(data);
+}
+
static void nfs_commit_release(void *calldata)
{
struct nfs_write_data *data = calldata;
@@ -1430,6 +1470,11 @@ static void nfs_commit_release(void *calldata)
req->wb_bytes,
(long long)req_offset(req));
if (status < 0) {
+ if (req->wb_lseg) {
+ nfs_mark_request_nopnfs(req);
+ nfs_mark_request_dirty(req);
+ goto next;
+ }
nfs_context_set_write_error(req->wb_context, status);
nfs_inode_remove_request(req);
dprintk(", error = %d\n", status);
@@ -1446,12 +1491,12 @@ static void nfs_commit_release(void *calldata)
}
/* We have a mismatch. Write the page again */
dprintk(" mismatch\n");
+ nfs_mark_request_nopnfs(req);
nfs_mark_request_dirty(req);
next:
nfs_clear_page_tag_locked(req);
}
- nfs_commit_clear_lock(NFS_I(data->inode));
- nfs_commitdata_release(calldata);
+ kref_put(&data->refcount, nfs_commit_cleanup);
}
static const struct rpc_call_ops nfs_commit_ops = {
@@ -1475,7 +1520,7 @@ int nfs_commit_inode(struct inode *inode, int how)
res = nfs_scan_commit(inode, &head, 0, 0, &use_pnfs);
spin_unlock(&inode->i_lock);
if (res) {
- int error = nfs_commit_list(inode, &head, how);
+ int error = nfs_commit_list(inode, &head, how, use_pnfs);
if (error < 0)
return error;
if (may_wait) {
diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
index b010ff1..ef160e6 100644
--- a/include/linux/nfs4_pnfs.h
+++ b/include/linux/nfs4_pnfs.h
@@ -124,6 +124,13 @@ struct layoutdriver_io_operations {
enum pnfs_try_status
(*write_pagelist) (struct nfs_write_data *nfs_data, unsigned nr_pages, int how);
+ /* Consistency ops */
+ /* 2 problems:
+ * 1) the page list contains nfs_pages, NOT pages
+ * 2) currently the NFS code doesn't create a page array (as it does with read/write)
+ */
+ enum pnfs_try_status
+ (*commit) (struct nfs_write_data *nfs_data, int how);
/* Layout information. For each inode, alloc_layout is executed once to retrieve an
* inode specific layout structure. Each subsequent layoutget operation results in
diff --git a/include/linux/nfs_iostat.h b/include/linux/nfs_iostat.h
index 8866bb3..f9b5f44 100644
--- a/include/linux/nfs_iostat.h
+++ b/include/linux/nfs_iostat.h
@@ -115,6 +115,7 @@ enum nfs_stat_eventcounters {
NFSIOS_DELAY,
NFSIOS_PNFS_READ,
NFSIOS_PNFS_WRITE,
+ NFSIOS_PNFS_COMMIT,
__NFSIOS_COUNTSMAX,
};
--
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 ` andros [this message]
2010-08-13 21:31 ` [PATCH 43/50] pnfs_submit: data server commit with no getattr andros
2010-08-13 21:31 ` [PATCH 44/50] pnfs_submit: filelayout commit andros
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-43-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).