diff options
-rw-r--r-- | fs/nfsd/nfs4recover.c | 90 |
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); |
934 | MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program"); | 934 | MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program"); |
935 | 935 | ||
936 | static bool cltrack_legacy_disable; | ||
937 | module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR); | ||
938 | MODULE_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 | |||
944 | static char * | ||
945 | nfsd4_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 | |||
972 | static char * | ||
973 | nfsd4_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 | |||
936 | static int | 1001 | static int |
937 | nfsd4_umh_cltrack_upcall(char *cmd, char *arg) | 1002 | nfsd4_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) | |||
992 | static int | 1061 | static int |
993 | nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net) | 1062 | nfsd4_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 | ||
998 | static void | 1067 | static 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 | |||
1027 | nfsd4_umh_cltrack_check(struct nfs4_client *clp) | 1096 | nfsd4_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 | |||
1043 | nfsd4_umh_cltrack_grace_done(struct net __attribute__((unused)) *net, | 1114 | nfsd4_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 | ||
1052 | static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { | 1126 | static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { |