mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 01:33:00 -04:00
Merge branch 'for-2.6.38' of git://linux-nfs.org/~bfields/linux
* 'for-2.6.38' of git://linux-nfs.org/~bfields/linux: (62 commits) nfsd4: fix callback restarting nfsd: break lease on unlink, link, and rename nfsd4: break lease on nfsd setattr nfsd: don't support msnfs export option nfsd4: initialize cb_per_client nfsd4: allow restarting callbacks nfsd4: simplify nfsd4_cb_prepare nfsd4: give out delegations more quickly in 4.1 case nfsd4: add helper function to run callbacks nfsd4: make sure sequence flags are set after destroy_session nfsd4: re-probe callback on connection loss nfsd4: set sequence flag when backchannel is down nfsd4: keep finer-grained callback status rpc: allow xprt_class->setup to return a preexisting xprt rpc: keep backchannel xprt as long as server connection rpc: move sk_bc_xprt to svc_xprt nfsd4: allow backchannel recovery nfsd4: support BIND_CONN_TO_SESSION nfsd4: modify session list under cl_lock Documentation: fl_mylease no longer exists ... Fix up conflicts in fs/nfsd/vfs.c with the vfs-scale work. The vfs-scale work touched some msnfs cases, and this merge removes support for that entirely, so the conflict was trivial to resolve.
This commit is contained in:
commit
18bce371ae
38 changed files with 608 additions and 383 deletions
|
|
@ -137,7 +137,7 @@ arcfour_hmac_md5_usage_to_salt(unsigned int usage, u8 salt[4])
|
|||
ms_usage = 13;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;;
|
||||
return -EINVAL;
|
||||
}
|
||||
salt[0] = (ms_usage >> 0) & 0xff;
|
||||
salt[1] = (ms_usage >> 8) & 0xff;
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ static int netobj_equal(struct xdr_netobj *a, struct xdr_netobj *b)
|
|||
|
||||
#define RSI_HASHBITS 6
|
||||
#define RSI_HASHMAX (1<<RSI_HASHBITS)
|
||||
#define RSI_HASHMASK (RSI_HASHMAX-1)
|
||||
|
||||
struct rsi {
|
||||
struct cache_head h;
|
||||
|
|
@ -319,7 +318,6 @@ static struct rsi *rsi_update(struct rsi *new, struct rsi *old)
|
|||
|
||||
#define RSC_HASHBITS 10
|
||||
#define RSC_HASHMAX (1<<RSC_HASHBITS)
|
||||
#define RSC_HASHMASK (RSC_HASHMAX-1)
|
||||
|
||||
#define GSS_SEQ_WIN 128
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#define RPCDBG_FACILITY RPCDBG_CACHE
|
||||
|
||||
static void cache_defer_req(struct cache_req *req, struct cache_head *item);
|
||||
static bool cache_defer_req(struct cache_req *req, struct cache_head *item);
|
||||
static void cache_revisit_request(struct cache_head *item);
|
||||
|
||||
static void cache_init(struct cache_head *h)
|
||||
|
|
@ -128,6 +128,7 @@ static void cache_fresh_locked(struct cache_head *head, time_t expiry)
|
|||
{
|
||||
head->expiry_time = expiry;
|
||||
head->last_refresh = seconds_since_boot();
|
||||
smp_wmb(); /* paired with smp_rmb() in cache_is_valid() */
|
||||
set_bit(CACHE_VALID, &head->flags);
|
||||
}
|
||||
|
||||
|
|
@ -208,11 +209,36 @@ static inline int cache_is_valid(struct cache_detail *detail, struct cache_head
|
|||
/* entry is valid */
|
||||
if (test_bit(CACHE_NEGATIVE, &h->flags))
|
||||
return -ENOENT;
|
||||
else
|
||||
else {
|
||||
/*
|
||||
* In combination with write barrier in
|
||||
* sunrpc_cache_update, ensures that anyone
|
||||
* using the cache entry after this sees the
|
||||
* updated contents:
|
||||
*/
|
||||
smp_rmb();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int try_to_negate_entry(struct cache_detail *detail, struct cache_head *h)
|
||||
{
|
||||
int rv;
|
||||
|
||||
write_lock(&detail->hash_lock);
|
||||
rv = cache_is_valid(detail, h);
|
||||
if (rv != -EAGAIN) {
|
||||
write_unlock(&detail->hash_lock);
|
||||
return rv;
|
||||
}
|
||||
set_bit(CACHE_NEGATIVE, &h->flags);
|
||||
cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY);
|
||||
write_unlock(&detail->hash_lock);
|
||||
cache_fresh_unlocked(h, detail);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the generic cache management routine for all
|
||||
* the authentication caches.
|
||||
|
|
@ -251,14 +277,8 @@ int cache_check(struct cache_detail *detail,
|
|||
case -EINVAL:
|
||||
clear_bit(CACHE_PENDING, &h->flags);
|
||||
cache_revisit_request(h);
|
||||
if (rv == -EAGAIN) {
|
||||
set_bit(CACHE_NEGATIVE, &h->flags);
|
||||
cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY);
|
||||
cache_fresh_unlocked(h, detail);
|
||||
rv = -ENOENT;
|
||||
}
|
||||
rv = try_to_negate_entry(detail, h);
|
||||
break;
|
||||
|
||||
case -EAGAIN:
|
||||
clear_bit(CACHE_PENDING, &h->flags);
|
||||
cache_revisit_request(h);
|
||||
|
|
@ -268,9 +288,11 @@ int cache_check(struct cache_detail *detail,
|
|||
}
|
||||
|
||||
if (rv == -EAGAIN) {
|
||||
cache_defer_req(rqstp, h);
|
||||
if (!test_bit(CACHE_PENDING, &h->flags)) {
|
||||
/* Request is not deferred */
|
||||
if (!cache_defer_req(rqstp, h)) {
|
||||
/*
|
||||
* Request was not deferred; handle it as best
|
||||
* we can ourselves:
|
||||
*/
|
||||
rv = cache_is_valid(detail, h);
|
||||
if (rv == -EAGAIN)
|
||||
rv = -ETIMEDOUT;
|
||||
|
|
@ -618,18 +640,19 @@ static void cache_limit_defers(void)
|
|||
discard->revisit(discard, 1);
|
||||
}
|
||||
|
||||
static void cache_defer_req(struct cache_req *req, struct cache_head *item)
|
||||
/* Return true if and only if a deferred request is queued. */
|
||||
static bool cache_defer_req(struct cache_req *req, struct cache_head *item)
|
||||
{
|
||||
struct cache_deferred_req *dreq;
|
||||
|
||||
if (req->thread_wait) {
|
||||
cache_wait_req(req, item);
|
||||
if (!test_bit(CACHE_PENDING, &item->flags))
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
dreq = req->defer(req);
|
||||
if (dreq == NULL)
|
||||
return;
|
||||
return false;
|
||||
setup_deferral(dreq, item, 1);
|
||||
if (!test_bit(CACHE_PENDING, &item->flags))
|
||||
/* Bit could have been cleared before we managed to
|
||||
|
|
@ -638,6 +661,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)
|
|||
cache_revisit_request(item);
|
||||
|
||||
cache_limit_defers();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cache_revisit_request(struct cache_head *item)
|
||||
|
|
|
|||
|
|
@ -1001,6 +1001,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
|
|||
rqstp->rq_splice_ok = 1;
|
||||
/* Will be turned off only when NFSv4 Sessions are used */
|
||||
rqstp->rq_usedeferral = 1;
|
||||
rqstp->rq_dropme = false;
|
||||
|
||||
/* Setup reply header */
|
||||
rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp);
|
||||
|
|
@ -1102,7 +1103,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
|
|||
*statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
|
||||
|
||||
/* Encode reply */
|
||||
if (*statp == rpc_drop_reply) {
|
||||
if (rqstp->rq_dropme) {
|
||||
if (procp->pc_release)
|
||||
procp->pc_release(rqstp, NULL, rqstp->rq_resp);
|
||||
goto dropit;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/sunrpc/stats.h>
|
||||
#include <linux/sunrpc/svc_xprt.h>
|
||||
#include <linux/sunrpc/svcsock.h>
|
||||
#include <linux/sunrpc/xprt.h>
|
||||
|
||||
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
|
||||
|
||||
|
|
@ -128,6 +129,9 @@ static void svc_xprt_free(struct kref *kref)
|
|||
if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags))
|
||||
svcauth_unix_info_release(xprt);
|
||||
put_net(xprt->xpt_net);
|
||||
/* See comment on corresponding get in xs_setup_bc_tcp(): */
|
||||
if (xprt->xpt_bc_xprt)
|
||||
xprt_put(xprt->xpt_bc_xprt);
|
||||
xprt->xpt_ops->xpo_free(xprt);
|
||||
module_put(owner);
|
||||
}
|
||||
|
|
@ -303,6 +307,15 @@ static void svc_thread_dequeue(struct svc_pool *pool, struct svc_rqst *rqstp)
|
|||
list_del(&rqstp->rq_list);
|
||||
}
|
||||
|
||||
static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt)
|
||||
{
|
||||
if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE)))
|
||||
return true;
|
||||
if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED)))
|
||||
return xprt->xpt_ops->xpo_has_wspace(xprt);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Queue up a transport with data pending. If there are idle nfsd
|
||||
* processes, wake 'em up.
|
||||
|
|
@ -315,8 +328,7 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
|
|||
struct svc_rqst *rqstp;
|
||||
int cpu;
|
||||
|
||||
if (!(xprt->xpt_flags &
|
||||
((1<<XPT_CONN)|(1<<XPT_DATA)|(1<<XPT_CLOSE)|(1<<XPT_DEFERRED))))
|
||||
if (!svc_xprt_has_something_to_do(xprt))
|
||||
return;
|
||||
|
||||
cpu = get_cpu();
|
||||
|
|
@ -343,28 +355,7 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
|
|||
dprintk("svc: transport %p busy, not enqueued\n", xprt);
|
||||
goto out_unlock;
|
||||
}
|
||||
BUG_ON(xprt->xpt_pool != NULL);
|
||||
xprt->xpt_pool = pool;
|
||||
|
||||
/* Handle pending connection */
|
||||
if (test_bit(XPT_CONN, &xprt->xpt_flags))
|
||||
goto process;
|
||||
|
||||
/* Handle close in-progress */
|
||||
if (test_bit(XPT_CLOSE, &xprt->xpt_flags))
|
||||
goto process;
|
||||
|
||||
/* Check if we have space to reply to a request */
|
||||
if (!xprt->xpt_ops->xpo_has_wspace(xprt)) {
|
||||
/* Don't enqueue while not enough space for reply */
|
||||
dprintk("svc: no write space, transport %p not enqueued\n",
|
||||
xprt);
|
||||
xprt->xpt_pool = NULL;
|
||||
clear_bit(XPT_BUSY, &xprt->xpt_flags);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
process:
|
||||
if (!list_empty(&pool->sp_threads)) {
|
||||
rqstp = list_entry(pool->sp_threads.next,
|
||||
struct svc_rqst,
|
||||
|
|
@ -381,13 +372,11 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
|
|||
rqstp->rq_reserved = serv->sv_max_mesg;
|
||||
atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
|
||||
pool->sp_stats.threads_woken++;
|
||||
BUG_ON(xprt->xpt_pool != pool);
|
||||
wake_up(&rqstp->rq_wait);
|
||||
} else {
|
||||
dprintk("svc: transport %p put into queue\n", xprt);
|
||||
list_add_tail(&xprt->xpt_ready, &pool->sp_sockets);
|
||||
pool->sp_stats.sockets_queued++;
|
||||
BUG_ON(xprt->xpt_pool != pool);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
|
|
@ -426,7 +415,6 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool)
|
|||
void svc_xprt_received(struct svc_xprt *xprt)
|
||||
{
|
||||
BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
|
||||
xprt->xpt_pool = NULL;
|
||||
/* As soon as we clear busy, the xprt could be closed and
|
||||
* 'put', so we need a reference to call svc_xprt_enqueue with:
|
||||
*/
|
||||
|
|
@ -722,7 +710,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
|
|||
if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
|
||||
dprintk("svc_recv: found XPT_CLOSE\n");
|
||||
svc_delete_xprt(xprt);
|
||||
} else if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
|
||||
/* Leave XPT_BUSY set on the dead xprt: */
|
||||
goto out;
|
||||
}
|
||||
if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
|
||||
struct svc_xprt *newxpt;
|
||||
newxpt = xprt->xpt_ops->xpo_accept(xprt);
|
||||
if (newxpt) {
|
||||
|
|
@ -747,28 +738,23 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
|
|||
spin_unlock_bh(&serv->sv_lock);
|
||||
svc_xprt_received(newxpt);
|
||||
}
|
||||
svc_xprt_received(xprt);
|
||||
} else {
|
||||
} else if (xprt->xpt_ops->xpo_has_wspace(xprt)) {
|
||||
dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
|
||||
rqstp, pool->sp_id, xprt,
|
||||
atomic_read(&xprt->xpt_ref.refcount));
|
||||
rqstp->rq_deferred = svc_deferred_dequeue(xprt);
|
||||
if (rqstp->rq_deferred) {
|
||||
svc_xprt_received(xprt);
|
||||
if (rqstp->rq_deferred)
|
||||
len = svc_deferred_recv(rqstp);
|
||||
} else {
|
||||
else
|
||||
len = xprt->xpt_ops->xpo_recvfrom(rqstp);
|
||||
svc_xprt_received(xprt);
|
||||
}
|
||||
dprintk("svc: got len=%d\n", len);
|
||||
}
|
||||
svc_xprt_received(xprt);
|
||||
|
||||
/* No data, incomplete (TCP) read, or accept() */
|
||||
if (len == 0 || len == -EAGAIN) {
|
||||
rqstp->rq_res.len = 0;
|
||||
svc_xprt_release(rqstp);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (len == 0 || len == -EAGAIN)
|
||||
goto out;
|
||||
|
||||
clear_bit(XPT_OLD, &xprt->xpt_flags);
|
||||
|
||||
rqstp->rq_secure = svc_port_is_privileged(svc_addr(rqstp));
|
||||
|
|
@ -777,6 +763,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
|
|||
if (serv->sv_stats)
|
||||
serv->sv_stats->netcnt++;
|
||||
return len;
|
||||
out:
|
||||
rqstp->rq_res.len = 0;
|
||||
svc_xprt_release(rqstp);
|
||||
return -EAGAIN;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(svc_recv);
|
||||
|
||||
|
|
@ -935,7 +925,12 @@ void svc_close_xprt(struct svc_xprt *xprt)
|
|||
if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags))
|
||||
/* someone else will have to effect the close */
|
||||
return;
|
||||
|
||||
/*
|
||||
* We expect svc_close_xprt() to work even when no threads are
|
||||
* running (e.g., while configuring the server before starting
|
||||
* any threads), so if the transport isn't busy, we delete
|
||||
* it ourself:
|
||||
*/
|
||||
svc_delete_xprt(xprt);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(svc_close_xprt);
|
||||
|
|
@ -945,16 +940,16 @@ void svc_close_all(struct list_head *xprt_list)
|
|||
struct svc_xprt *xprt;
|
||||
struct svc_xprt *tmp;
|
||||
|
||||
/*
|
||||
* The server is shutting down, and no more threads are running.
|
||||
* svc_xprt_enqueue() might still be running, but at worst it
|
||||
* will re-add the xprt to sp_sockets, which will soon get
|
||||
* freed. So we don't bother with any more locking, and don't
|
||||
* leave the close to the (nonexistent) server threads:
|
||||
*/
|
||||
list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) {
|
||||
set_bit(XPT_CLOSE, &xprt->xpt_flags);
|
||||
if (test_bit(XPT_BUSY, &xprt->xpt_flags)) {
|
||||
/* Waiting to be processed, but no threads left,
|
||||
* So just remove it from the waiting list
|
||||
*/
|
||||
list_del_init(&xprt->xpt_ready);
|
||||
clear_bit(XPT_BUSY, &xprt->xpt_flags);
|
||||
}
|
||||
svc_close_xprt(xprt);
|
||||
svc_delete_xprt(xprt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1028,6 +1023,7 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
|
|||
}
|
||||
svc_xprt_get(rqstp->rq_xprt);
|
||||
dr->xprt = rqstp->rq_xprt;
|
||||
rqstp->rq_dropme = true;
|
||||
|
||||
dr->handle.revisit = svc_revisit;
|
||||
return &dr->handle;
|
||||
|
|
@ -1065,14 +1061,13 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt)
|
|||
if (!test_bit(XPT_DEFERRED, &xprt->xpt_flags))
|
||||
return NULL;
|
||||
spin_lock(&xprt->xpt_lock);
|
||||
clear_bit(XPT_DEFERRED, &xprt->xpt_flags);
|
||||
if (!list_empty(&xprt->xpt_deferred)) {
|
||||
dr = list_entry(xprt->xpt_deferred.next,
|
||||
struct svc_deferred_req,
|
||||
handle.recent);
|
||||
list_del_init(&dr->handle.recent);
|
||||
set_bit(XPT_DEFERRED, &xprt->xpt_flags);
|
||||
}
|
||||
} else
|
||||
clear_bit(XPT_DEFERRED, &xprt->xpt_flags);
|
||||
spin_unlock(&xprt->xpt_lock);
|
||||
return dr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ EXPORT_SYMBOL_GPL(svc_auth_unregister);
|
|||
|
||||
#define DN_HASHBITS 6
|
||||
#define DN_HASHMAX (1<<DN_HASHBITS)
|
||||
#define DN_HASHMASK (DN_HASHMAX-1)
|
||||
|
||||
static struct hlist_head auth_domain_table[DN_HASHMAX];
|
||||
static spinlock_t auth_domain_lock =
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@
|
|||
|
||||
struct unix_domain {
|
||||
struct auth_domain h;
|
||||
#ifdef CONFIG_NFSD_DEPRECATED
|
||||
int addr_changes;
|
||||
#endif /* CONFIG_NFSD_DEPRECATED */
|
||||
/* other stuff later */
|
||||
};
|
||||
|
||||
|
|
@ -64,7 +66,9 @@ struct auth_domain *unix_domain_find(char *name)
|
|||
return NULL;
|
||||
}
|
||||
new->h.flavour = &svcauth_unix;
|
||||
#ifdef CONFIG_NFSD_DEPRECATED
|
||||
new->addr_changes = 0;
|
||||
#endif /* CONFIG_NFSD_DEPRECATED */
|
||||
rv = auth_domain_lookup(name, &new->h);
|
||||
}
|
||||
}
|
||||
|
|
@ -85,14 +89,15 @@ static void svcauth_unix_domain_release(struct auth_domain *dom)
|
|||
*/
|
||||
#define IP_HASHBITS 8
|
||||
#define IP_HASHMAX (1<<IP_HASHBITS)
|
||||
#define IP_HASHMASK (IP_HASHMAX-1)
|
||||
|
||||
struct ip_map {
|
||||
struct cache_head h;
|
||||
char m_class[8]; /* e.g. "nfsd" */
|
||||
struct in6_addr m_addr;
|
||||
struct unix_domain *m_client;
|
||||
#ifdef CONFIG_NFSD_DEPRECATED
|
||||
int m_add_change;
|
||||
#endif /* CONFIG_NFSD_DEPRECATED */
|
||||
};
|
||||
|
||||
static void ip_map_put(struct kref *kref)
|
||||
|
|
@ -146,7 +151,9 @@ static void update(struct cache_head *cnew, struct cache_head *citem)
|
|||
|
||||
kref_get(&item->m_client->h.ref);
|
||||
new->m_client = item->m_client;
|
||||
#ifdef CONFIG_NFSD_DEPRECATED
|
||||
new->m_add_change = item->m_add_change;
|
||||
#endif /* CONFIG_NFSD_DEPRECATED */
|
||||
}
|
||||
static struct cache_head *ip_map_alloc(void)
|
||||
{
|
||||
|
|
@ -331,6 +338,7 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
|
|||
ip.h.flags = 0;
|
||||
if (!udom)
|
||||
set_bit(CACHE_NEGATIVE, &ip.h.flags);
|
||||
#ifdef CONFIG_NFSD_DEPRECATED
|
||||
else {
|
||||
ip.m_add_change = udom->addr_changes;
|
||||
/* if this is from the legacy set_client system call,
|
||||
|
|
@ -339,6 +347,7 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
|
|||
if (expiry == NEVER)
|
||||
ip.m_add_change++;
|
||||
}
|
||||
#endif /* CONFIG_NFSD_DEPRECATED */
|
||||
ip.h.expiry_time = expiry;
|
||||
ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
|
||||
hash_str(ipm->m_class, IP_HASHBITS) ^
|
||||
|
|
@ -358,6 +367,7 @@ static inline int ip_map_update(struct net *net, struct ip_map *ipm,
|
|||
return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NFSD_DEPRECATED
|
||||
int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom)
|
||||
{
|
||||
struct unix_domain *udom;
|
||||
|
|
@ -402,8 +412,7 @@ struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
|
|||
return NULL;
|
||||
|
||||
if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
|
||||
if (test_and_set_bit(CACHE_NEGATIVE, &ipm->h.flags) == 0)
|
||||
auth_domain_put(&ipm->m_client->h);
|
||||
sunrpc_invalidate(&ipm->h, sn->ip_map_cache);
|
||||
rv = NULL;
|
||||
} else {
|
||||
rv = &ipm->m_client->h;
|
||||
|
|
@ -413,6 +422,7 @@ struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
|
|||
return rv;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(auth_unix_lookup);
|
||||
#endif /* CONFIG_NFSD_DEPRECATED */
|
||||
|
||||
void svcauth_unix_purge(void)
|
||||
{
|
||||
|
|
@ -497,7 +507,6 @@ svcauth_unix_info_release(struct svc_xprt *xpt)
|
|||
*/
|
||||
#define GID_HASHBITS 8
|
||||
#define GID_HASHMAX (1<<GID_HASHBITS)
|
||||
#define GID_HASHMASK (GID_HASHMAX - 1)
|
||||
|
||||
struct unix_gid {
|
||||
struct cache_head h;
|
||||
|
|
|
|||
|
|
@ -331,19 +331,21 @@ int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen,
|
|||
len = onelen;
|
||||
break;
|
||||
}
|
||||
if (toclose && strcmp(toclose, buf + len) == 0)
|
||||
if (toclose && strcmp(toclose, buf + len) == 0) {
|
||||
closesk = svsk;
|
||||
else
|
||||
svc_xprt_get(&closesk->sk_xprt);
|
||||
} else
|
||||
len += onelen;
|
||||
}
|
||||
spin_unlock_bh(&serv->sv_lock);
|
||||
|
||||
if (closesk)
|
||||
if (closesk) {
|
||||
/* Should unregister with portmap, but you cannot
|
||||
* unregister just one protocol...
|
||||
*/
|
||||
svc_close_xprt(&closesk->sk_xprt);
|
||||
else if (toclose)
|
||||
svc_xprt_put(&closesk->sk_xprt);
|
||||
} else if (toclose)
|
||||
return -ENOENT;
|
||||
return len;
|
||||
}
|
||||
|
|
@ -992,15 +994,17 @@ static int svc_process_calldir(struct svc_sock *svsk, struct svc_rqst *rqstp,
|
|||
vec[0] = rqstp->rq_arg.head[0];
|
||||
} else {
|
||||
/* REPLY */
|
||||
if (svsk->sk_bc_xprt)
|
||||
req = xprt_lookup_rqst(svsk->sk_bc_xprt, xid);
|
||||
struct rpc_xprt *bc_xprt = svsk->sk_xprt.xpt_bc_xprt;
|
||||
|
||||
if (bc_xprt)
|
||||
req = xprt_lookup_rqst(bc_xprt, xid);
|
||||
|
||||
if (!req) {
|
||||
printk(KERN_NOTICE
|
||||
"%s: Got unrecognized reply: "
|
||||
"calldir 0x%x sk_bc_xprt %p xid %08x\n",
|
||||
"calldir 0x%x xpt_bc_xprt %p xid %08x\n",
|
||||
__func__, ntohl(calldir),
|
||||
svsk->sk_bc_xprt, xid);
|
||||
bc_xprt, xid);
|
||||
vec[0] = rqstp->rq_arg.head[0];
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -965,6 +965,7 @@ struct rpc_xprt *xprt_alloc(struct net *net, int size, int max_req)
|
|||
xprt = kzalloc(size, GFP_KERNEL);
|
||||
if (xprt == NULL)
|
||||
goto out;
|
||||
kref_init(&xprt->kref);
|
||||
|
||||
xprt->max_reqs = max_req;
|
||||
xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL);
|
||||
|
|
@ -1101,8 +1102,10 @@ found:
|
|||
-PTR_ERR(xprt));
|
||||
return xprt;
|
||||
}
|
||||
if (test_and_set_bit(XPRT_INITIALIZED, &xprt->state))
|
||||
/* ->setup returned a pre-initialized xprt: */
|
||||
return xprt;
|
||||
|
||||
kref_init(&xprt->kref);
|
||||
spin_lock_init(&xprt->transport_lock);
|
||||
spin_lock_init(&xprt->reserve_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -2359,6 +2359,15 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
|
|||
struct svc_sock *bc_sock;
|
||||
struct rpc_xprt *ret;
|
||||
|
||||
if (args->bc_xprt->xpt_bc_xprt) {
|
||||
/*
|
||||
* This server connection already has a backchannel
|
||||
* export; we can't create a new one, as we wouldn't be
|
||||
* able to match replies based on xid any more. So,
|
||||
* reuse the already-existing one:
|
||||
*/
|
||||
return args->bc_xprt->xpt_bc_xprt;
|
||||
}
|
||||
xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
|
||||
if (IS_ERR(xprt))
|
||||
return xprt;
|
||||
|
|
@ -2375,16 +2384,6 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
|
|||
xprt->reestablish_timeout = 0;
|
||||
xprt->idle_timeout = 0;
|
||||
|
||||
/*
|
||||
* The backchannel uses the same socket connection as the
|
||||
* forechannel
|
||||
*/
|
||||
xprt->bc_xprt = args->bc_xprt;
|
||||
bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt);
|
||||
bc_sock->sk_bc_xprt = xprt;
|
||||
transport->sock = bc_sock->sk_sock;
|
||||
transport->inet = bc_sock->sk_sk;
|
||||
|
||||
xprt->ops = &bc_tcp_ops;
|
||||
|
||||
switch (addr->sa_family) {
|
||||
|
|
@ -2406,6 +2405,20 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
|
|||
xprt->address_strings[RPC_DISPLAY_PORT],
|
||||
xprt->address_strings[RPC_DISPLAY_PROTO]);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
xprt_get(xprt);
|
||||
args->bc_xprt->xpt_bc_xprt = xprt;
|
||||
xprt->bc_xprt = args->bc_xprt;
|
||||
bc_sock = container_of(args->bc_xprt, struct svc_sock, sk_xprt);
|
||||
transport->sock = bc_sock->sk_sock;
|
||||
transport->inet = bc_sock->sk_sk;
|
||||
|
||||
/*
|
||||
* Since we don't want connections for the backchannel, we set
|
||||
* the xprt status to connected
|
||||
|
|
@ -2415,6 +2428,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
|
|||
|
||||
if (try_module_get(THIS_MODULE))
|
||||
return xprt;
|
||||
xprt_put(xprt);
|
||||
ret = ERR_PTR(-EINVAL);
|
||||
out_err:
|
||||
xprt_free(xprt);
|
||||
|
|
|
|||
Loading…
Reference in a new issue