aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c128
-rw-r--r--fs/nfs/nfs4xdr.c67
-rw-r--r--include/linux/nfs4.h1
-rw-r--r--include/linux/nfs_xdr.h13
5 files changed, 209 insertions, 2 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 94e783ffcf08..2f0f8c216441 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -208,6 +208,7 @@ struct nfs4_state_maintenance_ops {
208struct nfs4_mig_recovery_ops { 208struct nfs4_mig_recovery_ops {
209 int (*get_locations)(struct inode *, struct nfs4_fs_locations *, 209 int (*get_locations)(struct inode *, struct nfs4_fs_locations *,
210 struct page *, struct rpc_cred *); 210 struct page *, struct rpc_cred *);
211 int (*fsid_present)(struct inode *, struct rpc_cred *);
211}; 212};
212 213
213extern const struct dentry_operations nfs4_dentry_operations; 214extern const struct dentry_operations nfs4_dentry_operations;
@@ -242,6 +243,7 @@ extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struc
242 struct nfs4_fs_locations *, struct page *); 243 struct nfs4_fs_locations *, struct page *);
243extern int nfs4_proc_get_locations(struct inode *, struct nfs4_fs_locations *, 244extern int nfs4_proc_get_locations(struct inode *, struct nfs4_fs_locations *,
244 struct page *page, struct rpc_cred *); 245 struct page *page, struct rpc_cred *);
246extern int nfs4_proc_fsid_present(struct inode *, struct rpc_cred *);
245extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *, 247extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *,
246 struct nfs_fh *, struct nfs_fattr *); 248 struct nfs_fh *, struct nfs_fattr *);
247extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); 249extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 552e4f7a8225..01b90bd341bb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6153,6 +6153,132 @@ int nfs4_proc_get_locations(struct inode *inode,
6153 return status; 6153 return status;
6154} 6154}
6155 6155
6156/*
6157 * This operation also signals the server that this client is
6158 * performing "lease moved" recovery. The server can stop
6159 * returning NFS4ERR_LEASE_MOVED to this client. A RENEW operation
6160 * is appended to this compound to identify the client ID which is
6161 * performing recovery.
6162 */
6163static int _nfs40_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
6164{
6165 struct nfs_server *server = NFS_SERVER(inode);
6166 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
6167 struct rpc_clnt *clnt = server->client;
6168 struct nfs4_fsid_present_arg args = {
6169 .fh = NFS_FH(inode),
6170 .clientid = clp->cl_clientid,
6171 .renew = 1, /* append RENEW */
6172 };
6173 struct nfs4_fsid_present_res res = {
6174 .renew = 1,
6175 };
6176 struct rpc_message msg = {
6177 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT],
6178 .rpc_argp = &args,
6179 .rpc_resp = &res,
6180 .rpc_cred = cred,
6181 };
6182 unsigned long now = jiffies;
6183 int status;
6184
6185 res.fh = nfs_alloc_fhandle();
6186 if (res.fh == NULL)
6187 return -ENOMEM;
6188
6189 nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
6190 nfs4_set_sequence_privileged(&args.seq_args);
6191 status = nfs4_call_sync_sequence(clnt, server, &msg,
6192 &args.seq_args, &res.seq_res);
6193 nfs_free_fhandle(res.fh);
6194 if (status)
6195 return status;
6196
6197 do_renew_lease(clp, now);
6198 return 0;
6199}
6200
6201#ifdef CONFIG_NFS_V4_1
6202
6203/*
6204 * This operation also signals the server that this client is
6205 * performing "lease moved" recovery. The server can stop asserting
6206 * SEQ4_STATUS_LEASE_MOVED for this client. The client ID performing
6207 * this operation is identified in the SEQUENCE operation in this
6208 * compound.
6209 */
6210static int _nfs41_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
6211{
6212 struct nfs_server *server = NFS_SERVER(inode);
6213 struct rpc_clnt *clnt = server->client;
6214 struct nfs4_fsid_present_arg args = {
6215 .fh = NFS_FH(inode),
6216 };
6217 struct nfs4_fsid_present_res res = {
6218 };
6219 struct rpc_message msg = {
6220 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT],
6221 .rpc_argp = &args,
6222 .rpc_resp = &res,
6223 .rpc_cred = cred,
6224 };
6225 int status;
6226
6227 res.fh = nfs_alloc_fhandle();
6228 if (res.fh == NULL)
6229 return -ENOMEM;
6230
6231 nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
6232 nfs4_set_sequence_privileged(&args.seq_args);
6233 status = nfs4_call_sync_sequence(clnt, server, &msg,
6234 &args.seq_args, &res.seq_res);
6235 nfs_free_fhandle(res.fh);
6236 if (status == NFS4_OK &&
6237 res.seq_res.sr_status_flags & SEQ4_STATUS_LEASE_MOVED)
6238 status = -NFS4ERR_LEASE_MOVED;
6239 return status;
6240}
6241
6242#endif /* CONFIG_NFS_V4_1 */
6243
6244/**
6245 * nfs4_proc_fsid_present - Is this FSID present or absent on server?
6246 * @inode: inode on FSID to check
6247 * @cred: credential to use for this operation
6248 *
6249 * Server indicates whether the FSID is present, moved, or not
6250 * recognized. This operation is necessary to clear a LEASE_MOVED
6251 * condition for this client ID.
6252 *
6253 * Returns NFS4_OK if the FSID is present on this server,
6254 * -NFS4ERR_MOVED if the FSID is no longer present, a negative
6255 * NFS4ERR code if some error occurred on the server, or a
6256 * negative errno if a local failure occurred.
6257 */
6258int nfs4_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
6259{
6260 struct nfs_server *server = NFS_SERVER(inode);
6261 struct nfs_client *clp = server->nfs_client;
6262 const struct nfs4_mig_recovery_ops *ops =
6263 clp->cl_mvops->mig_recovery_ops;
6264 struct nfs4_exception exception = { };
6265 int status;
6266
6267 dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__,
6268 (unsigned long long)server->fsid.major,
6269 (unsigned long long)server->fsid.minor,
6270 clp->cl_hostname);
6271 nfs_display_fhandle(NFS_FH(inode), __func__);
6272
6273 do {
6274 status = ops->fsid_present(inode, cred);
6275 if (status != -NFS4ERR_DELAY)
6276 break;
6277 nfs4_handle_exception(server, status, &exception);
6278 } while (exception.retry);
6279 return status;
6280}
6281
6156/** 6282/**
6157 * If 'use_integrity' is true and the state managment nfs_client 6283 * If 'use_integrity' is true and the state managment nfs_client
6158 * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient 6284 * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient
@@ -8052,11 +8178,13 @@ static const struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
8052 8178
8053static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = { 8179static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = {
8054 .get_locations = _nfs40_proc_get_locations, 8180 .get_locations = _nfs40_proc_get_locations,
8181 .fsid_present = _nfs40_proc_fsid_present,
8055}; 8182};
8056 8183
8057#if defined(CONFIG_NFS_V4_1) 8184#if defined(CONFIG_NFS_V4_1)
8058static const struct nfs4_mig_recovery_ops nfs41_mig_recovery_ops = { 8185static const struct nfs4_mig_recovery_ops nfs41_mig_recovery_ops = {
8059 .get_locations = _nfs41_proc_get_locations, 8186 .get_locations = _nfs41_proc_get_locations,
8187 .fsid_present = _nfs41_proc_fsid_present,
8060}; 8188};
8061#endif /* CONFIG_NFS_V4_1 */ 8189#endif /* CONFIG_NFS_V4_1 */
8062 8190
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1854b04f828f..f903389d90f1 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -595,11 +595,13 @@ static int nfs4_stat_to_errno(int);
595#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ 595#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
596 encode_sequence_maxsz + \ 596 encode_sequence_maxsz + \
597 encode_putfh_maxsz + \ 597 encode_putfh_maxsz + \
598 encode_getattr_maxsz) 598 encode_getattr_maxsz + \
599 encode_renew_maxsz)
599#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ 600#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
600 decode_sequence_maxsz + \ 601 decode_sequence_maxsz + \
601 decode_putfh_maxsz + \ 602 decode_putfh_maxsz + \
602 decode_getattr_maxsz) 603 decode_getattr_maxsz + \
604 decode_renew_maxsz)
603#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ 605#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
604 encode_sequence_maxsz + \ 606 encode_sequence_maxsz + \
605 encode_putfh_maxsz + \ 607 encode_putfh_maxsz + \
@@ -753,6 +755,18 @@ static int nfs4_stat_to_errno(int);
753 decode_sequence_maxsz + \ 755 decode_sequence_maxsz + \
754 decode_putfh_maxsz + \ 756 decode_putfh_maxsz + \
755 decode_secinfo_maxsz) 757 decode_secinfo_maxsz)
758#define NFS4_enc_fsid_present_sz \
759 (compound_encode_hdr_maxsz + \
760 encode_sequence_maxsz + \
761 encode_putfh_maxsz + \
762 encode_getfh_maxsz + \
763 encode_renew_maxsz)
764#define NFS4_dec_fsid_present_sz \
765 (compound_decode_hdr_maxsz + \
766 decode_sequence_maxsz + \
767 decode_putfh_maxsz + \
768 decode_getfh_maxsz + \
769 decode_renew_maxsz)
756#if defined(CONFIG_NFS_V4_1) 770#if defined(CONFIG_NFS_V4_1)
757#define NFS4_enc_bind_conn_to_session_sz \ 771#define NFS4_enc_bind_conn_to_session_sz \
758 (compound_encode_hdr_maxsz + \ 772 (compound_encode_hdr_maxsz + \
@@ -2726,6 +2740,26 @@ static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req,
2726 encode_nops(&hdr); 2740 encode_nops(&hdr);
2727} 2741}
2728 2742
2743/*
2744 * Encode FSID_PRESENT request
2745 */
2746static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req,
2747 struct xdr_stream *xdr,
2748 struct nfs4_fsid_present_arg *args)
2749{
2750 struct compound_hdr hdr = {
2751 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2752 };
2753
2754 encode_compound_hdr(xdr, req, &hdr);
2755 encode_sequence(xdr, &args->seq_args, &hdr);
2756 encode_putfh(xdr, args->fh, &hdr);
2757 encode_getfh(xdr, &hdr);
2758 if (args->renew)
2759 encode_renew(xdr, args->clientid, &hdr);
2760 encode_nops(&hdr);
2761}
2762
2729#if defined(CONFIG_NFS_V4_1) 2763#if defined(CONFIG_NFS_V4_1)
2730/* 2764/*
2731 * BIND_CONN_TO_SESSION request 2765 * BIND_CONN_TO_SESSION request
@@ -6883,6 +6917,34 @@ out:
6883 return status; 6917 return status;
6884} 6918}
6885 6919
6920/*
6921 * Decode FSID_PRESENT response
6922 */
6923static int nfs4_xdr_dec_fsid_present(struct rpc_rqst *rqstp,
6924 struct xdr_stream *xdr,
6925 struct nfs4_fsid_present_res *res)
6926{
6927 struct compound_hdr hdr;
6928 int status;
6929
6930 status = decode_compound_hdr(xdr, &hdr);
6931 if (status)
6932 goto out;
6933 status = decode_sequence(xdr, &res->seq_res, rqstp);
6934 if (status)
6935 goto out;
6936 status = decode_putfh(xdr);
6937 if (status)
6938 goto out;
6939 status = decode_getfh(xdr, res->fh);
6940 if (status)
6941 goto out;
6942 if (res->renew)
6943 status = decode_renew(xdr);
6944out:
6945 return status;
6946}
6947
6886#if defined(CONFIG_NFS_V4_1) 6948#if defined(CONFIG_NFS_V4_1)
6887/* 6949/*
6888 * Decode BIND_CONN_TO_SESSION response 6950 * Decode BIND_CONN_TO_SESSION response
@@ -7397,6 +7459,7 @@ struct rpc_procinfo nfs4_procedures[] = {
7397 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), 7459 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
7398 PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), 7460 PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner),
7399 PROC(SECINFO, enc_secinfo, dec_secinfo), 7461 PROC(SECINFO, enc_secinfo, dec_secinfo),
7462 PROC(FSID_PRESENT, enc_fsid_present, dec_fsid_present),
7400#if defined(CONFIG_NFS_V4_1) 7463#if defined(CONFIG_NFS_V4_1)
7401 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), 7464 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
7402 PROC(CREATE_SESSION, enc_create_session, dec_create_session), 7465 PROC(CREATE_SESSION, enc_create_session, dec_create_session),
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index e36dee52f224..c56fa8fedce9 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -460,6 +460,7 @@ enum {
460 NFSPROC4_CLNT_FS_LOCATIONS, 460 NFSPROC4_CLNT_FS_LOCATIONS,
461 NFSPROC4_CLNT_RELEASE_LOCKOWNER, 461 NFSPROC4_CLNT_RELEASE_LOCKOWNER,
462 NFSPROC4_CLNT_SECINFO, 462 NFSPROC4_CLNT_SECINFO,
463 NFSPROC4_CLNT_FSID_PRESENT,
463 464
464 /* nfs41 */ 465 /* nfs41 */
465 NFSPROC4_CLNT_EXCHANGE_ID, 466 NFSPROC4_CLNT_EXCHANGE_ID,
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 405dfadcbc3b..8fe5b940c5f2 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1088,6 +1088,19 @@ struct nfs4_secinfo_res {
1088 struct nfs4_secinfo_flavors *flavors; 1088 struct nfs4_secinfo_flavors *flavors;
1089}; 1089};
1090 1090
1091struct nfs4_fsid_present_arg {
1092 struct nfs4_sequence_args seq_args;
1093 const struct nfs_fh *fh;
1094 clientid4 clientid;
1095 unsigned char renew:1;
1096};
1097
1098struct nfs4_fsid_present_res {
1099 struct nfs4_sequence_res seq_res;
1100 struct nfs_fh *fh;
1101 unsigned char renew:1;
1102};
1103
1091#endif /* CONFIG_NFS_V4 */ 1104#endif /* CONFIG_NFS_V4 */
1092 1105
1093struct nfstime4 { 1106struct nfstime4 {