Skip to content

Commit 9cab1ba

Browse files
committed
Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: nfs: don't lose MS_SYNCHRONOUS on remount of noac mount NFS: Return meaningful status from decode_secinfo() NFSv4: Ensure we request the ordinary fileid when doing readdirplus NFSv4: Ensure that clientid and session establishment can time out SUNRPC: Allow RPC calls to return ETIMEDOUT instead of EIO NFSv4.1: Don't loop forever in nfs4_proc_create_session NFSv4: Handle NFS4ERR_WRONGSEC outside of nfs4_handle_exception() NFSv4.1: Don't update sequence number if rpc_task is not sent NFSv4.1: Ensure state manager thread dies on last umount SUNRPC: Fix the SUNRPC Kerberos V RPCSEC_GSS module dependencies NFS: Use correct variable for page bounds checking NFS: don't negotiate when user specifies sec flavor NFS: Attempt mount with default sec flavor first NFS: flav_array honors NFS_MAX_SECFLAVORS NFS: Fix infinite loop in gss_create_upcall() Don't mark_inode_dirty_sync() while holding lock NFS: Get rid of pointless test in nfs_commit_done NFS: Remove unused argument from nfs_find_best_sec() NFS: Eliminate duplicate call to nfs_mark_request_dirty NFS: Remove dead code from nfs_fs_mount()
2 parents cc03638 + 26c4c17 commit 9cab1ba

File tree

15 files changed

+163
-120
lines changed

15 files changed

+163
-120
lines changed

fs/nfs/namespace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
119119
}
120120

121121
#ifdef CONFIG_NFS_V4
122-
static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, struct inode *inode)
122+
static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
123123
{
124124
struct gss_api_mech *mech;
125125
struct xdr_netobj oid;
@@ -166,7 +166,7 @@ static int nfs_negotiate_security(const struct dentry *parent,
166166
}
167167
flavors = page_address(page);
168168
ret = secinfo(parent->d_inode, &dentry->d_name, flavors);
169-
*flavor = nfs_find_best_sec(flavors, dentry->d_inode);
169+
*flavor = nfs_find_best_sec(flavors);
170170
put_page(page);
171171
}
172172

fs/nfs/nfs4_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ enum nfs4_client_state {
4747
NFS4CLNT_LAYOUTRECALL,
4848
NFS4CLNT_SESSION_RESET,
4949
NFS4CLNT_RECALL_SLOT,
50+
NFS4CLNT_LEASE_CONFIRM,
5051
};
5152

5253
enum nfs4_session_state {

fs/nfs/nfs4proc.c

Lines changed: 58 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include <linux/nfs4.h>
4747
#include <linux/nfs_fs.h>
4848
#include <linux/nfs_page.h>
49+
#include <linux/nfs_mount.h>
4950
#include <linux/namei.h>
5051
#include <linux/mount.h>
5152
#include <linux/module.h>
@@ -443,8 +444,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
443444
if (res->sr_status == 1)
444445
res->sr_status = NFS_OK;
445446

446-
/* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
447-
if (!res->sr_slot)
447+
/* don't increment the sequence number if the task wasn't sent */
448+
if (!RPC_WAS_SENT(task))
448449
goto out;
449450

450451
/* Check the SEQUENCE operation status */
@@ -2185,9 +2186,14 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
21852186
struct nfs4_exception exception = { };
21862187
int err;
21872188
do {
2188-
err = nfs4_handle_exception(server,
2189-
_nfs4_lookup_root(server, fhandle, info),
2190-
&exception);
2189+
err = _nfs4_lookup_root(server, fhandle, info);
2190+
switch (err) {
2191+
case 0:
2192+
case -NFS4ERR_WRONGSEC:
2193+
break;
2194+
default:
2195+
err = nfs4_handle_exception(server, err, &exception);
2196+
}
21912197
} while (exception.retry);
21922198
return err;
21932199
}
@@ -2208,25 +2214,47 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl
22082214
return ret;
22092215
}
22102216

2211-
/*
2212-
* get the file handle for the "/" directory on the server
2213-
*/
2214-
static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
2217+
static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
22152218
struct nfs_fsinfo *info)
22162219
{
22172220
int i, len, status = 0;
2218-
rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2];
2221+
rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
22192222

2220-
flav_array[0] = RPC_AUTH_UNIX;
2221-
len = gss_mech_list_pseudoflavors(&flav_array[1]);
2222-
flav_array[1+len] = RPC_AUTH_NULL;
2223-
len += 2;
2223+
len = gss_mech_list_pseudoflavors(&flav_array[0]);
2224+
flav_array[len] = RPC_AUTH_NULL;
2225+
len += 1;
22242226

22252227
for (i = 0; i < len; i++) {
22262228
status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
2227-
if (status != -EPERM)
2228-
break;
2229+
if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
2230+
continue;
2231+
break;
22292232
}
2233+
/*
2234+
* -EACCESS could mean that the user doesn't have correct permissions
2235+
* to access the mount. It could also mean that we tried to mount
2236+
* with a gss auth flavor, but rpc.gssd isn't running. Either way,
2237+
* existing mount programs don't handle -EACCES very well so it should
2238+
* be mapped to -EPERM instead.
2239+
*/
2240+
if (status == -EACCES)
2241+
status = -EPERM;
2242+
return status;
2243+
}
2244+
2245+
/*
2246+
* get the file handle for the "/" directory on the server
2247+
*/
2248+
static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
2249+
struct nfs_fsinfo *info)
2250+
{
2251+
int status = nfs4_lookup_root(server, fhandle, info);
2252+
if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
2253+
/*
2254+
* A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
2255+
* by nfs4_map_errors() as this function exits.
2256+
*/
2257+
status = nfs4_find_root_sec(server, fhandle, info);
22302258
if (status == 0)
22312259
status = nfs4_server_capabilities(server, fhandle);
22322260
if (status == 0)
@@ -3723,21 +3751,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
37233751
sizeof(setclientid.sc_uaddr), "%s.%u.%u",
37243752
clp->cl_ipaddr, port >> 8, port & 255);
37253753

3726-
status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
3754+
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
37273755
if (status != -NFS4ERR_CLID_INUSE)
37283756
break;
3729-
if (signalled())
3757+
if (loop != 0) {
3758+
++clp->cl_id_uniquifier;
37303759
break;
3731-
if (loop++ & 1)
3732-
ssleep(clp->cl_lease_time / HZ + 1);
3733-
else
3734-
if (++clp->cl_id_uniquifier == 0)
3735-
break;
3760+
}
3761+
++loop;
3762+
ssleep(clp->cl_lease_time / HZ + 1);
37363763
}
37373764
return status;
37383765
}
37393766

3740-
static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
3767+
int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
37413768
struct nfs4_setclientid_res *arg,
37423769
struct rpc_cred *cred)
37433770
{
@@ -3752,7 +3779,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
37523779
int status;
37533780

37543781
now = jiffies;
3755-
status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
3782+
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
37563783
if (status == 0) {
37573784
spin_lock(&clp->cl_lock);
37583785
clp->cl_lease_time = fsinfo.lease_time * HZ;
@@ -3762,26 +3789,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
37623789
return status;
37633790
}
37643791

3765-
int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
3766-
struct nfs4_setclientid_res *arg,
3767-
struct rpc_cred *cred)
3768-
{
3769-
long timeout = 0;
3770-
int err;
3771-
do {
3772-
err = _nfs4_proc_setclientid_confirm(clp, arg, cred);
3773-
switch (err) {
3774-
case 0:
3775-
return err;
3776-
case -NFS4ERR_RESOURCE:
3777-
/* The IBM lawyers misread another document! */
3778-
case -NFS4ERR_DELAY:
3779-
err = nfs4_delay(clp->cl_rpcclient, &timeout);
3780-
}
3781-
} while (err == 0);
3782-
return err;
3783-
}
3784-
37853792
struct nfs4_delegreturndata {
37863793
struct nfs4_delegreturnargs args;
37873794
struct nfs4_delegreturnres res;
@@ -4786,7 +4793,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
47864793
init_utsname()->domainname,
47874794
clp->cl_rpcclient->cl_auth->au_flavor);
47884795

4789-
status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
4796+
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
47904797
if (!status)
47914798
status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
47924799
dprintk("<-- %s status= %d\n", __func__, status);
@@ -4869,7 +4876,8 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
48694876
.rpc_client = clp->cl_rpcclient,
48704877
.rpc_message = &msg,
48714878
.callback_ops = &nfs4_get_lease_time_ops,
4872-
.callback_data = &data
4879+
.callback_data = &data,
4880+
.flags = RPC_TASK_TIMEOUT,
48734881
};
48744882
int status;
48754883

@@ -5171,7 +5179,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp)
51715179
nfs4_init_channel_attrs(&args);
51725180
args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
51735181

5174-
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
5182+
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
51755183

