aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 4cfacc557b40..0589852007e6 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1223,6 +1223,119 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1223 stateowner->so_replay.rp_buflen); \ 1223 stateowner->so_replay.rp_buflen); \
1224 } } while (0); 1224 } } while (0);
1225 1225
1226/* Encode as an array of strings the string given with components
1227 * seperated @sep.
1228 */
1229static int nfsd4_encode_components(char sep, char *components,
1230 u32 **pp, int *buflen)
1231{
1232 u32 *p = *pp;
1233 u32 *countp = p;
1234 int strlen, count=0;
1235 char *str, *end;
1236
1237 dprintk("nfsd4_encode_components(%s)\n", components);
1238 if ((*buflen -= 4) < 0)
1239 return nfserr_resource;
1240 WRITE32(0); /* We will fill this in with @count later */
1241 end = str = components;
1242 while (*end) {
1243 for (; *end && (*end != sep); end++)
1244 ; /* Point to end of component */
1245 strlen = end - str;
1246 if (strlen) {
1247 if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0)
1248 return nfserr_resource;
1249 WRITE32(strlen);
1250 WRITEMEM(str, strlen);
1251 count++;
1252 }
1253 else
1254 end++;
1255 str = end;
1256 }
1257 *pp = p;
1258 p = countp;
1259 WRITE32(count);
1260 return 0;
1261}
1262
1263/*
1264 * encode a location element of a fs_locations structure
1265 */
1266static int nfsd4_encode_fs_location4(struct nfsd4_fs_location *location,
1267 u32 **pp, int *buflen)
1268{
1269 int status;
1270 u32 *p = *pp;
1271
1272 status = nfsd4_encode_components(':', location->hosts, &p, buflen);
1273 if (status)
1274 return status;
1275 status = nfsd4_encode_components('/', location->path, &p, buflen);
1276 if (status)
1277 return status;
1278 *pp = p;
1279 return 0;
1280}
1281
1282/*
1283 * Return the path to an export point in the pseudo filesystem namespace
1284 * Returned string is safe to use as long as the caller holds a reference
1285 * to @exp.
1286 */
1287static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp)
1288{
1289 struct svc_fh tmp_fh;
1290 char *path, *rootpath;
1291 int stat;
1292
1293 fh_init(&tmp_fh, NFS4_FHSIZE);
1294 stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle);
1295 if (stat)
1296 return ERR_PTR(stat);
1297 rootpath = tmp_fh.fh_export->ex_path;
1298
1299 path = exp->ex_path;
1300
1301 if (strncmp(path, rootpath, strlen(rootpath))) {
1302 printk("nfsd: fs_locations failed;"
1303 "%s is not contained in %s\n", path, rootpath);
1304 return ERR_PTR(-EOPNOTSUPP);
1305 }
1306
1307 return path + strlen(rootpath);
1308}
1309
1310/*
1311 * encode a fs_locations structure
1312 */
1313static int nfsd4_encode_fs_locations(struct svc_rqst *rqstp,
1314 struct svc_export *exp,
1315 u32 **pp, int *buflen)
1316{
1317 int status, i;
1318 u32 *p = *pp;
1319 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
1320 char *root = nfsd4_path(rqstp, exp);
1321
1322 if (IS_ERR(root))
1323 return PTR_ERR(root);
1324 status = nfsd4_encode_components('/', root, &p, buflen);
1325 if (status)
1326 return status;
1327 if ((*buflen -= 4) < 0)
1328 return nfserr_resource;
1329 WRITE32(fslocs->locations_count);
1330 for (i=0; i<fslocs->locations_count; i++) {
1331 status = nfsd4_encode_fs_location4(&fslocs->locations[i],
1332 &p, buflen);
1333 if (status)
1334 return status;
1335 }
1336 *pp = p;
1337 return 0;
1338}
1226 1339
1227static u32 nfs4_ftypes[16] = { 1340static u32 nfs4_ftypes[16] = {
1228 NF4BAD, NF4FIFO, NF4CHR, NF4BAD, 1341 NF4BAD, NF4FIFO, NF4CHR, NF4BAD,
@@ -1334,6 +1447,11 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1334 goto out_nfserr; 1447 goto out_nfserr;
1335 } 1448 }
1336 } 1449 }
1450 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
1451 if (exp->ex_fslocs.locations == NULL) {
1452 bmval0 &= ~FATTR4_WORD0_FS_LOCATIONS;
1453 }
1454 }
1337 if ((buflen -= 16) < 0) 1455 if ((buflen -= 16) < 0)
1338 goto out_resource; 1456 goto out_resource;
1339 1457
@@ -1513,6 +1631,13 @@ out_acl:
1513 goto out_resource; 1631 goto out_resource;
1514 WRITE64((u64) statfs.f_files); 1632 WRITE64((u64) statfs.f_files);
1515 } 1633 }
1634 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
1635 status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen);
1636 if (status == nfserr_resource)
1637 goto out_resource;
1638 if (status)
1639 goto out;
1640 }
1516 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) { 1641 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
1517 if ((buflen -= 4) < 0) 1642 if ((buflen -= 4) < 0)
1518 goto out_resource; 1643 goto out_resource;