nfs41: get_lease_time
authorAndy Adamson <andros@netapp.com>
Wed, 1 Apr 2009 13:22:30 +0000 (09:22 -0400)
committerBenny Halevy <bhalevy@panasas.com>
Wed, 17 Jun 2009 19:24:32 +0000 (12:24 -0700)
get_lease_time uses the FSINFO rpc operation to
get the lease time attribute.

nfs4_get_lease_time() is only called from the state manager on session setup
so don't recover from clientid or sequence level errors.

We do need to recover from NFS4ERR_DELAY or NFS4ERR_GRACE.
Use NFS4_POLL_RETRY_MIN - the Linux server returns NFS4ERR_DELAY when an
upcall is needed to resolve an uncached export referenced by a file handle.

[nfs41: sequence res use slotid]
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfs41: remove extraneous rpc_clnt pointer]
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfs41: have get_lease_time work on nfs_client]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfs41: get_lease_time recover from NFS4ERR_DELAY]
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfs41: pass *session in seq_args and seq_res]
[define nfs4_get_lease_time_{args,res}]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
include/linux/nfs_xdr.h

index 6f384e29075371923f30cd59825b8f00064e2c58..eafc99afd356fbf5d11bb57e2537539393ab0e17 100644 (file)
@@ -4189,6 +4189,100 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
        return status;
 }
 
+struct nfs4_get_lease_time_data {
+       struct nfs4_get_lease_time_args *args;
+       struct nfs4_get_lease_time_res *res;
+       struct nfs_client *clp;
+};
+
+static void nfs4_get_lease_time_prepare(struct rpc_task *task,
+                                       void *calldata)
+{
+       int ret;
+       struct nfs4_get_lease_time_data *data =
+                       (struct nfs4_get_lease_time_data *)calldata;
+
+       dprintk("--> %s\n", __func__);
+       /* just setup sequence, do not trigger session recovery
+          since we're invoked within one */
+       ret = nfs41_setup_sequence(data->clp->cl_session,
+                                       &data->args->la_seq_args,
+                                       &data->res->lr_seq_res, 0, task);
+
+       BUG_ON(ret == -EAGAIN);
+       rpc_call_start(task);
+       dprintk("<-- %s\n", __func__);
+}
+
+/*
+ * Called from nfs4_state_manager thread for session setup, so don't recover
+ * from sequence operation or clientid errors.
+ */
+static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
+{
+       struct nfs4_get_lease_time_data *data =
+                       (struct nfs4_get_lease_time_data *)calldata;
+
+       dprintk("--> %s\n", __func__);
+       nfs41_sequence_done(data->clp, &data->res->lr_seq_res, task->tk_status);
+       switch (task->tk_status) {
+       case -NFS4ERR_DELAY:
+       case -NFS4ERR_GRACE:
+               dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
+               rpc_delay(task, NFS4_POLL_RETRY_MIN);
+               task->tk_status = 0;
+               rpc_restart_call(task);
+               return;
+       }
+       nfs41_sequence_free_slot(data->clp, &data->res->lr_seq_res);
+       dprintk("<-- %s\n", __func__);
+}
+
+struct rpc_call_ops nfs4_get_lease_time_ops = {
+       .rpc_call_prepare = nfs4_get_lease_time_prepare,
+       .rpc_call_done = nfs4_get_lease_time_done,
+};
+
+int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
+{
+       struct rpc_task *task;
+       struct nfs4_get_lease_time_args args;
+       struct nfs4_get_lease_time_res res = {
+               .lr_fsinfo = fsinfo,
+       };
+       struct nfs4_get_lease_time_data data = {
+               .args = &args,
+               .res = &res,
+               .clp = clp,
+       };
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GET_LEASE_TIME],
+               .rpc_argp = &args,
+               .rpc_resp = &res,
+       };
+       struct rpc_task_setup task_setup = {
+               .rpc_client = clp->cl_rpcclient,
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_get_lease_time_ops,
+               .callback_data = &data
+       };
+       int status;
+
+       res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
+       dprintk("--> %s\n", __func__);
+       task = rpc_run_task(&task_setup);
+
+       if (IS_ERR(task))
+               status = PTR_ERR(task);
+       else {
+               status = task->tk_status;
+               rpc_put_task(task);
+       }
+       dprintk("<-- %s return %d\n", __func__, status);
+
+       return status;
+}
+
 /* Destroy the slot table */
 static void nfs4_destroy_slot_table(struct nfs4_session *session)
 {
index 783c4214dccd888d9fc122db3bccc2ac82a00730..85ee1d17a46194b6101cf087447df8ed6c96b09a 100644 (file)
@@ -622,6 +622,14 @@ static int nfs4_stat_to_errno(int);
 #define NFS4_dec_exchange_id_sz \
                                (compound_decode_hdr_maxsz + \
                                 decode_exchange_id_maxsz)
+#define NFS4_enc_get_lease_time_sz     (compound_encode_hdr_maxsz + \
+                                        encode_sequence_maxsz + \
+                                        encode_putrootfh_maxsz + \
+                                        encode_fsinfo_maxsz)
+#define NFS4_dec_get_lease_time_sz     (compound_decode_hdr_maxsz + \
+                                        decode_sequence_maxsz + \
+                                        decode_putrootfh_maxsz + \
+                                        decode_fsinfo_maxsz)
 #endif /* CONFIG_NFS_V4_1 */
 
 static const umode_t nfs_type2fmt[] = {
@@ -2231,6 +2239,27 @@ static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p,
        encode_nops(&hdr);
        return 0;
 }
+
+/*
+ * a GET_LEASE_TIME request
+ */
+static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
+                                      struct nfs4_get_lease_time_args *args)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr = {
+               .minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
+       };
+       const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
+
+       xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+       encode_compound_hdr(&xdr, req, &hdr);
+       encode_sequence(&xdr, &args->la_seq_args, &hdr);
+       encode_putrootfh(&xdr, &hdr);
+       encode_fsinfo(&xdr, lease_bitmap, &hdr);
+       encode_nops(&hdr);
+       return 0;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 /*
@@ -4908,6 +4937,27 @@ static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
                status = decode_exchange_id(&xdr, res);
        return status;
 }
+
+/*
+ * a GET_LEASE_TIME request
+ */
+static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
+                                      struct nfs4_get_lease_time_res *res)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr;
+       int status;
+
+       xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+       status = decode_compound_hdr(&xdr, &hdr);
+       if (!status)
+               status = decode_sequence(&xdr, &res->lr_seq_res, rqstp);
+       if (!status)
+               status = decode_putrootfh(&xdr);
+       if (!status)
+               status = decode_fsinfo(&xdr, res->lr_fsinfo);
+       return status;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
@@ -5081,6 +5131,7 @@ struct rpc_procinfo       nfs4_procedures[] = {
   PROC(FS_LOCATIONS,   enc_fs_locations, dec_fs_locations),
 #if defined(CONFIG_NFS_V4_1)
   PROC(EXCHANGE_ID,    enc_exchange_id,        dec_exchange_id),
+  PROC(GET_LEASE_TIME, enc_get_lease_time,     dec_get_lease_time),
 #endif /* CONFIG_NFS_V4_1 */
 };
 
index 5d70b924af5e8c07218b7610266a92122557fa7a..ca643aa87d462a7cadf6b9c7fddf4abdccea4676 100644 (file)
@@ -174,6 +174,15 @@ struct nfs4_sequence_res {
        int                     sr_status;      /* sequence operation status */
 };
 
+struct nfs4_get_lease_time_args {
+       struct nfs4_sequence_args       la_seq_args;
+};
+
+struct nfs4_get_lease_time_res {
+       struct nfs_fsinfo              *lr_fsinfo;
+       struct nfs4_sequence_res        lr_seq_res;
+};
+
 /*
  * Arguments to the open call.
  */