51765184
if (!status)
51775185
/* Verify the session's negotiated channel_attrs values */
@@ -5194,20 +5202,10 @@ int nfs4_proc_create_session(struct nfs_client *clp)
51945202
int status;
51955203
unsigned *ptr;
51965204
struct nfs4_session *session = clp->cl_session;
5197-
long timeout = 0;
5198-
int err;
51995205

52005206
dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
52015207

5202-
do {
5203-
status = _nfs4_proc_create_session(clp);
5204-
if (status == -NFS4ERR_DELAY) {
5205-
err = nfs4_delay(clp->cl_rpcclient, &timeout);
5206-
if (err)
5207-
status = err;
5208-
}
5209-
} while (status == -NFS4ERR_DELAY);
5210-
5208+
status = _nfs4_proc_create_session(clp);
52115209
if (status)
52125210
goto out;
52135211

@@ -5248,7 +5246,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
52485246
msg.rpc_argp = session;
52495247
msg.rpc_resp = NULL;
52505248
msg.rpc_cred = NULL;
5251-
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
5249+
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
52525250

52535251
if (status)
52545252
printk(KERN_WARNING

fs/nfs/nfs4state.c

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,30 @@ static LIST_HEAD(nfs4_clientid_list);
6464

6565
int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
6666
{
67-
struct nfs4_setclientid_res clid;
67+
struct nfs4_setclientid_res clid = {
68+
.clientid = clp->cl_clientid,
69+
.confirm = clp->cl_confirm,
70+
};
6871
unsigned short port;
6972
int status;
7073

74+
if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
75+
goto do_confirm;
7176
port = nfs_callback_tcpport;
7277
if (clp->cl_addr.ss_family == AF_INET6)
7378
port = nfs_callback_tcpport6;
7479

7580
status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid);
7681
if (status != 0)
7782
goto out;
83+
clp->cl_clientid = clid.clientid;
84+
clp->cl_confirm = clid.confirm;
85+
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
86+
do_confirm:
7887
status = nfs4_proc_setclientid_confirm(clp, &clid, cred);
7988
if (status != 0)
8089
goto out;
81-
clp->cl_clientid = clid.clientid;
90+
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
8291
nfs4_schedule_state_renewal(clp);
8392
out:
8493
return status;
@@ -230,13 +239,18 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
230239
{
231240
int status;
232241

242+
if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
243+
goto do_confirm;
233244
nfs4_begin_drain_session(clp);
234245
status = nfs4_proc_exchange_id(clp, cred);
235246
if (status != 0)
236247
goto out;
248+
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
249+
do_confirm:
237250
status = nfs4_proc_create_session(clp);
238251
if (status != 0)
239252
goto out;
253+
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
240254
nfs41_setup_state_renewal(clp);
241255
nfs_mark_client_ready(clp, NFS_CS_READY);
242256
out:
@@ -1584,20 +1598,23 @@ static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
15841598
*/
15851599
static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
15861600
{
1587-
if (nfs4_has_session(clp)) {
1588-
switch (status) {
1589-
case -NFS4ERR_DELAY:
1590-
case -NFS4ERR_CLID_INUSE:
1591-
case -EAGAIN:
1592-
break;
1601+
switch (status) {
1602+
case -NFS4ERR_CLID_INUSE:
1603+
case -NFS4ERR_STALE_CLIENTID:
1604+
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
1605+
break;
1606+
case -NFS4ERR_DELAY:
1607+
case -ETIMEDOUT:
1608+
case -EAGAIN:
1609+
ssleep(1);
1610+
break;
15931611

1594-
case -EKEYEXPIRED:
1595-
nfs4_warn_keyexpired(clp->cl_hostname);
1596-
case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
1597-
* in nfs4_exchange_id */
1598-
default:
1599-
return;
1600-
}
1612+
case -EKEYEXPIRED:
1613+
nfs4_warn_keyexpired(clp->cl_hostname);
1614+
case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
1615+
* in nfs4_exchange_id */
1616+
default:
1617+
return;
16011618
}
16021619
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
16031620
}
@@ -1607,7 +1624,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
16071624
int status = 0;
16081625

16091626
/* Ensure exclusive access to NFSv4 state */
1610-
for(;;) {
1627+
do {
16111628
if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
16121629
/* We're going to have to re-establish a clientid */
16131630
status = nfs4_reclaim_lease(clp);
@@ -1691,7 +1708,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
16911708
break;
16921709
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
16931710
break;
1694-
}
1711+
} while (atomic_read(&clp->cl_count) > 1);
16951712
return;
16961713
out_error:
16971714
printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"

0 commit comments

Comments
 (0)