Skip to content

Commit 136d558

Browse files
chuckleverTrond Myklebust
authored andcommitted
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>
1 parent 0076d7b commit 136d558

File tree

1 file changed

+95
-10
lines changed

1 file changed

+95
-10
lines changed

fs/nfs/super.c

Lines changed: 95 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,10 +1051,28 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
10511051
/*
10521052
* Validate the NFS2/NFS3 mount data
10531053
* - 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.
10541069
*/
1055-
static int nfs_validate_mount_data(struct nfs_mount_data *data,
1056-
struct nfs_fh *mntfh)
1070+
static int nfs_validate_mount_data(struct nfs_mount_data **options,
1071+
struct nfs_fh *mntfh,
1072+
const char *dev_name)
10571073
{
1074+
struct nfs_mount_data *data = *options;
1075+
10581076
if (data == NULL)
10591077
goto out_no_data;
10601078

@@ -1087,8 +1105,78 @@ static int nfs_validate_mount_data(struct nfs_mount_data *data,
10871105
memset(mntfh->data + mntfh->size, 0,
10881106
sizeof(mntfh->data) - mntfh->size);
10891107
break;
1090-
default:
1091-
goto out_bad_version;
1108+
default: {
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+
}
10921180
}
10931181

10941182
if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
@@ -1117,11 +1205,6 @@ static int nfs_validate_mount_data(struct nfs_mount_data *data,
11171205
dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n");
11181206
return -EINVAL;
11191207

1120-
out_bad_version:
1121-
dfprintk(MOUNT, "NFS: bad nfs_mount_data version %d\n",
1122-
data->version);
1123-
return -EINVAL;
1124-
11251208
#ifndef CONFIG_NFS_V3
11261209
out_v3_not_compiled:
11271210
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,
12421325
int error;
12431326

12441327
/* Validate the mount data */
1245-
error = nfs_validate_mount_data(data, &mntfh);
1328+
error = nfs_validate_mount_data(&data, &mntfh, dev_name);
12461329
if (error < 0)
12471330
goto out;
12481331

@@ -1283,6 +1366,8 @@ static int nfs_get_sb(struct file_system_type *fs_type,
12831366
error = 0;
12841367

12851368
out:
1369+
if (data != raw_data)
1370+
kfree(data);
12861371
return error;
12871372

12881373
out_err_nosb:

0 commit comments

Comments
 (0)