forked from Minki/linux
Merge branch 'for-3.14' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields: - Handle some loose ends from the vfs read delegation support. (For example nfsd can stop breaking leases on its own in a fewer places where it can now depend on the vfs to.) - Make life a little easier for NFSv4-only configurations (thanks to Kinglong Mee). - Fix some gss-proxy problems (thanks Jeff Layton). - miscellaneous bug fixes and cleanup * 'for-3.14' of git://linux-nfs.org/~bfields/linux: (38 commits) nfsd: consider CLAIM_FH when handing out delegation nfsd4: fix delegation-unlink/rename race nfsd4: delay setting current_fh in open nfsd4: minor nfs4_setlease cleanup gss_krb5: use lcm from kernel lib nfsd4: decrease nfsd4_encode_fattr stack usage nfsd: fix encode_entryplus_baggage stack usage nfsd4: simplify xdr encoding of nfsv4 names nfsd4: encode_rdattr_error cleanup nfsd4: nfsd4_encode_fattr cleanup minor svcauth_gss.c cleanup nfsd4: better VERIFY comment nfsd4: break only delegations when appropriate NFSD: Fix a memory leak in nfsd4_create_session sunrpc: get rid of use_gssp_lock sunrpc: fix potential race between setting use_gss_proxy and the upcall rpc_clnt sunrpc: don't wait for write before allowing reads from use-gss-proxy file nfsd: get rid of unused function definition Define op_iattr for nfsd4_open instead using macro NFSD: fix compile warning without CONFIG_NFSD_V3 ...
This commit is contained in:
commit
d9894c228b
@ -5,11 +5,11 @@ Server support for minorversion 1 can be controlled using the
|
||||
by reading this file will contain either "+4.1" or "-4.1"
|
||||
correspondingly.
|
||||
|
||||
Currently, server support for minorversion 1 is disabled by default.
|
||||
It can be enabled at run time by writing the string "+4.1" to
|
||||
Currently, server support for minorversion 1 is enabled by default.
|
||||
It can be disabled at run time by writing the string "-4.1" to
|
||||
the /proc/fs/nfsd/versions control file. Note that to write this
|
||||
control file, the nfsd service must be taken down. Use your user-mode
|
||||
nfs-utils to set this up; see rpc.nfsd(8)
|
||||
control file, the nfsd service must be taken down. You can use rpc.nfsd
|
||||
for this; see rpc.nfsd(8).
|
||||
|
||||
(Warning: older servers will interpret "+4.1" and "-4.1" as "+4" and
|
||||
"-4", respectively. Therefore, code meant to work on both new and old
|
||||
@ -29,29 +29,6 @@ are still under development out of tree.
|
||||
See http://wiki.linux-nfs.org/wiki/index.php/PNFS_prototype_design
|
||||
for more information.
|
||||
|
||||
The current implementation is intended for developers only: while it
|
||||
does support ordinary file operations on clients we have tested against
|
||||
(including the linux client), it is incomplete in ways which may limit
|
||||
features unexpectedly, cause known bugs in rare cases, or cause
|
||||
interoperability problems with future clients. Known issues:
|
||||
|
||||
- gss support is questionable: currently mounts with kerberos
|
||||
from a linux client are possible, but we aren't really
|
||||
conformant with the spec (for example, we don't use kerberos
|
||||
on the backchannel correctly).
|
||||
- We do not support SSV, which provides security for shared
|
||||
client-server state (thus preventing unauthorized tampering
|
||||
with locks and opens, for example). It is mandatory for
|
||||
servers to support this, though no clients use it yet.
|
||||
|
||||
In addition, some limitations are inherited from the current NFSv4
|
||||
implementation:
|
||||
|
||||
- Incomplete delegation enforcement: if a file is renamed or
|
||||
unlinked by a local process, a client holding a delegation may
|
||||
continue to indefinitely allow opens of the file under the old
|
||||
name.
|
||||
|
||||
The table below, taken from the NFSv4.1 document, lists
|
||||
the operations that are mandatory to implement (REQ), optional
|
||||
(OPT), and NFSv4.0 operations that are required not to implement (MNI)
|
||||
@ -169,6 +146,16 @@ NS*| CB_WANTS_CANCELLED | OPT | FDELG, | Section 20.10 |
|
||||
|
||||
Implementation notes:
|
||||
|
||||
SSV:
|
||||
* The spec claims this is mandatory, but we don't actually know of any
|
||||
implementations, so we're ignoring it for now. The server returns
|
||||
NFS4ERR_ENCR_ALG_UNSUPP on EXCHANGE_ID, which should be future-proof.
|
||||
|
||||
GSS on the backchannel:
|
||||
* Again, theoretically required but not widely implemented (in
|
||||
particular, the current Linux client doesn't request it). We return
|
||||
NFS4ERR_ENCR_ALG_UNSUPP on CREATE_SESSION.
|
||||
|
||||
DELEGPURGE:
|
||||
* mandatory only for servers that support CLAIM_DELEGATE_PREV and/or
|
||||
CLAIM_DELEG_PREV_FH (which allows clients to keep delegations that
|
||||
@ -176,7 +163,6 @@ DELEGPURGE:
|
||||
now.
|
||||
|
||||
EXCHANGE_ID:
|
||||
* only SP4_NONE state protection supported
|
||||
* implementation ids are ignored
|
||||
|
||||
CREATE_SESSION:
|
||||
|
@ -45,7 +45,7 @@ struct svc_rqst;
|
||||
|
||||
struct nfs4_acl *nfs4_acl_new(int);
|
||||
int nfs4_acl_get_whotype(char *, u32);
|
||||
int nfs4_acl_write_who(int who, char *p);
|
||||
__be32 nfs4_acl_write_who(int who, __be32 **p, int *len);
|
||||
|
||||
int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
|
||||
struct nfs4_acl **acl);
|
||||
|
@ -84,12 +84,4 @@ int nfsd_cache_lookup(struct svc_rqst *);
|
||||
void nfsd_cache_update(struct svc_rqst *, int, __be32 *);
|
||||
int nfsd_reply_cache_stats_open(struct inode *, struct file *);
|
||||
|
||||
#ifdef CONFIG_NFSD_V4
|
||||
void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp);
|
||||
#else /* CONFIG_NFSD_V4 */
|
||||
static inline void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_NFSD_V4 */
|
||||
|
||||
#endif /* NFSCACHE_H */
|
||||
|
@ -56,7 +56,7 @@ static inline void nfsd_idmap_shutdown(struct net *net)
|
||||
|
||||
__be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, kuid_t *);
|
||||
__be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, kgid_t *);
|
||||
int nfsd_map_uid_to_name(struct svc_rqst *, kuid_t, char *);
|
||||
int nfsd_map_gid_to_name(struct svc_rqst *, kgid_t, char *);
|
||||
__be32 nfsd4_encode_user(struct svc_rqst *, kuid_t, __be32 **, int *);
|
||||
__be32 nfsd4_encode_group(struct svc_rqst *, kgid_t, __be32 **, int *);
|
||||
|
||||
#endif /* LINUX_NFSD_IDMAP_H */
|
||||
|
@ -95,6 +95,7 @@ struct nfsd_net {
|
||||
time_t nfsd4_grace;
|
||||
|
||||
bool nfsd_net_up;
|
||||
bool lockd_up;
|
||||
|
||||
/*
|
||||
* Time of server startup
|
||||
|
@ -168,7 +168,7 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
|
||||
struct kstat *stat)
|
||||
{
|
||||
*p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
|
||||
*p++ = htonl((u32) stat->mode);
|
||||
*p++ = htonl((u32) (stat->mode & S_IALLUGO));
|
||||
*p++ = htonl((u32) stat->nlink);
|
||||
*p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
|
||||
*p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
|
||||
@ -842,21 +842,21 @@ out:
|
||||
|
||||
static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen)
|
||||
{
|
||||
struct svc_fh fh;
|
||||
struct svc_fh *fh = &cd->scratch;
|
||||
__be32 err;
|
||||
|
||||
fh_init(&fh, NFS3_FHSIZE);
|
||||
err = compose_entry_fh(cd, &fh, name, namlen);
|
||||
fh_init(fh, NFS3_FHSIZE);
|
||||
err = compose_entry_fh(cd, fh, name, namlen);
|
||||
if (err) {
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
goto out;
|
||||
}
|
||||
p = encode_post_op_attr(cd->rqstp, p, &fh);
|
||||
p = encode_post_op_attr(cd->rqstp, p, fh);
|
||||
*p++ = xdr_one; /* yes, a file handle follows */
|
||||
p = encode_fh(p, &fh);
|
||||
p = encode_fh(p, fh);
|
||||
out:
|
||||
fh_put(&fh);
|
||||
fh_put(fh);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <linux/export.h>
|
||||
#include "nfsfh.h"
|
||||
#include "nfsd.h"
|
||||
#include "acl.h"
|
||||
#include "vfs.h"
|
||||
|
||||
@ -916,17 +917,22 @@ nfs4_acl_get_whotype(char *p, u32 len)
|
||||
return NFS4_ACL_WHO_NAMED;
|
||||
}
|
||||
|
||||
int
|
||||
nfs4_acl_write_who(int who, char *p)
|
||||
__be32 nfs4_acl_write_who(int who, __be32 **p, int *len)
|
||||
{
|
||||
int i;
|
||||
int bytes;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
|
||||
if (s2t_map[i].type == who) {
|
||||
memcpy(p, s2t_map[i].string, s2t_map[i].stringlen);
|
||||
return s2t_map[i].stringlen;
|
||||
}
|
||||
if (s2t_map[i].type != who)
|
||||
continue;
|
||||
bytes = 4 + (XDR_QUADLEN(s2t_map[i].stringlen) << 2);
|
||||
if (bytes > *len)
|
||||
return nfserr_resource;
|
||||
*p = xdr_encode_opaque(*p, s2t_map[i].string,
|
||||
s2t_map[i].stringlen);
|
||||
*len -= bytes;
|
||||
return 0;
|
||||
}
|
||||
BUG();
|
||||
WARN_ON_ONCE(1);
|
||||
return -1;
|
||||
}
|
||||
|
@ -551,27 +551,46 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name)
|
||||
static __be32 encode_ascii_id(u32 id, __be32 **p, int *buflen)
|
||||
{
|
||||
char buf[11];
|
||||
int len;
|
||||
int bytes;
|
||||
|
||||
len = sprintf(buf, "%u", id);
|
||||
bytes = 4 + (XDR_QUADLEN(len) << 2);
|
||||
if (bytes > *buflen)
|
||||
return nfserr_resource;
|
||||
*p = xdr_encode_opaque(*p, buf, len);
|
||||
*buflen -= bytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __be32 idmap_id_to_name(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen)
|
||||
{
|
||||
struct ent *item, key = {
|
||||
.id = id,
|
||||
.type = type,
|
||||
};
|
||||
int ret;
|
||||
int bytes;
|
||||
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||
|
||||
strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
|
||||
ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
|
||||
if (ret == -ENOENT)
|
||||
return sprintf(name, "%u", id);
|
||||
return encode_ascii_id(id, p, buflen);
|
||||
if (ret)
|
||||
return ret;
|
||||
return nfserrno(ret);
|
||||
ret = strlen(item->name);
|
||||
BUG_ON(ret > IDMAP_NAMESZ);
|
||||
memcpy(name, item->name, ret);
|
||||
WARN_ON_ONCE(ret > IDMAP_NAMESZ);
|
||||
bytes = 4 + (XDR_QUADLEN(ret) << 2);
|
||||
if (bytes > *buflen)
|
||||
return nfserr_resource;
|
||||
*p = xdr_encode_opaque(*p, item->name, ret);
|
||||
*buflen -= bytes;
|
||||
cache_put(&item->h, nn->idtoname_cache);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -603,12 +622,11 @@ do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, u
|
||||
return idmap_name_to_id(rqstp, type, name, namelen, id);
|
||||
}
|
||||
|
||||
static int
|
||||
do_id_to_name(struct svc_rqst *rqstp, int type, u32 id, char *name)
|
||||
static __be32 encode_name_from_id(struct svc_rqst *rqstp, int type, u32 id, __be32 **p, int *buflen)
|
||||
{
|
||||
if (nfs4_disable_idmapping && rqstp->rq_cred.cr_flavor < RPC_AUTH_GSS)
|
||||
return sprintf(name, "%u", id);
|
||||
return idmap_id_to_name(rqstp, type, id, name);
|
||||
return encode_ascii_id(id, p, buflen);
|
||||
return idmap_id_to_name(rqstp, type, id, p, buflen);
|
||||
}
|
||||
|
||||
__be32
|
||||
@ -637,16 +655,14 @@ nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
nfsd_map_uid_to_name(struct svc_rqst *rqstp, kuid_t uid, char *name)
|
||||
__be32 nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t uid, __be32 **p, int *buflen)
|
||||
{
|
||||
u32 id = from_kuid(&init_user_ns, uid);
|
||||
return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
|
||||
return encode_name_from_id(rqstp, IDMAP_TYPE_USER, id, p, buflen);
|
||||
}
|
||||
|
||||
int
|
||||
nfsd_map_gid_to_name(struct svc_rqst *rqstp, kgid_t gid, char *name)
|
||||
__be32 nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t gid, __be32 **p, int *buflen)
|
||||
{
|
||||
u32 id = from_kgid(&init_user_ns, gid);
|
||||
return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
|
||||
return encode_name_from_id(rqstp, IDMAP_TYPE_GROUP, id, p, buflen);
|
||||
}
|
||||
|
@ -231,17 +231,16 @@ static void nfsd4_set_open_owner_reply_cache(struct nfsd4_compound_state *cstate
|
||||
}
|
||||
|
||||
static __be32
|
||||
do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
|
||||
do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh **resfh)
|
||||
{
|
||||
struct svc_fh *current_fh = &cstate->current_fh;
|
||||
struct svc_fh *resfh;
|
||||
int accmode;
|
||||
__be32 status;
|
||||
|
||||
resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
|
||||
if (!resfh)
|
||||
*resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
|
||||
if (!*resfh)
|
||||
return nfserr_jukebox;
|
||||
fh_init(resfh, NFS4_FHSIZE);
|
||||
fh_init(*resfh, NFS4_FHSIZE);
|
||||
open->op_truncate = 0;
|
||||
|
||||
if (open->op_create) {
|
||||
@ -266,12 +265,12 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
|
||||
*/
|
||||
status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
|
||||
open->op_fname.len, &open->op_iattr,
|
||||
resfh, open->op_createmode,
|
||||
*resfh, open->op_createmode,
|
||||
(u32 *)open->op_verf.data,
|
||||
&open->op_truncate, &open->op_created);
|
||||
|
||||
if (!status && open->op_label.len)
|
||||
nfsd4_security_inode_setsecctx(resfh, &open->op_label, open->op_bmval);
|
||||
nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval);
|
||||
|
||||
/*
|
||||
* Following rfc 3530 14.2.16, use the returned bitmask
|
||||
@ -281,31 +280,32 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
|
||||
if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
|
||||
open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS |
|
||||
FATTR4_WORD1_TIME_MODIFY);
|
||||
} else {
|
||||
} else
|
||||
/*
|
||||
* Note this may exit with the parent still locked.
|
||||
* We will hold the lock until nfsd4_open's final
|
||||
* lookup, to prevent renames or unlinks until we've had
|
||||
* a chance to an acquire a delegation if appropriate.
|
||||
*/
|
||||
status = nfsd_lookup(rqstp, current_fh,
|
||||
open->op_fname.data, open->op_fname.len, resfh);
|
||||
fh_unlock(current_fh);
|
||||
}
|
||||
open->op_fname.data, open->op_fname.len, *resfh);
|
||||
if (status)
|
||||
goto out;
|
||||
status = nfsd_check_obj_isreg(resfh);
|
||||
status = nfsd_check_obj_isreg(*resfh);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
if (is_create_with_attrs(open) && open->op_acl != NULL)
|
||||
do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval);
|
||||
do_set_nfs4_acl(rqstp, *resfh, open->op_acl, open->op_bmval);
|
||||
|
||||
nfsd4_set_open_owner_reply_cache(cstate, open, resfh);
|
||||
nfsd4_set_open_owner_reply_cache(cstate, open, *resfh);
|
||||
accmode = NFSD_MAY_NOP;
|
||||
if (open->op_created ||
|
||||
open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
|
||||
accmode |= NFSD_MAY_OWNER_OVERRIDE;
|
||||
status = do_open_permission(rqstp, resfh, open, accmode);
|
||||
status = do_open_permission(rqstp, *resfh, open, accmode);
|
||||
set_change_info(&open->op_cinfo, current_fh);
|
||||
fh_dup2(current_fh, resfh);
|
||||
out:
|
||||
fh_put(resfh);
|
||||
kfree(resfh);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -358,6 +358,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
struct nfsd4_open *open)
|
||||
{
|
||||
__be32 status;
|
||||
struct svc_fh *resfh = NULL;
|
||||
struct nfsd4_compoundres *resp;
|
||||
struct net *net = SVC_NET(rqstp);
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
@ -424,7 +425,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
switch (open->op_claim_type) {
|
||||
case NFS4_OPEN_CLAIM_DELEGATE_CUR:
|
||||
case NFS4_OPEN_CLAIM_NULL:
|
||||
status = do_open_lookup(rqstp, cstate, open);
|
||||
status = do_open_lookup(rqstp, cstate, open, &resfh);
|
||||
if (status)
|
||||
goto out;
|
||||
break;
|
||||
@ -440,6 +441,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
status = do_open_fhandle(rqstp, cstate, open);
|
||||
if (status)
|
||||
goto out;
|
||||
resfh = &cstate->current_fh;
|
||||
break;
|
||||
case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
|
||||
case NFS4_OPEN_CLAIM_DELEGATE_PREV:
|
||||
@ -459,9 +461,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
* successful, it (1) truncates the file if open->op_truncate was
|
||||
* set, (2) sets open->op_stateid, (3) sets open->op_delegation.
|
||||
*/
|
||||
status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
|
||||
status = nfsd4_process_open2(rqstp, resfh, open);
|
||||
WARN_ON(status && open->op_created);
|
||||
out:
|
||||
if (resfh && resfh != &cstate->current_fh) {
|
||||
fh_dup2(&cstate->current_fh, resfh);
|
||||
fh_put(resfh);
|
||||
kfree(resfh);
|
||||
}
|
||||
nfsd4_cleanup_open_state(open, status);
|
||||
if (open->op_openowner && !nfsd4_has_session(cstate))
|
||||
cstate->replay_owner = &open->op_openowner->oo_owner;
|
||||
@ -1070,8 +1077,10 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
cstate->current_fh.fh_dentry, &p,
|
||||
count, verify->ve_bmval,
|
||||
rqstp, 0);
|
||||
|
||||
/* this means that nfsd4_encode_fattr() ran out of space */
|
||||
/*
|
||||
* If nfsd4_encode_fattr() ran out of space, assume that's because
|
||||
* the attributes are longer (hence different) than those given:
|
||||
*/
|
||||
if (status == nfserr_resource)
|
||||
status = nfserr_not_same;
|
||||
if (status)
|
||||
@ -1525,7 +1534,8 @@ static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
|
||||
static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
|
||||
{
|
||||
return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\
|
||||
1 + 1 + 2 + /* eir_flags, spr_how, spo_must_enforce & _allow */\
|
||||
1 + 1 + /* eir_flags, spr_how */\
|
||||
4 + /* spo_must_enforce & _allow with bitmap */\
|
||||
2 + /*eir_server_owner.so_minor_id */\
|
||||
/* eir_server_owner.so_major_id<> */\
|
||||
XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\
|
||||
@ -1882,6 +1892,7 @@ struct svc_version nfsd_version4 = {
|
||||
.vs_proc = nfsd_procedures4,
|
||||
.vs_dispatch = nfsd_dispatch,
|
||||
.vs_xdrsize = NFS4_SVC_XDRSIZE,
|
||||
.vs_rpcb_optnl = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -832,10 +832,11 @@ static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca)
|
||||
spin_unlock(&nfsd_drc_lock);
|
||||
}
|
||||
|
||||
static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs)
|
||||
static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs,
|
||||
struct nfsd4_channel_attrs *battrs)
|
||||
{
|
||||
int numslots = attrs->maxreqs;
|
||||
int slotsize = slot_bytes(attrs);
|
||||
int numslots = fattrs->maxreqs;
|
||||
int slotsize = slot_bytes(fattrs);
|
||||
struct nfsd4_session *new;
|
||||
int mem, i;
|
||||
|
||||
@ -852,6 +853,10 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs)
|
||||
if (!new->se_slots[i])
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs));
|
||||
memcpy(&new->se_bchannel, battrs, sizeof(struct nfsd4_channel_attrs));
|
||||
|
||||
return new;
|
||||
out_free:
|
||||
while (i--)
|
||||
@ -997,8 +1002,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
|
||||
list_add(&new->se_perclnt, &clp->cl_sessions);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
spin_unlock(&nn->client_lock);
|
||||
memcpy(&new->se_fchannel, &cses->fore_channel,
|
||||
sizeof(struct nfsd4_channel_attrs));
|
||||
|
||||
if (cses->flags & SESSION4_BACK_CHAN) {
|
||||
struct sockaddr *sa = svc_addr(rqstp);
|
||||
/*
|
||||
@ -1851,6 +1855,11 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs
|
||||
return nfs_ok;
|
||||
}
|
||||
|
||||
#define NFSD_CB_MAX_REQ_SZ ((NFS4_enc_cb_recall_sz + \
|
||||
RPC_MAX_HEADER_WITH_AUTH) * sizeof(__be32))
|
||||
#define NFSD_CB_MAX_RESP_SZ ((NFS4_dec_cb_recall_sz + \
|
||||
RPC_MAX_REPHEADER_WITH_AUTH) * sizeof(__be32))
|
||||
|
||||
static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
|
||||
{
|
||||
ca->headerpadsz = 0;
|
||||
@ -1861,9 +1870,9 @@ static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
|
||||
* less than 1k. Tighten up this estimate in the unlikely event
|
||||
* it turns out to be a problem for some client:
|
||||
*/
|
||||
if (ca->maxreq_sz < NFS4_enc_cb_recall_sz + RPC_MAX_HEADER_WITH_AUTH)
|
||||
if (ca->maxreq_sz < NFSD_CB_MAX_REQ_SZ)
|
||||
return nfserr_toosmall;
|
||||
if (ca->maxresp_sz < NFS4_dec_cb_recall_sz + RPC_MAX_REPHEADER_WITH_AUTH)
|
||||
if (ca->maxresp_sz < NFSD_CB_MAX_RESP_SZ)
|
||||
return nfserr_toosmall;
|
||||
ca->maxresp_cached = 0;
|
||||
if (ca->maxops < 2)
|
||||
@ -1913,9 +1922,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
|
||||
return status;
|
||||
status = check_backchannel_attrs(&cr_ses->back_channel);
|
||||
if (status)
|
||||
return status;
|
||||
goto out_release_drc_mem;
|
||||
status = nfserr_jukebox;
|
||||
new = alloc_session(&cr_ses->fore_channel);
|
||||
new = alloc_session(&cr_ses->fore_channel, &cr_ses->back_channel);
|
||||
if (!new)
|
||||
goto out_release_drc_mem;
|
||||
conn = alloc_conn_from_crses(rqstp, cr_ses);
|
||||
@ -3034,18 +3043,18 @@ static int nfs4_setlease(struct nfs4_delegation *dp)
|
||||
if (!fl)
|
||||
return -ENOMEM;
|
||||
fl->fl_file = find_readable_file(fp);
|
||||
list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
|
||||
status = vfs_setlease(fl->fl_file, fl->fl_type, &fl);
|
||||
if (status) {
|
||||
list_del_init(&dp->dl_perclnt);
|
||||
locks_free_lock(fl);
|
||||
return status;
|
||||
}
|
||||
if (status)
|
||||
goto out_free;
|
||||
list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
|
||||
fp->fi_lease = fl;
|
||||
fp->fi_deleg_file = get_file(fl->fl_file);
|
||||
atomic_set(&fp->fi_delegees, 1);
|
||||
list_add(&dp->dl_perfile, &fp->fi_delegations);
|
||||
return 0;
|
||||
out_free:
|
||||
locks_free_lock(fl);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp)
|
||||
@ -3125,6 +3134,7 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
|
||||
goto out_no_deleg;
|
||||
break;
|
||||
case NFS4_OPEN_CLAIM_NULL:
|
||||
case NFS4_OPEN_CLAIM_FH:
|
||||
/*
|
||||
* Let's not give out any delegations till everyone's
|
||||
* had the chance to reclaim theirs....
|
||||
|
@ -103,11 +103,6 @@ xdr_error: \
|
||||
(x) = (u64)ntohl(*p++) << 32; \
|
||||
(x) |= ntohl(*p++); \
|
||||
} while (0)
|
||||
#define READTIME(x) do { \
|
||||
p++; \
|
||||
(x) = ntohl(*p++); \
|
||||
p++; \
|
||||
} while (0)
|
||||
#define READMEM(x,nbytes) do { \
|
||||
x = (char *)p; \
|
||||
p += XDR_QUADLEN(nbytes); \
|
||||
@ -190,6 +185,15 @@ static int zero_clientid(clientid_t *clid)
|
||||
return (clid->cl_boot == 0) && (clid->cl_id == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* defer_free - mark an allocation as deferred freed
|
||||
* @argp: NFSv4 compound argument structure to be freed with
|
||||
* @release: release callback to free @p, typically kfree()
|
||||
* @p: pointer to be freed
|
||||
*
|
||||
* Marks @p to be freed when processing the compound operation
|
||||
* described in @argp finishes.
|
||||
*/
|
||||
static int
|
||||
defer_free(struct nfsd4_compoundargs *argp,
|
||||
void (*release)(const void *), void *p)
|
||||
@ -206,6 +210,16 @@ defer_free(struct nfsd4_compoundargs *argp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* savemem - duplicate a chunk of memory for later processing
|
||||
* @argp: NFSv4 compound argument structure to be freed with
|
||||
* @p: pointer to be duplicated
|
||||
* @nbytes: length to be duplicated
|
||||
*
|
||||
* Returns a pointer to a copy of @nbytes bytes of memory at @p
|
||||
* that are preserved until processing of the NFSv4 compound
|
||||
* operation described by @argp finishes.
|
||||
*/
|
||||
static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
|
||||
{
|
||||
if (p == argp->tmp) {
|
||||
@ -257,7 +271,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
|
||||
int expected_len, len = 0;
|
||||
u32 dummy32;
|
||||
char *buf;
|
||||
int host_err;
|
||||
|
||||
DECODE_HEAD;
|
||||
iattr->ia_valid = 0;
|
||||
@ -284,10 +297,9 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
|
||||
return nfserr_resource;
|
||||
|
||||
*acl = nfs4_acl_new(nace);
|
||||
if (*acl == NULL) {
|
||||
host_err = -ENOMEM;
|
||||
goto out_nfserr;
|
||||
}
|
||||
if (*acl == NULL)
|
||||
return nfserr_jukebox;
|
||||
|
||||
defer_free(argp, kfree, *acl);
|
||||
|
||||
(*acl)->naces = nace;
|
||||
@ -425,10 +437,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
|
||||
goto xdr_error;
|
||||
|
||||
DECODE_TAIL;
|
||||
|
||||
out_nfserr:
|
||||
status = nfserrno(host_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static __be32
|
||||
@ -1957,56 +1965,16 @@ static u32 nfs4_file_type(umode_t mode)
|
||||
};
|
||||
}
|
||||
|
||||
static __be32
|
||||
nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, kuid_t uid, kgid_t gid,
|
||||
__be32 **p, int *buflen)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
|
||||
return nfserr_resource;
|
||||
if (whotype != NFS4_ACL_WHO_NAMED)
|
||||
status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
|
||||
else if (gid_valid(gid))
|
||||
status = nfsd_map_gid_to_name(rqstp, gid, (u8 *)(*p + 1));
|
||||
else
|
||||
status = nfsd_map_uid_to_name(rqstp, uid, (u8 *)(*p + 1));
|
||||
if (status < 0)
|
||||
return nfserrno(status);
|
||||
*p = xdr_encode_opaque(*p, NULL, status);
|
||||
*buflen -= (XDR_QUADLEN(status) << 2) + 4;
|
||||
BUG_ON(*buflen < 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline __be32
|
||||
nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t user, __be32 **p, int *buflen)
|
||||
{
|
||||
return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, user, INVALID_GID,
|
||||
p, buflen);
|
||||
}
|
||||
|
||||
static inline __be32
|
||||
nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t group, __be32 **p, int *buflen)
|
||||
{
|
||||
return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, INVALID_UID, group,
|
||||
p, buflen);
|
||||
}
|
||||
|
||||
static inline __be32
|
||||
nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace,
|
||||
__be32 **p, int *buflen)
|
||||
{
|
||||
kuid_t uid = INVALID_UID;
|
||||
kgid_t gid = INVALID_GID;
|
||||
|
||||
if (ace->whotype == NFS4_ACL_WHO_NAMED) {
|
||||
if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
|
||||
gid = ace->who_gid;
|
||||
else
|
||||
uid = ace->who_uid;
|
||||
}
|
||||
return nfsd4_encode_name(rqstp, ace->whotype, uid, gid, p, buflen);
|
||||
if (ace->whotype != NFS4_ACL_WHO_NAMED)
|
||||
return nfs4_acl_write_who(ace->whotype, p, buflen);
|
||||
else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
|
||||
return nfsd4_encode_group(rqstp, ace->who_gid, p, buflen);
|
||||
else
|
||||
return nfsd4_encode_user(rqstp, ace->who_uid, p, buflen);
|
||||
}
|
||||
|
||||
#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
|
||||
@ -2090,7 +2058,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
|
||||
u32 bmval1 = bmval[1];
|
||||
u32 bmval2 = bmval[2];
|
||||
struct kstat stat;
|
||||
struct svc_fh tempfh;
|
||||
struct svc_fh *tempfh = NULL;
|
||||
struct kstatfs statfs;
|
||||
int buflen = count << 2;
|
||||
__be32 *attrlenp;
|
||||
@ -2137,11 +2105,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
|
||||
goto out_nfserr;
|
||||
}
|
||||
if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
|
||||
fh_init(&tempfh, NFS4_FHSIZE);
|
||||
status = fh_compose(&tempfh, exp, dentry, NULL);
|
||||
tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
|
||||
status = nfserr_jukebox;
|
||||
if (!tempfh)
|
||||
goto out;
|
||||
fh_init(tempfh, NFS4_FHSIZE);
|
||||
status = fh_compose(tempfh, exp, dentry, NULL);
|
||||
if (status)
|
||||
goto out;
|
||||
fhp = &tempfh;
|
||||
fhp = tempfh;
|
||||
}
|
||||
if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
|
||||
| FATTR4_WORD0_SUPPORTED_ATTRS)) {
|
||||
@ -2222,8 +2194,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
|
||||
if ((buflen -= 4) < 0)
|
||||
goto out_resource;
|
||||
dummy = nfs4_file_type(stat.mode);
|
||||
if (dummy == NF4BAD)
|
||||
goto out_serverfault;
|
||||
if (dummy == NF4BAD) {
|
||||
status = nfserr_serverfault;
|
||||
goto out;
|
||||
}
|
||||
WRITE32(dummy);
|
||||
}
|
||||
if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
|
||||
@ -2317,8 +2291,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
|
||||
WRITE32(ace->flag);
|
||||
WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
|
||||
status = nfsd4_encode_aclname(rqstp, ace, &p, &buflen);
|
||||
if (status == nfserr_resource)
|
||||
goto out_resource;
|
||||
if (status)
|
||||
goto out;
|
||||
}
|
||||
@ -2379,8 +2351,6 @@ out_acl:
|
||||
}
|
||||
if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
|
||||
status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen);
|
||||
if (status == nfserr_resource)
|
||||
goto out_resource;
|
||||
if (status)
|
||||
goto out;
|
||||
}
|
||||
@ -2431,15 +2401,11 @@ out_acl:
|
||||
}
|
||||
if (bmval1 & FATTR4_WORD1_OWNER) {
|
||||
status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen);
|
||||
if (status == nfserr_resource)
|
||||
goto out_resource;
|
||||
if (status)
|
||||
goto out;
|
||||
}
|
||||
if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
|
||||
status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen);
|
||||
if (status == nfserr_resource)
|
||||
goto out_resource;
|
||||
if (status)
|
||||
goto out;
|
||||
}
|
||||
@ -2533,8 +2499,8 @@ out:
|
||||
security_release_secctx(context, contextlen);
|
||||
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
|
||||
kfree(acl);
|
||||
if (fhp == &tempfh)
|
||||
fh_put(&tempfh);
|
||||
if (tempfh)
|
||||
fh_put(tempfh);
|
||||
return status;
|
||||
out_nfserr:
|
||||
status = nfserrno(err);
|
||||
@ -2542,9 +2508,6 @@ out_nfserr:
|
||||
out_resource:
|
||||
status = nfserr_resource;
|
||||
goto out;
|
||||
out_serverfault:
|
||||
status = nfserr_serverfault;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static inline int attributes_need_mount(u32 *bmval)
|
||||
@ -2621,17 +2584,14 @@ out_put:
|
||||
static __be32 *
|
||||
nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr)
|
||||
{
|
||||
__be32 *attrlenp;
|
||||
|
||||
if (buflen < 6)
|
||||
return NULL;
|
||||
*p++ = htonl(2);
|
||||
*p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */
|
||||
*p++ = htonl(0); /* bmval1 */
|
||||
|
||||
attrlenp = p++;
|
||||
*p++ = htonl(4); /* attribute length */
|
||||
*p++ = nfserr; /* no htonl */
|
||||
*attrlenp = htonl((char *)p - (char *)attrlenp - 4);
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -3244,7 +3204,7 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp,
|
||||
|
||||
if (rpcauth_get_gssinfo(pf, &info) == 0) {
|
||||
supported++;
|
||||
RESERVE_SPACE(4 + 4 + info.oid.len + 4 + 4);
|
||||
RESERVE_SPACE(4 + 4 + XDR_LEN(info.oid.len) + 4 + 4);
|
||||
WRITE32(RPC_AUTH_GSS);
|
||||
WRITE32(info.oid.len);
|
||||
WRITEMEM(info.oid.data, info.oid.len);
|
||||
@ -3379,35 +3339,43 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
|
||||
8 /* eir_clientid */ +
|
||||
4 /* eir_sequenceid */ +
|
||||
4 /* eir_flags */ +
|
||||
4 /* spr_how */ +
|
||||
8 /* spo_must_enforce, spo_must_allow */ +
|
||||
8 /* so_minor_id */ +
|
||||
4 /* so_major_id.len */ +
|
||||
(XDR_QUADLEN(major_id_sz) * 4) +
|
||||
4 /* eir_server_scope.len */ +
|
||||
(XDR_QUADLEN(server_scope_sz) * 4) +
|
||||
4 /* eir_server_impl_id.count (0) */);
|
||||
4 /* spr_how */);
|
||||
|
||||
WRITEMEM(&exid->clientid, 8);
|
||||
WRITE32(exid->seqid);
|
||||
WRITE32(exid->flags);
|
||||
|
||||
WRITE32(exid->spa_how);
|
||||
ADJUST_ARGS();
|
||||
|
||||
switch (exid->spa_how) {
|
||||
case SP4_NONE:
|
||||
break;
|
||||
case SP4_MACH_CRED:
|
||||
/* spo_must_enforce, spo_must_allow */
|
||||
RESERVE_SPACE(16);
|
||||
|
||||
/* spo_must_enforce bitmap: */
|
||||
WRITE32(2);
|
||||
WRITE32(nfs4_minimal_spo_must_enforce[0]);
|
||||
WRITE32(nfs4_minimal_spo_must_enforce[1]);
|
||||
/* empty spo_must_allow bitmap: */
|
||||
WRITE32(0);
|
||||
|
||||
ADJUST_ARGS();
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
RESERVE_SPACE(
|
||||
8 /* so_minor_id */ +
|
||||
4 /* so_major_id.len */ +
|
||||
(XDR_QUADLEN(major_id_sz) * 4) +
|
||||
4 /* eir_server_scope.len */ +
|
||||
(XDR_QUADLEN(server_scope_sz) * 4) +
|
||||
4 /* eir_server_impl_id.count (0) */);
|
||||
|
||||
/* The server_owner struct */
|
||||
WRITE64(minor_id); /* Minor id */
|
||||
/* major id */
|
||||
@ -3473,28 +3441,6 @@ nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __be32
|
||||
nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, __be32 nfserr,
|
||||
struct nfsd4_destroy_session *destroy_session)
|
||||
{
|
||||
return nfserr;
|
||||
}
|
||||
|
||||
static __be32
|
||||
nfsd4_encode_free_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
|
||||
struct nfsd4_free_stateid *free_stateid)
|
||||
{
|
||||
__be32 *p;
|
||||
|
||||
if (nfserr)
|
||||
return nfserr;
|
||||
|
||||
RESERVE_SPACE(4);
|
||||
*p++ = nfserr;
|
||||
ADJUST_ARGS();
|
||||
return nfserr;
|
||||
}
|
||||
|
||||
static __be32
|
||||
nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr,
|
||||
struct nfsd4_sequence *seq)
|
||||
@ -3593,8 +3539,8 @@ static nfsd4_enc nfsd4_enc_ops[] = {
|
||||
[OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session,
|
||||
[OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id,
|
||||
[OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session,
|
||||
[OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session,
|
||||
[OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_free_stateid,
|
||||
[OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_noop,
|
||||
[OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_noop,
|
||||
[OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
|
||||
[OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop,
|
||||
[OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop,
|
||||
|
@ -131,13 +131,6 @@ nfsd_reply_cache_alloc(void)
|
||||
return rp;
|
||||
}
|
||||
|
||||
static void
|
||||
nfsd_reply_cache_unhash(struct svc_cacherep *rp)
|
||||
{
|
||||
hlist_del_init(&rp->c_hash);
|
||||
list_del_init(&rp->c_lru);
|
||||
}
|
||||
|
||||
static void
|
||||
nfsd_reply_cache_free_locked(struct svc_cacherep *rp)
|
||||
{
|
||||
@ -416,22 +409,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
|
||||
|
||||
/*
|
||||
* Since the common case is a cache miss followed by an insert,
|
||||
* preallocate an entry. First, try to reuse the first entry on the LRU
|
||||
* if it works, then go ahead and prune the LRU list.
|
||||
* preallocate an entry.
|
||||
*/
|
||||
spin_lock(&cache_lock);
|
||||
if (!list_empty(&lru_head)) {
|
||||
rp = list_first_entry(&lru_head, struct svc_cacherep, c_lru);
|
||||
if (nfsd_cache_entry_expired(rp) ||
|
||||
num_drc_entries >= max_drc_entries) {
|
||||
nfsd_reply_cache_unhash(rp);
|
||||
prune_cache_entries();
|
||||
goto search_cache;
|
||||
}
|
||||
}
|
||||
|
||||
/* No expired ones available, allocate a new one. */
|
||||
spin_unlock(&cache_lock);
|
||||
rp = nfsd_reply_cache_alloc();
|
||||
spin_lock(&cache_lock);
|
||||
if (likely(rp)) {
|
||||
@ -439,7 +418,9 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
|
||||
drc_mem_usage += sizeof(*rp);
|
||||
}
|
||||
|
||||
search_cache:
|
||||
/* go ahead and prune the cache */
|
||||
prune_cache_entries();
|
||||
|
||||
found = nfsd_cache_search(rqstp, csum);
|
||||
if (found) {
|
||||
if (likely(rp))
|
||||
@ -453,15 +434,6 @@ search_cache:
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We're keeping the one we just allocated. Are we now over the
|
||||
* limit? Prune one off the tip of the LRU in trade for the one we
|
||||
* just allocated if so.
|
||||
*/
|
||||
if (num_drc_entries >= max_drc_entries)
|
||||
nfsd_reply_cache_free_locked(list_first_entry(&lru_head,
|
||||
struct svc_cacherep, c_lru));
|
||||
|
||||
nfsdstats.rcmisses++;
|
||||
rqstp->rq_cacherep = rp;
|
||||
rp->c_state = RC_INPROG;
|
||||
|
@ -241,6 +241,15 @@ static void nfsd_shutdown_generic(void)
|
||||
nfsd_racache_shutdown();
|
||||
}
|
||||
|
||||
static bool nfsd_needs_lockd(void)
|
||||
{
|
||||
#if defined(CONFIG_NFSD_V3)
|
||||
return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL);
|
||||
#else
|
||||
return (nfsd_versions[2] != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int nfsd_startup_net(int nrservs, struct net *net)
|
||||
{
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
@ -255,9 +264,14 @@ static int nfsd_startup_net(int nrservs, struct net *net)
|
||||
ret = nfsd_init_socks(net);
|
||||
if (ret)
|
||||
goto out_socks;
|
||||
ret = lockd_up(net);
|
||||
if (ret)
|
||||
goto out_socks;
|
||||
|
||||
if (nfsd_needs_lockd() && !nn->lockd_up) {
|
||||
ret = lockd_up(net);
|
||||
if (ret)
|
||||
goto out_socks;
|
||||
nn->lockd_up = 1;
|
||||
}
|
||||
|
||||
ret = nfs4_state_start_net(net);
|
||||
if (ret)
|
||||
goto out_lockd;
|
||||
@ -266,7 +280,10 @@ static int nfsd_startup_net(int nrservs, struct net *net)
|
||||
return 0;
|
||||
|
||||
out_lockd:
|
||||
lockd_down(net);
|
||||
if (nn->lockd_up) {
|
||||
lockd_down(net);
|
||||
nn->lockd_up = 0;
|
||||
}
|
||||
out_socks:
|
||||
nfsd_shutdown_generic();
|
||||
return ret;
|
||||
@ -277,7 +294,10 @@ static void nfsd_shutdown_net(struct net *net)
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
nfs4_state_shutdown_net(net);
|
||||
lockd_down(net);
|
||||
if (nn->lockd_up) {
|
||||
lockd_down(net);
|
||||
nn->lockd_up = 0;
|
||||
}
|
||||
nn->nfsd_net_up = false;
|
||||
nfsd_shutdown_generic();
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
|
||||
type = (stat->mode & S_IFMT);
|
||||
|
||||
*p++ = htonl(nfs_ftypes[type >> 12]);
|
||||
*p++ = htonl((u32) stat->mode);
|
||||
*p++ = htonl((u32) (stat->mode & S_IALLUGO));
|
||||
*p++ = htonl((u32) stat->nlink);
|
||||
*p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
|
||||
*p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
|
||||
|
@ -207,7 +207,12 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
goto out_nfserr;
|
||||
}
|
||||
} else {
|
||||
fh_lock(fhp);
|
||||
/*
|
||||
* In the nfsd4_open() case, this may be held across
|
||||
* subsequent open and delegation acquisition which may
|
||||
* need to take the child's i_mutex:
|
||||
*/
|
||||
fh_lock_nested(fhp, I_MUTEX_PARENT);
|
||||
dentry = lookup_one_len(name, dparent, len);
|
||||
host_err = PTR_ERR(dentry);
|
||||
if (IS_ERR(dentry))
|
||||
@ -273,13 +278,6 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nfsd_break_lease(struct inode *inode)
|
||||
{
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
return 0;
|
||||
return break_lease(inode, O_WRONLY | O_NONBLOCK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Commit metadata changes to stable storage.
|
||||
*/
|
||||
@ -348,8 +346,7 @@ nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap)
|
||||
|
||||
/* Revoke setuid/setgid on chown */
|
||||
if (!S_ISDIR(inode->i_mode) &&
|
||||
(((iap->ia_valid & ATTR_UID) && !uid_eq(iap->ia_uid, inode->i_uid)) ||
|
||||
((iap->ia_valid & ATTR_GID) && !gid_eq(iap->ia_gid, inode->i_gid)))) {
|
||||
((iap->ia_valid & ATTR_UID) || (iap->ia_valid & ATTR_GID))) {
|
||||
iap->ia_valid |= ATTR_KILL_PRIV;
|
||||
if (iap->ia_valid & ATTR_MODE) {
|
||||
/* we're setting mode too, just clear the s*id bits */
|
||||
@ -449,16 +446,10 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
|
||||
goto out_put_write_access;
|
||||
}
|
||||
|
||||
host_err = nfsd_break_lease(inode);
|
||||
if (host_err)
|
||||
goto out_put_write_access_nfserror;
|
||||
|
||||
fh_lock(fhp);
|
||||
host_err = notify_change(dentry, iap, NULL);
|
||||
fh_unlock(fhp);
|
||||
|
||||
out_put_write_access_nfserror:
|
||||
err = nfserrno(host_err);
|
||||
out_put_write_access:
|
||||
if (size_change)
|
||||
put_write_access(inode);
|
||||
@ -1609,11 +1600,6 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
|
||||
err = nfserr_noent;
|
||||
if (!dold->d_inode)
|
||||
goto out_dput;
|
||||
host_err = nfsd_break_lease(dold->d_inode);
|
||||
if (host_err) {
|
||||
err = nfserrno(host_err);
|
||||
goto out_dput;
|
||||
}
|
||||
host_err = vfs_link(dold, dirp, dnew, NULL);
|
||||
if (!host_err) {
|
||||
err = nfserrno(commit_metadata(ffhp));
|
||||
@ -1707,14 +1693,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
|
||||
if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry)
|
||||
goto out_dput_new;
|
||||
|
||||
host_err = nfsd_break_lease(odentry->d_inode);
|
||||
if (host_err)
|
||||
goto out_dput_new;
|
||||
if (ndentry->d_inode) {
|
||||
host_err = nfsd_break_lease(ndentry->d_inode);
|
||||
if (host_err)
|
||||
goto out_dput_new;
|
||||
}
|
||||
host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
|
||||
if (!host_err) {
|
||||
host_err = commit_metadata(tfhp);
|
||||
@ -1784,16 +1762,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
|
||||
if (!type)
|
||||
type = rdentry->d_inode->i_mode & S_IFMT;
|
||||
|
||||
host_err = nfsd_break_lease(rdentry->d_inode);
|
||||
if (host_err)
|
||||
goto out_put;
|
||||
if (type != S_IFDIR)
|
||||
host_err = vfs_unlink(dirp, rdentry, NULL);
|
||||
else
|
||||
host_err = vfs_rmdir(dirp, rdentry);
|
||||
if (!host_err)
|
||||
host_err = commit_metadata(fhp);
|
||||
out_put:
|
||||
dput(rdentry);
|
||||
|
||||
out_nfserr:
|
||||
|
@ -86,8 +86,6 @@ __be32 nfsd_link(struct svc_rqst *, struct svc_fh *,
|
||||
__be32 nfsd_rename(struct svc_rqst *,
|
||||
struct svc_fh *, char *, int,
|
||||
struct svc_fh *, char *, int);
|
||||
__be32 nfsd_remove(struct svc_rqst *,
|
||||
struct svc_fh *, char *, int);
|
||||
__be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
|
||||
char *name, int len);
|
||||
__be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *,
|
||||
|
@ -174,6 +174,9 @@ struct nfsd3_linkres {
|
||||
struct nfsd3_readdirres {
|
||||
__be32 status;
|
||||
struct svc_fh fh;
|
||||
/* Just to save kmalloc on every readdirplus entry (svc_fh is a
|
||||
* little large for the stack): */
|
||||
struct svc_fh scratch;
|
||||
int count;
|
||||
__be32 verf[2];
|
||||
|
||||
|
@ -228,7 +228,7 @@ struct nfsd4_open {
|
||||
u32 op_create; /* request */
|
||||
u32 op_createmode; /* request */
|
||||
u32 op_bmval[3]; /* request */
|
||||
struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
|
||||
struct iattr op_iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
|
||||
nfs4_verifier op_verf __attribute__((aligned(32)));
|
||||
/* EXCLUSIVE4 */
|
||||
clientid_t op_clientid; /* request */
|
||||
@ -250,7 +250,6 @@ struct nfsd4_open {
|
||||
struct nfs4_acl *op_acl;
|
||||
struct xdr_netobj op_label;
|
||||
};
|
||||
#define op_iattr iattr
|
||||
|
||||
struct nfsd4_open_confirm {
|
||||
stateid_t oc_req_stateid /* request */;
|
||||
@ -374,7 +373,6 @@ struct nfsd4_test_stateid {
|
||||
|
||||
struct nfsd4_free_stateid {
|
||||
stateid_t fr_stateid; /* request */
|
||||
__be32 fr_status; /* response */
|
||||
};
|
||||
|
||||
/* also used for NVERIFY */
|
||||
|
@ -368,7 +368,7 @@ struct svc_program {
|
||||
struct svc_program * pg_next; /* other programs (same xprt) */
|
||||
u32 pg_prog; /* program number */
|
||||
unsigned int pg_lovers; /* lowest version */
|
||||
unsigned int pg_hivers; /* lowest version */
|
||||
unsigned int pg_hivers; /* highest version */
|
||||
unsigned int pg_nvers; /* number of versions */
|
||||
struct svc_version ** pg_vers; /* version array */
|
||||
char * pg_name; /* service name */
|
||||
@ -386,8 +386,10 @@ struct svc_version {
|
||||
struct svc_procedure * vs_proc; /* per-procedure info */
|
||||
u32 vs_xdrsize; /* xdrsize needed for this version */
|
||||
|
||||
unsigned int vs_hidden : 1; /* Don't register with portmapper.
|
||||
unsigned int vs_hidden : 1, /* Don't register with portmapper.
|
||||
* Only used for nfsacl so far. */
|
||||
vs_rpcb_optnl:1;/* Don't care the result of register.
|
||||
* Only used for nfsv4. */
|
||||
|
||||
/* Override dispatch function (e.g. when caching replies).
|
||||
* A return value of 0 means drop the request.
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/sunrpc/gss_krb5.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/lcm.h>
|
||||
|
||||
#ifdef RPC_DEBUG
|
||||
# define RPCDBG_FACILITY RPCDBG_AUTH
|
||||
@ -72,7 +73,7 @@
|
||||
static void krb5_nfold(u32 inbits, const u8 *in,
|
||||
u32 outbits, u8 *out)
|
||||
{
|
||||
int a, b, c, lcm;
|
||||
unsigned long ulcm;
|
||||
int byte, i, msbit;
|
||||
|
||||
/* the code below is more readable if I make these bytes
|
||||
@ -82,17 +83,7 @@ static void krb5_nfold(u32 inbits, const u8 *in,
|
||||
outbits >>= 3;
|
||||
|
||||
/* first compute lcm(n,k) */
|
||||
|
||||
a = outbits;
|
||||
b = inbits;
|
||||
|
||||
while (b != 0) {
|
||||
c = b;
|
||||
b = a%b;
|
||||
a = c;
|
||||
}
|
||||
|
||||
lcm = outbits*inbits/a;
|
||||
ulcm = lcm(inbits, outbits);
|
||||
|
||||
/* now do the real work */
|
||||
|
||||
@ -101,7 +92,7 @@ static void krb5_nfold(u32 inbits, const u8 *in,
|
||||
|
||||
/* this will end up cycling through k lcm(k,n)/k times, which
|
||||
is correct */
|
||||
for (i = lcm-1; i >= 0; i--) {
|
||||
for (i = ulcm-1; i >= 0; i--) {
|
||||
/* compute the msbit in k which gets added into this byte */
|
||||
msbit = (
|
||||
/* first, start with the msbit in the first,
|
||||
|
@ -137,7 +137,6 @@ void init_gssp_clnt(struct sunrpc_net *sn)
|
||||
{
|
||||
mutex_init(&sn->gssp_lock);
|
||||
sn->gssp_clnt = NULL;
|
||||
init_waitqueue_head(&sn->gssp_wq);
|
||||
}
|
||||
|
||||
int set_gssp_clnt(struct net *net)
|
||||
@ -154,7 +153,6 @@ int set_gssp_clnt(struct net *net)
|
||||
sn->gssp_clnt = clnt;
|
||||
}
|
||||
mutex_unlock(&sn->gssp_lock);
|
||||
wake_up(&sn->gssp_wq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1263,66 +1263,35 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_SPINLOCK(use_gssp_lock);
|
||||
/*
|
||||
* Try to set the sn->use_gss_proxy variable to a new value. We only allow
|
||||
* it to be changed if it's currently undefined (-1). If it's any other value
|
||||
* then return -EBUSY unless the type wouldn't have changed anyway.
|
||||
*/
|
||||
static int set_gss_proxy(struct net *net, int type)
|
||||
{
|
||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
int ret;
|
||||
|
||||
WARN_ON_ONCE(type != 0 && type != 1);
|
||||
ret = cmpxchg(&sn->use_gss_proxy, -1, type);
|
||||
if (ret != -1 && ret != type)
|
||||
return -EBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool use_gss_proxy(struct net *net)
|
||||
{
|
||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
|
||||
if (sn->use_gss_proxy != -1)
|
||||
return sn->use_gss_proxy;
|
||||
spin_lock(&use_gssp_lock);
|
||||
/*
|
||||
* If you wanted gss-proxy, you should have said so before
|
||||
* starting to accept requests:
|
||||
*/
|
||||
sn->use_gss_proxy = 0;
|
||||
spin_unlock(&use_gssp_lock);
|
||||
return 0;
|
||||
/* If use_gss_proxy is still undefined, then try to disable it */
|
||||
if (sn->use_gss_proxy == -1)
|
||||
set_gss_proxy(net, 0);
|
||||
return sn->use_gss_proxy;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
static int set_gss_proxy(struct net *net, int type)
|
||||
{
|
||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
int ret = 0;
|
||||
|
||||
WARN_ON_ONCE(type != 0 && type != 1);
|
||||
spin_lock(&use_gssp_lock);
|
||||
if (sn->use_gss_proxy == -1 || sn->use_gss_proxy == type)
|
||||
sn->use_gss_proxy = type;
|
||||
else
|
||||
ret = -EBUSY;
|
||||
spin_unlock(&use_gssp_lock);
|
||||
wake_up(&sn->gssp_wq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool gssp_ready(struct sunrpc_net *sn)
|
||||
{
|
||||
switch (sn->use_gss_proxy) {
|
||||
case -1:
|
||||
return false;
|
||||
case 0:
|
||||
return true;
|
||||
case 1:
|
||||
return sn->gssp_clnt;
|
||||
}
|
||||
WARN_ON_ONCE(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int wait_for_gss_proxy(struct net *net, struct file *file)
|
||||
{
|
||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
|
||||
if (file->f_flags & O_NONBLOCK && !gssp_ready(sn))
|
||||
return -EAGAIN;
|
||||
return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn));
|
||||
}
|
||||
|
||||
|
||||
static ssize_t write_gssp(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -1342,10 +1311,10 @@ static ssize_t write_gssp(struct file *file, const char __user *buf,
|
||||
return res;
|
||||
if (i != 1)
|
||||
return -EINVAL;
|
||||
res = set_gss_proxy(net, 1);
|
||||
res = set_gssp_clnt(net);
|
||||
if (res)
|
||||
return res;
|
||||
res = set_gssp_clnt(net);
|
||||
res = set_gss_proxy(net, 1);
|
||||
if (res)
|
||||
return res;
|
||||
return count;
|
||||
@ -1355,16 +1324,12 @@ static ssize_t read_gssp(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct net *net = PDE_DATA(file_inode(file));
|
||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
unsigned long p = *ppos;
|
||||
char tbuf[10];
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
ret = wait_for_gss_proxy(net, file);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
snprintf(tbuf, sizeof(tbuf), "%d\n", use_gss_proxy(net));
|
||||
snprintf(tbuf, sizeof(tbuf), "%d\n", sn->use_gss_proxy);
|
||||
len = strlen(tbuf);
|
||||
if (p >= len)
|
||||
return 0;
|
||||
@ -1626,8 +1591,7 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
|
||||
BUG_ON(integ_len % 4);
|
||||
*p++ = htonl(integ_len);
|
||||
*p++ = htonl(gc->gc_seq);
|
||||
if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset,
|
||||
integ_len))
|
||||
if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len))
|
||||
BUG();
|
||||
if (resbuf->tail[0].iov_base == NULL) {
|
||||
if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE)
|
||||
@ -1635,10 +1599,8 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
|
||||
resbuf->tail[0].iov_base = resbuf->head[0].iov_base
|
||||
+ resbuf->head[0].iov_len;
|
||||
resbuf->tail[0].iov_len = 0;
|
||||
resv = &resbuf->tail[0];
|
||||
} else {
|
||||
resv = &resbuf->tail[0];
|
||||
}
|
||||
resv = &resbuf->tail[0];
|
||||
mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
|
||||
if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
|
||||
goto out_err;
|
||||
|
@ -1111,9 +1111,7 @@ void qword_addhex(char **bpp, int *lp, char *buf, int blen)
|
||||
*bp++ = 'x';
|
||||
len -= 2;
|
||||
while (blen && len >= 2) {
|
||||
unsigned char c = *buf++;
|
||||
*bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
|
||||
*bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
|
||||
bp = hex_byte_pack(bp, *buf++);
|
||||
len -= 2;
|
||||
blen--;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ struct sunrpc_net {
|
||||
unsigned int rpcb_is_af_local : 1;
|
||||
|
||||
struct mutex gssp_lock;
|
||||
wait_queue_head_t gssp_wq;
|
||||
struct rpc_clnt *gssp_clnt;
|
||||
int use_gss_proxy;
|
||||
int pipe_version;
|
||||
|
@ -916,9 +916,6 @@ static int __svc_register(struct net *net, const char *progname,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (error < 0)
|
||||
printk(KERN_WARNING "svc: failed to register %sv%u RPC "
|
||||
"service (errno %d).\n", progname, version, -error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -937,6 +934,7 @@ int svc_register(const struct svc_serv *serv, struct net *net,
|
||||
const unsigned short port)
|
||||
{
|
||||
struct svc_program *progp;
|
||||
struct svc_version *vers;
|
||||
unsigned int i;
|
||||
int error = 0;
|
||||
|
||||
@ -946,7 +944,8 @@ int svc_register(const struct svc_serv *serv, struct net *net,
|
||||
|
||||
for (progp = serv->sv_program; progp; progp = progp->pg_next) {
|
||||
for (i = 0; i < progp->pg_nvers; i++) {
|
||||
if (progp->pg_vers[i] == NULL)
|
||||
vers = progp->pg_vers[i];
|
||||
if (vers == NULL)
|
||||
continue;
|
||||
|
||||
dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n",
|
||||
@ -955,16 +954,26 @@ int svc_register(const struct svc_serv *serv, struct net *net,
|
||||
proto == IPPROTO_UDP? "udp" : "tcp",
|
||||
port,
|
||||
family,
|
||||
progp->pg_vers[i]->vs_hidden?
|
||||
" (but not telling portmap)" : "");
|
||||
vers->vs_hidden ?
|
||||
" (but not telling portmap)" : "");
|
||||
|
||||
if (progp->pg_vers[i]->vs_hidden)
|
||||
if (vers->vs_hidden)
|
||||
continue;
|
||||
|
||||
error = __svc_register(net, progp->pg_name, progp->pg_prog,
|
||||
i, family, proto, port);
|
||||
if (error < 0)
|
||||
|
||||
if (vers->vs_rpcb_optnl) {
|
||||
error = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (error < 0) {
|
||||
printk(KERN_WARNING "svc: failed to register "
|
||||
"%sv%u RPC service (errno %d).\n",
|
||||
progp->pg_name, i, -error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2964,10 +2964,9 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
|
||||
|
||||
/*
|
||||
* Once we've associated a backchannel xprt with a connection,
|
||||
* we want to keep it around as long as long as the connection
|
||||
* lasts, in case we need to start using it for a backchannel
|
||||
* again; this reference won't be dropped until bc_xprt is
|
||||
* destroyed.
|
||||
* we want to keep it around as long as the connection lasts,
|
||||
* in case we need to start using it for a backchannel again;
|
||||
* this reference won't be dropped until bc_xprt is destroyed.
|
||||
*/
|
||||
xprt_get(xprt);
|
||||
args->bc_xprt->xpt_bc_xprt = xprt;
|
||||
|
Loading…
Reference in New Issue
Block a user