aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r--fs/nfs/client.c171
1 files changed, 112 insertions, 59 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index bc3a8620e8c3..11eb9934c747 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -410,70 +410,28 @@ static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
410 return 0; 410 return 0;
411} 411}
412 412
413/* 413/* Common match routine for v4.0 and v4.1 callback services */
414 * Find a client by IP address and protocol version 414bool
415 * - returns NULL if no such client 415nfs4_cb_match_client(const struct sockaddr *addr, struct nfs_client *clp,
416 */ 416 u32 minorversion)
417struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
418{ 417{
419 struct nfs_client *clp; 418 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
420 419
421 spin_lock(&nfs_client_lock); 420 /* Don't match clients that failed to initialise */
422 list_for_each_entry(clp, &nfs_client_list, cl_share_link) { 421 if (!(clp->cl_cons_state == NFS_CS_READY ||
423 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; 422 clp->cl_cons_state == NFS_CS_SESSION_INITING))
423 return false;
424 424
425 /* Don't match clients that failed to initialise properly */ 425 /* Match the version and minorversion */
426 if (!(clp->cl_cons_state == NFS_CS_READY || 426 if (clp->rpc_ops->version != 4 ||
427 clp->cl_cons_state == NFS_CS_SESSION_INITING)) 427 clp->cl_minorversion != minorversion)
428 continue; 428 return false;
429 429
430 /* Different NFS versions cannot share the same nfs_client */ 430 /* Match only the IP address, not the port number */
431 if (clp->rpc_ops->version != nfsversion) 431 if (!nfs_sockaddr_match_ipaddr(addr, clap))
432 continue; 432 return false;
433
434 /* Match only the IP address, not the port number */
435 if (!nfs_sockaddr_match_ipaddr(addr, clap))
436 continue;
437 433
438 atomic_inc(&clp->cl_count); 434 return true;
439 spin_unlock(&nfs_client_lock);
440 return clp;
441 }
442 spin_unlock(&nfs_client_lock);
443 return NULL;
444}
445
446/*
447 * Find a client by IP address and protocol version
448 * - returns NULL if no such client
449 */
450struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
451{
452 struct sockaddr *sap = (struct sockaddr *)&clp->cl_addr;
453 u32 nfsvers = clp->rpc_ops->version;
454
455 spin_lock(&nfs_client_lock);
456 list_for_each_entry_continue(clp, &nfs_client_list, cl_share_link) {
457 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
458
459 /* Don't match clients that failed to initialise properly */
460 if (clp->cl_cons_state != NFS_CS_READY)
461 continue;
462
463 /* Different NFS versions cannot share the same nfs_client */
464 if (clp->rpc_ops->version != nfsvers)
465 continue;
466
467 /* Match only the IP address, not the port number */
468 if (!nfs_sockaddr_match_ipaddr(sap, clap))
469 continue;
470
471 atomic_inc(&clp->cl_count);
472 spin_unlock(&nfs_client_lock);
473 return clp;
474 }
475 spin_unlock(&nfs_client_lock);
476 return NULL;
477} 435}
478 436
479/* 437/*
@@ -1172,6 +1130,101 @@ error:
1172 1130
1173#ifdef CONFIG_NFS_V4 1131#ifdef CONFIG_NFS_V4
1174/* 1132/*
1133 * NFSv4.0 callback thread helper
1134 *
1135 * Find a client by IP address, protocol version, and minorversion
1136 *
1137 * Called from the pg_authenticate method. The callback identifier
1138 * is not used as it has not been decoded.
1139 *
1140 * Returns NULL if no such client
1141 */
1142struct nfs_client *
1143nfs4_find_client_no_ident(const struct sockaddr *addr)
1144{
1145 struct nfs_client *clp;
1146
1147 spin_lock(&nfs_client_lock);
1148 list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
1149 if (nfs4_cb_match_client(addr, clp, 0) == false)
1150 continue;
1151 atomic_inc(&clp->cl_count);
1152 spin_unlock(&nfs_client_lock);
1153 return clp;
1154 }
1155 spin_unlock(&nfs_client_lock);
1156 return NULL;
1157}
1158
1159/*
1160 * NFSv4.0 callback thread helper
1161 *
1162 * Find a client by callback identifier
1163 */
1164struct nfs_client *
1165nfs4_find_client_ident(int cb_ident)
1166{
1167 struct nfs_client *clp;
1168
1169 spin_lock(&nfs_client_lock);
1170 clp = idr_find(&cb_ident_idr, cb_ident);
1171 if (clp)
1172 atomic_inc(&clp->cl_count);
1173 spin_unlock(&nfs_client_lock);
1174 return clp;
1175}
1176
1177#if defined(CONFIG_NFS_V4_1)
1178/*
1179 * NFSv4.1 callback thread helper
1180 * For CB_COMPOUND calls, find a client by IP address, protocol version,
1181 * minorversion, and sessionID
1182 *
1183 * CREATE_SESSION triggers a CB_NULL ping from servers. The callback service
1184 * sessionid can only be set after the CREATE_SESSION return, so a CB_NULL
1185 * can arrive before the callback sessionid is set. For CB_NULL calls,
1186 * find a client by IP address protocol version, and minorversion.
1187 *
1188 * Returns NULL if no such client
1189 */
1190struct nfs_client *
1191nfs4_find_client_sessionid(const struct sockaddr *addr,
1192 struct nfs4_sessionid *sid, int is_cb_compound)
1193{
1194 struct nfs_client *clp;
1195
1196 spin_lock(&nfs_client_lock);
1197 list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
1198 if (nfs4_cb_match_client(addr, clp, 1) == false)
1199 continue;
1200
1201 if (!nfs4_has_session(clp))
1202 continue;
1203
1204 /* Match sessionid unless cb_null call*/
1205 if (is_cb_compound && (memcmp(clp->cl_session->sess_id.data,
1206 sid->data, NFS4_MAX_SESSIONID_LEN) != 0))
1207 continue;
1208
1209 atomic_inc(&clp->cl_count);
1210 spin_unlock(&nfs_client_lock);
1211 return clp;
1212 }
1213 spin_unlock(&nfs_client_lock);
1214 return NULL;
1215}
1216
1217#else /* CONFIG_NFS_V4_1 */
1218
1219struct nfs_client *
1220nfs4_find_client_sessionid(const struct sockaddr *addr,
1221 struct nfs4_sessionid *sid, int is_cb_compound)
1222{
1223 return NULL;
1224}
1225#endif /* CONFIG_NFS_V4_1 */
1226
1227/*
1175 * Initialize the NFS4 callback service 1228 * Initialize the NFS4 callback service
1176 */ 1229 */
1177static int nfs4_init_callback(struct nfs_client *clp) 1230static int nfs4_init_callback(struct nfs_client *clp)