aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2008-06-23 12:36:37 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-07-09 12:09:26 -0400
commitdc04589827f7e1af12714af8bb00e3f3c4c48c62 (patch)
treefb1436269bd041af0609ef4f748f1c58f91f974b /fs/nfs/super.c
parentcd100725620a8063fbc81bcf16d7c9e71a9583e0 (diff)
NFS: Use common device name parsing logic for NFSv4 and NFSv2/v3
To support passing a raw IPv6 address as a server hostname, we need to expand the logic that handles splitting the passed-in device name into a server hostname and export path Start by pulling device name parsing out of the mount option validation functions and into separate helper functions. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c124
1 files changed, 79 insertions, 45 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index b880db18035b..c4ee8b3a27c1 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1196,6 +1196,67 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1196} 1196}
1197 1197
1198/* 1198/*
1199 * Split "dev_name" into "hostname:export_path".
1200 *
1201 * Note: caller frees hostname and export path, even on error.
1202 */
1203static int nfs_parse_devname(const char *dev_name,
1204 char **hostname, size_t maxnamlen,
1205 char **export_path, size_t maxpathlen)
1206{
1207 size_t len;
1208 char *colon, *comma;
1209
1210 colon = strchr(dev_name, ':');
1211 if (colon == NULL)
1212 goto out_bad_devname;
1213
1214 len = colon - dev_name;
1215 if (len > maxnamlen)
1216 goto out_hostname;
1217
1218 /* N.B. caller will free nfs_server.hostname in all cases */
1219 *hostname = kstrndup(dev_name, len, GFP_KERNEL);
1220 if (!*hostname)
1221 goto out_nomem;
1222
1223 /* kill possible hostname list: not supported */
1224 comma = strchr(*hostname, ',');
1225 if (comma != NULL) {
1226 if (comma == *hostname)
1227 goto out_bad_devname;
1228 *comma = '\0';
1229 }
1230
1231 colon++;
1232 len = strlen(colon);
1233 if (len > maxpathlen)
1234 goto out_path;
1235 *export_path = kstrndup(colon, len, GFP_KERNEL);
1236 if (!*export_path)
1237 goto out_nomem;
1238
1239 dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *export_path);
1240 return 0;
1241
1242out_bad_devname:
1243 dfprintk(MOUNT, "NFS: device name not in host:path format\n");
1244 return -EINVAL;
1245
1246out_nomem:
1247 dfprintk(MOUNT, "NFS: not enough memory to parse device name\n");
1248 return -ENOMEM;
1249
1250out_hostname:
1251 dfprintk(MOUNT, "NFS: server hostname too long\n");
1252 return -ENAMETOOLONG;
1253
1254out_path:
1255 dfprintk(MOUNT, "NFS: export pathname too long\n");
1256 return -ENAMETOOLONG;
1257}
1258
1259/*
1199 * Validate the NFS2/NFS3 mount data 1260 * Validate the NFS2/NFS3 mount data
1200 * - fills in the mount root filehandle 1261 * - fills in the mount root filehandle
1201 * 1262 *
@@ -1323,8 +1384,6 @@ static int nfs_validate_mount_data(void *options,
1323 1384
1324 break; 1385 break;
1325 default: { 1386 default: {
1326 unsigned int len;
1327 char *c;
1328 int status; 1387 int status;
1329 1388
1330 if (nfs_parse_mount_options((char *)options, args) == 0) 1389 if (nfs_parse_mount_options((char *)options, args) == 0)
@@ -1334,21 +1393,17 @@ static int nfs_validate_mount_data(void *options,
1334 &args->nfs_server.address)) 1393 &args->nfs_server.address))
1335 goto out_no_address; 1394 goto out_no_address;
1336 1395
1337 c = strchr(dev_name, ':'); 1396 status = nfs_parse_devname(dev_name,
1338 if (c == NULL) 1397 &args->nfs_server.hostname,
1339 return -EINVAL; 1398 PAGE_SIZE,
1340 len = c - dev_name; 1399 &args->nfs_server.export_path,
1341 /* N.B. caller will free nfs_server.hostname in all cases */ 1400 NFS_MAXPATHLEN);
1342 args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); 1401 if (!status)
1343 if (!args->nfs_server.hostname) 1402 status = nfs_try_mount(args, mntfh);
1344 goto out_nomem;
1345 1403
1346 c++; 1404 kfree(args->nfs_server.export_path);
1347 if (strlen(c) > NFS_MAXPATHLEN) 1405 args->nfs_server.export_path = NULL;
1348 return -ENAMETOOLONG;
1349 args->nfs_server.export_path = c;
1350 1406
1351 status = nfs_try_mount(args, mntfh);
1352 if (status) 1407 if (status)
1353 return status; 1408 return status;
1354 1409
@@ -1958,7 +2013,7 @@ static int nfs4_validate_mount_data(void *options,
1958 2013
1959 break; 2014 break;
1960 default: { 2015 default: {
1961 unsigned int len; 2016 int status;
1962 2017
1963 if (nfs_parse_mount_options((char *)options, args) == 0) 2018 if (nfs_parse_mount_options((char *)options, args) == 0)
1964 return -EINVAL; 2019 return -EINVAL;
@@ -1977,34 +2032,17 @@ static int nfs4_validate_mount_data(void *options,
1977 goto out_inval_auth; 2032 goto out_inval_auth;
1978 } 2033 }
1979 2034
1980 /*
1981 * Split "dev_name" into "hostname:mntpath".
1982 */
1983 c = strchr(dev_name, ':');
1984 if (c == NULL)
1985 return -EINVAL;
1986 /* while calculating len, pretend ':' is '\0' */
1987 len = c - dev_name;
1988 if (len > NFS4_MAXNAMLEN)
1989 return -ENAMETOOLONG;
1990 /* N.B. caller will free nfs_server.hostname in all cases */
1991 args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL);
1992 if (!args->nfs_server.hostname)
1993 goto out_nomem;
1994
1995 c++; /* step over the ':' */
1996 len = strlen(c);
1997 if (len > NFS4_MAXPATHLEN)
1998 return -ENAMETOOLONG;
1999 args->nfs_server.export_path = kstrndup(c, len, GFP_KERNEL);
2000 if (!args->nfs_server.export_path)
2001 goto out_nomem;
2002
2003 dprintk("NFS: MNTPATH: '%s'\n", args->nfs_server.export_path);
2004
2005 if (args->client_address == NULL) 2035 if (args->client_address == NULL)
2006 goto out_no_client_address; 2036 goto out_no_client_address;
2007 2037
2038 status = nfs_parse_devname(dev_name,
2039 &args->nfs_server.hostname,
2040 NFS4_MAXNAMLEN,
2041 &args->nfs_server.export_path,
2042 NFS4_MAXPATHLEN);
2043 if (status < 0)
2044 return status;
2045
2008 break; 2046 break;
2009 } 2047 }
2010 } 2048 }
@@ -2020,10 +2058,6 @@ out_inval_auth:
2020 data->auth_flavourlen); 2058 data->auth_flavourlen);
2021 return -EINVAL; 2059 return -EINVAL;
2022 2060
2023out_nomem:
2024 dfprintk(MOUNT, "NFS4: not enough memory to handle mount options\n");
2025 return -ENOMEM;
2026
2027out_no_address: 2061out_no_address:
2028 dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n"); 2062 dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
2029 return -EINVAL; 2063 return -EINVAL;