aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4recover.c90
1 files changed, 82 insertions, 8 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index e71f713bd7c0..38af61556895 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -933,10 +933,75 @@ module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
933 S_IRUGO|S_IWUSR); 933 S_IRUGO|S_IWUSR);
934MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program"); 934MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program");
935 935
936static bool cltrack_legacy_disable;
937module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR);
938MODULE_PARM_DESC(cltrack_legacy_disable,
939 "Disable legacy recoverydir conversion. Default: false");
940
941#define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR="
942#define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR="
943
944static char *
945nfsd4_cltrack_legacy_topdir(void)
946{
947 int copied;
948 size_t len;
949 char *result;
950
951 if (cltrack_legacy_disable)
952 return NULL;
953
954 len = strlen(LEGACY_TOPDIR_ENV_PREFIX) +
955 strlen(nfs4_recoverydir()) + 1;
956
957 result = kmalloc(len, GFP_KERNEL);
958 if (!result)
959 return result;
960
961 copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s",
962 nfs4_recoverydir());
963 if (copied >= len) {
964 /* just return nothing if output was truncated */
965 kfree(result);
966 return NULL;
967 }
968
969 return result;
970}
971
972static char *
973nfsd4_cltrack_legacy_recdir(const char *recdir)
974{
975 int copied;
976 size_t len;
977 char *result;
978
979 if (cltrack_legacy_disable)
980 return NULL;
981
982 /* +1 is for '/' between "topdir" and "recdir" */
983 len = strlen(LEGACY_RECDIR_ENV_PREFIX) +
984 strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN;
985
986 result = kmalloc(len, GFP_KERNEL);
987 if (!result)
988 return result;
989
990 copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/%s",
991 nfs4_recoverydir(), recdir);
992 if (copied >= len) {
993 /* just return nothing if output was truncated */
994 kfree(result);
995 return NULL;
996 }
997
998 return result;
999}
1000
936static int 1001static int
937nfsd4_umh_cltrack_upcall(char *cmd, char *arg) 1002nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *legacy)
938{ 1003{
939 char *envp[] = { NULL }; 1004 char *envp[2];
940 char *argv[4]; 1005 char *argv[4];
941 int ret; 1006 int ret;
942 1007
@@ -947,6 +1012,10 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg)
947 1012
948 dprintk("%s: cmd: %s\n", __func__, cmd); 1013 dprintk("%s: cmd: %s\n", __func__, cmd);
949 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)"); 1014 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)");
1015 dprintk("%s: legacy: %s\n", __func__, legacy ? legacy : "(null)");
1016
1017 envp[0] = legacy;
1018 envp[1] = NULL;
950 1019
951 argv[0] = (char *)cltrack_prog; 1020 argv[0] = (char *)cltrack_prog;
952 argv[1] = cmd; 1021 argv[1] = cmd;
@@ -992,7 +1061,7 @@ bin_to_hex_dup(const unsigned char *src, int srclen)
992static int 1061static int
993nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net) 1062nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net)
994{ 1063{
995 return nfsd4_umh_cltrack_upcall("init", NULL); 1064 return nfsd4_umh_cltrack_upcall("init", NULL, NULL);
996} 1065}
997 1066
998static void 1067static void
@@ -1005,7 +1074,7 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
1005 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1074 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1006 return; 1075 return;
1007 } 1076 }
1008 nfsd4_umh_cltrack_upcall("create", hexid); 1077 nfsd4_umh_cltrack_upcall("create", hexid, NULL);
1009 kfree(hexid); 1078 kfree(hexid);
1010} 1079}
1011 1080
@@ -1019,7 +1088,7 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
1019 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1088 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1020 return; 1089 return;
1021 } 1090 }
1022 nfsd4_umh_cltrack_upcall("remove", hexid); 1091 nfsd4_umh_cltrack_upcall("remove", hexid, NULL);
1023 kfree(hexid); 1092 kfree(hexid);
1024} 1093}
1025 1094
@@ -1027,14 +1096,16 @@ static int
1027nfsd4_umh_cltrack_check(struct nfs4_client *clp) 1096nfsd4_umh_cltrack_check(struct nfs4_client *clp)
1028{ 1097{
1029 int ret; 1098 int ret;
1030 char *hexid; 1099 char *hexid, *legacy;
1031 1100
1032 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1101 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
1033 if (!hexid) { 1102 if (!hexid) {
1034 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1103 dprintk("%s: can't allocate memory for upcall!\n", __func__);
1035 return -ENOMEM; 1104 return -ENOMEM;
1036 } 1105 }
1037 ret = nfsd4_umh_cltrack_upcall("check", hexid); 1106 legacy = nfsd4_cltrack_legacy_recdir(clp->cl_recdir);
1107 ret = nfsd4_umh_cltrack_upcall("check", hexid, legacy);
1108 kfree(legacy);
1038 kfree(hexid); 1109 kfree(hexid);
1039 return ret; 1110 return ret;
1040} 1111}
@@ -1043,10 +1114,13 @@ static void
1043nfsd4_umh_cltrack_grace_done(struct net __attribute__((unused)) *net, 1114nfsd4_umh_cltrack_grace_done(struct net __attribute__((unused)) *net,
1044 time_t boot_time) 1115 time_t boot_time)
1045{ 1116{
1117 char *legacy;
1046 char timestr[22]; /* FIXME: better way to determine max size? */ 1118 char timestr[22]; /* FIXME: better way to determine max size? */
1047 1119
1048 sprintf(timestr, "%ld", boot_time); 1120 sprintf(timestr, "%ld", boot_time);
1049 nfsd4_umh_cltrack_upcall("gracedone", timestr); 1121 legacy = nfsd4_cltrack_legacy_topdir();
1122 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy);
1123 kfree(legacy);
1050} 1124}
1051 1125
1052static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { 1126static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = {