diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 2aacd1357dc5..c71c16e0ac22 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -5984,6 +5984,157 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | |||
5984 | return err; | 5984 | return err; |
5985 | } | 5985 | } |
5986 | 5986 | ||
5987 | /* | ||
5988 | * This operation also signals the server that this client is | ||
5989 | * performing migration recovery. The server can stop returning | ||
5990 | * NFS4ERR_LEASE_MOVED to this client. A RENEW operation is | ||
5991 | * appended to this compound to identify the client ID which is | ||
5992 | * performing recovery. | ||
5993 | */ | ||
5994 | static int _nfs40_proc_get_locations(struct inode *inode, | ||
5995 | struct nfs4_fs_locations *locations, | ||
5996 | struct page *page, struct rpc_cred *cred) | ||
5997 | { | ||
5998 | struct nfs_server *server = NFS_SERVER(inode); | ||
5999 | struct rpc_clnt *clnt = server->client; | ||
6000 | u32 bitmask[2] = { | ||
6001 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, | ||
6002 | }; | ||
6003 | struct nfs4_fs_locations_arg args = { | ||
6004 | .clientid = server->nfs_client->cl_clientid, | ||
6005 | .fh = NFS_FH(inode), | ||
6006 | .page = page, | ||
6007 | .bitmask = bitmask, | ||
6008 | .migration = 1, /* skip LOOKUP */ | ||
6009 | .renew = 1, /* append RENEW */ | ||
6010 | }; | ||
6011 | struct nfs4_fs_locations_res res = { | ||
6012 | .fs_locations = locations, | ||
6013 | .migration = 1, | ||
6014 | .renew = 1, | ||
6015 | }; | ||
6016 | struct rpc_message msg = { | ||
6017 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS], | ||
6018 | .rpc_argp = &args, | ||
6019 | .rpc_resp = &res, | ||
6020 | .rpc_cred = cred, | ||
6021 | }; | ||
6022 | unsigned long now = jiffies; | ||
6023 | int status; | ||
6024 | |||
6025 | nfs_fattr_init(&locations->fattr); | ||
6026 | locations->server = server; | ||
6027 | locations->nlocations = 0; | ||
6028 | |||
6029 | nfs4_init_sequence(&args.seq_args, &res.seq_res, 0); | ||
6030 | nfs4_set_sequence_privileged(&args.seq_args); | ||
6031 | status = nfs4_call_sync_sequence(clnt, server, &msg, | ||
6032 | &args.seq_args, &res.seq_res); | ||
6033 | if (status) | ||
6034 | return status; | ||
6035 | |||
6036 | renew_lease(server, now); | ||
6037 | return 0; | ||
6038 | } | ||
6039 | |||
6040 | #ifdef CONFIG_NFS_V4_1 | ||
6041 | |||
6042 | /* | ||
6043 | * This operation also signals the server that this client is | ||
6044 | * performing migration recovery. The server can stop asserting | ||
6045 | * SEQ4_STATUS_LEASE_MOVED for this client. The client ID | ||
6046 | * performing this operation is identified in the SEQUENCE | ||
6047 | * operation in this compound. | ||
6048 | * | ||
6049 | * When the client supports GETATTR(fs_locations_info), it can | ||
6050 | * be plumbed in here. | ||
6051 | */ | ||
6052 | static int _nfs41_proc_get_locations(struct inode *inode, | ||
6053 | struct nfs4_fs_locations *locations, | ||
6054 | struct page *page, struct rpc_cred *cred) | ||
6055 | { | ||
6056 | struct nfs_server *server = NFS_SERVER(inode); | ||
6057 | struct rpc_clnt *clnt = server->client; | ||
6058 | u32 bitmask[2] = { | ||
6059 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, | ||
6060 | }; | ||
6061 | struct nfs4_fs_locations_arg args = { | ||
6062 | .fh = NFS_FH(inode), | ||
6063 | .page = page, | ||
6064 | .bitmask = bitmask, | ||
6065 | .migration = 1, /* skip LOOKUP */ | ||
6066 | }; | ||
6067 | struct nfs4_fs_locations_res res = { | ||
6068 | .fs_locations = locations, | ||
6069 | .migration = 1, | ||
6070 | }; | ||
6071 | struct rpc_message msg = { | ||
6072 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS], | ||
6073 | .rpc_argp = &args, | ||
6074 | .rpc_resp = &res, | ||
6075 | .rpc_cred = cred, | ||
6076 | }; | ||
6077 | int status; | ||
6078 | |||
6079 | nfs_fattr_init(&locations->fattr); | ||
6080 | locations->server = server; | ||
6081 | locations->nlocations = 0; | ||
6082 | |||
6083 | nfs4_init_sequence(&args.seq_args, &res.seq_res, 0); | ||
6084 | nfs4_set_sequence_privileged(&args.seq_args); | ||
6085 | status = nfs4_call_sync_sequence(clnt, server, &msg, | ||
6086 | &args.seq_args, &res.seq_res); | ||
6087 | if (status == NFS4_OK && | ||
6088 | res.seq_res.sr_status_flags & SEQ4_STATUS_LEASE_MOVED) | ||
6089 | status = -NFS4ERR_LEASE_MOVED; | ||
6090 | return status; | ||
6091 | } | ||
6092 | |||
6093 | #endif /* CONFIG_NFS_V4_1 */ | ||
6094 | |||
6095 | /** | ||
6096 | * nfs4_proc_get_locations - discover locations for a migrated FSID | ||
6097 | * @inode: inode on FSID that is migrating | ||
6098 | * @locations: result of query | ||
6099 | * @page: buffer | ||
6100 | * @cred: credential to use for this operation | ||
6101 | * | ||
6102 | * Returns NFS4_OK on success, a negative NFS4ERR status code if the | ||
6103 | * operation failed, or a negative errno if a local error occurred. | ||
6104 | * | ||
6105 | * On success, "locations" is filled in, but if the server has | ||
6106 | * no locations information, NFS_ATTR_FATTR_V4_LOCATIONS is not | ||
6107 | * asserted. | ||
6108 | * | ||
6109 | * -NFS4ERR_LEASE_MOVED is returned if the server still has leases | ||
6110 | * from this client that require migration recovery. | ||
6111 | */ | ||
6112 | int nfs4_proc_get_locations(struct inode *inode, | ||
6113 | struct nfs4_fs_locations *locations, | ||
6114 | struct page *page, struct rpc_cred *cred) | ||
6115 | { | ||
6116 | struct nfs_server *server = NFS_SERVER(inode); | ||
6117 | struct nfs_client *clp = server->nfs_client; | ||
6118 | const struct nfs4_mig_recovery_ops *ops = | ||
6119 | clp->cl_mvops->mig_recovery_ops; | ||
6120 | struct nfs4_exception exception = { }; | ||
6121 | int status; | ||
6122 | |||
6123 | dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__, | ||
6124 | (unsigned long long)server->fsid.major, | ||
6125 | (unsigned long long)server->fsid.minor, | ||
6126 | clp->cl_hostname); | ||
6127 | nfs_display_fhandle(NFS_FH(inode), __func__); | ||
6128 | |||
6129 | do { | ||
6130 | status = ops->get_locations(inode, locations, page, cred); | ||
6131 | if (status != -NFS4ERR_DELAY) | ||
6132 | break; | ||
6133 | nfs4_handle_exception(server, status, &exception); | ||
6134 | } while (exception.retry); | ||
6135 | return status; | ||
6136 | } | ||
6137 | |||
5987 | /** | 6138 | /** |
5988 | * If 'use_integrity' is true and the state managment nfs_client | 6139 | * If 'use_integrity' is true and the state managment nfs_client |
5989 | * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient | 6140 | * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient |
@@ -7882,10 +8033,12 @@ static const struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = { | |||
7882 | #endif | 8033 | #endif |
7883 | 8034 | ||
7884 | static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = { | 8035 | static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = { |
8036 | .get_locations = _nfs40_proc_get_locations, | ||
7885 | }; | 8037 | }; |
7886 | 8038 | ||
7887 | #if defined(CONFIG_NFS_V4_1) | 8039 | #if defined(CONFIG_NFS_V4_1) |
7888 | static const struct nfs4_mig_recovery_ops nfs41_mig_recovery_ops = { | 8040 | static const struct nfs4_mig_recovery_ops nfs41_mig_recovery_ops = { |
8041 | .get_locations = _nfs41_proc_get_locations, | ||
7889 | }; | 8042 | }; |
7890 | #endif /* CONFIG_NFS_V4_1 */ | 8043 | #endif /* CONFIG_NFS_V4_1 */ |
7891 | 8044 | ||