aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-07-01 12:13:54 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:48 -0400
commit136d558ce766967fe3cbf54c3351aba261b5d53b (patch)
treec1c66b7478149fc2f3ef3cf1a04bd1e22324eedc
parent0076d7b7bab580ca2e94637d351fa7cd357743a8 (diff)
NFS: Add final pieces to support in-kernel mount option parsing
Hook in final components required for supporting in-kernel mount option parsing for NFSv2 and NFSv3 mounts. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/super.c105
1 files changed, 95 insertions, 10 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 48db52a7067a..757aa3b7e64b 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1051,10 +1051,28 @@ out_err:
1051/* 1051/*
1052 * Validate the NFS2/NFS3 mount data 1052 * Validate the NFS2/NFS3 mount data
1053 * - fills in the mount root filehandle 1053 * - fills in the mount root filehandle
1054 *
1055 * For option strings, user space handles the following behaviors:
1056 *
1057 * + DNS: mapping server host name to IP address ("addr=" option)
1058 *
1059 * + failure mode: how to behave if a mount request can't be handled
1060 * immediately ("fg/bg" option)
1061 *
1062 * + retry: how often to retry a mount request ("retry=" option)
1063 *
1064 * + breaking back: trying proto=udp after proto=tcp, v2 after v3,
1065 * mountproto=tcp after mountproto=udp, and so on
1066 *
1067 * XXX: as far as I can tell, changing the NFS program number is not
1068 * supported in the NFS client.
1054 */ 1069 */
1055static int nfs_validate_mount_data(struct nfs_mount_data *data, 1070static int nfs_validate_mount_data(struct nfs_mount_data **options,
1056 struct nfs_fh *mntfh) 1071 struct nfs_fh *mntfh,
1072 const char *dev_name)
1057{ 1073{
1074 struct nfs_mount_data *data = *options;
1075
1058 if (data == NULL) 1076 if (data == NULL)
1059 goto out_no_data; 1077 goto out_no_data;
1060 1078
@@ -1087,8 +1105,78 @@ static int nfs_validate_mount_data(struct nfs_mount_data *data,
1087 memset(mntfh->data + mntfh->size, 0, 1105 memset(mntfh->data + mntfh->size, 0,
1088 sizeof(mntfh->data) - mntfh->size); 1106 sizeof(mntfh->data) - mntfh->size);
1089 break; 1107 break;
1090 default: 1108 default: {
1091 goto out_bad_version; 1109 unsigned int len;
1110 char *c;
1111 int status;
1112 struct nfs_parsed_mount_data args = {
1113 .flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP),
1114 .rsize = NFS_MAX_FILE_IO_SIZE,
1115 .wsize = NFS_MAX_FILE_IO_SIZE,
1116 .timeo = 600,
1117 .retrans = 2,
1118 .acregmin = 3,
1119 .acregmax = 60,
1120 .acdirmin = 30,
1121 .acdirmax = 60,
1122 .mount_server.protocol = IPPROTO_UDP,
1123 .mount_server.program = NFS_MNT_PROGRAM,
1124 .nfs_server.protocol = IPPROTO_TCP,
1125 .nfs_server.program = NFS_PROGRAM,
1126 };
1127
1128 if (nfs_parse_mount_options((char *) *options, &args) == 0)
1129 return -EINVAL;
1130
1131 data = kzalloc(sizeof(*data), GFP_KERNEL);
1132 if (data == NULL)
1133 return -ENOMEM;
1134
1135 /*
1136 * NB: after this point, caller will free "data"
1137 * if we return an error
1138 */
1139 *options = data;
1140
1141 c = strchr(dev_name, ':');
1142 if (c == NULL)
1143 return -EINVAL;
1144 len = c - dev_name - 1;
1145 if (len > sizeof(data->hostname))
1146 return -EINVAL;
1147 strncpy(data->hostname, dev_name, len);
1148 args.nfs_server.hostname = data->hostname;
1149
1150 c++;
1151 if (strlen(c) > NFS_MAXPATHLEN)
1152 return -EINVAL;
1153 args.nfs_server.export_path = c;
1154
1155 status = nfs_try_mount(&args, mntfh);
1156 if (status)
1157 return -EINVAL;
1158
1159 /*
1160 * Translate to nfs_mount_data, which nfs_fill_super
1161 * can deal with.
1162 */
1163 data->version = 6;
1164 data->flags = args.flags;
1165 data->rsize = args.rsize;
1166 data->wsize = args.wsize;
1167 data->timeo = args.timeo;
1168 data->retrans = args.retrans;
1169 data->acregmin = args.acregmin;
1170 data->acregmax = args.acregmax;
1171 data->acdirmin = args.acdirmin;
1172 data->acdirmax = args.acdirmax;
1173 data->addr = args.nfs_server.address;
1174 data->namlen = args.namlen;
1175 data->bsize = args.bsize;
1176 data->pseudoflavor = args.auth_flavors[0];
1177
1178 break;
1179 }
1092 } 1180 }
1093 1181
1094 if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) 1182 if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
@@ -1117,11 +1205,6 @@ out_no_sec:
1117 dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n"); 1205 dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n");
1118 return -EINVAL; 1206 return -EINVAL;
1119 1207
1120out_bad_version:
1121 dfprintk(MOUNT, "NFS: bad nfs_mount_data version %d\n",
1122 data->version);
1123 return -EINVAL;
1124
1125#ifndef CONFIG_NFS_V3 1208#ifndef CONFIG_NFS_V3
1126out_v3_not_compiled: 1209out_v3_not_compiled:
1127 dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n"); 1210 dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n");
@@ -1242,7 +1325,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
1242 int error; 1325 int error;
1243 1326
1244 /* Validate the mount data */ 1327 /* Validate the mount data */
1245 error = nfs_validate_mount_data(data, &mntfh); 1328 error = nfs_validate_mount_data(&data, &mntfh, dev_name);
1246 if (error < 0) 1329 if (error < 0)
1247 goto out; 1330 goto out;
1248 1331
@@ -1283,6 +1366,8 @@ static int nfs_get_sb(struct file_system_type *fs_type,
1283 error = 0; 1366 error = 0;
1284 1367
1285out: 1368out:
1369 if (data != raw_data)
1370 kfree(data);
1286 return error; 1371 return error;
1287 1372
1288out_err_nosb: 1373out_err_nosb: