Skip to content

Commit df632d3

Browse files
committed
Merge tag 'nfs-for-3.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Features include: - Remove CONFIG_EXPERIMENTAL dependency from NFSv4.1 Aside from the issues discussed at the LKS, distros are shipping NFSv4.1 with all the trimmings. - Fix fdatasync()/fsync() for the corner case of a server reboot. - NFSv4 OPEN access fix: finally distinguish correctly between open-for-read and open-for-execute permissions in all situations. - Ensure that the TCP socket is closed when we're in CLOSE_WAIT - More idmapper bugfixes - Lots of pNFS bugfixes and cleanups to remove unnecessary state and make the code easier to read. - In cases where a pNFS read or write fails, allow the client to resume trying layoutgets after two minutes of read/write- through-mds. - More net namespace fixes to the NFSv4 callback code. - More net namespace fixes to the NFSv3 locking code. - More NFSv4 migration preparatory patches. Including patches to detect network trunking in both NFSv4 and NFSv4.1 - pNFS block updates to optimise LAYOUTGET calls." * tag 'nfs-for-3.7-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (113 commits) pnfsblock: cleanup nfs4_blkdev_get NFS41: send real read size in layoutget NFS41: send real write size in layoutget NFS: track direct IO left bytes NFSv4.1: Cleanup ugliness in pnfs_layoutgets_blocked() NFSv4.1: Ensure that the layout sequence id stays 'close' to the current NFSv4.1: Deal with seqid wraparound in the pNFS return-on-close code NFSv4 set open access operation call flag in nfs4_init_opendata_res NFSv4.1: Remove the dependency on CONFIG_EXPERIMENTAL NFSv4 reduce attribute requests for open reclaim NFSv4: nfs4_open_done first must check that GETATTR decoded a file type NFSv4.1: Deal with wraparound when updating the layout "barrier" seqid NFSv4.1: Deal with wraparound issues when updating the layout stateid NFSv4.1: Always set the layout stateid if this is the first layoutget NFSv4.1: Fix another refcount issue in pnfs_find_alloc_layout NFSv4: don't put ACCESS in OPEN compound if O_EXCL NFSv4: don't check MAY_WRITE access bit in OPEN NFS: Set key construction data for the legacy upcall NFSv4.1: don't do two EXCHANGE_IDs on mount NFS: nfs41_walk_client_list(): re-lock before iterating ...
2 parents 2474542 + af28388 commit df632d3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2126
-814
lines changed

Documentation/filesystems/nfs/nfs.txt

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,47 @@ and work is in progress on adding support for minor version 1 of the NFSv4
1212
protocol.
1313

1414
The purpose of this document is to provide information on some of the
15-
upcall interfaces that are used in order to provide the NFS client with
16-
some of the information that it requires in order to fully comply with
17-
the NFS spec.
15+
special features of the NFS client that can be configured by system
16+
administrators.
17+
18+
19+
The nfs4_unique_id parameter
20+
============================
21+
22+
NFSv4 requires clients to identify themselves to servers with a unique
23+
string. File open and lock state shared between one client and one server
24+
is associated with this identity. To support robust NFSv4 state recovery
25+
and transparent state migration, this identity string must not change
26+
across client reboots.
27+
28+
Without any other intervention, the Linux client uses a string that contains
29+
the local system's node name. System administrators, however, often do not
30+
take care to ensure that node names are fully qualified and do not change
31+
over the lifetime of a client system. Node names can have other
32+
administrative requirements that require particular behavior that does not
33+
work well as part of an nfs_client_id4 string.
34+
35+
The nfs.nfs4_unique_id boot parameter specifies a unique string that can be
36+
used instead of a system's node name when an NFS client identifies itself to
37+
a server. Thus, if the system's node name is not unique, or it changes, its
38+
nfs.nfs4_unique_id stays the same, preventing collision with other clients
39+
or loss of state during NFS reboot recovery or transparent state migration.
40+
41+
The nfs.nfs4_unique_id string is typically a UUID, though it can contain
42+
anything that is believed to be unique across all NFS clients. An
43+
nfs4_unique_id string should be chosen when a client system is installed,
44+
just as a system's root file system gets a fresh UUID in its label at
45+
install time.
46+
47+
The string should remain fixed for the lifetime of the client. It can be
48+
changed safely if care is taken that the client shuts down cleanly and all
49+
outstanding NFSv4 state has expired, to prevent loss of NFSv4 state.
50+
51+
This string can be stored in an NFS client's grub.conf, or it can be provided
52+
via a net boot facility such as PXE. It may also be specified as an nfs.ko
53+
module parameter. Specifying a uniquifier string is not support for NFS
54+
clients running in containers.
55+
1856

1957
The DNS resolver
2058
================

Documentation/kernel-parameters.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,6 +1730,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
17301730
will be autodetected by the client, and it will fall
17311731
back to using the idmapper.
17321732
To turn off this behaviour, set the value to '0'.
1733+
nfs.nfs4_unique_id=
1734+
[NFS4] Specify an additional fixed unique ident-
1735+
ification string that NFSv4 clients can insert into
1736+
their nfs_client_id4 string. This is typically a
1737+
UUID that is generated at system install time.
17331738

17341739
nfs.send_implementation_id =
17351740
[NFSv4.1] Send client implementation identification

fs/lockd/mon.c

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*/
88

99
#include <linux/types.h>
10-
#include <linux/utsname.h>
1110
#include <linux/kernel.h>
1211
#include <linux/ktime.h>
1312
#include <linux/slab.h>
@@ -19,6 +18,8 @@
1918

2019
#include <asm/unaligned.h>
2120

21+
#include "netns.h"
22+
2223
#define NLMDBG_FACILITY NLMDBG_MONITOR
2324
#define NSM_PROGRAM 100024
2425
#define NSM_VERSION 1
@@ -40,6 +41,7 @@ struct nsm_args {
4041
u32 proc;
4142

4243
char *mon_name;
44+
char *nodename;
4345
};
4446

4547
struct nsm_res {
@@ -70,7 +72,7 @@ static struct rpc_clnt *nsm_create(struct net *net)
7072
};
7173
struct rpc_create_args args = {
7274
.net = net,
73-
.protocol = XPRT_TRANSPORT_UDP,
75+
.protocol = XPRT_TRANSPORT_TCP,
7476
.address = (struct sockaddr *)&sin,
7577
.addrsize = sizeof(sin),
7678
.servername = "rpc.statd",
@@ -83,42 +85,79 @@ static struct rpc_clnt *nsm_create(struct net *net)
8385
return rpc_create(&args);
8486
}
8587

86-
static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
87-
struct net *net)
88+
static struct rpc_clnt *nsm_client_get(struct net *net)
8889
{
90+
static DEFINE_MUTEX(nsm_create_mutex);
8991
struct rpc_clnt *clnt;
92+
struct lockd_net *ln = net_generic(net, lockd_net_id);
93+
94+
spin_lock(&ln->nsm_clnt_lock);
95+
if (ln->nsm_users) {
96+
ln->nsm_users++;
97+
clnt = ln->nsm_clnt;
98+
spin_unlock(&ln->nsm_clnt_lock);
99+
goto out;
100+
}
101+
spin_unlock(&ln->nsm_clnt_lock);
102+
103+
mutex_lock(&nsm_create_mutex);
104+
clnt = nsm_create(net);
105+
if (!IS_ERR(clnt)) {
106+
ln->nsm_clnt = clnt;
107+
smp_wmb();
108+
ln->nsm_users = 1;
109+
}
110+
mutex_unlock(&nsm_create_mutex);
111+
out:
112+
return clnt;
113+
}
114+
115+
static void nsm_client_put(struct net *net)
116+
{
117+
struct lockd_net *ln = net_generic(net, lockd_net_id);
118+
struct rpc_clnt *clnt = ln->nsm_clnt;
119+
int shutdown = 0;
120+
121+
spin_lock(&ln->nsm_clnt_lock);
122+
if (ln->nsm_users) {
123+
if (--ln->nsm_users)
124+
ln->nsm_clnt = NULL;
125+
shutdown = !ln->nsm_users;
126+
}
127+
spin_unlock(&ln->nsm_clnt_lock);
128+
129+
if (shutdown)
130+
rpc_shutdown_client(clnt);
131+
}
132+
133+
static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
134+
struct rpc_clnt *clnt)
135+
{
90136
int status;
91137
struct nsm_args args = {
92138
.priv = &nsm->sm_priv,
93139
.prog = NLM_PROGRAM,
94140
.vers = 3,
95141
.proc = NLMPROC_NSM_NOTIFY,
96142
.mon_name = nsm->sm_mon_name,
143+
.nodename = clnt->cl_nodename,
97144
};
98145
struct rpc_message msg = {
99146
.rpc_argp = &args,
100147
.rpc_resp = res,
101148
};
102149

103-
clnt = nsm_create(net);
104-
if (IS_ERR(clnt)) {
105-
status = PTR_ERR(clnt);
106-
dprintk("lockd: failed to create NSM upcall transport, "
107-
"status=%d\n", status);
108-
goto out;
109-
}
150+
BUG_ON(clnt == NULL);
110151

111152
memset(res, 0, sizeof(*res));
112153

113154
msg.rpc_proc = &clnt->cl_procinfo[proc];
114-
status = rpc_call_sync(clnt, &msg, 0);
155+
status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
115156
if (status < 0)
116157
dprintk("lockd: NSM upcall RPC failed, status=%d\n",
117158
status);
118159
else
119160
status = 0;
120-
rpc_shutdown_client(clnt);
121-
out:
122161
return status;
123162
}
124163

@@ -138,6 +177,7 @@ int nsm_monitor(const struct nlm_host *host)
138177
struct nsm_handle *nsm = host->h_nsmhandle;
139178
struct nsm_res res;
140179
int status;
180+
struct rpc_clnt *clnt;
141181

142182
dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
143183

@@ -150,7 +190,15 @@ int nsm_monitor(const struct nlm_host *host)
150190
*/
151191
nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
152192

153-
status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host->net);
193+
clnt = nsm_client_get(host->net);
194+
if (IS_ERR(clnt)) {
195+
status = PTR_ERR(clnt);
196+
dprintk("lockd: failed to create NSM upcall transport, "
197+
"status=%d, net=%p\n", status, host->net);
198+
return status;
199+
}
200+
201+
status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, clnt);
154202
if (unlikely(res.status != 0))
155203
status = -EIO;
156204
if (unlikely(status < 0)) {
@@ -182,16 +230,20 @@ void nsm_unmonitor(const struct nlm_host *host)
182230

183231
if (atomic_read(&nsm->sm_count) == 1
184232
&& nsm->sm_monitored && !nsm->sm_sticky) {
233+
struct lockd_net *ln = net_generic(host->net, lockd_net_id);
234+
185235
dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
186236

187-
status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host->net);
237+
status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt);
188238
if (res.status != 0)
189239
status = -EIO;
190240
if (status < 0)
191241
printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
192242
nsm->sm_name);
193243
else
194244
nsm->sm_monitored = 0;
245+
246+
nsm_client_put(host->net);
195247
}
196248
}
197249

@@ -430,7 +482,7 @@ static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
430482
{
431483
__be32 *p;
432484

433-
encode_nsm_string(xdr, utsname()->nodename);
485+
encode_nsm_string(xdr, argp->nodename);
434486
p = xdr_reserve_space(xdr, 4 + 4 + 4);
435487
*p++ = cpu_to_be32(argp->prog);
436488
*p++ = cpu_to_be32(argp->vers);

fs/lockd/netns.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ struct lockd_net {
1212
struct delayed_work grace_period_end;
1313
struct lock_manager lockd_manager;
1414
struct list_head grace_list;
15+
16+
spinlock_t nsm_clnt_lock;
17+
unsigned int nsm_users;
18+
struct rpc_clnt *nsm_clnt;
1519
};
1620

1721
extern int lockd_net_id;

fs/lockd/svc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ static int lockd_init_net(struct net *net)
596596

597597
INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
598598
INIT_LIST_HEAD(&ln->grace_list);
599+
spin_lock_init(&ln->nsm_clnt_lock);
599600
return 0;
600601
}
601602

fs/nfs/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ config NFS_SWAP
9595
This option enables swapon to work on files located on NFS mounts.
9696

9797
config NFS_V4_1
98-
bool "NFS client support for NFSv4.1 (EXPERIMENTAL)"
99-
depends on NFS_V4 && EXPERIMENTAL
98+
bool "NFS client support for NFSv4.1"
99+
depends on NFS_V4
100100
select SUNRPC_BACKCHANNEL
101101
help
102102
This option enables support for minor version 1 of the NFSv4 protocol

0 commit comments

Comments
 (0)