History

NFSv4.2: add client side XDR handling for extended attributes

Define the argument and response structures that will be used for RFC 8276 extended attribute RPC calls, and implement the necessary functions to encode/decode the extended attribute operations.

Frank van der Linden committed 6 years ago

Commit 3e1f0211 parent b78ef843 files · +430 −3Browse files

Unified · Split

3 files
  1. fs/nfs/nfs42xdr.c +366 −2
  2. fs/nfs/nfs4xdr.c +6 −0
  3. include/linux/nfs_xdr.h +58 −1
fs/nfs/nfs42xdr.c+366−2
@@ -169,7 +169,6 @@ · 168 unmodified lines
169 decode_clone_maxsz + \169 decode_clone_maxsz + \
170 decode_getattr_maxsz)170 decode_getattr_maxsz)
171 171
172#ifdef CONFIG_NFS_V4_2
173/* Not limited by NFS itself, limited by the generic xattr code */172/* Not limited by NFS itself, limited by the generic xattr code */
174#define nfs4_xattr_name_maxsz XDR_QUADLEN(XATTR_NAME_MAX)173#define nfs4_xattr_name_maxsz XDR_QUADLEN(XATTR_NAME_MAX)
175 174
@@ -241,7 +240,6 @@ const u32 nfs42_maxlistxattrs_overhead = ((RPC_MAX_HEADER_WITH_AUTH + · 65 unmodified lines
241 compound_decode_hdr_maxsz +240 compound_decode_hdr_maxsz +
242 decode_sequence_maxsz +241 decode_sequence_maxsz +
243 decode_putfh_maxsz + 3) * XDR_UNIT);242 decode_putfh_maxsz + 3) * XDR_UNIT);
244#endif
245 243
246static void encode_fallocate(struct xdr_stream *xdr,244static void encode_fallocate(struct xdr_stream *xdr,
247 const struct nfs42_falloc_args *args)245 const struct nfs42_falloc_args *args)
@@ -407,6 +405,210 @@ static void encode_layouterror(struct xdr_stream *xdr, · 159 unmodified lines
407 encode_device_error(xdr, &args->errors[0]);405 encode_device_error(xdr, &args->errors[0]);
408}406}
409 407
408static void encode_setxattr(struct xdr_stream *xdr,
409 const struct nfs42_setxattrargs *arg,
410 struct compound_hdr *hdr)
411{
412 __be32 *p;
413
414 BUILD_BUG_ON(XATTR_CREATE != SETXATTR4_CREATE);
415 BUILD_BUG_ON(XATTR_REPLACE != SETXATTR4_REPLACE);
416
417 encode_op_hdr(xdr, OP_SETXATTR, decode_setxattr_maxsz, hdr);
418 p = reserve_space(xdr, 4);
419 *p = cpu_to_be32(arg->xattr_flags);
420 encode_string(xdr, strlen(arg->xattr_name), arg->xattr_name);
421 p = reserve_space(xdr, 4);
422 *p = cpu_to_be32(arg->xattr_len);
423 if (arg->xattr_len)
424 xdr_write_pages(xdr, arg->xattr_pages, 0, arg->xattr_len);
425}
426
427static int decode_setxattr(struct xdr_stream *xdr,
428 struct nfs4_change_info *cinfo)
429{
430 int status;
431
432 status = decode_op_hdr(xdr, OP_SETXATTR);
433 if (status)
434 goto out;
435 status = decode_change_info(xdr, cinfo);
436out:
437 return status;
438}
439
440
441static void encode_getxattr(struct xdr_stream *xdr, const char *name,
442 struct compound_hdr *hdr)
443{
444 encode_op_hdr(xdr, OP_GETXATTR, decode_getxattr_maxsz, hdr);
445 encode_string(xdr, strlen(name), name);
446}
447
448static int decode_getxattr(struct xdr_stream *xdr,
449 struct nfs42_getxattrres *res,
450 struct rpc_rqst *req)
451{
452 int status;
453 __be32 *p;
454 u32 len, rdlen;
455
456 status = decode_op_hdr(xdr, OP_GETXATTR);
457 if (status)
458 return status;
459
460 p = xdr_inline_decode(xdr, 4);
461 if (unlikely(!p))
462 return -EIO;
463
464 len = be32_to_cpup(p);
465 if (len > req->rq_rcv_buf.page_len)
466 return -ERANGE;
467
468 res->xattr_len = len;
469
470 if (len > 0) {
471 rdlen = xdr_read_pages(xdr, len);
472 if (rdlen < len)
473 return -EIO;
474 }
475
476 return 0;
477}
478
479static void encode_removexattr(struct xdr_stream *xdr, const char *name,
480 struct compound_hdr *hdr)
481{
482 encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr);
483 encode_string(xdr, strlen(name), name);
484}
485
486
487static int decode_removexattr(struct xdr_stream *xdr,
488 struct nfs4_change_info *cinfo)
489{
490 int status;
491
492 status = decode_op_hdr(xdr, OP_REMOVEXATTR);
493 if (status)
494 goto out;
495
496 status = decode_change_info(xdr, cinfo);
497out:
498 return status;
499}
500
501static void encode_listxattrs(struct xdr_stream *xdr,
502 const struct nfs42_listxattrsargs *arg,
503 struct compound_hdr *hdr)
504{
505 __be32 *p;
506
507 encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz + 1, hdr);
508
509 p = reserve_space(xdr, 12);
510 if (unlikely(!p))
511 return;
512
513 p = xdr_encode_hyper(p, arg->cookie);
514 /*
515 * RFC 8276 says to specify the full max length of the LISTXATTRS
516 * XDR reply. Count is set to the XDR length of the names array
517 * plus the EOF marker. So, add the cookie and the names count.
518 */
519 *p = cpu_to_be32(arg->count + 8 + 4);
520}
521
522static int decode_listxattrs(struct xdr_stream *xdr,
523 struct nfs42_listxattrsres *res)
524{
525 int status;
526 __be32 *p;
527 u32 count, len, ulen;
528 size_t left, copied;
529 char *buf;
530
531 status = decode_op_hdr(xdr, OP_LISTXATTRS);
532 if (status) {
533 /*
534 * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL
535 * should be translated to ERANGE.
536 */
537 if (status == -ETOOSMALL)
538 status = -ERANGE;
539 goto out;
540 }
541
542 p = xdr_inline_decode(xdr, 8);
543 if (unlikely(!p))
544 return -EIO;
545
546 xdr_decode_hyper(p, &res->cookie);
547
548 p = xdr_inline_decode(xdr, 4);
549 if (unlikely(!p))
550 return -EIO;
551
552 left = res->xattr_len;
553 buf = res->xattr_buf;
554
555 count = be32_to_cpup(p);
556 copied = 0;
557
558 /*
559 * We have asked for enough room to encode the maximum number
560 * of possible attribute names, so everything should fit.
561 *
562 * But, don't rely on that assumption. Just decode entries
563 * until they don't fit anymore, just in case the server did
564 * something odd.
565 */
566 while (count--) {
567 p = xdr_inline_decode(xdr, 4);
568 if (unlikely(!p))
569 return -EIO;
570
571 len = be32_to_cpup(p);
572 if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
573 status = -ERANGE;
574 goto out;
575 }
576
577 p = xdr_inline_decode(xdr, len);
578 if (unlikely(!p))
579 return -EIO;
580
581 ulen = len + XATTR_USER_PREFIX_LEN + 1;
582 if (buf) {
583 if (ulen > left) {
584 status = -ERANGE;
585 goto out;
586 }
587
588 memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
589 memcpy(buf + XATTR_USER_PREFIX_LEN, p, len);
590
591 buf[ulen - 1] = 0;
592 buf += ulen;
593 left -= ulen;
594 }
595 copied += ulen;
596 }
597
598 p = xdr_inline_decode(xdr, 4);
599 if (unlikely(!p))
600 return -EIO;
601
602 res->eof = be32_to_cpup(p);
603 res->copied = copied;
604
605out:
606 if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX)
607 status = -E2BIG;
608
609 return status;
610}
611
410/*612/*
411 * Encode ALLOCATE request613 * Encode ALLOCATE request
412 */614 */
@@ -1062,4 +1264,166 @@ out: · 649 unmodified lines
1062 return status;1264 return status;
1063}1265}
1064 1266
1267#ifdef CONFIG_NFS_V4_2
1268static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1269 const void *data)
1270{
1271 const struct nfs42_setxattrargs *args = data;
1272 struct compound_hdr hdr = {
1273 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1274 };
1275
1276 encode_compound_hdr(xdr, req, &hdr);
1277 encode_sequence(xdr, &args->seq_args, &hdr);
1278 encode_putfh(xdr, args->fh, &hdr);
1279 encode_setxattr(xdr, args, &hdr);
1280 encode_nops(&hdr);
1281}
1282
1283static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1284 void *data)
1285{
1286 struct nfs42_setxattrres *res = data;
1287 struct compound_hdr hdr;
1288 int status;
1289
1290 status = decode_compound_hdr(xdr, &hdr);
1291 if (status)
1292 goto out;
1293 status = decode_sequence(xdr, &res->seq_res, req);
1294 if (status)
1295 goto out;
1296 status = decode_putfh(xdr);
1297 if (status)
1298 goto out;
1299
1300 status = decode_setxattr(xdr, &res->cinfo);
1301out:
1302 return status;
1303}
1304
1305static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1306 const void *data)
1307{
1308 const struct nfs42_getxattrargs *args = data;
1309 struct compound_hdr hdr = {
1310 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1311 };
1312 size_t plen;
1313
1314 encode_compound_hdr(xdr, req, &hdr);
1315 encode_sequence(xdr, &args->seq_args, &hdr);
1316 encode_putfh(xdr, args->fh, &hdr);
1317 encode_getxattr(xdr, args->xattr_name, &hdr);
1318
1319 plen = args->xattr_len ? args->xattr_len : XATTR_SIZE_MAX;
1320
1321 rpc_prepare_reply_pages(req, args->xattr_pages, 0, plen,
1322 hdr.replen);
1323 req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
1324
1325 encode_nops(&hdr);
1326}
1327
1328static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
1329 struct xdr_stream *xdr, void *data)
1330{
1331 struct nfs42_getxattrres *res = data;
1332 struct compound_hdr hdr;
1333 int status;
1334
1335 status = decode_compound_hdr(xdr, &hdr);
1336 if (status)
1337 goto out;
1338 status = decode_sequence(xdr, &res->seq_res, rqstp);
1339 if (status)
1340 goto out;
1341 status = decode_putfh(xdr);
1342 if (status)
1343 goto out;
1344 status = decode_getxattr(xdr, res, rqstp);
1345out:
1346 return status;
1347}
1348
1349static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
1350 struct xdr_stream *xdr, const void *data)
1351{
1352 const struct nfs42_listxattrsargs *args = data;
1353 struct compound_hdr hdr = {
1354 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1355 };
1356
1357 encode_compound_hdr(xdr, req, &hdr);
1358 encode_sequence(xdr, &args->seq_args, &hdr);
1359 encode_putfh(xdr, args->fh, &hdr);
1360 encode_listxattrs(xdr, args, &hdr);
1361
1362 rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count,
1363 hdr.replen);
1364 req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
1365
1366 encode_nops(&hdr);
1367}
1368
1369static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
1370 struct xdr_stream *xdr, void *data)
1371{
1372 struct nfs42_listxattrsres *res = data;
1373 struct compound_hdr hdr;
1374 int status;
1375
1376 xdr_set_scratch_buffer(xdr, page_address(res->scratch), PAGE_SIZE);
1377
1378 status = decode_compound_hdr(xdr, &hdr);
1379 if (status)
1380 goto out;
1381 status = decode_sequence(xdr, &res->seq_res, rqstp);
1382 if (status)
1383 goto out;
1384 status = decode_putfh(xdr);
1385 if (status)
1386 goto out;
1387 status = decode_listxattrs(xdr, res);
1388out:
1389 return status;
1390}
1391
1392static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
1393 struct xdr_stream *xdr, const void *data)
1394{
1395 const struct nfs42_removexattrargs *args = data;
1396 struct compound_hdr hdr = {
1397 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1398 };
1399
1400 encode_compound_hdr(xdr, req, &hdr);
1401 encode_sequence(xdr, &args->seq_args, &hdr);
1402 encode_putfh(xdr, args->fh, &hdr);
1403 encode_removexattr(xdr, args->xattr_name, &hdr);
1404 encode_nops(&hdr);
1405}
1406
1407static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
1408 struct xdr_stream *xdr, void *data)
1409{
1410 struct nfs42_removexattrres *res = data;
1411 struct compound_hdr hdr;
1412 int status;
1413
1414 status = decode_compound_hdr(xdr, &hdr);
1415 if (status)
1416 goto out;
1417 status = decode_sequence(xdr, &res->seq_res, req);
1418 if (status)
1419 goto out;
1420 status = decode_putfh(xdr);
1421 if (status)
1422 goto out;
1423
1424 status = decode_removexattr(xdr, &res->cinfo);
1425out:
1426 return status;
1427}
1428#endif
1065#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */1429#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
fs/nfs/nfs4xdr.c+6−0
@@ -7481,6 +7481,8 @@ static struct { · 7480 unmodified lines
7481 { NFS4ERR_SYMLINK, -ELOOP },7481 { NFS4ERR_SYMLINK, -ELOOP },
7482 { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },7482 { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
7483 { NFS4ERR_DEADLOCK, -EDEADLK },7483 { NFS4ERR_DEADLOCK, -EDEADLK },
7484 { NFS4ERR_NOXATTR, -ENODATA },
7485 { NFS4ERR_XATTR2BIG, -E2BIG },
7484 { -1, -EIO }7486 { -1, -EIO }
7485};7487};
7486 7488
@@ -7609,6 +7611,10 @@ const struct rpc_procinfo nfs4_procedures[] = { · 122 unmodified lines
7609 PROC42(COPY_NOTIFY, enc_copy_notify, dec_copy_notify),7611 PROC42(COPY_NOTIFY, enc_copy_notify, dec_copy_notify),
7610 PROC(LOOKUPP, enc_lookupp, dec_lookupp),7612 PROC(LOOKUPP, enc_lookupp, dec_lookupp),
7611 PROC42(LAYOUTERROR, enc_layouterror, dec_layouterror),7613 PROC42(LAYOUTERROR, enc_layouterror, dec_layouterror),
7614 PROC42(GETXATTR, enc_getxattr, dec_getxattr),
7615 PROC42(SETXATTR, enc_setxattr, dec_setxattr),
7616 PROC42(LISTXATTRS, enc_listxattrs, dec_listxattrs),
7617 PROC42(REMOVEXATTR, enc_removexattr, dec_removexattr),
7612};7618};
7613 7619
7614static unsigned int nfs_version4_counts[ARRAY_SIZE(nfs4_procedures)];7620static unsigned int nfs_version4_counts[ARRAY_SIZE(nfs4_procedures)];
include/linux/nfs_xdr.h+58−1
@@ -1498,7 +1498,64 @@ struct nfs42_seek_res { · 1497 unmodified lines
1498 u32 sr_eof;1498 u32 sr_eof;
1499 u64 sr_offset;1499 u64 sr_offset;
1500};1500};
1501#endif1501
1502struct nfs42_setxattrargs {
1503 struct nfs4_sequence_args seq_args;
1504 struct nfs_fh *fh;
1505 const char *xattr_name;
1506 u32 xattr_flags;
1507 size_t xattr_len;
1508 struct page **xattr_pages;
1509};
1510
1511struct nfs42_setxattrres {
1512 struct nfs4_sequence_res seq_res;
1513 struct nfs4_change_info cinfo;
1514};
1515
1516struct nfs42_getxattrargs {
1517 struct nfs4_sequence_args seq_args;
1518 struct nfs_fh *fh;
1519 const char *xattr_name;
1520 size_t xattr_len;
1521 struct page **xattr_pages;
1522};
1523
1524struct nfs42_getxattrres {
1525 struct nfs4_sequence_res seq_res;
1526 size_t xattr_len;
1527};
1528
1529struct nfs42_listxattrsargs {
1530 struct nfs4_sequence_args seq_args;
1531 struct nfs_fh *fh;
1532 u32 count;
1533 u64 cookie;
1534 struct page **xattr_pages;
1535};
1536
1537struct nfs42_listxattrsres {
1538 struct nfs4_sequence_res seq_res;
1539 struct page *scratch;
1540 void *xattr_buf;
1541 size_t xattr_len;
1542 u64 cookie;
1543 bool eof;
1544 size_t copied;
1545};
1546
1547struct nfs42_removexattrargs {
1548 struct nfs4_sequence_args seq_args;
1549 struct nfs_fh *fh;
1550 const char *xattr_name;
1551};
1552
1553struct nfs42_removexattrres {
1554 struct nfs4_sequence_res seq_res;
1555 struct nfs4_change_info cinfo;
1556};
1557
1558#endif /* CONFIG_NFS_V4_2 */
1502 1559
1503struct nfs_page;1560struct nfs_page;
1504 1561

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t