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: Fix the fix to Bugzilla #11061, when IPv6 isn't defined... SUNRPC: xprt_connect() don't abort the task if the transport isn't bound SUNRPC: Fix an Oops due to socket not set up yet... Bug 11061, NFS mounts dropped NFS: Handle -ESTALE error in access() NLM: Fix GRANT callback address comparison when IPv6 is enabled NLM: Shrink the IPv4-only version of nlm_cmp_addr() NFSv3: Fix posix ACL code NFS: Fix misparsing of nfsv4 fs_locations attribute (take 2) SUNRPC: Tighten up the task locking rules in __rpc_execute()
This commit is contained in:
Коммит
f1823acfbc
|
@ -139,6 +139,55 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
|
static const struct in6_addr *nlmclnt_map_v4addr(const struct sockaddr *sap,
|
||||||
|
struct in6_addr *addr_mapped)
|
||||||
|
{
|
||||||
|
const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
|
||||||
|
|
||||||
|
switch (sap->sa_family) {
|
||||||
|
case AF_INET6:
|
||||||
|
return &((const struct sockaddr_in6 *)sap)->sin6_addr;
|
||||||
|
case AF_INET:
|
||||||
|
ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, addr_mapped);
|
||||||
|
return addr_mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If lockd is using a PF_INET6 listener, all incoming requests appear
|
||||||
|
* to come from AF_INET6 remotes. The address of AF_INET remotes are
|
||||||
|
* mapped to AF_INET6 automatically by the network layer. In case the
|
||||||
|
* user passed an AF_INET server address at mount time, ensure both
|
||||||
|
* addresses are AF_INET6 before comparing them.
|
||||||
|
*/
|
||||||
|
static int nlmclnt_cmp_addr(const struct nlm_host *host,
|
||||||
|
const struct sockaddr *sap)
|
||||||
|
{
|
||||||
|
const struct in6_addr *addr1;
|
||||||
|
const struct in6_addr *addr2;
|
||||||
|
struct in6_addr addr1_mapped;
|
||||||
|
struct in6_addr addr2_mapped;
|
||||||
|
|
||||||
|
addr1 = nlmclnt_map_v4addr(nlm_addr(host), &addr1_mapped);
|
||||||
|
if (likely(addr1 != NULL)) {
|
||||||
|
addr2 = nlmclnt_map_v4addr(sap, &addr2_mapped);
|
||||||
|
if (likely(addr2 != NULL))
|
||||||
|
return ipv6_addr_equal(addr1, addr2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
|
||||||
|
static int nlmclnt_cmp_addr(const struct nlm_host *host,
|
||||||
|
const struct sockaddr *sap)
|
||||||
|
{
|
||||||
|
return nlm_cmp_addr(nlm_addr(host), sap);
|
||||||
|
}
|
||||||
|
#endif /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The server lockd has called us back to tell us the lock was granted
|
* The server lockd has called us back to tell us the lock was granted
|
||||||
*/
|
*/
|
||||||
|
@ -166,7 +215,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
|
||||||
*/
|
*/
|
||||||
if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
|
if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
|
||||||
continue;
|
continue;
|
||||||
if (!nlm_cmp_addr(nlm_addr(block->b_host), addr))
|
if (!nlmclnt_cmp_addr(block->b_host, addr))
|
||||||
continue;
|
continue;
|
||||||
if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
|
if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -255,6 +255,32 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if two ip6 socket addresses refer to the same socket by
|
||||||
|
* comparing relevant fields. The padding bytes specifically, are not
|
||||||
|
* compared. sin6_flowinfo is not compared because it only affects QoS
|
||||||
|
* and sin6_scope_id is only compared if the address is "link local"
|
||||||
|
* because "link local" addresses need only be unique to a specific
|
||||||
|
* link. Conversely, ordinary unicast addresses might have different
|
||||||
|
* sin6_scope_id.
|
||||||
|
*
|
||||||
|
* The caller should ensure both socket addresses are AF_INET6.
|
||||||
|
*/
|
||||||
|
static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1,
|
||||||
|
const struct sockaddr *sa2)
|
||||||
|
{
|
||||||
|
const struct sockaddr_in6 *saddr1 = (const struct sockaddr_in6 *)sa1;
|
||||||
|
const struct sockaddr_in6 *saddr2 = (const struct sockaddr_in6 *)sa2;
|
||||||
|
|
||||||
|
if (!ipv6_addr_equal(&saddr1->sin6_addr,
|
||||||
|
&saddr1->sin6_addr))
|
||||||
|
return 0;
|
||||||
|
if (ipv6_addr_scope(&saddr1->sin6_addr) == IPV6_ADDR_SCOPE_LINKLOCAL &&
|
||||||
|
saddr1->sin6_scope_id != saddr2->sin6_scope_id)
|
||||||
|
return 0;
|
||||||
|
return saddr1->sin6_port == saddr2->sin6_port;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
|
static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1,
|
||||||
const struct sockaddr_in *sa2)
|
const struct sockaddr_in *sa2)
|
||||||
|
@ -270,8 +296,51 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
|
||||||
return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
|
return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1,
|
||||||
(const struct sockaddr_in *)sa2);
|
(const struct sockaddr_in *)sa2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nfs_sockaddr_cmp_ip6(const struct sockaddr * sa1,
|
||||||
|
const struct sockaddr * sa2)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if two ip4 socket addresses refer to the same socket, by
|
||||||
|
* comparing relevant fields. The padding bytes specifically, are
|
||||||
|
* not compared.
|
||||||
|
*
|
||||||
|
* The caller should ensure both socket addresses are AF_INET.
|
||||||
|
*/
|
||||||
|
static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1,
|
||||||
|
const struct sockaddr *sa2)
|
||||||
|
{
|
||||||
|
const struct sockaddr_in *saddr1 = (const struct sockaddr_in *)sa1;
|
||||||
|
const struct sockaddr_in *saddr2 = (const struct sockaddr_in *)sa2;
|
||||||
|
|
||||||
|
if (saddr1->sin_addr.s_addr != saddr2->sin_addr.s_addr)
|
||||||
|
return 0;
|
||||||
|
return saddr1->sin_port == saddr2->sin_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test if two socket addresses represent the same actual socket,
|
||||||
|
* by comparing (only) relevant fields.
|
||||||
|
*/
|
||||||
|
static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
|
||||||
|
const struct sockaddr *sa2)
|
||||||
|
{
|
||||||
|
if (sa1->sa_family != sa2->sa_family)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (sa1->sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
return nfs_sockaddr_cmp_ip4(sa1, sa2);
|
||||||
|
case AF_INET6:
|
||||||
|
return nfs_sockaddr_cmp_ip6(sa1, sa2);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a client by IP address and protocol version
|
* Find a client by IP address and protocol version
|
||||||
* - returns NULL if no such client
|
* - returns NULL if no such client
|
||||||
|
@ -344,8 +413,10 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
|
||||||
static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data)
|
static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data)
|
||||||
{
|
{
|
||||||
struct nfs_client *clp;
|
struct nfs_client *clp;
|
||||||
|
const struct sockaddr *sap = data->addr;
|
||||||
|
|
||||||
list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
|
list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
|
||||||
|
const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
|
||||||
/* Don't match clients that failed to initialise properly */
|
/* Don't match clients that failed to initialise properly */
|
||||||
if (clp->cl_cons_state < 0)
|
if (clp->cl_cons_state < 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -358,7 +429,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Match the full socket address */
|
/* Match the full socket address */
|
||||||
if (memcmp(&clp->cl_addr, data->addr, sizeof(clp->cl_addr)) != 0)
|
if (!nfs_sockaddr_cmp(sap, clap))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
atomic_inc(&clp->cl_count);
|
atomic_inc(&clp->cl_count);
|
||||||
|
|
|
@ -1892,8 +1892,14 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
|
||||||
cache.cred = cred;
|
cache.cred = cred;
|
||||||
cache.jiffies = jiffies;
|
cache.jiffies = jiffies;
|
||||||
status = NFS_PROTO(inode)->access(inode, &cache);
|
status = NFS_PROTO(inode)->access(inode, &cache);
|
||||||
if (status != 0)
|
if (status != 0) {
|
||||||
|
if (status == -ESTALE) {
|
||||||
|
nfs_zap_caches(inode);
|
||||||
|
if (!S_ISDIR(inode->i_mode))
|
||||||
|
set_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
|
||||||
|
}
|
||||||
return status;
|
return status;
|
||||||
|
}
|
||||||
nfs_access_add_cache(inode, &cache);
|
nfs_access_add_cache(inode, &cache);
|
||||||
out:
|
out:
|
||||||
if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
|
if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
|
||||||
|
|
|
@ -292,7 +292,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
|
||||||
{
|
{
|
||||||
struct nfs_server *server = NFS_SERVER(inode);
|
struct nfs_server *server = NFS_SERVER(inode);
|
||||||
struct nfs_fattr fattr;
|
struct nfs_fattr fattr;
|
||||||
struct page *pages[NFSACL_MAXPAGES] = { };
|
struct page *pages[NFSACL_MAXPAGES];
|
||||||
struct nfs3_setaclargs args = {
|
struct nfs3_setaclargs args = {
|
||||||
.inode = inode,
|
.inode = inode,
|
||||||
.mask = NFS_ACL,
|
.mask = NFS_ACL,
|
||||||
|
@ -303,7 +303,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
|
||||||
.rpc_argp = &args,
|
.rpc_argp = &args,
|
||||||
.rpc_resp = &fattr,
|
.rpc_resp = &fattr,
|
||||||
};
|
};
|
||||||
int status, count;
|
int status;
|
||||||
|
|
||||||
status = -EOPNOTSUPP;
|
status = -EOPNOTSUPP;
|
||||||
if (!nfs_server_capable(inode, NFS_CAP_ACLS))
|
if (!nfs_server_capable(inode, NFS_CAP_ACLS))
|
||||||
|
@ -319,6 +319,20 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
|
||||||
if (S_ISDIR(inode->i_mode)) {
|
if (S_ISDIR(inode->i_mode)) {
|
||||||
args.mask |= NFS_DFACL;
|
args.mask |= NFS_DFACL;
|
||||||
args.acl_default = dfacl;
|
args.acl_default = dfacl;
|
||||||
|
args.len = nfsacl_size(acl, dfacl);
|
||||||
|
} else
|
||||||
|
args.len = nfsacl_size(acl, NULL);
|
||||||
|
|
||||||
|
if (args.len > NFS_ACL_INLINE_BUFSIZE) {
|
||||||
|
unsigned int npages = 1 + ((args.len - 1) >> PAGE_SHIFT);
|
||||||
|
|
||||||
|
status = -ENOMEM;
|
||||||
|
do {
|
||||||
|
args.pages[args.npages] = alloc_page(GFP_KERNEL);
|
||||||
|
if (args.pages[args.npages] == NULL)
|
||||||
|
goto out_freepages;
|
||||||
|
args.npages++;
|
||||||
|
} while (args.npages < npages);
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintk("NFS call setacl\n");
|
dprintk("NFS call setacl\n");
|
||||||
|
@ -329,10 +343,6 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
|
||||||
nfs_zap_acl_cache(inode);
|
nfs_zap_acl_cache(inode);
|
||||||
dprintk("NFS reply setacl: %d\n", status);
|
dprintk("NFS reply setacl: %d\n", status);
|
||||||
|
|
||||||
/* pages may have been allocated at the xdr layer. */
|
|
||||||
for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
|
|
||||||
__free_page(args.pages[count]);
|
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 0:
|
case 0:
|
||||||
status = nfs_refresh_inode(inode, &fattr);
|
status = nfs_refresh_inode(inode, &fattr);
|
||||||
|
@ -346,6 +356,11 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
|
||||||
case -ENOTSUPP:
|
case -ENOTSUPP:
|
||||||
status = -EOPNOTSUPP;
|
status = -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
out_freepages:
|
||||||
|
while (args.npages != 0) {
|
||||||
|
args.npages--;
|
||||||
|
__free_page(args.pages[args.npages]);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,10 @@
|
||||||
#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
|
#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
|
||||||
|
|
||||||
#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
|
#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
|
||||||
#define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3))
|
#define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
|
||||||
#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3))
|
XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
|
||||||
|
#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
|
||||||
|
XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
|
||||||
#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
|
#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -703,28 +705,18 @@ nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
|
||||||
struct nfs3_setaclargs *args)
|
struct nfs3_setaclargs *args)
|
||||||
{
|
{
|
||||||
struct xdr_buf *buf = &req->rq_snd_buf;
|
struct xdr_buf *buf = &req->rq_snd_buf;
|
||||||
unsigned int base, len_in_head, len = nfsacl_size(
|
unsigned int base;
|
||||||
(args->mask & NFS_ACL) ? args->acl_access : NULL,
|
int err;
|
||||||
(args->mask & NFS_DFACL) ? args->acl_default : NULL);
|
|
||||||
int count, err;
|
|
||||||
|
|
||||||
p = xdr_encode_fhandle(p, NFS_FH(args->inode));
|
p = xdr_encode_fhandle(p, NFS_FH(args->inode));
|
||||||
*p++ = htonl(args->mask);
|
*p++ = htonl(args->mask);
|
||||||
base = (char *)p - (char *)buf->head->iov_base;
|
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
|
||||||
/* put as much of the acls into head as possible. */
|
base = req->rq_slen;
|
||||||
len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
|
|
||||||
len -= len_in_head;
|
|
||||||
req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
|
|
||||||
|
|
||||||
for (count = 0; (count << PAGE_SHIFT) < len; count++) {
|
if (args->npages != 0)
|
||||||
args->pages[count] = alloc_page(GFP_KERNEL);
|
xdr_encode_pages(buf, args->pages, 0, args->len);
|
||||||
if (!args->pages[count]) {
|
else
|
||||||
while (count)
|
req->rq_slen += args->len;
|
||||||
__free_page(args->pages[--count]);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xdr_encode_pages(buf, args->pages, 0, len);
|
|
||||||
|
|
||||||
err = nfsacl_encode(buf, base, args->inode,
|
err = nfsacl_encode(buf, base, args->inode,
|
||||||
(args->mask & NFS_ACL) ?
|
(args->mask & NFS_ACL) ?
|
||||||
|
|
|
@ -21,7 +21,9 @@
|
||||||
#define NFSDBG_FACILITY NFSDBG_VFS
|
#define NFSDBG_FACILITY NFSDBG_VFS
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if fs_root is valid
|
* Convert the NFSv4 pathname components into a standard posix path.
|
||||||
|
*
|
||||||
|
* Note that the resulting string will be placed at the end of the buffer
|
||||||
*/
|
*/
|
||||||
static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname,
|
static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname,
|
||||||
char *buffer, ssize_t buflen)
|
char *buffer, ssize_t buflen)
|
||||||
|
@ -99,21 +101,20 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
|
||||||
{
|
{
|
||||||
struct vfsmount *mnt = ERR_PTR(-ENOENT);
|
struct vfsmount *mnt = ERR_PTR(-ENOENT);
|
||||||
char *mnt_path;
|
char *mnt_path;
|
||||||
int page2len;
|
unsigned int maxbuflen;
|
||||||
unsigned int s;
|
unsigned int s;
|
||||||
|
|
||||||
mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
|
mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
|
||||||
if (IS_ERR(mnt_path))
|
if (IS_ERR(mnt_path))
|
||||||
return mnt;
|
return mnt;
|
||||||
mountdata->mnt_path = mnt_path;
|
mountdata->mnt_path = mnt_path;
|
||||||
page2 += strlen(mnt_path) + 1;
|
maxbuflen = mnt_path - 1 - page2;
|
||||||
page2len = PAGE_SIZE - strlen(mnt_path) - 1;
|
|
||||||
|
|
||||||
for (s = 0; s < location->nservers; s++) {
|
for (s = 0; s < location->nservers; s++) {
|
||||||
const struct nfs4_string *buf = &location->servers[s];
|
const struct nfs4_string *buf = &location->servers[s];
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
|
|
||||||
if (buf->len <= 0 || buf->len >= PAGE_SIZE)
|
if (buf->len <= 0 || buf->len >= maxbuflen)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mountdata->addr = (struct sockaddr *)&addr;
|
mountdata->addr = (struct sockaddr *)&addr;
|
||||||
|
@ -126,8 +127,8 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
|
||||||
continue;
|
continue;
|
||||||
nfs_set_port(mountdata->addr, NFS_PORT);
|
nfs_set_port(mountdata->addr, NFS_PORT);
|
||||||
|
|
||||||
strncpy(page2, buf->data, page2len);
|
memcpy(page2, buf->data, buf->len);
|
||||||
page2[page2len] = '\0';
|
page2[buf->len] = '\0';
|
||||||
mountdata->hostname = page2;
|
mountdata->hostname = page2;
|
||||||
|
|
||||||
snprintf(page, PAGE_SIZE, "%s:%s",
|
snprintf(page, PAGE_SIZE, "%s:%s",
|
||||||
|
|
|
@ -346,6 +346,7 @@ static inline int __nlm_cmp_addr4(const struct sockaddr *sap1,
|
||||||
return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
|
return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||||
static inline int __nlm_cmp_addr6(const struct sockaddr *sap1,
|
static inline int __nlm_cmp_addr6(const struct sockaddr *sap1,
|
||||||
const struct sockaddr *sap2)
|
const struct sockaddr *sap2)
|
||||||
{
|
{
|
||||||
|
@ -353,6 +354,13 @@ static inline int __nlm_cmp_addr6(const struct sockaddr *sap1,
|
||||||
const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
|
const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
|
||||||
return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
|
return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
|
||||||
}
|
}
|
||||||
|
#else /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
|
||||||
|
static inline int __nlm_cmp_addr6(const struct sockaddr *sap1,
|
||||||
|
const struct sockaddr *sap2)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compare two host addresses
|
* Compare two host addresses
|
||||||
|
|
|
@ -406,6 +406,8 @@ struct nfs3_setaclargs {
|
||||||
int mask;
|
int mask;
|
||||||
struct posix_acl * acl_access;
|
struct posix_acl * acl_access;
|
||||||
struct posix_acl * acl_default;
|
struct posix_acl * acl_default;
|
||||||
|
size_t len;
|
||||||
|
unsigned int npages;
|
||||||
struct page ** pages;
|
struct page ** pages;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,9 @@
|
||||||
#define NFSACL_MAXPAGES ((2*(8+12*NFS_ACL_MAX_ENTRIES) + PAGE_SIZE-1) \
|
#define NFSACL_MAXPAGES ((2*(8+12*NFS_ACL_MAX_ENTRIES) + PAGE_SIZE-1) \
|
||||||
>> PAGE_SHIFT)
|
>> PAGE_SHIFT)
|
||||||
|
|
||||||
|
#define NFS_ACL_MAX_ENTRIES_INLINE (5)
|
||||||
|
#define NFS_ACL_INLINE_BUFSIZE ((2*(2+3*NFS_ACL_MAX_ENTRIES_INLINE)) << 2)
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
nfsacl_size(struct posix_acl *acl_access, struct posix_acl *acl_default)
|
nfsacl_size(struct posix_acl *acl_access, struct posix_acl *acl_default)
|
||||||
{
|
{
|
||||||
|
|
|
@ -293,11 +293,6 @@ static void rpc_make_runnable(struct rpc_task *task)
|
||||||
rpc_clear_queued(task);
|
rpc_clear_queued(task);
|
||||||
if (rpc_test_and_set_running(task))
|
if (rpc_test_and_set_running(task))
|
||||||
return;
|
return;
|
||||||
/* We might have raced */
|
|
||||||
if (RPC_IS_QUEUED(task)) {
|
|
||||||
rpc_clear_running(task);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (RPC_IS_ASYNC(task)) {
|
if (RPC_IS_ASYNC(task)) {
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
@ -607,7 +602,9 @@ void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata)
|
||||||
*/
|
*/
|
||||||
static void __rpc_execute(struct rpc_task *task)
|
static void __rpc_execute(struct rpc_task *task)
|
||||||
{
|
{
|
||||||
int status = 0;
|
struct rpc_wait_queue *queue;
|
||||||
|
int task_is_async = RPC_IS_ASYNC(task);
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
dprintk("RPC: %5u __rpc_execute flags=0x%x\n",
|
dprintk("RPC: %5u __rpc_execute flags=0x%x\n",
|
||||||
task->tk_pid, task->tk_flags);
|
task->tk_pid, task->tk_flags);
|
||||||
|
@ -647,15 +644,25 @@ static void __rpc_execute(struct rpc_task *task)
|
||||||
*/
|
*/
|
||||||
if (!RPC_IS_QUEUED(task))
|
if (!RPC_IS_QUEUED(task))
|
||||||
continue;
|
continue;
|
||||||
rpc_clear_running(task);
|
/*
|
||||||
if (RPC_IS_ASYNC(task)) {
|
* The queue->lock protects against races with
|
||||||
/* Careful! we may have raced... */
|
* rpc_make_runnable().
|
||||||
if (RPC_IS_QUEUED(task))
|
*
|
||||||
return;
|
* Note that once we clear RPC_TASK_RUNNING on an asynchronous
|
||||||
if (rpc_test_and_set_running(task))
|
* rpc_task, rpc_make_runnable() can assign it to a
|
||||||
return;
|
* different workqueue. We therefore cannot assume that the
|
||||||
|
* rpc_task pointer may still be dereferenced.
|
||||||
|
*/
|
||||||
|
queue = task->tk_waitqueue;
|
||||||
|
spin_lock_bh(&queue->lock);
|
||||||
|
if (!RPC_IS_QUEUED(task)) {
|
||||||
|
spin_unlock_bh(&queue->lock);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
rpc_clear_running(task);
|
||||||
|
spin_unlock_bh(&queue->lock);
|
||||||
|
if (task_is_async)
|
||||||
|
return;
|
||||||
|
|
||||||
/* sync task: sleep here */
|
/* sync task: sleep here */
|
||||||
dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid);
|
dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid);
|
||||||
|
|
|
@ -663,7 +663,7 @@ void xprt_connect(struct rpc_task *task)
|
||||||
xprt, (xprt_connected(xprt) ? "is" : "is not"));
|
xprt, (xprt_connected(xprt) ? "is" : "is not"));
|
||||||
|
|
||||||
if (!xprt_bound(xprt)) {
|
if (!xprt_bound(xprt)) {
|
||||||
task->tk_status = -EIO;
|
task->tk_status = -EAGAIN;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!xprt_lock_write(xprt, task))
|
if (!xprt_lock_write(xprt, task))
|
||||||
|
|
|
@ -467,7 +467,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
|
||||||
int err, sent = 0;
|
int err, sent = 0;
|
||||||
|
|
||||||
if (unlikely(!sock))
|
if (unlikely(!sock))
|
||||||
return -ENOTCONN;
|
return -ENOTSOCK;
|
||||||
|
|
||||||
clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
|
clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
|
||||||
if (base != 0) {
|
if (base != 0) {
|
||||||
|
@ -577,6 +577,8 @@ static int xs_udp_send_request(struct rpc_task *task)
|
||||||
req->rq_svec->iov_base,
|
req->rq_svec->iov_base,
|
||||||
req->rq_svec->iov_len);
|
req->rq_svec->iov_len);
|
||||||
|
|
||||||
|
if (!xprt_bound(xprt))
|
||||||
|
return -ENOTCONN;
|
||||||
status = xs_sendpages(transport->sock,
|
status = xs_sendpages(transport->sock,
|
||||||
xs_addr(xprt),
|
xs_addr(xprt),
|
||||||
xprt->addrlen, xdr,
|
xprt->addrlen, xdr,
|
||||||
|
@ -594,6 +596,10 @@ static int xs_udp_send_request(struct rpc_task *task)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
case -ENOTSOCK:
|
||||||
|
status = -ENOTCONN;
|
||||||
|
/* Should we call xs_close() here? */
|
||||||
|
break;
|
||||||
case -EAGAIN:
|
case -EAGAIN:
|
||||||
xs_nospace(task);
|
xs_nospace(task);
|
||||||
break;
|
break;
|
||||||
|
@ -693,6 +699,10 @@ static int xs_tcp_send_request(struct rpc_task *task)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
case -ENOTSOCK:
|
||||||
|
status = -ENOTCONN;
|
||||||
|
/* Should we call xs_close() here? */
|
||||||
|
break;
|
||||||
case -EAGAIN:
|
case -EAGAIN:
|
||||||
xs_nospace(task);
|
xs_nospace(task);
|
||||||
break;
|
break;
|
||||||
|
@ -1523,7 +1533,7 @@ static void xs_udp_connect_worker4(struct work_struct *work)
|
||||||
struct socket *sock = transport->sock;
|
struct socket *sock = transport->sock;
|
||||||
int err, status = -EIO;
|
int err, status = -EIO;
|
||||||
|
|
||||||
if (xprt->shutdown || !xprt_bound(xprt))
|
if (xprt->shutdown)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Start by resetting any existing state */
|
/* Start by resetting any existing state */
|
||||||
|
@ -1564,7 +1574,7 @@ static void xs_udp_connect_worker6(struct work_struct *work)
|
||||||
struct socket *sock = transport->sock;
|
struct socket *sock = transport->sock;
|
||||||
int err, status = -EIO;
|
int err, status = -EIO;
|
||||||
|
|
||||||
if (xprt->shutdown || !xprt_bound(xprt))
|
if (xprt->shutdown)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Start by resetting any existing state */
|
/* Start by resetting any existing state */
|
||||||
|
@ -1648,6 +1658,9 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
|
||||||
write_unlock_bh(&sk->sk_callback_lock);
|
write_unlock_bh(&sk->sk_callback_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!xprt_bound(xprt))
|
||||||
|
return -ENOTCONN;
|
||||||
|
|
||||||
/* Tell the socket layer to start connecting... */
|
/* Tell the socket layer to start connecting... */
|
||||||
xprt->stat.connect_count++;
|
xprt->stat.connect_count++;
|
||||||
xprt->stat.connect_start = jiffies;
|
xprt->stat.connect_start = jiffies;
|
||||||
|
@ -1668,7 +1681,7 @@ static void xs_tcp_connect_worker4(struct work_struct *work)
|
||||||
struct socket *sock = transport->sock;
|
struct socket *sock = transport->sock;
|
||||||
int err, status = -EIO;
|
int err, status = -EIO;
|
||||||
|
|
||||||
if (xprt->shutdown || !xprt_bound(xprt))
|
if (xprt->shutdown)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
|
@ -1728,7 +1741,7 @@ static void xs_tcp_connect_worker6(struct work_struct *work)
|
||||||
struct socket *sock = transport->sock;
|
struct socket *sock = transport->sock;
|
||||||
int err, status = -EIO;
|
int err, status = -EIO;
|
||||||
|
|
||||||
if (xprt->shutdown || !xprt_bound(xprt))
|
if (xprt->shutdown)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче