Skip to content

Commit 96890bc

Browse files
committed
Merge tag 'nfs-for-5.14-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Highlights include: Features: - Multiple patches to add support for fcntl() leases over NFSv4. - A sysfs interface to display more information about the various transport connections used by the RPC client - A sysfs interface to allow a suitably privileged user to offline a transport that may no longer point to a valid server - A sysfs interface to allow a suitably privileged user to change the server IP address used by the RPC client Stable fixes: - Two sunrpc fixes for deadlocks involving privileged rpc_wait_queues Bugfixes: - SUNRPC: Avoid a KASAN slab-out-of-bounds bug in xdr_set_page_base() - SUNRPC: prevent port reuse on transports which don't request it. - NFSv3: Fix memory leak in posix_acl_create() - NFS: Various fixes to attribute revalidation timeouts - NFSv4: Fix handling of non-atomic change attribute updates - NFSv4: If a server is down, don't cause mounts to other servers to hang as well - pNFS: Fix an Oops in pnfs_mark_request_commit() when doing O_DIRECT - NFS: Fix mount failures due to incorrect setting of the has_sec_mnt_opts filesystem flag - NFS: Ensure nfs_readpage returns promptly when an internal error occurs - NFS: Fix fscache read from NFS after cache error - pNFS: Various bugfixes around the LAYOUTGET operation" * tag 'nfs-for-5.14-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (46 commits) NFSv4/pNFS: Return an error if _nfs4_pnfs_v3_ds_connect can't load NFSv3 NFSv4/pNFS: Don't call _nfs4_pnfs_v3_ds_connect multiple times NFSv4/pnfs: Clean up layout get on open NFSv4/pnfs: Fix layoutget behaviour after invalidation NFSv4/pnfs: Fix the layout barrier update NFS: Fix fscache read from NFS after cache error NFS: Ensure nfs_readpage returns promptly when internal error occurs sunrpc: remove an offlined xprt using sysfs sunrpc: provide showing transport's state info in the sysfs directory sunrpc: display xprt's queuelen of assigned tasks via sysfs sunrpc: provide multipath info in the sysfs directory NFSv4.1 identify and mark RPC tasks that can move between transports sunrpc: provide transport info in the sysfs directory SUNRPC: take a xprt offline using sysfs sunrpc: add dst_attr attributes to the sysfs xprt directory SUNRPC for TCP display xprt's source port in sysfs xprt_info SUNRPC query transport's source port SUNRPC display xprt's main value in sysfs's xprt_info SUNRPC mark the first transport sunrpc: add add sysfs directory per xprt under each xprt_switch ...
2 parents 227c4d5 + 878b3df commit 96890bc

34 files changed

Lines changed: 1140 additions & 234 deletions

fs/nfs/delegation.c

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
7575
set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
7676
}
7777

78+
static void nfs_mark_return_delegation(struct nfs_server *server,
79+
struct nfs_delegation *delegation)
80+
{
81+
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
82+
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
83+
}
84+
7885
static bool
7986
nfs4_is_valid_delegation(const struct nfs_delegation *delegation,
8087
fmode_t flags)
@@ -293,6 +300,7 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi)
293300
goto out;
294301
spin_lock(&delegation->lock);
295302
if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
303+
clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags);
296304
/* Refcount matched in nfs_end_delegation_return() */
297305
ret = nfs_get_delegation(delegation);
298306
}
@@ -314,16 +322,17 @@ nfs_start_delegation_return(struct nfs_inode *nfsi)
314322
return delegation;
315323
}
316324

317-
static void
318-
nfs_abort_delegation_return(struct nfs_delegation *delegation,
319-
struct nfs_client *clp)
325+
static void nfs_abort_delegation_return(struct nfs_delegation *delegation,
326+
struct nfs_client *clp, int err)
320327
{
321328

322329
spin_lock(&delegation->lock);
323330
clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
324-
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
331+
if (err == -EAGAIN) {
332+
set_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags);
333+
set_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state);
334+
}
325335
spin_unlock(&delegation->lock);
326-
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
327336
}
328337

329338
static struct nfs_delegation *
@@ -521,11 +530,18 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
521530
static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation *delegation, int issync)
522531
{
523532
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
533+
unsigned int mode = O_WRONLY | O_RDWR;
524534
int err = 0;
525535

526536
if (delegation == NULL)
527537
return 0;
528-
do {
538+
539+
if (!issync)
540+
mode |= O_NONBLOCK;
541+
/* Recall of any remaining application leases */
542+
err = break_lease(inode, mode);
543+
544+
while (err == 0) {
529545
if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
530546
break;
531547
err = nfs_delegation_claim_opens(inode, &delegation->stateid,
@@ -536,10 +552,10 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
536552
* Guard against state recovery
537553
*/
538554
err = nfs4_wait_clnt_recover(clp);
539-
} while (err == 0);
555+
}
540556

541557
if (err) {
542-
nfs_abort_delegation_return(delegation, clp);
558+
nfs_abort_delegation_return(delegation, clp, err);
543559
goto out;
544560
}
545561

@@ -568,6 +584,7 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
568584
if (ret)
569585
clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
570586
if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags) ||
587+
test_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags) ||
571588
test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
572589
ret = false;
573590

@@ -647,6 +664,38 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
647664
return err;
648665
}
649666

667+
static bool nfs_server_clear_delayed_delegations(struct nfs_server *server)
668+
{
669+
struct nfs_delegation *d;
670+
bool ret = false;
671+
672+
list_for_each_entry_rcu (d, &server->delegations, super_list) {
673+
if (!test_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags))
674+
continue;
675+
nfs_mark_return_delegation(server, d);
676+
clear_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags);
677+
ret = true;
678+
}
679+
return ret;
680+
}
681+
682+
static bool nfs_client_clear_delayed_delegations(struct nfs_client *clp)
683+
{
684+
struct nfs_server *server;
685+
bool ret = false;
686+
687+
if (!test_and_clear_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state))
688+
goto out;
689+
rcu_read_lock();
690+
list_for_each_entry_rcu (server, &clp->cl_superblocks, client_link) {
691+
if (nfs_server_clear_delayed_delegations(server))
692+
ret = true;
693+
}
694+
rcu_read_unlock();
695+
out:
696+
return ret;
697+
}
698+
650699
/**
651700
* nfs_client_return_marked_delegations - return previously marked delegations
652701
* @clp: nfs_client to process
@@ -659,8 +708,14 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
659708
*/
660709
int nfs_client_return_marked_delegations(struct nfs_client *clp)
661710
{
662-
return nfs_client_for_each_server(clp,
663-
nfs_server_return_marked_delegations, NULL);
711+
int err = nfs_client_for_each_server(
712+
clp, nfs_server_return_marked_delegations, NULL);
713+
if (err)
714+
return err;
715+
/* If a return was delayed, sleep to prevent hard looping */
716+
if (nfs_client_clear_delayed_delegations(clp))
717+
ssleep(1);
718+
return 0;
664719
}
665720

666721
/**
@@ -698,13 +753,14 @@ int nfs4_inode_return_delegation(struct inode *inode)
698753
{
699754
struct nfs_inode *nfsi = NFS_I(inode);
700755
struct nfs_delegation *delegation;
701-
int err = 0;
702756

703-
nfs_wb_all(inode);
704757
delegation = nfs_start_delegation_return(nfsi);
758+
/* Synchronous recall of any application leases */
759+
break_lease(inode, O_WRONLY | O_RDWR);
760+
nfs_wb_all(inode);
705761
if (delegation != NULL)
706-
err = nfs_end_delegation_return(inode, delegation, 1);
707-
return err;
762+
return nfs_end_delegation_return(inode, delegation, 1);
763+
return 0;
708764
}
709765

710766
/**
@@ -775,13 +831,6 @@ static void nfs_mark_return_if_closed_delegation(struct nfs_server *server,
775831
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
776832
}
777833

778-
static void nfs_mark_return_delegation(struct nfs_server *server,
779-
struct nfs_delegation *delegation)
780-
{
781-
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
782-
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
783-
}
784-
785834
static bool nfs_server_mark_return_all_delegations(struct nfs_server *server)
786835
{
787836
struct nfs_delegation *delegation;
@@ -1010,6 +1059,9 @@ int nfs_async_inode_return_delegation(struct inode *inode,
10101059
nfs_mark_return_delegation(server, delegation);
10111060
rcu_read_unlock();
10121061

1062+
/* If there are any application leases or delegations, recall them */
1063+
break_lease(inode, O_WRONLY | O_RDWR | O_NONBLOCK);
1064+
10131065
nfs_delegation_run_state_manager(clp);
10141066
return 0;
10151067
out_enoent:

fs/nfs/delegation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ enum {
3636
NFS_DELEGATION_REVOKED,
3737
NFS_DELEGATION_TEST_EXPIRED,
3838
NFS_DELEGATION_INODE_FREEING,
39+
NFS_DELEGATION_RETURN_DELAYED,
3940
};
4041

4142
int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,

fs/nfs/direct.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -700,8 +700,8 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
700700
{
701701
struct nfs_direct_req *dreq = hdr->dreq;
702702
struct nfs_commit_info cinfo;
703-
bool request_commit = false;
704703
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
704+
int flags = NFS_ODIRECT_DONE;
705705

706706
nfs_init_cinfo_from_dreq(&cinfo, dreq);
707707

@@ -713,28 +713,25 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
713713

714714
nfs_direct_count_bytes(dreq, hdr);
715715
if (hdr->good_bytes != 0 && nfs_write_need_commit(hdr)) {
716-
switch (dreq->flags) {
717-
case 0:
716+
if (!dreq->flags)
718717
dreq->flags = NFS_ODIRECT_DO_COMMIT;
719-
request_commit = true;
720-
break;
721-
case NFS_ODIRECT_RESCHED_WRITES:
722-
case NFS_ODIRECT_DO_COMMIT:
723-
request_commit = true;
724-
}
718+
flags = dreq->flags;
725719
}
726720
spin_unlock(&dreq->lock);
727721

728722
while (!list_empty(&hdr->pages)) {
729723

730724
req = nfs_list_entry(hdr->pages.next);
731725
nfs_list_remove_request(req);
732-
if (request_commit) {
726+
if (flags == NFS_ODIRECT_DO_COMMIT) {
733727
kref_get(&req->wb_kref);
734728
memcpy(&req->wb_verf, &hdr->verf.verifier,
735729
sizeof(req->wb_verf));
736730
nfs_mark_request_commit(req, hdr->lseg, &cinfo,
737731
hdr->ds_commit_idx);
732+
} else if (flags == NFS_ODIRECT_RESCHED_WRITES) {
733+
kref_get(&req->wb_kref);
734+
nfs_mark_request_commit(req, NULL, &cinfo, 0);
738735
}
739736
nfs_unlock_and_release_request(req);
740737
}

fs/nfs/fscache.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -385,12 +385,15 @@ static void nfs_readpage_from_fscache_complete(struct page *page,
385385
"NFS: readpage_from_fscache_complete (0x%p/0x%p/%d)\n",
386386
page, context, error);
387387

388-
/* if the read completes with an error, we just unlock the page and let
389-
* the VM reissue the readpage */
390-
if (!error) {
388+
/*
389+
* If the read completes with an error, mark the page with PG_checked,
390+
* unlock the page, and let the VM reissue the readpage.
391+
*/
392+
if (!error)
391393
SetPageUptodate(page);
392-
unlock_page(page);
393-
}
394+
else
395+
SetPageChecked(page);
396+
unlock_page(page);
394397
}
395398

396399
/*
@@ -405,6 +408,11 @@ int __nfs_readpage_from_fscache(struct nfs_open_context *ctx,
405408
"NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n",
406409
nfs_i_fscache(inode), page, page->index, page->flags, inode);
407410

411+
if (PageChecked(page)) {
412+
ClearPageChecked(page);
413+
return 1;
414+
}
415+
408416
ret = fscache_read_or_alloc_page(nfs_i_fscache(inode),
409417
page,
410418
nfs_readpage_from_fscache_complete,

fs/nfs/getroot.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
6767
int nfs_get_root(struct super_block *s, struct fs_context *fc)
6868
{
6969
struct nfs_fs_context *ctx = nfs_fc2context(fc);
70-
struct nfs_server *server = NFS_SB(s);
70+
struct nfs_server *server = NFS_SB(s), *clone_server;
7171
struct nfs_fsinfo fsinfo;
7272
struct dentry *root;
7373
struct inode *inode;
@@ -127,7 +127,7 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
127127
}
128128
spin_unlock(&root->d_lock);
129129
fc->root = root;
130-
if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
130+
if (server->caps & NFS_CAP_SECURITY_LABEL)
131131
kflags |= SECURITY_LSM_NATIVE_LABELS;
132132
if (ctx->clone_data.sb) {
133133
if (d_inode(fc->root)->i_fop != &nfs_dir_operations) {
@@ -137,15 +137,19 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
137137
/* clone lsm security options from the parent to the new sb */
138138
error = security_sb_clone_mnt_opts(ctx->clone_data.sb,
139139
s, kflags, &kflags_out);
140+
if (error)
141+
goto error_splat_root;
142+
clone_server = NFS_SB(ctx->clone_data.sb);
143+
server->has_sec_mnt_opts = clone_server->has_sec_mnt_opts;
140144
} else {
141145
error = security_sb_set_mnt_opts(s, fc->security,
142146
kflags, &kflags_out);
143147
}
144148
if (error)
145149
goto error_splat_root;
146-
if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL &&
150+
if (server->caps & NFS_CAP_SECURITY_LABEL &&
147151
!(kflags_out & SECURITY_LSM_NATIVE_LABELS))
148-
NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL;
152+
server->caps &= ~NFS_CAP_SECURITY_LABEL;
149153

150154
nfs_setsecurity(inode, fsinfo.fattr, fsinfo.fattr->label);
151155
error = 0;

0 commit comments

Comments
 (0)