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:15 -0400
commitd4318acd5d2d34d69a46537f057b20a8f0266e1e (patch)
tree421a5776f63b395dec5d16b5dbbb0217b03dff54
parent7f5ef2e900d9462bf9cffaf6bb246ed87a20a6d6 (diff)
nfsd: pass extra info in env vars to upcalls to allow for early grace period end
In order to support lifting the grace period early, we must tell nfsdcltrack what sort of client the "create" upcall is for. We can't reliably tell if a v4.0 client has completed reclaiming, so we can only lift the grace period once all the v4.1+ clients have issued a RECLAIM_COMPLETE and if there are no v4.0 clients. Also, in order to lift the grace period, we have to tell userland when the grace period started so that it can tell whether a RECLAIM_COMPLETE has been issued for each client since then. Since this is all optional info, we pass it along in environment variables to the "init" and "create" upcalls. By doing this, we don't need to revise the upcall format. The UMH upcall can simply make use of this info if it happens to be present. If it's not then it can just avoid lifting the grace period early. Signed-off-by: Jeff Layton <jlayton@primarydata.com>
-rw-r--r--fs/nfsd/nfs4recover.c96
-rw-r--r--fs/nfsd/nfs4state.c4
2 files changed, 85 insertions, 15 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 9affa22e7d35..b4289060ebaf 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -1067,6 +1067,8 @@ MODULE_PARM_DESC(cltrack_legacy_disable,
1067 1067
1068#define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR=" 1068#define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR="
1069#define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR=" 1069#define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR="
1070#define HAS_SESSION_ENV_PREFIX "NFSDCLTRACK_CLIENT_HAS_SESSION="
1071#define GRACE_START_ENV_PREFIX "NFSDCLTRACK_GRACE_START="
1070 1072
1071static char * 1073static char *
1072nfsd4_cltrack_legacy_topdir(void) 1074nfsd4_cltrack_legacy_topdir(void)
@@ -1131,10 +1133,60 @@ nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name)
1131 return result; 1133 return result;
1132} 1134}
1133 1135
1136static char *
1137nfsd4_cltrack_client_has_session(struct nfs4_client *clp)
1138{
1139 int copied;
1140 size_t len;
1141 char *result;
1142
1143 /* prefix + Y/N character + terminating NULL */
1144 len = strlen(HAS_SESSION_ENV_PREFIX) + 1 + 1;
1145
1146 result = kmalloc(len, GFP_KERNEL);
1147 if (!result)
1148 return result;
1149
1150 copied = snprintf(result, len, HAS_SESSION_ENV_PREFIX "%c",
1151 clp->cl_minorversion ? 'Y' : 'N');
1152 if (copied >= len) {
1153 /* just return nothing if output was truncated */
1154 kfree(result);
1155 return NULL;
1156 }
1157
1158 return result;
1159}
1160
1161static char *
1162nfsd4_cltrack_grace_start(time_t grace_start)
1163{
1164 int copied;
1165 size_t len;
1166 char *result;
1167
1168 /* prefix + max width of int64_t string + terminating NULL */
1169 len = strlen(GRACE_START_ENV_PREFIX) + 22 + 1;
1170
1171 result = kmalloc(len, GFP_KERNEL);
1172 if (!result)
1173 return result;
1174
1175 copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%ld",
1176 grace_start);
1177 if (copied >= len) {
1178 /* just return nothing if output was truncated */
1179 kfree(result);
1180 return NULL;
1181 }
1182
1183 return result;
1184}
1185
1134static int 1186static int
1135nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *legacy) 1187nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
1136{ 1188{
1137 char *envp[2]; 1189 char *envp[3];
1138 char *argv[4]; 1190 char *argv[4];
1139 int ret; 1191 int ret;
1140 1192
@@ -1145,10 +1197,12 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *legacy)
1145 1197
1146 dprintk("%s: cmd: %s\n", __func__, cmd); 1198 dprintk("%s: cmd: %s\n", __func__, cmd);
1147 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)"); 1199 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)");
1148 dprintk("%s: legacy: %s\n", __func__, legacy ? legacy : "(null)"); 1200 dprintk("%s: env0: %s\n", __func__, env0 ? env0 : "(null)");
1201 dprintk("%s: env1: %s\n", __func__, env1 ? env1 : "(null)");
1149 1202
1150 envp[0] = legacy; 1203 envp[0] = env0;
1151 envp[1] = NULL; 1204 envp[1] = env1;
1205 envp[2] = NULL;
1152 1206
1153 argv[0] = (char *)cltrack_prog; 1207 argv[0] = (char *)cltrack_prog;
1154 argv[1] = cmd; 1208 argv[1] = cmd;
@@ -1192,28 +1246,40 @@ bin_to_hex_dup(const unsigned char *src, int srclen)
1192} 1246}
1193 1247
1194static int 1248static int
1195nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net) 1249nfsd4_umh_cltrack_init(struct net *net)
1196{ 1250{
1251 int ret;
1252 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1253 char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
1254
1197 /* XXX: The usermode helper s not working in container yet. */ 1255 /* XXX: The usermode helper s not working in container yet. */
1198 if (net != &init_net) { 1256 if (net != &init_net) {
1199 WARN(1, KERN_ERR "NFSD: attempt to initialize umh client " 1257 WARN(1, KERN_ERR "NFSD: attempt to initialize umh client "
1200 "tracking in a container!\n"); 1258 "tracking in a container!\n");
1201 return -EINVAL; 1259 return -EINVAL;
1202 } 1260 }
1203 return nfsd4_umh_cltrack_upcall("init", NULL, NULL); 1261
1262 ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
1263 kfree(grace_start);
1264 return ret;
1204} 1265}
1205 1266
1206static void 1267static void
1207nfsd4_umh_cltrack_create(struct nfs4_client *clp) 1268nfsd4_umh_cltrack_create(struct nfs4_client *clp)
1208{ 1269{
1209 char *hexid; 1270 char *hexid, *has_session, *grace_start;
1271 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1210 1272
1211 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1273 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
1212 if (!hexid) { 1274 if (!hexid) {
1213 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1275 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1214 return; 1276 return;
1215 } 1277 }
1216 nfsd4_umh_cltrack_upcall("create", hexid, NULL); 1278 has_session = nfsd4_cltrack_client_has_session(clp);
1279 grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
1280 nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start);
1281 kfree(has_session);
1282 kfree(grace_start);
1217 kfree(hexid); 1283 kfree(hexid);
1218} 1284}
1219 1285
@@ -1227,7 +1293,7 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
1227 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1293 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1228 return; 1294 return;
1229 } 1295 }
1230 nfsd4_umh_cltrack_upcall("remove", hexid, NULL); 1296 nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL);
1231 kfree(hexid); 1297 kfree(hexid);
1232} 1298}
1233 1299
@@ -1235,17 +1301,21 @@ static int
1235nfsd4_umh_cltrack_check(struct nfs4_client *clp) 1301nfsd4_umh_cltrack_check(struct nfs4_client *clp)
1236{ 1302{
1237 int ret; 1303 int ret;
1238 char *hexid, *legacy; 1304 char *hexid, *has_session, *legacy;
1239 1305
1240 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1306 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
1241 if (!hexid) { 1307 if (!hexid) {
1242 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1308 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1243 return -ENOMEM; 1309 return -ENOMEM;
1244 } 1310 }
1311
1312 has_session = nfsd4_cltrack_client_has_session(clp);
1245 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name); 1313 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name);
1246 ret = nfsd4_umh_cltrack_upcall("check", hexid, legacy); 1314 ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy);
1315 kfree(has_session);
1247 kfree(legacy); 1316 kfree(legacy);
1248 kfree(hexid); 1317 kfree(hexid);
1318
1249 return ret; 1319 return ret;
1250} 1320}
1251 1321
@@ -1257,7 +1327,7 @@ nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn)
1257 1327
1258 sprintf(timestr, "%ld", nn->boot_time); 1328 sprintf(timestr, "%ld", nn->boot_time);
1259 legacy = nfsd4_cltrack_legacy_topdir(); 1329 legacy = nfsd4_cltrack_legacy_topdir();
1260 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy); 1330 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL);
1261 kfree(legacy); 1331 kfree(legacy);
1262} 1332}
1263 1333
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 8f7ace5942be..fc88b57516b2 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -6350,10 +6350,10 @@ nfs4_state_start_net(struct net *net)
6350 ret = nfs4_state_create_net(net); 6350 ret = nfs4_state_create_net(net);
6351 if (ret) 6351 if (ret)
6352 return ret; 6352 return ret;
6353 nfsd4_client_tracking_init(net);
6354 nn->boot_time = get_seconds(); 6353 nn->boot_time = get_seconds();
6355 locks_start_grace(net, &nn->nfsd4_manager);
6356 nn->grace_ended = false; 6354 nn->grace_ended = false;
6355 locks_start_grace(net, &nn->nfsd4_manager);
6356 nfsd4_client_tracking_init(net);
6357 printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n", 6357 printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n",
6358 nn->nfsd4_grace, net); 6358 nn->nfsd4_grace, net);
6359 queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ); 6359 queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ);