Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'nfs-for-6.17-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client updates from Trond Myklebust:
"Highlights include:

Stable fixes:
- don't inherit NFS filesystem capabilities when crossing from one
filesystem to another

Bugfixes:
- NFS wakeup of __nfs_lookup_revalidate() needs memory barriers
- NFS improve bounds checking in nfs_fh_to_dentry()
- NFS Fix allocation errors when writing to a NFS file backed
loopback device
- NFSv4: More listxattr fixes
- SUNRPC: fix client handling of TLS alerts
- pNFS block/scsi layout fix for an uninitialised pointer
dereference
- pNFS block/scsi layout fixes for the extent encoding, stripe
mapping, and disk offset overflows
- pNFS layoutcommit work around for RPC size limitations
- pNFS/flexfiles avoid looping when handling fatal errors after
layoutget
- localio: fix various race conditions

Features and cleanups:
- Add NFSv4 support for retrieving the btime
- NFS: Allow folio migration for the case of mode == MIGRATE_SYNC
- NFS: Support using a kernel keyring to store TLS certificates
- NFSv4: Speed up delegation lookup using a hash table
- Assorted cleanups to remove unused variables and struct fields
- Assorted new tracepoints to improve debugging"

* tag 'nfs-for-6.17-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (44 commits)
NFS/localio: nfs_uuid_put() fix the wake up after unlinking the file
NFS/localio: nfs_uuid_put() fix races with nfs_open/close_local_fh()
NFS/localio: nfs_close_local_fh() fix check for file closed
NFSv4: Remove duplicate lookups, capability probes and fsinfo calls
NFS: Fix the setting of capabilities when automounting a new filesystem
sunrpc: fix client side handling of tls alerts
nfs/localio: use read_seqbegin() rather than read_seqbegin_or_lock()
NFS: Fixup allocation flags for nfsiod's __GFP_NORETRY
NFSv4.2: another fix for listxattr
NFS: Fix filehandle bounds checking in nfs_fh_to_dentry()
SUNRPC: Silence warnings about parameters not being described
NFS: Clean up pnfs_put_layout_hdr()/pnfs_destroy_layout_final()
NFS: Fix wakeup of __nfs_lookup_revalidate() in unblock_revalidate()
NFS: use a hash table for delegation lookup
NFS: track active delegations per-server
NFS: move the delegation_watermark module parameter
NFS: cleanup nfs_inode_reclaim_delegation
NFS: cleanup error handling in nfs4_server_common_setup
pNFS/flexfiles: don't attempt pnfs on fatal DS errors
NFS: drop __exit from nfs_exit_keyring
...

