aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2010-10-20 00:18:03 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-24 18:07:10 -0400
commitb1f69b754ee312ec75f2c7ead0e6851cd9598cc2 (patch)
tree1d8e70abb2cd087e3b97f73d86db8b9568467378 /fs/nfs/nfs4proc.c
parent974cec8ca0352eb5d281535b714cf194a606e98f (diff)
NFSv4.1: pnfs: add LAYOUTGET and GETDEVICEINFO infrastructure
Add the ability to actually send LAYOUTGET and GETDEVICEINFO. This also adds in the machinery to handle layout state and the deviceid cache. Note that GETDEVICEINFO is not called directly by the generic layer. Instead it is called by the drivers while parsing the LAYOUTGET opaque data in response to an unknown device id embedded therein. RFC 5661 only encodes device ids within the driver-specific opaque data. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Dean Hildebrand <dhildebz@umich.edu> Signed-off-by: Marc Eshel <eshel@almaden.ibm.com> Signed-off-by: Mike Sager <sager@netapp.com> Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com> Signed-off-by: Tao Guo <guotao@nrchpc.ac.cn> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a5f1edb45b47..7e14e991ddfa 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -55,6 +55,7 @@
55#include "internal.h" 55#include "internal.h"
56#include "iostat.h" 56#include "iostat.h"
57#include "callback.h" 57#include "callback.h"
58#include "pnfs.h"
58 59
59#define NFSDBG_FACILITY NFSDBG_PROC 60#define NFSDBG_FACILITY NFSDBG_PROC
60 61
@@ -5256,6 +5257,147 @@ out:
5256 dprintk("<-- %s status=%d\n", __func__, status); 5257 dprintk("<-- %s status=%d\n", __func__, status);
5257 return status; 5258 return status;
5258} 5259}
5260
5261static void
5262nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
5263{
5264 struct nfs4_layoutget *lgp = calldata;
5265 struct inode *ino = lgp->args.inode;
5266 struct nfs_server *server = NFS_SERVER(ino);
5267
5268 dprintk("--> %s\n", __func__);
5269 if (nfs4_setup_sequence(server, &lgp->args.seq_args,
5270 &lgp->res.seq_res, 0, task))
5271 return;
5272 rpc_call_start(task);
5273}
5274
5275static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
5276{
5277 struct nfs4_layoutget *lgp = calldata;
5278 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
5279
5280 dprintk("--> %s\n", __func__);
5281
5282 if (!nfs4_sequence_done(task, &lgp->res.seq_res))
5283 return;
5284
5285 switch (task->tk_status) {
5286 case 0:
5287 break;
5288 case -NFS4ERR_LAYOUTTRYLATER:
5289 case -NFS4ERR_RECALLCONFLICT:
5290 task->tk_status = -NFS4ERR_DELAY;
5291 /* Fall through */
5292 default:
5293 if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
5294 rpc_restart_call_prepare(task);
5295 return;
5296 }
5297 }
5298 lgp->status = task->tk_status;
5299 dprintk("<-- %s\n", __func__);
5300}
5301
5302static void nfs4_layoutget_release(void *calldata)
5303{
5304 struct nfs4_layoutget *lgp = calldata;
5305
5306 dprintk("--> %s\n", __func__);
5307 put_layout_hdr(lgp->args.inode);
5308 if (lgp->res.layout.buf != NULL)
5309 free_page((unsigned long) lgp->res.layout.buf);
5310 put_nfs_open_context(lgp->args.ctx);
5311 kfree(calldata);
5312 dprintk("<-- %s\n", __func__);
5313}
5314
5315static const struct rpc_call_ops nfs4_layoutget_call_ops = {
5316 .rpc_call_prepare = nfs4_layoutget_prepare,
5317 .rpc_call_done = nfs4_layoutget_done,
5318 .rpc_release = nfs4_layoutget_release,
5319};
5320
5321int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
5322{
5323 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
5324 struct rpc_task *task;
5325 struct rpc_message msg = {
5326 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
5327 .rpc_argp = &lgp->args,
5328 .rpc_resp = &lgp->res,
5329 };
5330 struct rpc_task_setup task_setup_data = {
5331 .rpc_client = server->client,
5332 .rpc_message = &msg,
5333 .callback_ops = &nfs4_layoutget_call_ops,
5334 .callback_data = lgp,
5335 .flags = RPC_TASK_ASYNC,
5336 };
5337 int status = 0;
5338
5339 dprintk("--> %s\n", __func__);
5340
5341 lgp->res.layout.buf = (void *)__get_free_page(GFP_NOFS);
5342 if (lgp->res.layout.buf == NULL) {
5343 nfs4_layoutget_release(lgp);
5344 return -ENOMEM;
5345 }
5346
5347 lgp->res.seq_res.sr_slot = NULL;
5348 task = rpc_run_task(&task_setup_data);
5349 if (IS_ERR(task))
5350 return PTR_ERR(task);
5351 status = nfs4_wait_for_completion_rpc_task(task);
5352 if (status != 0)
5353 goto out;
5354 status = lgp->status;
5355 if (status != 0)
5356 goto out;
5357 status = pnfs_layout_process(lgp);
5358out:
5359 rpc_put_task(task);
5360 dprintk("<-- %s status=%d\n", __func__, status);
5361 return status;
5362}
5363
5364static int
5365_nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
5366{
5367 struct nfs4_getdeviceinfo_args args = {
5368 .pdev = pdev,
5369 };
5370 struct nfs4_getdeviceinfo_res res = {
5371 .pdev = pdev,
5372 };
5373 struct rpc_message msg = {
5374 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO],
5375 .rpc_argp = &args,
5376 .rpc_resp = &res,
5377 };
5378 int status;
5379
5380 dprintk("--> %s\n", __func__);
5381 status = nfs4_call_sync(server, &msg, &args, &res, 0);
5382 dprintk("<-- %s status=%d\n", __func__, status);
5383
5384 return status;
5385}
5386
5387int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
5388{
5389 struct nfs4_exception exception = { };
5390 int err;
5391
5392 do {
5393 err = nfs4_handle_exception(server,
5394 _nfs4_proc_getdeviceinfo(server, pdev),
5395 &exception);
5396 } while (exception.retry);
5397 return err;
5398}
5399EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo);
5400
5259#endif /* CONFIG_NFS_V4_1 */ 5401#endif /* CONFIG_NFS_V4_1 */
5260 5402
5261struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { 5403struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {