aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@primarydata.com>2014-09-12 16:40:21 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-09-17 16:33:16 -0400
commitd682e750ce14cfb3be655e6d492c77511e637228 (patch)
treef862ca27fa345f0e08ca7683e9349a87cb88a1a0
parentd4318acd5d2d34d69a46537f057b20a8f0266e1e (diff)
nfsd: serialize nfsdcltrack upcalls for a particular client
In a later patch, we want to add a flag that will allow us to reduce the need for upcalls. In order to handle that correctly, we'll need to ensure that racing upcalls for the same client can't occur. In practice it should be rare for this to occur with a well-behaved client, but it is possible. Convert one of the bits in the cl_flags field to be an upcall bitlock, and use it to ensure that upcalls for the same client are serialized. Signed-off-by: Jeff Layton <jlayton@primarydata.com>
-rw-r--r--fs/nfsd/nfs4recover.c29
-rw-r--r--fs/nfsd/state.h1
2 files changed, 30 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index b4289060ebaf..bf3a3575d060 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -1265,6 +1265,22 @@ nfsd4_umh_cltrack_init(struct net *net)
1265} 1265}
1266 1266
1267static void 1267static void
1268nfsd4_cltrack_upcall_lock(struct nfs4_client *clp)
1269{
1270 wait_on_bit_lock(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK,
1271 TASK_UNINTERRUPTIBLE);
1272}
1273
1274static void
1275nfsd4_cltrack_upcall_unlock(struct nfs4_client *clp)
1276{
1277 smp_mb__before_atomic();
1278 clear_bit(NFSD4_CLIENT_UPCALL_LOCK, &clp->cl_flags);
1279 smp_mb__after_atomic();
1280 wake_up_bit(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK);
1281}
1282
1283static void
1268nfsd4_umh_cltrack_create(struct nfs4_client *clp) 1284nfsd4_umh_cltrack_create(struct nfs4_client *clp)
1269{ 1285{
1270 char *hexid, *has_session, *grace_start; 1286 char *hexid, *has_session, *grace_start;
@@ -1275,9 +1291,14 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
1275 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1291 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1276 return; 1292 return;
1277 } 1293 }
1294
1278 has_session = nfsd4_cltrack_client_has_session(clp); 1295 has_session = nfsd4_cltrack_client_has_session(clp);
1279 grace_start = nfsd4_cltrack_grace_start(nn->boot_time); 1296 grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
1297
1298 nfsd4_cltrack_upcall_lock(clp);
1280 nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start); 1299 nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start);
1300 nfsd4_cltrack_upcall_unlock(clp);
1301
1281 kfree(has_session); 1302 kfree(has_session);
1282 kfree(grace_start); 1303 kfree(grace_start);
1283 kfree(hexid); 1304 kfree(hexid);
@@ -1293,7 +1314,11 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
1293 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1314 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1294 return; 1315 return;
1295 } 1316 }
1317
1318 nfsd4_cltrack_upcall_lock(clp);
1296 nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL); 1319 nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL);
1320 nfsd4_cltrack_upcall_unlock(clp);
1321
1297 kfree(hexid); 1322 kfree(hexid);
1298} 1323}
1299 1324
@@ -1311,7 +1336,11 @@ nfsd4_umh_cltrack_check(struct nfs4_client *clp)
1311 1336
1312 has_session = nfsd4_cltrack_client_has_session(clp); 1337 has_session = nfsd4_cltrack_client_has_session(clp);
1313 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name); 1338 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name);
1339
1340 nfsd4_cltrack_upcall_lock(clp);
1314 ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy); 1341 ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy);
1342 nfsd4_cltrack_upcall_unlock(clp);
1343
1315 kfree(has_session); 1344 kfree(has_session);
1316 kfree(legacy); 1345 kfree(legacy);
1317 kfree(hexid); 1346 kfree(hexid);
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 854f0c574ccf..62a82ab06cf1 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -306,6 +306,7 @@ struct nfs4_client {
306#define NFSD4_CLIENT_STABLE (2) /* client on stable storage */ 306#define NFSD4_CLIENT_STABLE (2) /* client on stable storage */
307#define NFSD4_CLIENT_RECLAIM_COMPLETE (3) /* reclaim_complete done */ 307#define NFSD4_CLIENT_RECLAIM_COMPLETE (3) /* reclaim_complete done */
308#define NFSD4_CLIENT_CONFIRMED (4) /* client is confirmed */ 308#define NFSD4_CLIENT_CONFIRMED (4) /* client is confirmed */
309#define NFSD4_CLIENT_UPCALL_LOCK (5) /* upcall serialization */
309#define NFSD4_CLIENT_CB_FLAG_MASK (1 << NFSD4_CLIENT_CB_UPDATE | \ 310#define NFSD4_CLIENT_CB_FLAG_MASK (1 << NFSD4_CLIENT_CB_UPDATE | \
310 1 << NFSD4_CLIENT_CB_KILL) 311 1 << NFSD4_CLIENT_CB_KILL)
311 unsigned long cl_flags; 312 unsigned long cl_flags;