+858 -562
+2 -2
fs/nfs/blocklayout/blocklayout.c
··· 149 149 150 150 /* limit length to what the device mapping allows */ 151 151 end = disk_addr + *len; 152 - if (end >= map->start + map->len) 153 - *len = map->start + map->len - disk_addr; 152 + if (end >= map->disk_offset + map->len) 153 + *len = map->disk_offset + map->len - disk_addr; 154 154 155 155 retry: 156 156 if (!bio) {
+3 -2
fs/nfs/blocklayout/dev.c
··· 257 257 struct pnfs_block_dev *child; 258 258 u64 chunk; 259 259 u32 chunk_idx; 260 + u64 disk_chunk; 260 261 u64 disk_offset; 261 262 262 263 chunk = div_u64(offset, dev->chunk_size); 263 - div_u64_rem(chunk, dev->nr_children, &chunk_idx); 264 + disk_chunk = div_u64_rem(chunk, dev->nr_children, &chunk_idx); 264 265 265 266 if (chunk_idx >= dev->nr_children) { 266 267 dprintk("%s: invalid chunk idx %d (%lld/%lld)\n", ··· 274 273 offset = chunk * dev->chunk_size; 275 274 276 275 /* disk offset of the stripe */ 277 - disk_offset = div_u64(offset, dev->nr_children); 276 + disk_offset = disk_chunk * dev->chunk_size; 278 277 279 278 child = &dev->children[chunk_idx]; 280 279 child->map(child, disk_offset, map);
+91 -13
fs/nfs/blocklayout/extent_tree.c
··· 6 6 #include <linux/vmalloc.h> 7 7 8 8 #include "blocklayout.h" 9 + #include "../nfs4trace.h" 9 10 10 11 #define NFSDBG_FACILITY NFSDBG_PNFS_LD 11 12 ··· 521 520 return xdr_encode_hyper(p, be->be_length << SECTOR_SHIFT); 522 521 } 523 522 524 - static int ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p, 523 + /** 524 + * ext_tree_try_encode_commit - try to encode all extents into the buffer 525 + * @bl: pointer to the layout 526 + * @p: pointer to the output buffer 527 + * @buffer_size: size of the output buffer 528 + * @count: output pointer to the number of encoded extents 529 + * @lastbyte: output pointer to the last written byte 530 + * 531 + * Return values: 532 + * %0: Success, all required extents encoded, outputs are valid 533 + * %-ENOSPC: Buffer too small, nothing encoded, outputs are invalid 534 + */ 535 + static int 536 + ext_tree_try_encode_commit(struct pnfs_block_layout *bl, __be32 *p, 525 537 size_t buffer_size, size_t *count, __u64 *lastbyte) 526 538 { 527 539 struct pnfs_block_extent *be; 540 + 541 + spin_lock(&bl->bl_ext_lock); 542 + for (be = ext_tree_first(&bl->bl_ext_rw); be; be = ext_tree_next(be)) { 543 + if (be->be_state != PNFS_BLOCK_INVALID_DATA || 544 + be->be_tag != EXTENT_WRITTEN) 545 + continue; 546 + 547 + (*count)++; 548 + if (ext_tree_layoutupdate_size(bl, *count) > buffer_size) { 549 + spin_unlock(&bl->bl_ext_lock); 550 + return -ENOSPC; 551 + } 552 + } 553 + for (be = ext_tree_first(&bl->bl_ext_rw); be; be = ext_tree_next(be)) { 554 + if (be->be_state != PNFS_BLOCK_INVALID_DATA || 555 + be->be_tag != EXTENT_WRITTEN) 556 + continue; 557 + 558 + if (bl->bl_scsi_layout) 559 + p = encode_scsi_range(be, p); 560 + else 561 + p = encode_block_extent(be, p); 562 + be->be_tag = EXTENT_COMMITTING; 563 + } 564 + *lastbyte = (bl->bl_lwb != 0) ? bl->bl_lwb - 1 : U64_MAX; 565 + bl->bl_lwb = 0; 566 + spin_unlock(&bl->bl_ext_lock); 567 + 568 + return 0; 569 + } 570 + 571 + /** 572 + * ext_tree_encode_commit - encode as much as possible extents into the buffer 573 + * @bl: pointer to the layout 574 + * @p: pointer to the output buffer 575 + * @buffer_size: size of the output buffer 576 + * @count: output pointer to the number of encoded extents 577 + * @lastbyte: output pointer to the last written byte 578 + * 579 + * Return values: 580 + * %0: Success, all required extents encoded, outputs are valid 581 + * %-ENOSPC: Buffer too small, some extents are encoded, outputs are valid 582 + */ 583 + static int 584 + ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p, 585 + size_t buffer_size, size_t *count, __u64 *lastbyte) 586 + { 587 + struct pnfs_block_extent *be, *be_prev; 528 588 int ret = 0; 529 589 530 590 spin_lock(&bl->bl_ext_lock); ··· 596 534 597 535 (*count)++; 598 536 if (ext_tree_layoutupdate_size(bl, *count) > buffer_size) { 599 - /* keep counting.. */ 537 + (*count)--; 600 538 ret = -ENOSPC; 601 - continue; 539 + break; 602 540 } 603 541 604 542 if (bl->bl_scsi_layout) ··· 606 544 else 607 545 p = encode_block_extent(be, p); 608 546 be->be_tag = EXTENT_COMMITTING; 547 + be_prev = be; 609 548 } 610 - *lastbyte = bl->bl_lwb - 1; 611 - bl->bl_lwb = 0; 549 + if (!ret) { 550 + *lastbyte = (bl->bl_lwb != 0) ? bl->bl_lwb - 1 : U64_MAX; 551 + bl->bl_lwb = 0; 552 + } else { 553 + *lastbyte = be_prev->be_f_offset + be_prev->be_length; 554 + *lastbyte <<= SECTOR_SHIFT; 555 + *lastbyte -= 1; 556 + } 612 557 spin_unlock(&bl->bl_ext_lock); 613 558 614 559 return ret; 615 560 } 616 561 562 + /** 563 + * ext_tree_prepare_commit - encode extents that need to be committed 564 + * @arg: layout commit data 565 + * 566 + * Return values: 567 + * %0: Success, all required extents are encoded 568 + * %-ENOSPC: Some extents are encoded, but not all, due to RPC size limit 569 + * %-ENOMEM: Out of memory, extents not encoded 570 + */ 617 571 int 618 572 ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg) 619 573 { ··· 638 560 __be32 *start_p; 639 561 int ret; 640 562 641 - dprintk("%s enter\n", __func__); 642 - 643 563 arg->layoutupdate_page = alloc_page(GFP_NOFS); 644 564 if (!arg->layoutupdate_page) 645 565 return -ENOMEM; 646 566 start_p = page_address(arg->layoutupdate_page); 647 567 arg->layoutupdate_pages = &arg->layoutupdate_page; 648 568 649 - retry: 650 - ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, &count, &arg->lastbytewritten); 569 + ret = ext_tree_try_encode_commit(bl, start_p + 1, buffer_size, 570 + &count, &arg->lastbytewritten); 651 571 if (unlikely(ret)) { 652 572 ext_tree_free_commitdata(arg, buffer_size); 653 573 654 - buffer_size = ext_tree_layoutupdate_size(bl, count); 574 + buffer_size = NFS_SERVER(arg->inode)->wsize; 655 575 count = 0; 656 576 657 577 arg->layoutupdate_pages = ··· 664 588 return -ENOMEM; 665 589 } 666 590 667 - goto retry; 591 + ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, 592 + &count, &arg->lastbytewritten); 668 593 } 669 594 670 595 *start_p = cpu_to_be32(count); ··· 684 607 } 685 608 } 686 609 687 - dprintk("%s found %zu ranges\n", __func__, count); 688 - return 0; 610 + trace_bl_ext_tree_prepare_commit(ret, count, 611 + arg->lastbytewritten, !!ret); 612 + return ret; 689 613 } 690 614 691 615 void
+43 -4
fs/nfs/client.c
··· 682 682 } 683 683 EXPORT_SYMBOL_GPL(nfs_init_client); 684 684 685 + static void nfs4_server_set_init_caps(struct nfs_server *server) 686 + { 687 + #if IS_ENABLED(CONFIG_NFS_V4) 688 + /* Set the basic capabilities */ 689 + server->caps = server->nfs_client->cl_mvops->init_caps; 690 + if (server->flags & NFS_MOUNT_NORDIRPLUS) 691 + server->caps &= ~NFS_CAP_READDIRPLUS; 692 + if (server->nfs_client->cl_proto == XPRT_TRANSPORT_RDMA) 693 + server->caps &= ~NFS_CAP_READ_PLUS; 694 + 695 + /* 696 + * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower 697 + * authentication. 698 + */ 699 + if (nfs4_disable_idmapping && 700 + server->client->cl_auth->au_flavor == RPC_AUTH_UNIX) 701 + server->caps |= NFS_CAP_UIDGID_NOMAP; 702 + #endif 703 + } 704 + 705 + void nfs_server_set_init_caps(struct nfs_server *server) 706 + { 707 + switch (server->nfs_client->rpc_ops->version) { 708 + case 2: 709 + server->caps = NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS; 710 + break; 711 + case 3: 712 + server->caps = NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS; 713 + if (!(server->flags & NFS_MOUNT_NORDIRPLUS)) 714 + server->caps |= NFS_CAP_READDIRPLUS; 715 + break; 716 + default: 717 + nfs4_server_set_init_caps(server); 718 + break; 719 + } 720 + } 721 + EXPORT_SYMBOL_GPL(nfs_server_set_init_caps); 722 + 685 723 /* 686 724 * Create a version 2 or 3 client 687 725 */ ··· 764 726 /* Initialise the client representation from the mount data */ 765 727 server->flags = ctx->flags; 766 728 server->options = ctx->options; 767 - server->caps |= NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS; 768 729 769 730 switch (clp->rpc_ops->version) { 770 731 case 2: ··· 798 761 ctx->selected_flavor); 799 762 if (error < 0) 800 763 goto error; 764 + 765 + nfs_server_set_init_caps(server); 801 766 802 767 /* Preserve the values of mount_server-related mount options */ 803 768 if (ctx->mount_server.addrlen) { ··· 853 814 server->wsize = max_rpc_payload; 854 815 if (server->wsize > NFS_MAX_FILE_IO_SIZE) 855 816 server->wsize = NFS_MAX_FILE_IO_SIZE; 856 - server->wpages = (server->wsize + PAGE_SIZE - 1) >> PAGE_SHIFT; 857 817 858 818 server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); 859 819 ··· 869 831 870 832 server->maxfilesize = fsinfo->maxfilesize; 871 833 872 - server->time_delta = fsinfo->time_delta; 873 834 server->change_attr_type = fsinfo->change_attr_type; 874 835 875 836 server->clone_blksize = fsinfo->clone_blksize; ··· 973 936 target->acregmax = source->acregmax; 974 937 target->acdirmin = source->acdirmin; 975 938 target->acdirmax = source->acdirmax; 976 - target->caps = source->caps; 977 939 target->options = source->options; 978 940 target->auth_info = source->auth_info; 979 941 target->port = source->port; ··· 1043 1007 INIT_LIST_HEAD(&server->ss_src_copies); 1044 1008 1045 1009 atomic_set(&server->active, 0); 1010 + atomic_long_set(&server->nr_active_delegations, 0); 1046 1011 1047 1012 server->io_stats = nfs_alloc_iostats(); 1048 1013 if (!server->io_stats) { ··· 1206 1169 flavor); 1207 1170 if (error < 0) 1208 1171 goto out_free_server; 1172 + 1173 + nfs_server_set_init_caps(server); 1209 1174 1210 1175 /* probe the filesystem info for this server filesystem */ 1211 1176 error = nfs_probe_server(server, fh);
+73 -41
fs/nfs/delegation.c
··· 27 27 28 28 #define NFS_DEFAULT_DELEGATION_WATERMARK (5000U) 29 29 30 - static atomic_long_t nfs_active_delegations; 31 30 static unsigned nfs_delegation_watermark = NFS_DEFAULT_DELEGATION_WATERMARK; 31 + module_param_named(delegation_watermark, nfs_delegation_watermark, uint, 0644); 32 + 33 + static struct hlist_head *nfs_delegation_hash(struct nfs_server *server, 34 + const struct nfs_fh *fhandle) 35 + { 36 + return server->delegation_hash_table + 37 + (nfs_fhandle_hash(fhandle) & server->delegation_hash_mask); 38 + } 32 39 33 40 static void __nfs_free_delegation(struct nfs_delegation *delegation) 34 41 { ··· 44 37 kfree_rcu(delegation, rcu); 45 38 } 46 39 47 - static void nfs_mark_delegation_revoked(struct nfs_delegation *delegation) 40 + static void nfs_mark_delegation_revoked(struct nfs_server *server, 41 + struct nfs_delegation *delegation) 48 42 { 49 43 if (!test_and_set_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) { 50 44 delegation->stateid.type = NFS4_INVALID_STATEID_TYPE; 51 - atomic_long_dec(&nfs_active_delegations); 45 + atomic_long_dec(&server->nr_active_delegations); 52 46 if (!test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) 53 47 nfs_clear_verifier_delegated(delegation->inode); 54 48 } ··· 67 59 __nfs_free_delegation(delegation); 68 60 } 69 61 70 - static void nfs_free_delegation(struct nfs_delegation *delegation) 62 + static void nfs_free_delegation(struct nfs_server *server, 63 + struct nfs_delegation *delegation) 71 64 { 72 - nfs_mark_delegation_revoked(delegation); 65 + nfs_mark_delegation_revoked(server, delegation); 73 66 nfs_put_delegation(delegation); 74 67 } 75 68 ··· 246 237 247 238 rcu_read_lock(); 248 239 delegation = rcu_dereference(NFS_I(inode)->delegation); 249 - if (delegation != NULL) { 250 - spin_lock(&delegation->lock); 251 - nfs4_stateid_copy(&delegation->stateid, stateid); 252 - delegation->type = type; 253 - delegation->pagemod_limit = pagemod_limit; 254 - oldcred = delegation->cred; 255 - delegation->cred = get_cred(cred); 256 - switch (deleg_type) { 257 - case NFS4_OPEN_DELEGATE_READ_ATTRS_DELEG: 258 - case NFS4_OPEN_DELEGATE_WRITE_ATTRS_DELEG: 259 - set_bit(NFS_DELEGATION_DELEGTIME, &delegation->flags); 260 - break; 261 - default: 262 - clear_bit(NFS_DELEGATION_DELEGTIME, &delegation->flags); 263 - } 264 - clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); 265 - if (test_and_clear_bit(NFS_DELEGATION_REVOKED, 266 - &delegation->flags)) 267 - atomic_long_inc(&nfs_active_delegations); 268 - spin_unlock(&delegation->lock); 269 - rcu_read_unlock(); 270 - put_cred(oldcred); 271 - trace_nfs4_reclaim_delegation(inode, type); 272 - } else { 240 + if (!delegation) { 273 241 rcu_read_unlock(); 274 242 nfs_inode_set_delegation(inode, cred, type, stateid, 275 243 pagemod_limit, deleg_type); 244 + return; 276 245 } 246 + 247 + spin_lock(&delegation->lock); 248 + nfs4_stateid_copy(&delegation->stateid, stateid); 249 + delegation->type = type; 250 + delegation->pagemod_limit = pagemod_limit; 251 + oldcred = delegation->cred; 252 + delegation->cred = get_cred(cred); 253 + switch (deleg_type) { 254 + case NFS4_OPEN_DELEGATE_READ_ATTRS_DELEG: 255 + case NFS4_OPEN_DELEGATE_WRITE_ATTRS_DELEG: 256 + set_bit(NFS_DELEGATION_DELEGTIME, &delegation->flags); 257 + break; 258 + default: 259 + clear_bit(NFS_DELEGATION_DELEGTIME, &delegation->flags); 260 + } 261 + clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); 262 + if (test_and_clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) 263 + atomic_long_inc(&NFS_SERVER(inode)->nr_active_delegations); 264 + spin_unlock(&delegation->lock); 265 + rcu_read_unlock(); 266 + put_cred(oldcred); 267 + trace_nfs4_reclaim_delegation(inode, type); 277 268 } 278 269 279 270 static int nfs_do_return_delegation(struct inode *inode, ··· 364 355 rcu_dereference_protected(nfsi->delegation, 365 356 lockdep_is_held(&clp->cl_lock)); 366 357 358 + trace_nfs4_detach_delegation(&nfsi->vfs_inode, delegation->type); 359 + 367 360 if (deleg_cur == NULL || delegation != deleg_cur) 368 361 return NULL; 369 362 ··· 374 363 spin_unlock(&delegation->lock); 375 364 return NULL; 376 365 } 366 + hlist_del_init_rcu(&delegation->hash); 377 367 list_del_rcu(&delegation->super_list); 378 368 delegation->inode = NULL; 379 369 rcu_assign_pointer(nfsi->delegation, NULL); ··· 422 410 } 423 411 424 412 static void 425 - nfs_update_inplace_delegation(struct nfs_delegation *delegation, 413 + nfs_update_inplace_delegation(struct nfs_server *server, 414 + struct nfs_delegation *delegation, 426 415 const struct nfs_delegation *update) 427 416 { 428 417 if (nfs4_stateid_is_newer(&update->stateid, &delegation->stateid)) { ··· 436 423 nfs_update_delegation_cred(delegation, update->cred); 437 424 /* smp_mb__before_atomic() is implicit due to xchg() */ 438 425 clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags); 439 - atomic_long_inc(&nfs_active_delegations); 426 + atomic_long_inc(&server->nr_active_delegations); 440 427 } 441 428 } 442 429 } ··· 491 478 if (nfs4_stateid_match_other(&old_delegation->stateid, 492 479 &delegation->stateid)) { 493 480 spin_lock(&old_delegation->lock); 494 - nfs_update_inplace_delegation(old_delegation, 481 + nfs_update_inplace_delegation(server, old_delegation, 495 482 delegation); 496 483 spin_unlock(&old_delegation->lock); 497 484 goto out; ··· 537 524 spin_unlock(&inode->i_lock); 538 525 539 526 list_add_tail_rcu(&delegation->super_list, &server->delegations); 527 + hlist_add_head_rcu(&delegation->hash, 528 + nfs_delegation_hash(server, &NFS_I(inode)->fh)); 540 529 rcu_assign_pointer(nfsi->delegation, delegation); 541 530 delegation = NULL; 542 531 543 - atomic_long_inc(&nfs_active_delegations); 532 + atomic_long_inc(&server->nr_active_delegations); 544 533 545 534 trace_nfs4_set_delegation(inode, type); 546 535 ··· 556 541 __nfs_free_delegation(delegation); 557 542 if (freeme != NULL) { 558 543 nfs_do_return_delegation(inode, freeme, 0); 559 - nfs_free_delegation(freeme); 544 + nfs_free_delegation(server, freeme); 560 545 } 561 546 return status; 562 547 } ··· 606 591 static bool nfs_delegation_need_return(struct nfs_delegation *delegation) 607 592 { 608 593 bool ret = false; 594 + 595 + trace_nfs_delegation_need_return(delegation); 609 596 610 597 if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) 611 598 ret = true; ··· 768 751 set_bit(NFS_DELEGATION_RETURNING, &delegation->flags); 769 752 set_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags); 770 753 nfs_do_return_delegation(inode, delegation, 1); 771 - nfs_free_delegation(delegation); 754 + nfs_free_delegation(NFS_SERVER(inode), delegation); 772 755 } 773 756 } 774 757 ··· 854 837 if (!delegation) 855 838 goto out; 856 839 if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) || 857 - atomic_long_read(&nfs_active_delegations) >= nfs_delegation_watermark) { 840 + atomic_long_read(&NFS_SERVER(inode)->nr_active_delegations) >= 841 + nfs_delegation_watermark) { 858 842 spin_lock(&delegation->lock); 859 843 if (delegation->inode && 860 844 list_empty(&NFS_I(inode)->open_files) && ··· 1031 1013 } 1032 1014 spin_unlock(&delegation->lock); 1033 1015 } 1034 - nfs_mark_delegation_revoked(delegation); 1016 + nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation); 1035 1017 ret = true; 1036 1018 out: 1037 1019 rcu_read_unlock(); ··· 1063 1045 delegation->stateid.seqid = stateid->seqid; 1064 1046 } 1065 1047 1066 - nfs_mark_delegation_revoked(delegation); 1048 + nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation); 1067 1049 clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags); 1068 1050 spin_unlock(&delegation->lock); 1069 1051 if (nfs_detach_delegation(NFS_I(inode), delegation, NFS_SERVER(inode))) ··· 1176 1158 nfs_delegation_find_inode_server(struct nfs_server *server, 1177 1159 const struct nfs_fh *fhandle) 1178 1160 { 1161 + struct hlist_head *head = nfs_delegation_hash(server, fhandle); 1179 1162 struct nfs_delegation *delegation; 1180 1163 struct super_block *freeme = NULL; 1181 1164 struct inode *res = NULL; 1182 1165 1183 - list_for_each_entry_rcu(delegation, &server->delegations, super_list) { 1166 + hlist_for_each_entry_rcu(delegation, head, hash) { 1184 1167 spin_lock(&delegation->lock); 1185 1168 if (delegation->inode != NULL && 1186 1169 !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) && ··· 1284 1265 if (delegation != NULL) { 1285 1266 if (nfs_detach_delegation(NFS_I(inode), delegation, 1286 1267 server) != NULL) 1287 - nfs_free_delegation(delegation); 1268 + nfs_free_delegation(server, delegation); 1288 1269 /* Match nfs_start_delegation_return_locked */ 1289 1270 nfs_put_delegation(delegation); 1290 1271 } ··· 1589 1570 return ret; 1590 1571 } 1591 1572 1592 - module_param_named(delegation_watermark, nfs_delegation_watermark, uint, 0644); 1573 + int nfs4_delegation_hash_alloc(struct nfs_server *server) 1574 + { 1575 + int delegation_buckets, i; 1576 + 1577 + delegation_buckets = roundup_pow_of_two(nfs_delegation_watermark / 16); 1578 + server->delegation_hash_mask = delegation_buckets - 1; 1579 + server->delegation_hash_table = kmalloc_array(delegation_buckets, 1580 + sizeof(*server->delegation_hash_table), GFP_KERNEL); 1581 + if (!server->delegation_hash_table) 1582 + return -ENOMEM; 1583 + for (i = 0; i < delegation_buckets; i++) 1584 + INIT_HLIST_HEAD(&server->delegation_hash_table[i]); 1585 + return 0; 1586 + }
+3
fs/nfs/delegation.h
··· 14 14 * NFSv4 delegation 15 15 */ 16 16 struct nfs_delegation { 17 + struct hlist_node hash; 17 18 struct list_head super_list; 18 19 const struct cred *cred; 19 20 struct inode *inode; ··· 123 122 return NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE, 124 123 NFS_DELEGATION_FLAG_TIME); 125 124 } 125 + 126 + int nfs4_delegation_hash_alloc(struct nfs_server *server); 126 127 127 128 #endif
+1 -3
fs/nfs/dir.c
··· 1828 1828 1829 1829 static void unblock_revalidate(struct dentry *dentry) 1830 1830 { 1831 - /* store_release ensures wait_var_event() sees the update */ 1832 - smp_store_release(&dentry->d_fsdata, NULL); 1833 - wake_up_var(&dentry->d_fsdata); 1831 + store_release_wake_up(&dentry->d_fsdata, NULL); 1834 1832 } 1835 1833 1836 1834 /*
+9 -2
fs/nfs/export.c
··· 66 66 { 67 67 struct nfs_fattr *fattr = NULL; 68 68 struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw); 69 - size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size; 69 + size_t fh_size = offsetof(struct nfs_fh, data); 70 70 const struct nfs_rpc_ops *rpc_ops; 71 71 struct dentry *dentry; 72 72 struct inode *inode; 73 - int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size); 73 + int len = EMBED_FH_OFF; 74 74 u32 *p = fid->raw; 75 75 int ret; 76 76 77 + /* Initial check of bounds */ 78 + if (fh_len < len + XDR_QUADLEN(fh_size) || 79 + fh_len > XDR_QUADLEN(NFS_MAXFHSIZE)) 80 + return NULL; 81 + /* Calculate embedded filehandle size */ 82 + fh_size += server_fh->size; 83 + len += XDR_QUADLEN(fh_size); 77 84 /* NULL translates to ESTALE */ 78 85 if (fh_len < len || fh_type != len) 79 86 return NULL;
+16 -10
fs/nfs/flexfilelayout/flexfilelayout.c
··· 762 762 { 763 763 struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg); 764 764 struct nfs4_ff_layout_mirror *mirror; 765 - struct nfs4_pnfs_ds *ds; 765 + struct nfs4_pnfs_ds *ds = ERR_PTR(-EAGAIN); 766 766 u32 idx; 767 767 768 768 /* mirrors are initially sorted by efficiency */ 769 769 for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) { 770 770 mirror = FF_LAYOUT_COMP(lseg, idx); 771 771 ds = nfs4_ff_layout_prepare_ds(lseg, mirror, false); 772 - if (!ds) 772 + if (IS_ERR(ds)) 773 773 continue; 774 774 775 775 if (check_device && ··· 777 777 continue; 778 778 779 779 *best_idx = idx; 780 - return ds; 780 + break; 781 781 } 782 782 783 - return NULL; 783 + return ds; 784 784 } 785 785 786 786 static struct nfs4_pnfs_ds * ··· 942 942 for (i = 0; i < pgio->pg_mirror_count; i++) { 943 943 mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i); 944 944 ds = nfs4_ff_layout_prepare_ds(pgio->pg_lseg, mirror, true); 945 - if (!ds) { 945 + if (IS_ERR(ds)) { 946 946 if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg)) 947 947 goto out_mds; 948 948 pnfs_generic_pg_cleanup(pgio); ··· 1867 1867 u32 idx = hdr->pgio_mirror_idx; 1868 1868 int vers; 1869 1869 struct nfs_fh *fh; 1870 + bool ds_fatal_error = false; 1870 1871 1871 1872 dprintk("--> %s ino %lu pgbase %u req %zu@%llu\n", 1872 1873 __func__, hdr->inode->i_ino, ··· 1875 1874 1876 1875 mirror = FF_LAYOUT_COMP(lseg, idx); 1877 1876 ds = nfs4_ff_layout_prepare_ds(lseg, mirror, false); 1878 - if (!ds) 1877 + if (IS_ERR(ds)) { 1878 + ds_fatal_error = nfs_error_is_fatal(PTR_ERR(ds)); 1879 1879 goto out_failed; 1880 + } 1880 1881 1881 1882 ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, 1882 1883 hdr->inode); ··· 1926 1923 return PNFS_ATTEMPTED; 1927 1924 1928 1925 out_failed: 1929 - if (ff_layout_avoid_mds_available_ds(lseg)) 1926 + if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error) 1930 1927 return PNFS_TRY_AGAIN; 1931 1928 trace_pnfs_mds_fallback_read_pagelist(hdr->inode, 1932 1929 hdr->args.offset, hdr->args.count, ··· 1948 1945 int vers; 1949 1946 struct nfs_fh *fh; 1950 1947 u32 idx = hdr->pgio_mirror_idx; 1948 + bool ds_fatal_error = false; 1951 1949 1952 1950 mirror = FF_LAYOUT_COMP(lseg, idx); 1953 1951 ds = nfs4_ff_layout_prepare_ds(lseg, mirror, true); 1954 - if (!ds) 1952 + if (IS_ERR(ds)) { 1953 + ds_fatal_error = nfs_error_is_fatal(PTR_ERR(ds)); 1955 1954 goto out_failed; 1955 + } 1956 1956 1957 1957 ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, 1958 1958 hdr->inode); ··· 2006 2000 return PNFS_ATTEMPTED; 2007 2001 2008 2002 out_failed: 2009 - if (ff_layout_avoid_mds_available_ds(lseg)) 2003 + if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error) 2010 2004 return PNFS_TRY_AGAIN; 2011 2005 trace_pnfs_mds_fallback_write_pagelist(hdr->inode, 2012 2006 hdr->args.offset, hdr->args.count, ··· 2049 2043 idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); 2050 2044 mirror = FF_LAYOUT_COMP(lseg, idx); 2051 2045 ds = nfs4_ff_layout_prepare_ds(lseg, mirror, true); 2052 - if (!ds) 2046 + if (IS_ERR(ds)) 2053 2047 goto out_err; 2054 2048 2055 2049 ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp,
+3 -3
fs/nfs/flexfilelayout/flexfilelayoutdev.c
··· 370 370 struct nfs4_ff_layout_mirror *mirror, 371 371 bool fail_return) 372 372 { 373 - struct nfs4_pnfs_ds *ds = NULL; 373 + struct nfs4_pnfs_ds *ds; 374 374 struct inode *ino = lseg->pls_layout->plh_inode; 375 375 struct nfs_server *s = NFS_SERVER(ino); 376 376 unsigned int max_payload; 377 - int status; 377 + int status = -EAGAIN; 378 378 379 379 if (!ff_layout_init_mirror_ds(lseg->pls_layout, mirror)) 380 380 goto noconnect; ··· 418 418 ff_layout_send_layouterror(lseg); 419 419 if (fail_return || !ff_layout_has_available_ds(lseg)) 420 420 pnfs_error_mark_layout_for_return(ino, lseg); 421 - ds = NULL; 421 + ds = ERR_PTR(status); 422 422 out: 423 423 return ds; 424 424 }
+42
fs/nfs/fs_context.c
··· 96 96 Opt_wsize, 97 97 Opt_write, 98 98 Opt_xprtsec, 99 + Opt_cert_serial, 100 + Opt_privkey_serial, 99 101 }; 100 102 101 103 enum { ··· 223 221 fsparam_enum ("write", Opt_write, nfs_param_enums_write), 224 222 fsparam_u32 ("wsize", Opt_wsize), 225 223 fsparam_string("xprtsec", Opt_xprtsec), 224 + fsparam_s32("cert_serial", Opt_cert_serial), 225 + fsparam_s32("privkey_serial", Opt_privkey_serial), 226 226 {} 227 227 }; 228 228 ··· 555 551 return 0; 556 552 } 557 553 554 + #ifdef CONFIG_KEYS 555 + static int nfs_tls_key_verify(key_serial_t key_id) 556 + { 557 + struct key *key = key_lookup(key_id); 558 + int error = 0; 559 + 560 + if (IS_ERR(key)) { 561 + pr_err("key id %08x not found\n", key_id); 562 + return PTR_ERR(key); 563 + } 564 + if (test_bit(KEY_FLAG_REVOKED, &key->flags) || 565 + test_bit(KEY_FLAG_INVALIDATED, &key->flags)) { 566 + pr_err("key id %08x revoked\n", key_id); 567 + error = -EKEYREVOKED; 568 + } 569 + 570 + key_put(key); 571 + return error; 572 + } 573 + #else 574 + static inline int nfs_tls_key_verify(key_serial_t key_id) 575 + { 576 + return -ENOENT; 577 + } 578 + #endif /* CONFIG_KEYS */ 579 + 558 580 /* 559 581 * Parse a single mount parameter. 560 582 */ ··· 836 806 ret = nfs_parse_xprtsec_policy(fc, param); 837 807 if (ret < 0) 838 808 return ret; 809 + break; 810 + case Opt_cert_serial: 811 + ret = nfs_tls_key_verify(result.int_32); 812 + if (ret < 0) 813 + return ret; 814 + ctx->xprtsec.cert_serial = result.int_32; 815 + break; 816 + case Opt_privkey_serial: 817 + ret = nfs_tls_key_verify(result.int_32); 818 + if (ret < 0) 819 + return ret; 820 + ctx->xprtsec.privkey_serial = result.int_32; 839 821 break; 840 822 841 823 case Opt_proto:
+64 -5
fs/nfs/inode.c
··· 197 197 if (!(flags & NFS_INO_REVAL_FORCED)) 198 198 flags &= ~(NFS_INO_INVALID_MODE | 199 199 NFS_INO_INVALID_OTHER | 200 + NFS_INO_INVALID_BTIME | 200 201 NFS_INO_INVALID_XATTR); 201 202 flags &= ~(NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_SIZE); 202 203 } ··· 523 522 inode_set_atime(inode, 0, 0); 524 523 inode_set_mtime(inode, 0, 0); 525 524 inode_set_ctime(inode, 0, 0); 525 + memset(&nfsi->btime, 0, sizeof(nfsi->btime)); 526 526 inode_set_iversion_raw(inode, 0); 527 527 inode->i_size = 0; 528 528 clear_nlink(inode); ··· 547 545 inode_set_ctime_to_ts(inode, fattr->ctime); 548 546 else if (fattr_supported & NFS_ATTR_FATTR_CTIME) 549 547 nfs_set_cache_invalid(inode, NFS_INO_INVALID_CTIME); 548 + if (fattr->valid & NFS_ATTR_FATTR_BTIME) 549 + nfsi->btime = fattr->btime; 550 + else if (fattr_supported & NFS_ATTR_FATTR_BTIME) 551 + nfs_set_cache_invalid(inode, NFS_INO_INVALID_BTIME); 550 552 if (fattr->valid & NFS_ATTR_FATTR_CHANGE) 551 553 inode_set_iversion_raw(inode, fattr->change_attr); 552 554 else ··· 937 931 938 932 static u32 nfs_get_valid_attrmask(struct inode *inode) 939 933 { 934 + u64 fattr_valid = NFS_SERVER(inode)->fattr_valid; 940 935 unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity); 941 936 u32 reply_mask = STATX_INO | STATX_TYPE; 942 937 ··· 957 950 reply_mask |= STATX_UID | STATX_GID; 958 951 if (!(cache_validity & NFS_INO_INVALID_BLOCKS)) 959 952 reply_mask |= STATX_BLOCKS; 953 + if (!(cache_validity & NFS_INO_INVALID_BTIME) && 954 + (fattr_valid & NFS_ATTR_FATTR_BTIME)) 955 + reply_mask |= STATX_BTIME; 960 956 if (!(cache_validity & NFS_INO_INVALID_CHANGE)) 961 957 reply_mask |= STATX_CHANGE_COOKIE; 962 958 return reply_mask; ··· 970 960 { 971 961 struct inode *inode = d_inode(path->dentry); 972 962 struct nfs_server *server = NFS_SERVER(inode); 963 + u64 fattr_valid = server->fattr_valid; 973 964 unsigned long cache_validity; 974 965 int err = 0; 975 966 bool force_sync = query_flags & AT_STATX_FORCE_SYNC; ··· 981 970 982 971 request_mask &= STATX_TYPE | STATX_MODE | STATX_NLINK | STATX_UID | 983 972 STATX_GID | STATX_ATIME | STATX_MTIME | STATX_CTIME | 984 - STATX_INO | STATX_SIZE | STATX_BLOCKS | 973 + STATX_INO | STATX_SIZE | STATX_BLOCKS | STATX_BTIME | 985 974 STATX_CHANGE_COOKIE; 975 + 976 + if (!(fattr_valid & NFS_ATTR_FATTR_BTIME)) 977 + request_mask &= ~STATX_BTIME; 986 978 987 979 if ((query_flags & AT_STATX_DONT_SYNC) && !force_sync) { 988 980 if (readdirplus_enabled) ··· 1018 1004 /* Is the user requesting attributes that might need revalidation? */ 1019 1005 if (!(request_mask & (STATX_MODE|STATX_NLINK|STATX_ATIME|STATX_CTIME| 1020 1006 STATX_MTIME|STATX_UID|STATX_GID| 1021 - STATX_SIZE|STATX_BLOCKS| 1007 + STATX_SIZE|STATX_BLOCKS|STATX_BTIME| 1022 1008 STATX_CHANGE_COOKIE))) 1023 1009 goto out_no_revalidate; 1024 1010 ··· 1042 1028 do_update |= cache_validity & NFS_INO_INVALID_OTHER; 1043 1029 if (request_mask & STATX_BLOCKS) 1044 1030 do_update |= cache_validity & NFS_INO_INVALID_BLOCKS; 1031 + if (request_mask & STATX_BTIME) 1032 + do_update |= cache_validity & NFS_INO_INVALID_BTIME; 1045 1033 1046 1034 if (do_update) { 1047 1035 if (readdirplus_enabled) ··· 1065 1049 stat->attributes |= STATX_ATTR_CHANGE_MONOTONIC; 1066 1050 if (S_ISDIR(inode->i_mode)) 1067 1051 stat->blksize = NFS_SERVER(inode)->dtsize; 1052 + stat->btime = NFS_I(inode)->btime; 1068 1053 out: 1069 1054 trace_nfs_getattr_exit(inode, err); 1070 1055 return err; ··· 1960 1943 NFS_INO_INVALID_ATIME | NFS_INO_INVALID_CTIME | 1961 1944 NFS_INO_INVALID_MTIME | NFS_INO_INVALID_SIZE | 1962 1945 NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_OTHER | 1963 - NFS_INO_INVALID_NLINK; 1946 + NFS_INO_INVALID_NLINK | NFS_INO_INVALID_BTIME; 1964 1947 unsigned long cache_validity = NFS_I(inode)->cache_validity; 1965 1948 enum nfs4_change_attr_type ctype = NFS_SERVER(inode)->change_attr_type; 1966 1949 ··· 2226 2209 bool attr_changed = false; 2227 2210 bool have_delegation; 2228 2211 2229 - dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%x)\n", 2212 + dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%llx)\n", 2230 2213 __func__, inode->i_sb->s_id, inode->i_ino, 2231 2214 nfs_display_fhandle_hash(NFS_FH(inode)), 2232 2215 atomic_read(&inode->i_count), fattr->valid); ··· 2321 2304 | NFS_INO_INVALID_BLOCKS 2322 2305 | NFS_INO_INVALID_NLINK 2323 2306 | NFS_INO_INVALID_MODE 2324 - | NFS_INO_INVALID_OTHER; 2307 + | NFS_INO_INVALID_OTHER 2308 + | NFS_INO_INVALID_BTIME; 2325 2309 if (S_ISDIR(inode->i_mode)) 2326 2310 nfs_force_lookup_revalidate(inode); 2327 2311 attr_changed = true; ··· 2355 2337 else if (fattr_supported & NFS_ATTR_FATTR_CTIME) 2356 2338 nfsi->cache_validity |= 2357 2339 save_cache_validity & NFS_INO_INVALID_CTIME; 2340 + 2341 + if (fattr->valid & NFS_ATTR_FATTR_BTIME) 2342 + nfsi->btime = fattr->btime; 2343 + else if (fattr_supported & NFS_ATTR_FATTR_BTIME) 2344 + nfsi->cache_validity |= 2345 + save_cache_validity & NFS_INO_INVALID_BTIME; 2358 2346 2359 2347 /* Check if our cached file size is stale */ 2360 2348 if (fattr->valid & NFS_ATTR_FATTR_SIZE) { ··· 2649 2625 .size = sizeof(struct nfs_net), 2650 2626 }; 2651 2627 2628 + #ifdef CONFIG_KEYS 2629 + static struct key *nfs_keyring; 2630 + 2631 + static int __init nfs_init_keyring(void) 2632 + { 2633 + nfs_keyring = keyring_alloc(".nfs", 2634 + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, 2635 + current_cred(), 2636 + (KEY_POS_ALL & ~KEY_POS_SETATTR) | 2637 + (KEY_USR_ALL & ~KEY_USR_SETATTR), 2638 + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); 2639 + return PTR_ERR_OR_ZERO(nfs_keyring); 2640 + } 2641 + 2642 + static void nfs_exit_keyring(void) 2643 + { 2644 + key_put(nfs_keyring); 2645 + } 2646 + #else 2647 + static inline int nfs_init_keyring(void) 2648 + { 2649 + return 0; 2650 + } 2651 + 2652 + static inline void nfs_exit_keyring(void) 2653 + { 2654 + } 2655 + #endif /* CONFIG_KEYS */ 2656 + 2652 2657 /* 2653 2658 * Initialize NFS 2654 2659 */ 2655 2660 static int __init init_nfs_fs(void) 2656 2661 { 2657 2662 int err; 2663 + 2664 + err = nfs_init_keyring(); 2665 + if (err) 2666 + return err; 2658 2667 2659 2668 err = nfs_sysfs_init(); 2660 2669 if (err < 0) ··· 2749 2692 out9: 2750 2693 nfs_sysfs_exit(); 2751 2694 out10: 2695 + nfs_exit_keyring(); 2752 2696 return err; 2753 2697 } 2754 2698 ··· 2765 2707 nfs_fs_proc_exit(); 2766 2708 nfsiod_stop(); 2767 2709 nfs_sysfs_exit(); 2710 + nfs_exit_keyring(); 2768 2711 } 2769 2712 2770 2713 /* Not quite true; I just maintain it */
+7 -5
fs/nfs/internal.h
··· 207 207 }; 208 208 209 209 extern int nfs_mount(struct nfs_mount_request *info, int timeo, int retrans); 210 - extern void nfs_umount(const struct nfs_mount_request *info); 211 210 212 211 /* client.c */ 213 212 extern const struct rpc_program nfs_program; ··· 231 232 nfs4_find_client_sessionid(struct net *, const struct sockaddr *, 232 233 struct nfs4_sessionid *, u32); 233 234 extern struct nfs_server *nfs_create_server(struct fs_context *); 234 - extern void nfs4_server_set_init_caps(struct nfs_server *); 235 + extern void nfs_server_set_init_caps(struct nfs_server *); 235 236 extern struct nfs_server *nfs4_create_server(struct fs_context *); 236 237 extern struct nfs_server *nfs4_create_referral_server(struct fs_context *); 237 238 extern int nfs4_update_server(struct nfs_server *server, const char *hostname, ··· 670 671 671 672 static inline gfp_t nfs_io_gfp_mask(void) 672 673 { 673 - if (current->flags & PF_WQ_WORKER) 674 - return GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN; 675 - return GFP_KERNEL; 674 + gfp_t ret = current_gfp_context(GFP_KERNEL); 675 + 676 + /* For workers __GFP_NORETRY only with __GFP_IO or __GFP_FS */ 677 + if ((current->flags & PF_WQ_WORKER) && ret == GFP_KERNEL) 678 + ret |= __GFP_NORETRY | __GFP_NOWARN; 679 + return ret; 676 680 } 677 681 678 682 /*
+3 -4
fs/nfs/localio.c
··· 500 500 { 501 501 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 502 502 u32 *verf = (u32 *)verifier->data; 503 - int seq = 0; 503 + unsigned int seq; 504 504 505 505 do { 506 - read_seqbegin_or_lock(&clp->cl_boot_lock, &seq); 506 + seq = read_seqbegin(&clp->cl_boot_lock); 507 507 verf[0] = (u32)clp->cl_nfssvc_boot.tv_sec; 508 508 verf[1] = (u32)clp->cl_nfssvc_boot.tv_nsec; 509 - } while (need_seqretry(&clp->cl_boot_lock, seq)); 510 - done_seqretry(&clp->cl_boot_lock, seq); 509 + } while (read_seqretry(&clp->cl_boot_lock, seq)); 511 510 } 512 511 513 512 static void
-68
fs/nfs/mount_clnt.c
··· 223 223 goto out; 224 224 } 225 225 226 - /** 227 - * nfs_umount - Notify a server that we have unmounted this export 228 - * @info: pointer to umount request arguments 229 - * 230 - * MOUNTPROC_UMNT is advisory, so we set a short timeout, and always 231 - * use UDP. 232 - */ 233 - void nfs_umount(const struct nfs_mount_request *info) 234 - { 235 - static const struct rpc_timeout nfs_umnt_timeout = { 236 - .to_initval = 1 * HZ, 237 - .to_maxval = 3 * HZ, 238 - .to_retries = 2, 239 - }; 240 - struct rpc_create_args args = { 241 - .net = info->net, 242 - .protocol = IPPROTO_UDP, 243 - .address = (struct sockaddr *)info->sap, 244 - .addrsize = info->salen, 245 - .timeout = &nfs_umnt_timeout, 246 - .servername = info->hostname, 247 - .program = &mnt_program, 248 - .version = info->version, 249 - .authflavor = RPC_AUTH_UNIX, 250 - .flags = RPC_CLNT_CREATE_NOPING, 251 - .cred = current_cred(), 252 - }; 253 - struct rpc_message msg = { 254 - .rpc_argp = info->dirpath, 255 - }; 256 - struct rpc_clnt *clnt; 257 - int status; 258 - 259 - if (strlen(info->dirpath) > MNTPATHLEN) 260 - return; 261 - 262 - if (info->noresvport) 263 - args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; 264 - 265 - clnt = rpc_create(&args); 266 - if (IS_ERR(clnt)) 267 - goto out_clnt_err; 268 - 269 - dprintk("NFS: sending UMNT request for %s:%s\n", 270 - (info->hostname ? info->hostname : "server"), info->dirpath); 271 - 272 - if (info->version == NFS_MNT3_VERSION) 273 - msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC3_UMNT]; 274 - else 275 - msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC_UMNT]; 276 - 277 - status = rpc_call_sync(clnt, &msg, 0); 278 - rpc_shutdown_client(clnt); 279 - 280 - if (unlikely(status < 0)) 281 - goto out_call_err; 282 - 283 - return; 284 - 285 - out_clnt_err: 286 - dprintk("NFS: failed to create UMNT RPC client, status=%ld\n", 287 - PTR_ERR(clnt)); 288 - return; 289 - 290 - out_call_err: 291 - dprintk("NFS: UMNT request failed, status=%d\n", status); 292 - } 293 - 294 226 /* 295 227 * XDR encode/decode functions for MOUNT 296 228 */
+3 -2
fs/nfs/nfs4_fs.h
··· 63 63 bool (*match_stateid)(const nfs4_stateid *, 64 64 const nfs4_stateid *); 65 65 int (*find_root_sec)(struct nfs_server *, struct nfs_fh *, 66 - struct nfs_fsinfo *); 66 + struct nfs_fattr *); 67 67 void (*free_lock_state)(struct nfs_server *, 68 68 struct nfs4_lock_state *); 69 69 int (*test_and_free_expired)(struct nfs_server *, ··· 296 296 extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int, int); 297 297 extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, const struct cred *, struct nfs4_setclientid_res *); 298 298 extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, const struct cred *); 299 - extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool); 299 + extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, 300 + struct nfs_fattr *, bool); 300 301 extern int nfs4_proc_bind_conn_to_session(struct nfs_client *, const struct cred *cred); 301 302 extern int nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cred); 302 303 extern int nfs4_destroy_clientid(struct nfs_client *clp);
+78 -107
fs/nfs/nfs4client.c
··· 802 802 unset_pnfs_layoutdriver(server); 803 803 nfs4_purge_state_owners(server, &freeme); 804 804 nfs4_free_state_owners(&freeme); 805 + kfree(server->delegation_hash_table); 805 806 } 806 807 807 808 /* ··· 896 895 * Set up an NFS4 client 897 896 */ 898 897 static int nfs4_set_client(struct nfs_server *server, 899 - const char *hostname, 900 - const struct sockaddr_storage *addr, 901 - const size_t addrlen, 902 - const char *ip_addr, 903 - int proto, const struct rpc_timeout *timeparms, 904 - u32 minorversion, unsigned int nconnect, 905 - unsigned int max_connect, 906 - struct net *net, 907 - struct xprtsec_parms *xprtsec) 898 + struct nfs_client_initdata *cl_init) 908 899 { 909 - struct nfs_client_initdata cl_init = { 910 - .hostname = hostname, 911 - .addr = addr, 912 - .addrlen = addrlen, 913 - .ip_addr = ip_addr, 914 - .nfs_mod = &nfs_v4, 915 - .proto = proto, 916 - .minorversion = minorversion, 917 - .net = net, 918 - .timeparms = timeparms, 919 - .cred = server->cred, 920 - .xprtsec = *xprtsec, 921 - }; 922 900 struct nfs_client *clp; 923 901 924 - if (minorversion == 0) 925 - __set_bit(NFS_CS_REUSEPORT, &cl_init.init_flags); 926 - else 927 - cl_init.max_connect = max_connect; 928 - switch (proto) { 902 + cl_init->nfs_mod = &nfs_v4; 903 + cl_init->cred = server->cred; 904 + 905 + if (cl_init->minorversion == 0) { 906 + __set_bit(NFS_CS_REUSEPORT, &cl_init->init_flags); 907 + cl_init->max_connect = 0; 908 + } 909 + 910 + switch (cl_init->proto) { 929 911 case XPRT_TRANSPORT_RDMA: 930 912 case XPRT_TRANSPORT_TCP: 931 913 case XPRT_TRANSPORT_TCP_TLS: 932 - cl_init.nconnect = nconnect; 914 + break; 915 + default: 916 + cl_init->nconnect = 0; 933 917 } 934 918 935 919 if (server->flags & NFS_MOUNT_NORESVPORT) 936 - __set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); 920 + __set_bit(NFS_CS_NORESVPORT, &cl_init->init_flags); 937 921 if (server->options & NFS_OPTION_MIGRATION) 938 - __set_bit(NFS_CS_MIGRATION, &cl_init.init_flags); 922 + __set_bit(NFS_CS_MIGRATION, &cl_init->init_flags); 939 923 if (test_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status)) 940 - __set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags); 941 - server->port = rpc_get_port((struct sockaddr *)addr); 924 + __set_bit(NFS_CS_TSM_POSSIBLE, &cl_init->init_flags); 925 + server->port = rpc_get_port((struct sockaddr *)cl_init->addr); 942 926 943 927 if (server->flags & NFS_MOUNT_NETUNREACH_FATAL) 944 - __set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags); 928 + __set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init->init_flags); 945 929 946 930 /* Allocate or find a client reference we can use */ 947 - clp = nfs_get_client(&cl_init); 931 + clp = nfs_get_client(cl_init); 948 932 if (IS_ERR(clp)) 949 933 return PTR_ERR(clp); 950 934 ··· 1074 1088 #endif 1075 1089 } 1076 1090 1077 - void nfs4_server_set_init_caps(struct nfs_server *server) 1078 - { 1079 - /* Set the basic capabilities */ 1080 - server->caps |= server->nfs_client->cl_mvops->init_caps; 1081 - if (server->flags & NFS_MOUNT_NORDIRPLUS) 1082 - server->caps &= ~NFS_CAP_READDIRPLUS; 1083 - if (server->nfs_client->cl_proto == XPRT_TRANSPORT_RDMA) 1084 - server->caps &= ~NFS_CAP_READ_PLUS; 1085 - 1086 - /* 1087 - * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower 1088 - * authentication. 1089 - */ 1090 - if (nfs4_disable_idmapping && 1091 - server->client->cl_auth->au_flavor == RPC_AUTH_UNIX) 1092 - server->caps |= NFS_CAP_UIDGID_NOMAP; 1093 - } 1094 - 1095 1091 static int nfs4_server_common_setup(struct nfs_server *server, 1096 1092 struct nfs_fh *mntfh, bool auth_probe) 1097 1093 { 1098 1094 int error; 1095 + 1096 + error = nfs4_delegation_hash_alloc(server); 1097 + if (error) 1098 + return error; 1099 1099 1100 1100 /* data servers support only a subset of NFSv4.1 */ 1101 1101 if (is_ds_only_client(server->nfs_client)) ··· 1090 1118 /* We must ensure the session is initialised first */ 1091 1119 error = nfs4_init_session(server->nfs_client); 1092 1120 if (error < 0) 1093 - goto out; 1121 + return error; 1094 1122 1095 - nfs4_server_set_init_caps(server); 1123 + nfs_server_set_init_caps(server); 1096 1124 1097 1125 /* Probe the root fh to retrieve its FSID and filehandle */ 1098 1126 error = nfs4_get_rootfh(server, mntfh, auth_probe); 1099 1127 if (error < 0) 1100 - goto out; 1128 + return error; 1101 1129 1102 1130 dprintk("Server FSID: %llx:%llx\n", 1103 1131 (unsigned long long) server->fsid.major, ··· 1106 1134 1107 1135 error = nfs_probe_server(server, mntfh); 1108 1136 if (error < 0) 1109 - goto out; 1137 + return error; 1110 1138 1111 1139 nfs4_session_limit_rwsize(server); 1112 1140 nfs4_session_limit_xasize(server); ··· 1117 1145 nfs_server_insert_lists(server); 1118 1146 server->mount_time = jiffies; 1119 1147 server->destroy = nfs4_destroy_server; 1120 - out: 1121 - return error; 1148 + return 0; 1122 1149 } 1123 1150 1124 1151 /* ··· 1127 1156 { 1128 1157 struct nfs_fs_context *ctx = nfs_fc2context(fc); 1129 1158 struct rpc_timeout timeparms; 1159 + struct nfs_client_initdata cl_init = { 1160 + .hostname = ctx->nfs_server.hostname, 1161 + .addr = &ctx->nfs_server._address, 1162 + .addrlen = ctx->nfs_server.addrlen, 1163 + .ip_addr = ctx->client_address, 1164 + .proto = ctx->nfs_server.protocol, 1165 + .minorversion = ctx->minorversion, 1166 + .net = fc->net_ns, 1167 + .timeparms = &timeparms, 1168 + .xprtsec = ctx->xprtsec, 1169 + .nconnect = ctx->nfs_server.nconnect, 1170 + .max_connect = ctx->nfs_server.max_connect, 1171 + }; 1130 1172 int error; 1131 1173 1132 1174 nfs_init_timeout_values(&timeparms, ctx->nfs_server.protocol, ··· 1159 1175 ctx->selected_flavor = RPC_AUTH_UNIX; 1160 1176 1161 1177 /* Get a client record */ 1162 - error = nfs4_set_client(server, 1163 - ctx->nfs_server.hostname, 1164 - &ctx->nfs_server._address, 1165 - ctx->nfs_server.addrlen, 1166 - ctx->client_address, 1167 - ctx->nfs_server.protocol, 1168 - &timeparms, 1169 - ctx->minorversion, 1170 - ctx->nfs_server.nconnect, 1171 - ctx->nfs_server.max_connect, 1172 - fc->net_ns, 1173 - &ctx->xprtsec); 1178 + error = nfs4_set_client(server, &cl_init); 1174 1179 if (error < 0) 1175 1180 return error; 1176 1181 ··· 1219 1246 struct nfs_server *nfs4_create_referral_server(struct fs_context *fc) 1220 1247 { 1221 1248 struct nfs_fs_context *ctx = nfs_fc2context(fc); 1222 - struct nfs_client *parent_client; 1223 - struct nfs_server *server, *parent_server; 1224 - int proto, error; 1249 + struct nfs_server *parent_server = NFS_SB(ctx->clone_data.sb); 1250 + struct nfs_client *parent_client = parent_server->nfs_client; 1251 + struct nfs_client_initdata cl_init = { 1252 + .hostname = ctx->nfs_server.hostname, 1253 + .addr = &ctx->nfs_server._address, 1254 + .addrlen = ctx->nfs_server.addrlen, 1255 + .ip_addr = parent_client->cl_ipaddr, 1256 + .minorversion = parent_client->cl_mvops->minor_version, 1257 + .net = parent_client->cl_net, 1258 + .timeparms = parent_server->client->cl_timeout, 1259 + .xprtsec = parent_client->cl_xprtsec, 1260 + .nconnect = parent_client->cl_nconnect, 1261 + .max_connect = parent_client->cl_max_connect, 1262 + }; 1263 + struct nfs_server *server; 1225 1264 bool auth_probe; 1265 + int error; 1226 1266 1227 1267 server = nfs_alloc_server(); 1228 1268 if (!server) 1229 1269 return ERR_PTR(-ENOMEM); 1230 - 1231 - parent_server = NFS_SB(ctx->clone_data.sb); 1232 - parent_client = parent_server->nfs_client; 1233 1270 1234 1271 server->cred = get_cred(parent_server->cred); 1235 1272 ··· 1249 1266 /* Get a client representation */ 1250 1267 #if IS_ENABLED(CONFIG_SUNRPC_XPRT_RDMA) 1251 1268 rpc_set_port(&ctx->nfs_server.address, NFS_RDMA_PORT); 1252 - error = nfs4_set_client(server, 1253 - ctx->nfs_server.hostname, 1254 - &ctx->nfs_server._address, 1255 - ctx->nfs_server.addrlen, 1256 - parent_client->cl_ipaddr, 1257 - XPRT_TRANSPORT_RDMA, 1258 - parent_server->client->cl_timeout, 1259 - parent_client->cl_mvops->minor_version, 1260 - parent_client->cl_nconnect, 1261 - parent_client->cl_max_connect, 1262 - parent_client->cl_net, 1263 - &parent_client->cl_xprtsec); 1269 + cl_init.proto = XPRT_TRANSPORT_RDMA; 1270 + error = nfs4_set_client(server, &cl_init); 1264 1271 if (!error) 1265 1272 goto init_server; 1266 1273 #endif /* IS_ENABLED(CONFIG_SUNRPC_XPRT_RDMA) */ 1267 1274 1268 - proto = XPRT_TRANSPORT_TCP; 1275 + cl_init.proto = XPRT_TRANSPORT_TCP; 1269 1276 if (parent_client->cl_xprtsec.policy != RPC_XPRTSEC_NONE) 1270 - proto = XPRT_TRANSPORT_TCP_TLS; 1277 + cl_init.proto = XPRT_TRANSPORT_TCP_TLS; 1271 1278 rpc_set_port(&ctx->nfs_server.address, NFS_PORT); 1272 - error = nfs4_set_client(server, 1273 - ctx->nfs_server.hostname, 1274 - &ctx->nfs_server._address, 1275 - ctx->nfs_server.addrlen, 1276 - parent_client->cl_ipaddr, 1277 - proto, 1278 - parent_server->client->cl_timeout, 1279 - parent_client->cl_mvops->minor_version, 1280 - parent_client->cl_nconnect, 1281 - parent_client->cl_max_connect, 1282 - parent_client->cl_net, 1283 - &parent_client->cl_xprtsec); 1279 + error = nfs4_set_client(server, &cl_init); 1284 1280 if (error < 0) 1285 1281 goto error; 1286 1282 ··· 1315 1353 char buf[INET6_ADDRSTRLEN + 1]; 1316 1354 struct sockaddr_storage address; 1317 1355 struct sockaddr *localaddr = (struct sockaddr *)&address; 1356 + struct nfs_client_initdata cl_init = { 1357 + .hostname = hostname, 1358 + .addr = sap, 1359 + .addrlen = salen, 1360 + .ip_addr = buf, 1361 + .proto = clp->cl_proto, 1362 + .minorversion = clp->cl_minorversion, 1363 + .net = net, 1364 + .timeparms = clnt->cl_timeout, 1365 + .xprtsec = clp->cl_xprtsec, 1366 + .nconnect = clp->cl_nconnect, 1367 + .max_connect = clp->cl_max_connect, 1368 + }; 1318 1369 int error; 1319 1370 1320 1371 error = rpc_switch_client_transport(clnt, &xargs, clnt->cl_timeout); ··· 1343 1368 1344 1369 nfs_server_remove_lists(server); 1345 1370 set_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status); 1346 - error = nfs4_set_client(server, hostname, sap, salen, buf, 1347 - clp->cl_proto, clnt->cl_timeout, 1348 - clp->cl_minorversion, 1349 - clp->cl_nconnect, clp->cl_max_connect, 1350 - net, &clp->cl_xprtsec); 1371 + error = nfs4_set_client(server, &cl_init); 1351 1372 clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status); 1352 1373 if (error != 0) { 1353 1374 nfs_server_insert_lists(server);
+2 -23
fs/nfs/nfs4file.c
··· 253 253 struct nfs_server *server = NFS_SERVER(dst_inode); 254 254 struct inode *src_inode = file_inode(src_file); 255 255 unsigned int bs = server->clone_blksize; 256 - bool same_inode = false; 257 256 int ret; 258 257 259 258 /* NFS does not support deduplication. */ ··· 274 275 goto out; 275 276 } 276 277 277 - if (src_inode == dst_inode) 278 - same_inode = true; 279 - 280 278 /* XXX: do we lock at all? what if server needs CB_RECALL_LAYOUT? */ 281 - if (same_inode) { 282 - inode_lock(src_inode); 283 - } else if (dst_inode < src_inode) { 284 - inode_lock_nested(dst_inode, I_MUTEX_PARENT); 285 - inode_lock_nested(src_inode, I_MUTEX_CHILD); 286 - } else { 287 - inode_lock_nested(src_inode, I_MUTEX_PARENT); 288 - inode_lock_nested(dst_inode, I_MUTEX_CHILD); 289 - } 290 - 279 + lock_two_nondirectories(src_inode, dst_inode); 291 280 /* flush all pending writes on both src and dst so that server 292 281 * has the latest data */ 293 282 ret = nfs_sync_inode(src_inode); ··· 293 306 truncate_inode_pages_range(&dst_inode->i_data, dst_off, dst_off + count - 1); 294 307 295 308 out_unlock: 296 - if (same_inode) { 297 - inode_unlock(src_inode); 298 - } else if (dst_inode < src_inode) { 299 - inode_unlock(src_inode); 300 - inode_unlock(dst_inode); 301 - } else { 302 - inode_unlock(dst_inode); 303 - inode_unlock(src_inode); 304 - } 309 + unlock_two_nondirectories(src_inode, dst_inode); 305 310 out: 306 311 return ret < 0 ? ret : count; 307 312 }
+6 -8
fs/nfs/nfs4getroot.c
··· 12 12 13 13 int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool auth_probe) 14 14 { 15 - struct nfs_fsinfo fsinfo; 15 + struct nfs_fattr *fattr = nfs_alloc_fattr(); 16 16 int ret = -ENOMEM; 17 17 18 - fsinfo.fattr = nfs_alloc_fattr(); 19 - if (fsinfo.fattr == NULL) 18 + if (fattr == NULL) 20 19 goto out; 21 20 22 21 /* Start by getting the root filehandle from the server */ 23 - ret = nfs4_proc_get_rootfh(server, mntfh, &fsinfo, auth_probe); 22 + ret = nfs4_proc_get_rootfh(server, mntfh, fattr, auth_probe); 24 23 if (ret < 0) { 25 24 dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret); 26 25 goto out; 27 26 } 28 27 29 - if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE) 30 - || !S_ISDIR(fsinfo.fattr->mode)) { 28 + if (!(fattr->valid & NFS_ATTR_FATTR_TYPE) || !S_ISDIR(fattr->mode)) { 31 29 printk(KERN_ERR "nfs4_get_rootfh:" 32 30 " getroot encountered non-directory\n"); 33 31 ret = -ENOTDIR; 34 32 goto out; 35 33 } 36 34 37 - memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid)); 35 + memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); 38 36 out: 39 - nfs_free_fattr(fsinfo.fattr); 37 + nfs_free_fattr(fattr); 40 38 return ret; 41 39 }
+84 -55
fs/nfs/nfs4proc.c
··· 222 222 | FATTR4_WORD1_RAWDEV 223 223 | FATTR4_WORD1_SPACE_USED 224 224 | FATTR4_WORD1_TIME_ACCESS 225 + | FATTR4_WORD1_TIME_CREATE 225 226 | FATTR4_WORD1_TIME_METADATA 226 227 | FATTR4_WORD1_TIME_MODIFY 227 228 | FATTR4_WORD1_MOUNTED_ON_FILEID, ··· 244 243 | FATTR4_WORD1_RAWDEV 245 244 | FATTR4_WORD1_SPACE_USED 246 245 | FATTR4_WORD1_TIME_ACCESS 246 + | FATTR4_WORD1_TIME_CREATE 247 247 | FATTR4_WORD1_TIME_METADATA 248 248 | FATTR4_WORD1_TIME_MODIFY, 249 249 FATTR4_WORD2_MDSTHRESHOLD ··· 324 322 dst[1] &= ~FATTR4_WORD1_MODE; 325 323 if (!(cache_validity & NFS_INO_INVALID_OTHER)) 326 324 dst[1] &= ~(FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP); 325 + 326 + if (!(cache_validity & NFS_INO_INVALID_BTIME)) 327 + dst[1] &= ~FATTR4_WORD1_TIME_CREATE; 327 328 328 329 if (nfs_have_delegated_mtime(inode)) { 329 330 if (!(cache_validity & NFS_INO_INVALID_ATIME)) ··· 1312 1307 NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL | 1313 1308 NFS_INO_INVALID_SIZE | NFS_INO_INVALID_OTHER | 1314 1309 NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_NLINK | 1315 - NFS_INO_INVALID_MODE | NFS_INO_INVALID_XATTR; 1310 + NFS_INO_INVALID_MODE | NFS_INO_INVALID_BTIME | 1311 + NFS_INO_INVALID_XATTR; 1316 1312 nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); 1317 1313 } 1318 1314 nfsi->attrtimeo_timestamp = jiffies; ··· 4053 4047 server->fattr_valid &= ~NFS_ATTR_FATTR_CTIME; 4054 4048 if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY)) 4055 4049 server->fattr_valid &= ~NFS_ATTR_FATTR_MTIME; 4050 + if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY)) 4051 + server->fattr_valid &= ~NFS_ATTR_FATTR_MTIME; 4052 + if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_CREATE)) 4053 + server->fattr_valid &= ~NFS_ATTR_FATTR_BTIME; 4056 4054 memcpy(server->attr_bitmask_nl, res.attr_bitmask, 4057 4055 sizeof(server->attr_bitmask)); 4058 4056 server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL; ··· 4092 4082 }; 4093 4083 int err; 4094 4084 4095 - nfs4_server_set_init_caps(server); 4085 + nfs_server_set_init_caps(server); 4096 4086 do { 4097 4087 err = nfs4_handle_exception(server, 4098 4088 _nfs4_server_capabilities(server, fhandle), ··· 4240 4230 } 4241 4231 4242 4232 static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, 4243 - struct nfs_fsinfo *info) 4233 + struct nfs_fattr *fattr) 4244 4234 { 4245 - u32 bitmask[3]; 4235 + u32 bitmask[3] = { 4236 + [0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE | 4237 + FATTR4_WORD0_SIZE | FATTR4_WORD0_FSID, 4238 + }; 4246 4239 struct nfs4_lookup_root_arg args = { 4247 4240 .bitmask = bitmask, 4248 4241 }; 4249 4242 struct nfs4_lookup_res res = { 4250 4243 .server = server, 4251 - .fattr = info->fattr, 4244 + .fattr = fattr, 4252 4245 .fh = fhandle, 4253 4246 }; 4254 4247 struct rpc_message msg = { ··· 4260 4247 .rpc_resp = &res, 4261 4248 }; 4262 4249 4263 - bitmask[0] = nfs4_fattr_bitmap[0]; 4264 - bitmask[1] = nfs4_fattr_bitmap[1]; 4265 - /* 4266 - * Process the label in the upcoming getfattr 4267 - */ 4268 - bitmask[2] = nfs4_fattr_bitmap[2] & ~FATTR4_WORD2_SECURITY_LABEL; 4269 - 4270 - nfs_fattr_init(info->fattr); 4250 + nfs_fattr_init(fattr); 4271 4251 return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); 4272 4252 } 4273 4253 4274 4254 static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, 4275 - struct nfs_fsinfo *info) 4255 + struct nfs_fattr *fattr) 4276 4256 { 4277 4257 struct nfs4_exception exception = { 4278 4258 .interruptible = true, 4279 4259 }; 4280 4260 int err; 4281 4261 do { 4282 - err = _nfs4_lookup_root(server, fhandle, info); 4283 - trace_nfs4_lookup_root(server, fhandle, info->fattr, err); 4262 + err = _nfs4_lookup_root(server, fhandle, fattr); 4263 + trace_nfs4_lookup_root(server, fhandle, fattr, err); 4284 4264 switch (err) { 4285 4265 case 0: 4286 4266 case -NFS4ERR_WRONGSEC: ··· 4286 4280 return err; 4287 4281 } 4288 4282 4289 - static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, 4290 - struct nfs_fsinfo *info, rpc_authflavor_t flavor) 4283 + static int nfs4_lookup_root_sec(struct nfs_server *server, 4284 + struct nfs_fh *fhandle, struct nfs_fattr *fattr, 4285 + rpc_authflavor_t flavor) 4291 4286 { 4292 4287 struct rpc_auth_create_args auth_args = { 4293 4288 .pseudoflavor = flavor, ··· 4298 4291 auth = rpcauth_create(&auth_args, server->client); 4299 4292 if (IS_ERR(auth)) 4300 4293 return -EACCES; 4301 - return nfs4_lookup_root(server, fhandle, info); 4294 + return nfs4_lookup_root(server, fhandle, fattr); 4302 4295 } 4303 4296 4304 4297 /* ··· 4311 4304 * negative errno value. 4312 4305 */ 4313 4306 static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, 4314 - struct nfs_fsinfo *info) 4307 + struct nfs_fattr *fattr) 4315 4308 { 4316 4309 /* Per 3530bis 15.33.5 */ 4317 4310 static const rpc_authflavor_t flav_array[] = { ··· 4327 4320 if (server->auth_info.flavor_len > 0) { 4328 4321 /* try each flavor specified by user */ 4329 4322 for (i = 0; i < server->auth_info.flavor_len; i++) { 4330 - status = nfs4_lookup_root_sec(server, fhandle, info, 4331 - server->auth_info.flavors[i]); 4323 + status = nfs4_lookup_root_sec( 4324 + server, fhandle, fattr, 4325 + server->auth_info.flavors[i]); 4332 4326 if (status == -NFS4ERR_WRONGSEC || status == -EACCES) 4333 4327 continue; 4334 4328 break; ··· 4337 4329 } else { 4338 4330 /* no flavors specified by user, try default list */ 4339 4331 for (i = 0; i < ARRAY_SIZE(flav_array); i++) { 4340 - status = nfs4_lookup_root_sec(server, fhandle, info, 4332 + status = nfs4_lookup_root_sec(server, fhandle, fattr, 4341 4333 flav_array[i]); 4342 4334 if (status == -NFS4ERR_WRONGSEC || status == -EACCES) 4343 4335 continue; ··· 4361 4353 * nfs4_proc_get_rootfh - get file handle for server's pseudoroot 4362 4354 * @server: initialized nfs_server handle 4363 4355 * @fhandle: we fill in the pseudo-fs root file handle 4364 - * @info: we fill in an FSINFO struct 4356 + * @fattr: we fill in a bare bones struct fattr 4365 4357 * @auth_probe: probe the auth flavours 4366 4358 * 4367 4359 * Returns zero on success, or a negative errno. 4368 4360 */ 4369 4361 int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, 4370 - struct nfs_fsinfo *info, 4371 - bool auth_probe) 4362 + struct nfs_fattr *fattr, bool auth_probe) 4372 4363 { 4373 4364 int status = 0; 4374 4365 4375 4366 if (!auth_probe) 4376 - status = nfs4_lookup_root(server, fhandle, info); 4367 + status = nfs4_lookup_root(server, fhandle, fattr); 4377 4368 4378 4369 if (auth_probe || status == NFS4ERR_WRONGSEC) 4379 - status = server->nfs_client->cl_mvops->find_root_sec(server, 4380 - fhandle, info); 4381 - 4382 - if (status == 0) 4383 - status = nfs4_server_capabilities(server, fhandle); 4384 - if (status == 0) 4385 - status = nfs4_do_fsinfo(server, fhandle, info); 4370 + status = server->nfs_client->cl_mvops->find_root_sec( 4371 + server, fhandle, fattr); 4386 4372 4387 4373 return nfs4_map_errors(status); 4388 4374 } ··· 5783 5781 bitmask[1] |= FATTR4_WORD1_TIME_MODIFY; 5784 5782 if (cache_validity & NFS_INO_INVALID_BLOCKS) 5785 5783 bitmask[1] |= FATTR4_WORD1_SPACE_USED; 5784 + if (cache_validity & NFS_INO_INVALID_BTIME) 5785 + bitmask[1] |= FATTR4_WORD1_TIME_CREATE; 5786 5786 5787 5787 if (cache_validity & NFS_INO_INVALID_SIZE) 5788 5788 bitmask[0] |= FATTR4_WORD0_SIZE; ··· 10343 10339 * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if 10344 10340 * possible) as per RFC3530bis and RFC5661 Security Considerations sections 10345 10341 */ 10346 - static int 10347 - _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, 10348 - struct nfs_fsinfo *info, 10349 - struct nfs4_secinfo_flavors *flavors, bool use_integrity) 10342 + static int _nfs41_proc_secinfo_no_name(struct nfs_server *server, 10343 + struct nfs_fh *fhandle, 10344 + struct nfs4_secinfo_flavors *flavors, 10345 + bool use_integrity) 10350 10346 { 10351 10347 struct nfs41_secinfo_no_name_args args = { 10352 10348 .style = SECINFO_STYLE_CURRENT_FH, ··· 10390 10386 return status; 10391 10387 } 10392 10388 10393 - static int 10394 - nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, 10395 - struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors) 10389 + static int nfs41_proc_secinfo_no_name(struct nfs_server *server, 10390 + struct nfs_fh *fhandle, 10391 + struct nfs4_secinfo_flavors *flavors) 10396 10392 { 10397 10393 struct nfs4_exception exception = { 10398 10394 .interruptible = true, ··· 10404 10400 10405 10401 /* try to use integrity protection with machine cred */ 10406 10402 if (_nfs4_is_integrity_protected(server->nfs_client)) 10407 - err = _nfs41_proc_secinfo_no_name(server, fhandle, info, 10403 + err = _nfs41_proc_secinfo_no_name(server, fhandle, 10408 10404 flavors, true); 10409 10405 10410 10406 /* ··· 10414 10410 * the current filesystem's rpc_client and the user cred. 10415 10411 */ 10416 10412 if (err == -NFS4ERR_WRONGSEC) 10417 - err = _nfs41_proc_secinfo_no_name(server, fhandle, info, 10413 + err = _nfs41_proc_secinfo_no_name(server, fhandle, 10418 10414 flavors, false); 10419 10415 10420 10416 switch (err) { ··· 10430 10426 return err; 10431 10427 } 10432 10428 10433 - static int 10434 - nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, 10435 - struct nfs_fsinfo *info) 10429 + static int nfs41_find_root_sec(struct nfs_server *server, 10430 + struct nfs_fh *fhandle, struct nfs_fattr *fattr) 10436 10431 { 10437 10432 int err; 10438 10433 struct page *page; ··· 10447 10444 } 10448 10445 10449 10446 flavors = page_address(page); 10450 - err = nfs41_proc_secinfo_no_name(server, fhandle, info, flavors); 10447 + err = nfs41_proc_secinfo_no_name(server, fhandle, flavors); 10451 10448 10452 10449 /* 10453 10450 * Fall back on "guess and check" method if 10454 10451 * the server doesn't support SECINFO_NO_NAME 10455 10452 */ 10456 10453 if (err == -NFS4ERR_WRONGSEC || err == -ENOTSUPP) { 10457 - err = nfs4_find_root_sec(server, fhandle, info); 10454 + err = nfs4_find_root_sec(server, fhandle, fattr); 10458 10455 goto out_freepage; 10459 10456 } 10460 10457 if (err) ··· 10479 10476 flavor = RPC_AUTH_MAXFLAVOR; 10480 10477 10481 10478 if (flavor != RPC_AUTH_MAXFLAVOR) { 10482 - err = nfs4_lookup_root_sec(server, fhandle, 10483 - info, flavor); 10479 + err = nfs4_lookup_root_sec(server, fhandle, fattr, 10480 + flavor); 10484 10481 if (!err) 10485 10482 break; 10486 10483 } ··· 10683 10680 static bool nfs41_match_stateid(const nfs4_stateid *s1, 10684 10681 const nfs4_stateid *s2) 10685 10682 { 10683 + trace_nfs41_match_stateid(s1, s2); 10684 + 10686 10685 if (s1->type != s2->type) 10687 10686 return false; 10688 10687 ··· 10702 10697 static bool nfs4_match_stateid(const nfs4_stateid *s1, 10703 10698 const nfs4_stateid *s2) 10704 10699 { 10700 + trace_nfs4_match_stateid(s1, s2); 10701 + 10705 10702 return nfs4_stateid_match(s1, s2); 10706 10703 } 10707 10704 ··· 10874 10867 10875 10868 static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size) 10876 10869 { 10877 - ssize_t error, error2, error3, error4; 10870 + ssize_t error, error2, error3, error4 = 0; 10878 10871 size_t left = size; 10879 10872 10880 10873 error = generic_listxattr(dentry, list, left); ··· 10902 10895 left -= error3; 10903 10896 } 10904 10897 10905 - error4 = security_inode_listsecurity(d_inode(dentry), list, left); 10906 - if (error4 < 0) 10907 - return error4; 10898 + if (!nfs_server_capable(d_inode(dentry), NFS_CAP_SECURITY_LABEL)) { 10899 + error4 = security_inode_listsecurity(d_inode(dentry), list, left); 10900 + if (error4 < 0) 10901 + return error4; 10902 + } 10908 10903 10909 10904 error += error2 + error3 + error4; 10910 10905 if (size && error > size) ··· 10960 10951 .listxattr = nfs4_listxattr, 10961 10952 }; 10962 10953 10954 + static struct nfs_server *nfs4_clone_server(struct nfs_server *source, 10955 + struct nfs_fh *fh, struct nfs_fattr *fattr, 10956 + rpc_authflavor_t flavor) 10957 + { 10958 + struct nfs_server *server; 10959 + int error; 10960 + 10961 + server = nfs_clone_server(source, fh, fattr, flavor); 10962 + if (IS_ERR(server)) 10963 + return server; 10964 + 10965 + error = nfs4_delegation_hash_alloc(server); 10966 + if (error) { 10967 + nfs_free_server(server); 10968 + return ERR_PTR(error); 10969 + } 10970 + 10971 + return server; 10972 + } 10973 + 10963 10974 const struct nfs_rpc_ops nfs_v4_clientops = { 10964 10975 .version = 4, /* protocol version */ 10965 10976 .dentry_ops = &nfs4_dentry_operations, ··· 11032 11003 .init_client = nfs4_init_client, 11033 11004 .free_client = nfs4_free_client, 11034 11005 .create_server = nfs4_create_server, 11035 - .clone_server = nfs_clone_server, 11006 + .clone_server = nfs4_clone_server, 11036 11007 .discover_trunking = nfs4_discover_trunking, 11037 11008 .enable_swap = nfs4_enable_swap, 11038 11009 .disable_swap = nfs4_disable_swap,
+2
fs/nfs/nfs4trace.c
··· 26 26 EXPORT_TRACEPOINT_SYMBOL_GPL(pnfs_mds_fallback_write_done); 27 27 EXPORT_TRACEPOINT_SYMBOL_GPL(pnfs_mds_fallback_read_pagelist); 28 28 EXPORT_TRACEPOINT_SYMBOL_GPL(pnfs_mds_fallback_write_pagelist); 29 + EXPORT_TRACEPOINT_SYMBOL_GPL(pnfs_ds_connect); 29 30 30 31 EXPORT_TRACEPOINT_SYMBOL_GPL(ff_layout_read_error); 31 32 EXPORT_TRACEPOINT_SYMBOL_GPL(ff_layout_write_error); 32 33 EXPORT_TRACEPOINT_SYMBOL_GPL(ff_layout_commit_error); 33 34 35 + EXPORT_TRACEPOINT_SYMBOL_GPL(bl_ext_tree_prepare_commit); 34 36 EXPORT_TRACEPOINT_SYMBOL_GPL(bl_pr_key_reg); 35 37 EXPORT_TRACEPOINT_SYMBOL_GPL(bl_pr_key_reg_err); 36 38 EXPORT_TRACEPOINT_SYMBOL_GPL(bl_pr_key_unreg);
+167 -1
fs/nfs/nfs4trace.h
··· 14 14 #include <trace/misc/fs.h> 15 15 #include <trace/misc/nfs.h> 16 16 17 + #include "delegation.h" 18 + 17 19 #define show_nfs_fattr_flags(valid) \ 18 20 __print_flags((unsigned long)valid, "|", \ 19 21 { NFS_ATTR_FATTR_TYPE, "TYPE" }, \ ··· 32 30 { NFS_ATTR_FATTR_CTIME, "CTIME" }, \ 33 31 { NFS_ATTR_FATTR_CHANGE, "CHANGE" }, \ 34 32 { NFS_ATTR_FATTR_OWNER_NAME, "OWNER_NAME" }, \ 35 - { NFS_ATTR_FATTR_GROUP_NAME, "GROUP_NAME" }) 33 + { NFS_ATTR_FATTR_GROUP_NAME, "GROUP_NAME" }, \ 34 + { NFS_ATTR_FATTR_BTIME, "BTIME" }) 36 35 37 36 DECLARE_EVENT_CLASS(nfs4_clientid_event, 38 37 TP_PROTO( ··· 276 273 show_nfs_stable_how(__entry->cb_how) 277 274 ) 278 275 ); 276 + 277 + TRACE_EVENT(pnfs_ds_connect, 278 + TP_PROTO( 279 + char *ds_remotestr, 280 + int status 281 + ), 282 + 283 + TP_ARGS(ds_remotestr, status), 284 + 285 + TP_STRUCT__entry( 286 + __string(ds_ips, ds_remotestr) 287 + __field(int, status) 288 + ), 289 + 290 + TP_fast_assign( 291 + __assign_str(ds_ips); 292 + __entry->status = status; 293 + ), 294 + 295 + TP_printk( 296 + "ds_ips=%s, status=%d", 297 + __get_str(ds_ips), 298 + __entry->status 299 + ) 300 + ); 301 + 279 302 #endif /* CONFIG_NFS_V4_1 */ 280 303 281 304 TRACE_EVENT(nfs4_setup_sequence, ··· 985 956 TP_ARGS(inode, fmode)) 986 957 DEFINE_NFS4_SET_DELEGATION_EVENT(nfs4_set_delegation); 987 958 DEFINE_NFS4_SET_DELEGATION_EVENT(nfs4_reclaim_delegation); 959 + DEFINE_NFS4_SET_DELEGATION_EVENT(nfs4_detach_delegation); 960 + 961 + #define show_delegation_flags(flags) \ 962 + __print_flags(flags, "|", \ 963 + { BIT(NFS_DELEGATION_NEED_RECLAIM), "NEED_RECLAIM" }, \ 964 + { BIT(NFS_DELEGATION_RETURN), "RETURN" }, \ 965 + { BIT(NFS_DELEGATION_RETURN_IF_CLOSED), "RETURN_IF_CLOSED" }, \ 966 + { BIT(NFS_DELEGATION_REFERENCED), "REFERENCED" }, \ 967 + { BIT(NFS_DELEGATION_RETURNING), "RETURNING" }, \ 968 + { BIT(NFS_DELEGATION_REVOKED), "REVOKED" }, \ 969 + { BIT(NFS_DELEGATION_TEST_EXPIRED), "TEST_EXPIRED" }, \ 970 + { BIT(NFS_DELEGATION_INODE_FREEING), "INODE_FREEING" }, \ 971 + { BIT(NFS_DELEGATION_RETURN_DELAYED), "RETURN_DELAYED" }) 972 + 973 + DECLARE_EVENT_CLASS(nfs4_delegation_event, 974 + TP_PROTO( 975 + const struct nfs_delegation *delegation 976 + ), 977 + 978 + TP_ARGS(delegation), 979 + 980 + TP_STRUCT__entry( 981 + __field(u32, fhandle) 982 + __field(unsigned int, fmode) 983 + __field(unsigned long, flags) 984 + ), 985 + 986 + TP_fast_assign( 987 + __entry->fhandle = nfs_fhandle_hash(NFS_FH(delegation->inode)); 988 + __entry->fmode = delegation->type; 989 + __entry->flags = delegation->flags; 990 + ), 991 + 992 + TP_printk( 993 + "fhandle=0x%08x fmode=%s flags=%s", 994 + __entry->fhandle, show_fs_fmode_flags(__entry->fmode), 995 + show_delegation_flags(__entry->flags) 996 + ) 997 + ); 998 + #define DEFINE_NFS4_DELEGATION_EVENT(name) \ 999 + DEFINE_EVENT(nfs4_delegation_event, name, \ 1000 + TP_PROTO( \ 1001 + const struct nfs_delegation *delegation \ 1002 + ), \ 1003 + TP_ARGS(delegation)) 1004 + DEFINE_NFS4_DELEGATION_EVENT(nfs_delegation_need_return); 988 1005 989 1006 TRACE_EVENT(nfs4_delegreturn_exit, 990 1007 TP_PROTO( ··· 1523 1448 TP_ARGS(clp, fhandle, inode, stateid, error)) 1524 1449 DEFINE_NFS4_INODE_STATEID_CALLBACK_EVENT(nfs4_cb_recall); 1525 1450 DEFINE_NFS4_INODE_STATEID_CALLBACK_EVENT(nfs4_cb_layoutrecall_file); 1451 + 1452 + #define show_stateid_type(type) \ 1453 + __print_symbolic(type, \ 1454 + { NFS4_INVALID_STATEID_TYPE, "INVALID" }, \ 1455 + { NFS4_SPECIAL_STATEID_TYPE, "SPECIAL" }, \ 1456 + { NFS4_OPEN_STATEID_TYPE, "OPEN" }, \ 1457 + { NFS4_LOCK_STATEID_TYPE, "LOCK" }, \ 1458 + { NFS4_DELEGATION_STATEID_TYPE, "DELEGATION" }, \ 1459 + { NFS4_LAYOUT_STATEID_TYPE, "LAYOUT" }, \ 1460 + { NFS4_PNFS_DS_STATEID_TYPE, "PNFS_DS" }, \ 1461 + { NFS4_REVOKED_STATEID_TYPE, "REVOKED" }, \ 1462 + { NFS4_FREED_STATEID_TYPE, "FREED" }) 1463 + 1464 + DECLARE_EVENT_CLASS(nfs4_match_stateid_event, 1465 + TP_PROTO( 1466 + const nfs4_stateid *s1, 1467 + const nfs4_stateid *s2 1468 + ), 1469 + 1470 + TP_ARGS(s1, s2), 1471 + 1472 + TP_STRUCT__entry( 1473 + __field(int, s1_seq) 1474 + __field(int, s2_seq) 1475 + __field(u32, s1_hash) 1476 + __field(u32, s2_hash) 1477 + __field(int, s1_type) 1478 + __field(int, s2_type) 1479 + ), 1480 + 1481 + TP_fast_assign( 1482 + __entry->s1_seq = s1->seqid; 1483 + __entry->s1_hash = nfs_stateid_hash(s1); 1484 + __entry->s1_type = s1->type; 1485 + __entry->s2_seq = s2->seqid; 1486 + __entry->s2_hash = nfs_stateid_hash(s2); 1487 + __entry->s2_type = s2->type; 1488 + ), 1489 + 1490 + TP_printk( 1491 + "s1=%s:%x:%u s2=%s:%x:%u", 1492 + show_stateid_type(__entry->s1_type), 1493 + __entry->s1_hash, __entry->s1_seq, 1494 + show_stateid_type(__entry->s2_type), 1495 + __entry->s2_hash, __entry->s2_seq 1496 + ) 1497 + ); 1498 + 1499 + #define DEFINE_NFS4_MATCH_STATEID_EVENT(name) \ 1500 + DEFINE_EVENT(nfs4_match_stateid_event, name, \ 1501 + TP_PROTO( \ 1502 + const nfs4_stateid *s1, \ 1503 + const nfs4_stateid *s2 \ 1504 + ), \ 1505 + TP_ARGS(s1, s2)) 1506 + DEFINE_NFS4_MATCH_STATEID_EVENT(nfs41_match_stateid); 1507 + DEFINE_NFS4_MATCH_STATEID_EVENT(nfs4_match_stateid); 1526 1508 1527 1509 DECLARE_EVENT_CLASS(nfs4_idmap_event, 1528 1510 TP_PROTO( ··· 2292 2160 __entry->offset, __entry->count, 2293 2161 __get_str(dstaddr), __entry->nfs_error, 2294 2162 show_nfs4_status(__entry->nfs_error) 2163 + ) 2164 + ); 2165 + 2166 + TRACE_EVENT(bl_ext_tree_prepare_commit, 2167 + TP_PROTO( 2168 + int ret, 2169 + size_t count, 2170 + u64 lwb, 2171 + bool not_all_ranges 2172 + ), 2173 + 2174 + TP_ARGS(ret, count, lwb, not_all_ranges), 2175 + 2176 + TP_STRUCT__entry( 2177 + __field(int, ret) 2178 + __field(size_t, count) 2179 + __field(u64, lwb) 2180 + __field(bool, not_all_ranges) 2181 + ), 2182 + 2183 + TP_fast_assign( 2184 + __entry->ret = ret; 2185 + __entry->count = count; 2186 + __entry->lwb = lwb; 2187 + __entry->not_all_ranges = not_all_ranges; 2188 + ), 2189 + 2190 + TP_printk( 2191 + "ret=%d, found %zu ranges, lwb=%llu%s", 2192 + __entry->ret, 2193 + __entry->count, 2194 + __entry->lwb, 2195 + __entry->not_all_ranges ? ", not all ranges encoded" : 2196 + "" 2295 2197 ) 2296 2198 ); 2297 2199
+24
fs/nfs/nfs4xdr.c
··· 1623 1623 | FATTR4_WORD1_RAWDEV 1624 1624 | FATTR4_WORD1_SPACE_USED 1625 1625 | FATTR4_WORD1_TIME_ACCESS 1626 + | FATTR4_WORD1_TIME_CREATE 1626 1627 | FATTR4_WORD1_TIME_METADATA 1627 1628 | FATTR4_WORD1_TIME_MODIFY; 1628 1629 attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; ··· 4208 4207 return status; 4209 4208 } 4210 4209 4210 + static int decode_attr_time_create(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time) 4211 + { 4212 + int status = 0; 4213 + 4214 + time->tv_sec = 0; 4215 + time->tv_nsec = 0; 4216 + if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_CREATE - 1U))) 4217 + return -EIO; 4218 + if (likely(bitmap[1] & FATTR4_WORD1_TIME_CREATE)) { 4219 + status = decode_attr_time(xdr, time); 4220 + if (status == 0) 4221 + status = NFS_ATTR_FATTR_BTIME; 4222 + bitmap[1] &= ~FATTR4_WORD1_TIME_CREATE; 4223 + } 4224 + dprintk("%s: btime=%lld\n", __func__, time->tv_sec); 4225 + return status; 4226 + } 4227 + 4211 4228 static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time) 4212 4229 { 4213 4230 int status = 0; ··· 4796 4777 fattr->valid |= status; 4797 4778 4798 4779 status = decode_attr_time_access(xdr, bitmap, &fattr->atime); 4780 + if (status < 0) 4781 + goto xdr_error; 4782 + fattr->valid |= status; 4783 + 4784 + status = decode_attr_time_create(xdr, bitmap, &fattr->btime); 4799 4785 if (status < 0) 4800 4786 goto xdr_error; 4801 4787 fattr->valid |= status;
+8 -3
fs/nfs/nfstrace.h
··· 32 32 { NFS_INO_INVALID_BLOCKS, "INVALID_BLOCKS" }, \ 33 33 { NFS_INO_INVALID_XATTR, "INVALID_XATTR" }, \ 34 34 { NFS_INO_INVALID_NLINK, "INVALID_NLINK" }, \ 35 - { NFS_INO_INVALID_MODE, "INVALID_MODE" }) 35 + { NFS_INO_INVALID_MODE, "INVALID_MODE" }, \ 36 + { NFS_INO_INVALID_BTIME, "INVALID_BTIME" }) 36 37 37 38 #define nfs_show_nfsi_flags(v) \ 38 39 __print_flags(v, "|", \ ··· 57 56 __field(u32, fhandle) 58 57 __field(u64, fileid) 59 58 __field(u64, version) 59 + __field(unsigned long, cache_validity) 60 60 ), 61 61 62 62 TP_fast_assign( ··· 66 64 __entry->fileid = nfsi->fileid; 67 65 __entry->fhandle = nfs_fhandle_hash(&nfsi->fh); 68 66 __entry->version = inode_peek_iversion_raw(inode); 67 + __entry->cache_validity = nfsi->cache_validity; 69 68 ), 70 69 71 70 TP_printk( 72 - "fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu ", 71 + "fileid=%02x:%02x:%llu fhandle=0x%08x version=%llu cache_validity=0x%lx (%s)", 73 72 MAJOR(__entry->dev), MINOR(__entry->dev), 74 73 (unsigned long long)__entry->fileid, 75 74 __entry->fhandle, 76 - (unsigned long long)__entry->version 75 + (unsigned long long)__entry->version, 76 + __entry->cache_validity, 77 + nfs_show_cache_validity(__entry->cache_validity) 77 78 ) 78 79 ); 79 80
+18 -21
fs/nfs/pnfs.c
··· 306 306 pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo) 307 307 { 308 308 struct inode *inode; 309 - unsigned long i_state; 310 309 311 310 if (!lo) 312 311 return; ··· 316 317 if (!list_empty(&lo->plh_segs)) 317 318 WARN_ONCE(1, "NFS: BUG unfreed layout segments.\n"); 318 319 pnfs_detach_layout_hdr(lo); 319 - i_state = inode->i_state; 320 + /* Notify pnfs_destroy_layout_final() that we're done */ 321 + if (inode->i_state & (I_FREEING | I_CLEAR)) 322 + wake_up_var_locked(lo, &inode->i_lock); 320 323 spin_unlock(&inode->i_lock); 321 324 pnfs_free_layout_hdr(lo); 322 - /* Notify pnfs_destroy_layout_final() that we're done */ 323 - if (i_state & (I_FREEING | I_CLEAR)) 324 - wake_up_var(lo); 325 325 } 326 326 } 327 327 ··· 807 809 } 808 810 EXPORT_SYMBOL_GPL(pnfs_destroy_layout); 809 811 810 - static bool pnfs_layout_removed(struct nfs_inode *nfsi, 811 - struct pnfs_layout_hdr *lo) 812 - { 813 - bool ret; 814 - 815 - spin_lock(&nfsi->vfs_inode.i_lock); 816 - ret = nfsi->layout != lo; 817 - spin_unlock(&nfsi->vfs_inode.i_lock); 818 - return ret; 819 - } 820 - 821 812 void pnfs_destroy_layout_final(struct nfs_inode *nfsi) 822 813 { 823 814 struct pnfs_layout_hdr *lo = __pnfs_destroy_layout(nfsi); 815 + struct inode *inode = &nfsi->vfs_inode; 824 816 825 - if (lo) 826 - wait_var_event(lo, pnfs_layout_removed(nfsi, lo)); 817 + if (lo) { 818 + spin_lock(&inode->i_lock); 819 + wait_var_event_spinlock(lo, nfsi->layout != lo, 820 + &inode->i_lock); 821 + spin_unlock(&inode->i_lock); 822 + } 827 823 } 828 824 829 825 static bool ··· 3332 3340 struct nfs_inode *nfsi = NFS_I(inode); 3333 3341 loff_t end_pos; 3334 3342 int status; 3343 + bool mark_as_dirty = false; 3335 3344 3336 3345 if (!pnfs_layoutcommit_outstanding(inode)) 3337 3346 return 0; ··· 3384 3391 if (ld->prepare_layoutcommit) { 3385 3392 status = ld->prepare_layoutcommit(&data->args); 3386 3393 if (status) { 3387 - put_cred(data->cred); 3394 + if (status != -ENOSPC) 3395 + put_cred(data->cred); 3388 3396 spin_lock(&inode->i_lock); 3389 3397 set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags); 3390 3398 if (end_pos > nfsi->layout->plh_lwb) 3391 3399 nfsi->layout->plh_lwb = end_pos; 3392 - goto out_unlock; 3400 + if (status != -ENOSPC) 3401 + goto out_unlock; 3402 + spin_unlock(&inode->i_lock); 3403 + mark_as_dirty = true; 3393 3404 } 3394 3405 } 3395 3406 3396 3407 3397 3408 status = nfs4_proc_layoutcommit(data, sync); 3398 3409 out: 3399 - if (status) 3410 + if (status || mark_as_dirty) 3400 3411 mark_inode_dirty_sync(inode); 3401 3412 dprintk("<-- %s status %d\n", __func__, status); 3402 3413 return status;
+9 -5
fs/nfs/pnfs_nfs.c
··· 17 17 #include "internal.h" 18 18 #include "pnfs.h" 19 19 #include "netns.h" 20 + #include "nfs4trace.h" 20 21 21 22 #define NFSDBG_FACILITY NFSDBG_PNFS 22 23 ··· 1008 1007 err = nfs4_wait_ds_connect(ds); 1009 1008 if (err || ds->ds_clp) 1010 1009 goto out; 1011 - if (nfs4_test_deviceid_unavailable(devid)) 1012 - return -ENODEV; 1010 + if (nfs4_test_deviceid_unavailable(devid)) { 1011 + err = -ENODEV; 1012 + goto out; 1013 + } 1013 1014 } while (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) != 0); 1014 1015 1015 1016 if (ds->ds_clp) ··· 1041 1038 if (!ds->ds_clp || !nfs_client_init_is_complete(ds->ds_clp)) { 1042 1039 WARN_ON_ONCE(ds->ds_clp || 1043 1040 !nfs4_test_deviceid_unavailable(devid)); 1044 - return -EINVAL; 1045 - } 1046 - err = nfs_client_init_status(ds->ds_clp); 1041 + err = -EINVAL; 1042 + } else 1043 + err = nfs_client_init_status(ds->ds_clp); 1047 1044 } 1048 1045 1046 + trace_pnfs_ds_connect(ds->ds_remotestr, err); 1049 1047 return err; 1050 1048 } 1051 1049 EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_connect);
+6 -2
fs/nfs/write.c
··· 2113 2113 * that we can safely release the inode reference while holding 2114 2114 * the folio lock. 2115 2115 */ 2116 - if (folio_test_private(src)) 2117 - return -EBUSY; 2116 + if (folio_test_private(src)) { 2117 + if (mode == MIGRATE_SYNC) 2118 + nfs_wb_folio(src->mapping->host, src); 2119 + if (folio_test_private(src)) 2120 + return -EBUSY; 2121 + } 2118 2122 2119 2123 if (folio_test_private_2(src)) { /* [DEPRECATED] */ 2120 2124 if (mode == MIGRATE_ASYNC)
+17 -11
fs/nfs_common/nfslocalio.c
··· 177 177 /* nfs_close_local_fh() is doing the 178 178 * close and we must wait. until it unlinks 179 179 */ 180 - wait_var_event_spinlock(nfl, 180 + wait_var_event_spinlock(nfs_uuid, 181 181 list_first_entry_or_null( 182 182 &nfs_uuid->files, 183 183 struct nfs_file_localio, ··· 198 198 /* Now we can allow racing nfs_close_local_fh() to 199 199 * skip the locking. 200 200 */ 201 - RCU_INIT_POINTER(nfl->nfs_uuid, NULL); 202 - wake_up_var_locked(&nfl->nfs_uuid, &nfs_uuid->lock); 201 + store_release_wake_up(&nfl->nfs_uuid, RCU_INITIALIZER(NULL)); 203 202 } 204 203 205 204 /* Remove client from nn->local_clients */ ··· 242 243 } 243 244 EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients); 244 245 245 - static void nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl) 246 + static int nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl) 246 247 { 248 + int ret = 0; 249 + 247 250 /* Add nfl to nfs_uuid->files if it isn't already */ 248 251 spin_lock(&nfs_uuid->lock); 249 - if (list_empty(&nfl->list)) { 252 + if (rcu_access_pointer(nfs_uuid->net) == NULL) { 253 + ret = -ENXIO; 254 + } else if (list_empty(&nfl->list)) { 250 255 rcu_assign_pointer(nfl->nfs_uuid, nfs_uuid); 251 256 list_add_tail(&nfl->list, &nfs_uuid->files); 252 257 } 253 258 spin_unlock(&nfs_uuid->lock); 259 + return ret; 254 260 } 255 261 256 262 /* ··· 289 285 } 290 286 rcu_read_unlock(); 291 287 /* We have an implied reference to net thanks to nfsd_net_try_get */ 292 - localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt, 293 - cred, nfs_fh, pnf, fmode); 288 + localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt, cred, 289 + nfs_fh, pnf, fmode); 290 + if (!IS_ERR(localio) && nfs_uuid_add_file(uuid, nfl) < 0) { 291 + /* Delete the cached file when racing with nfs_uuid_put() */ 292 + nfs_to_nfsd_file_put_local(pnf); 293 + } 294 294 nfs_to_nfsd_net_put(net); 295 - if (!IS_ERR(localio)) 296 - nfs_uuid_add_file(uuid, nfl); 297 295 298 296 return localio; 299 297 } ··· 320 314 rcu_read_unlock(); 321 315 return; 322 316 } 323 - if (list_empty(&nfs_uuid->files)) { 317 + if (list_empty(&nfl->list)) { 324 318 /* nfs_uuid_put() has started closing files, wait for it 325 319 * to finished 326 320 */ ··· 344 338 */ 345 339 spin_lock(&nfs_uuid->lock); 346 340 list_del_init(&nfl->list); 347 - wake_up_var_locked(&nfl->nfs_uuid, &nfs_uuid->lock); 341 + wake_up_var_locked(nfs_uuid, &nfs_uuid->lock); 348 342 spin_unlock(&nfs_uuid->lock); 349 343 } 350 344 EXPORT_SYMBOL_GPL(nfs_close_local_fh);
+8
include/linux/nfs_fs.h
··· 161 161 unsigned long cache_validity; /* bit mask */ 162 162 163 163 /* 164 + * NFS Attributes not included in struct inode 165 + */ 166 + 167 + struct timespec64 btime; 168 + 169 + /* 164 170 * read_cache_jiffies is when we started read-caching this inode. 165 171 * attrtimeo is for how long the cached information is assumed 166 172 * to be valid. A successful attribute revalidation doubles ··· 322 316 #define NFS_INO_INVALID_XATTR BIT(15) /* xattrs are invalid */ 323 317 #define NFS_INO_INVALID_NLINK BIT(16) /* cached nlinks is invalid */ 324 318 #define NFS_INO_INVALID_MODE BIT(17) /* cached mode is invalid */ 319 + #define NFS_INO_INVALID_BTIME BIT(18) /* cached btime is invalid */ 325 320 326 321 #define NFS_INO_INVALID_ATTR (NFS_INO_INVALID_CHANGE \ 327 322 | NFS_INO_INVALID_CTIME \ 328 323 | NFS_INO_INVALID_MTIME \ 324 + | NFS_INO_INVALID_BTIME \ 329 325 | NFS_INO_INVALID_SIZE \ 330 326 | NFS_INO_INVALID_NLINK \ 331 327 | NFS_INO_INVALID_MODE \
+4 -4
include/linux/nfs_fs_sb.h
··· 172 172 #define NFS_MOUNT_FORCE_RDIRPLUS 0x20000000 173 173 #define NFS_MOUNT_NETUNREACH_FATAL 0x40000000 174 174 175 - unsigned int fattr_valid; /* Valid attributes */ 176 175 unsigned int caps; /* server capabilities */ 176 + __u64 fattr_valid; /* Valid attributes */ 177 177 unsigned int rsize; /* read size */ 178 178 unsigned int rpages; /* read size (in pages) */ 179 179 unsigned int wsize; /* write size */ 180 - unsigned int wpages; /* write size (in pages) */ 181 180 unsigned int wtmult; /* server disk block size */ 182 181 unsigned int dtsize; /* readdir size */ 183 182 unsigned short port; /* "port=" setting */ ··· 202 203 struct nfs_fsid fsid; 203 204 int s_sysfs_id; /* sysfs dentry index */ 204 205 __u64 maxfilesize; /* maximum file size */ 205 - struct timespec64 time_delta; /* smallest time granularity */ 206 206 unsigned long mount_time; /* when this fs was mounted */ 207 207 struct super_block *super; /* VFS super block */ 208 208 dev_t s_dev; /* superblock dev numbers */ ··· 246 248 filesystem */ 247 249 struct pnfs_layoutdriver_type *pnfs_curr_ld; /* Active layout driver */ 248 250 struct rpc_wait_queue roc_rpcwaitq; 249 - void *pnfs_ld_data; /* per mount point data */ 250 251 251 252 /* the following fields are protected by nfs_client->cl_lock */ 252 253 struct rb_root state_owners; ··· 254 257 struct list_head state_owners_lru; 255 258 struct list_head layouts; 256 259 struct list_head delegations; 260 + atomic_long_t nr_active_delegations; 261 + unsigned int delegation_hash_mask; 262 + struct hlist_head *delegation_hash_table; 257 263 struct list_head ss_copies; 258 264 struct list_head ss_src_copies; 259 265
+30 -27
include/linux/nfs_xdr.h
··· 45 45 }; 46 46 47 47 struct nfs_fattr { 48 - unsigned int valid; /* which fields are valid */ 48 + __u64 valid; /* which fields are valid */ 49 49 umode_t mode; 50 50 __u32 nlink; 51 51 kuid_t uid; ··· 67 67 struct timespec64 atime; 68 68 struct timespec64 mtime; 69 69 struct timespec64 ctime; 70 + struct timespec64 btime; 70 71 __u64 change_attr; /* NFSv4 change attribute */ 71 72 __u64 pre_change_attr;/* pre-op NFSv4 change attribute */ 72 73 __u64 pre_size; /* pre_op_attr.size */ ··· 81 80 struct nfs4_label *label; 82 81 }; 83 82 84 - #define NFS_ATTR_FATTR_TYPE (1U << 0) 85 - #define NFS_ATTR_FATTR_MODE (1U << 1) 86 - #define NFS_ATTR_FATTR_NLINK (1U << 2) 87 - #define NFS_ATTR_FATTR_OWNER (1U << 3) 88 - #define NFS_ATTR_FATTR_GROUP (1U << 4) 89 - #define NFS_ATTR_FATTR_RDEV (1U << 5) 90 - #define NFS_ATTR_FATTR_SIZE (1U << 6) 91 - #define NFS_ATTR_FATTR_PRESIZE (1U << 7) 92 - #define NFS_ATTR_FATTR_BLOCKS_USED (1U << 8) 93 - #define NFS_ATTR_FATTR_SPACE_USED (1U << 9) 94 - #define NFS_ATTR_FATTR_FSID (1U << 10) 95 - #define NFS_ATTR_FATTR_FILEID (1U << 11) 96 - #define NFS_ATTR_FATTR_ATIME (1U << 12) 97 - #define NFS_ATTR_FATTR_MTIME (1U << 13) 98 - #define NFS_ATTR_FATTR_CTIME (1U << 14) 99 - #define NFS_ATTR_FATTR_PREMTIME (1U << 15) 100 - #define NFS_ATTR_FATTR_PRECTIME (1U << 16) 101 - #define NFS_ATTR_FATTR_CHANGE (1U << 17) 102 - #define NFS_ATTR_FATTR_PRECHANGE (1U << 18) 103 - #define NFS_ATTR_FATTR_V4_LOCATIONS (1U << 19) 104 - #define NFS_ATTR_FATTR_V4_REFERRAL (1U << 20) 105 - #define NFS_ATTR_FATTR_MOUNTPOINT (1U << 21) 106 - #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 22) 107 - #define NFS_ATTR_FATTR_OWNER_NAME (1U << 23) 108 - #define NFS_ATTR_FATTR_GROUP_NAME (1U << 24) 109 - #define NFS_ATTR_FATTR_V4_SECURITY_LABEL (1U << 25) 83 + #define NFS_ATTR_FATTR_TYPE BIT_ULL(0) 84 + #define NFS_ATTR_FATTR_MODE BIT_ULL(1) 85 + #define NFS_ATTR_FATTR_NLINK BIT_ULL(2) 86 + #define NFS_ATTR_FATTR_OWNER BIT_ULL(3) 87 + #define NFS_ATTR_FATTR_GROUP BIT_ULL(4) 88 + #define NFS_ATTR_FATTR_RDEV BIT_ULL(5) 89 + #define NFS_ATTR_FATTR_SIZE BIT_ULL(6) 90 + #define NFS_ATTR_FATTR_PRESIZE BIT_ULL(7) 91 + #define NFS_ATTR_FATTR_BLOCKS_USED BIT_ULL(8) 92 + #define NFS_ATTR_FATTR_SPACE_USED BIT_ULL(9) 93 + #define NFS_ATTR_FATTR_FSID BIT_ULL(10) 94 + #define NFS_ATTR_FATTR_FILEID BIT_ULL(11) 95 + #define NFS_ATTR_FATTR_ATIME BIT_ULL(12) 96 + #define NFS_ATTR_FATTR_MTIME BIT_ULL(13) 97 + #define NFS_ATTR_FATTR_CTIME BIT_ULL(14) 98 + #define NFS_ATTR_FATTR_PREMTIME BIT_ULL(15) 99 + #define NFS_ATTR_FATTR_PRECTIME BIT_ULL(16) 100 + #define NFS_ATTR_FATTR_CHANGE BIT_ULL(17) 101 + #define NFS_ATTR_FATTR_PRECHANGE BIT_ULL(18) 102 + #define NFS_ATTR_FATTR_V4_LOCATIONS BIT_ULL(19) 103 + #define NFS_ATTR_FATTR_V4_REFERRAL BIT_ULL(20) 104 + #define NFS_ATTR_FATTR_MOUNTPOINT BIT_ULL(21) 105 + #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID BIT_ULL(22) 106 + #define NFS_ATTR_FATTR_OWNER_NAME BIT_ULL(23) 107 + #define NFS_ATTR_FATTR_GROUP_NAME BIT_ULL(24) 108 + #define NFS_ATTR_FATTR_V4_SECURITY_LABEL BIT_ULL(25) 109 + #define NFS_ATTR_FATTR_BTIME BIT_ULL(26) 110 110 111 111 #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ 112 112 | NFS_ATTR_FATTR_MODE \ ··· 128 126 | NFS_ATTR_FATTR_SPACE_USED) 129 127 #define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \ 130 128 | NFS_ATTR_FATTR_SPACE_USED \ 129 + | NFS_ATTR_FATTR_BTIME \ 131 130 | NFS_ATTR_FATTR_V4_SECURITY_LABEL) 132 131 133 132 /*
-9
include/linux/sunrpc/xdr.h
··· 130 130 __be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int len); 131 131 __be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int len); 132 132 __be32 *xdr_encode_string(__be32 *p, const char *s); 133 - __be32 *xdr_decode_string_inplace(__be32 *p, char **sp, unsigned int *lenp, 134 - unsigned int maxlen); 135 133 __be32 *xdr_encode_netobj(__be32 *p, const struct xdr_netobj *); 136 - __be32 *xdr_decode_netobj(__be32 *p, struct xdr_netobj *); 137 134 138 135 void xdr_inline_pages(struct xdr_buf *, unsigned int, 139 136 struct page **, unsigned int, unsigned int); ··· 339 342 return xdr->nwords << 2; 340 343 } 341 344 342 - ssize_t xdr_stream_decode_opaque(struct xdr_stream *xdr, void *ptr, 343 - size_t size); 344 - ssize_t xdr_stream_decode_opaque_dup(struct xdr_stream *xdr, void **ptr, 345 - size_t maxlen, gfp_t gfp_flags); 346 - ssize_t xdr_stream_decode_string(struct xdr_stream *xdr, char *str, 347 - size_t size); 348 345 ssize_t xdr_stream_decode_string_dup(struct xdr_stream *xdr, char **str, 349 346 size_t maxlen, gfp_t gfp_flags); 350 347 ssize_t xdr_stream_decode_opaque_auth(struct xdr_stream *xdr, u32 *flavor,
+2 -2
net/sunrpc/auth_gss/gss_krb5_crypto.c
··· 875 875 * krb5_etm_decrypt - Decrypt using the RFC 8009 rules 876 876 * @kctx: Kerberos context 877 877 * @offset: starting offset of the ciphertext, in bytes 878 - * @len: 879 - * @buf: 878 + * @len: size of ciphertext to unwrap 879 + * @buf: ciphertext to unwrap 880 880 * @headskip: OUT: the enctype's confounder length, in octets 881 881 * @tailskip: OUT: the enctype's HMAC length, in octets 882 882 *
-110
net/sunrpc/xdr.c
··· 37 37 } 38 38 EXPORT_SYMBOL_GPL(xdr_encode_netobj); 39 39 40 - __be32 * 41 - xdr_decode_netobj(__be32 *p, struct xdr_netobj *obj) 42 - { 43 - unsigned int len; 44 - 45 - if ((len = be32_to_cpu(*p++)) > XDR_MAX_NETOBJ) 46 - return NULL; 47 - obj->len = len; 48 - obj->data = (u8 *) p; 49 - return p + XDR_QUADLEN(len); 50 - } 51 - EXPORT_SYMBOL_GPL(xdr_decode_netobj); 52 - 53 40 /** 54 41 * xdr_encode_opaque_fixed - Encode fixed length opaque data 55 42 * @p: pointer to current position in XDR buffer. ··· 88 101 return xdr_encode_array(p, string, strlen(string)); 89 102 } 90 103 EXPORT_SYMBOL_GPL(xdr_encode_string); 91 - 92 - __be32 * 93 - xdr_decode_string_inplace(__be32 *p, char **sp, 94 - unsigned int *lenp, unsigned int maxlen) 95 - { 96 - u32 len; 97 - 98 - len = be32_to_cpu(*p++); 99 - if (len > maxlen) 100 - return NULL; 101 - *lenp = len; 102 - *sp = (char *) p; 103 - return p + XDR_QUADLEN(len); 104 - } 105 - EXPORT_SYMBOL_GPL(xdr_decode_string_inplace); 106 104 107 105 /** 108 106 * xdr_terminate_string - '\0'-terminate a string residing in an xdr_buf ··· 2215 2243 return ret; 2216 2244 } 2217 2245 EXPORT_SYMBOL_GPL(xdr_process_buf); 2218 - 2219 - /** 2220 - * xdr_stream_decode_opaque - Decode variable length opaque 2221 - * @xdr: pointer to xdr_stream 2222 - * @ptr: location to store opaque data 2223 - * @size: size of storage buffer @ptr 2224 - * 2225 - * Return values: 2226 - * On success, returns size of object stored in *@ptr 2227 - * %-EBADMSG on XDR buffer overflow 2228 - * %-EMSGSIZE on overflow of storage buffer @ptr 2229 - */ 2230 - ssize_t xdr_stream_decode_opaque(struct xdr_stream *xdr, void *ptr, size_t size) 2231 - { 2232 - ssize_t ret; 2233 - void *p; 2234 - 2235 - ret = xdr_stream_decode_opaque_inline(xdr, &p, size); 2236 - if (ret <= 0) 2237 - return ret; 2238 - memcpy(ptr, p, ret); 2239 - return ret; 2240 - } 2241 - EXPORT_SYMBOL_GPL(xdr_stream_decode_opaque); 2242 - 2243 - /** 2244 - * xdr_stream_decode_opaque_dup - Decode and duplicate variable length opaque 2245 - * @xdr: pointer to xdr_stream 2246 - * @ptr: location to store pointer to opaque data 2247 - * @maxlen: maximum acceptable object size 2248 - * @gfp_flags: GFP mask to use 2249 - * 2250 - * Return values: 2251 - * On success, returns size of object stored in *@ptr 2252 - * %-EBADMSG on XDR buffer overflow 2253 - * %-EMSGSIZE if the size of the object would exceed @maxlen 2254 - * %-ENOMEM on memory allocation failure 2255 - */ 2256 - ssize_t xdr_stream_decode_opaque_dup(struct xdr_stream *xdr, void **ptr, 2257 - size_t maxlen, gfp_t gfp_flags) 2258 - { 2259 - ssize_t ret; 2260 - void *p; 2261 - 2262 - ret = xdr_stream_decode_opaque_inline(xdr, &p, maxlen); 2263 - if (ret > 0) { 2264 - *ptr = kmemdup(p, ret, gfp_flags); 2265 - if (*ptr != NULL) 2266 - return ret; 2267 - ret = -ENOMEM; 2268 - } 2269 - *ptr = NULL; 2270 - return ret; 2271 - } 2272 - EXPORT_SYMBOL_GPL(xdr_stream_decode_opaque_dup); 2273 - 2274 - /** 2275 - * xdr_stream_decode_string - Decode variable length string 2276 - * @xdr: pointer to xdr_stream 2277 - * @str: location to store string 2278 - * @size: size of storage buffer @str 2279 - * 2280 - * Return values: 2281 - * On success, returns length of NUL-terminated string stored in *@str 2282 - * %-EBADMSG on XDR buffer overflow 2283 - * %-EMSGSIZE on overflow of storage buffer @str 2284 - */ 2285 - ssize_t xdr_stream_decode_string(struct xdr_stream *xdr, char *str, size_t size) 2286 - { 2287 - ssize_t ret; 2288 - void *p; 2289 - 2290 - ret = xdr_stream_decode_opaque_inline(xdr, &p, size); 2291 - if (ret > 0) { 2292 - memcpy(str, p, ret); 2293 - str[ret] = '\0'; 2294 - return strlen(str); 2295 - } 2296 - *str = '\0'; 2297 - return ret; 2298 - } 2299 - EXPORT_SYMBOL_GPL(xdr_stream_decode_string); 2300 2246 2301 2247 /** 2302 2248 * xdr_stream_decode_string_dup - Decode and duplicate variable length string
+30 -10
net/sunrpc/xprtsock.c
··· 358 358 359 359 static int 360 360 xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg, 361 - struct cmsghdr *cmsg, int ret) 361 + unsigned int *msg_flags, struct cmsghdr *cmsg, int ret) 362 362 { 363 363 u8 content_type = tls_get_record_type(sock->sk, cmsg); 364 364 u8 level, description; ··· 371 371 * record, even though there might be more frames 372 372 * waiting to be decrypted. 373 373 */ 374 - msg->msg_flags &= ~MSG_EOR; 374 + *msg_flags &= ~MSG_EOR; 375 375 break; 376 376 case TLS_RECORD_TYPE_ALERT: 377 377 tls_alert_recv(sock->sk, msg, &level, &description); ··· 386 386 } 387 387 388 388 static int 389 - xs_sock_recv_cmsg(struct socket *sock, struct msghdr *msg, int flags) 389 + xs_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags, int flags) 390 390 { 391 391 union { 392 392 struct cmsghdr cmsg; 393 393 u8 buf[CMSG_SPACE(sizeof(u8))]; 394 394 } u; 395 + u8 alert[2]; 396 + struct kvec alert_kvec = { 397 + .iov_base = alert, 398 + .iov_len = sizeof(alert), 399 + }; 400 + struct msghdr msg = { 401 + .msg_flags = *msg_flags, 402 + .msg_control = &u, 403 + .msg_controllen = sizeof(u), 404 + }; 395 405 int ret; 396 406 397 - msg->msg_control = &u; 398 - msg->msg_controllen = sizeof(u); 399 - ret = sock_recvmsg(sock, msg, flags); 400 - if (msg->msg_controllen != sizeof(u)) 401 - ret = xs_sock_process_cmsg(sock, msg, &u.cmsg, ret); 407 + iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1, 408 + alert_kvec.iov_len); 409 + ret = sock_recvmsg(sock, &msg, flags); 410 + if (ret > 0 && 411 + tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) { 412 + iov_iter_revert(&msg.msg_iter, ret); 413 + ret = xs_sock_process_cmsg(sock, &msg, msg_flags, &u.cmsg, 414 + -EAGAIN); 415 + } 402 416 return ret; 403 417 } 404 418 ··· 422 408 ssize_t ret; 423 409 if (seek != 0) 424 410 iov_iter_advance(&msg->msg_iter, seek); 425 - ret = xs_sock_recv_cmsg(sock, msg, flags); 411 + ret = sock_recvmsg(sock, msg, flags); 412 + /* Handle TLS inband control message lazily */ 413 + if (msg->msg_flags & MSG_CTRUNC) { 414 + msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR); 415 + if (ret == 0 || ret == -EIO) 416 + ret = xs_sock_recv_cmsg(sock, &msg->msg_flags, flags); 417 + } 426 418 return ret > 0 ? ret + seek : ret; 427 419 } 428 420 ··· 454 434 size_t count) 455 435 { 456 436 iov_iter_discard(&msg->msg_iter, ITER_DEST, count); 457 - return xs_sock_recv_cmsg(sock, msg, flags); 437 + return xs_sock_recvmsg(sock, msg, flags, 0); 458 438 } 459 439 460 440 #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE