mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-20 00:26:39 +08:00
Merge branch 'fixes' of git://git.linux-nfs.org/pub/linux/nfs-2.6
* 'fixes' of git://git.linux-nfs.org/pub/linux/nfs-2.6: SUNRPC: Fix obvious refcounting bugs in rpc_pipefs. RPC: Ensure that we disconnect TCP socket when client requests error out NLM/lockd: remove b_done NFS: make 2 functions static NFS: Release dcache_lock in an error path of nfs_path
This commit is contained in:
commit
3b445eeac4
@ -638,9 +638,6 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
|
|||||||
if (task->tk_status < 0) {
|
if (task->tk_status < 0) {
|
||||||
/* RPC error: Re-insert for retransmission */
|
/* RPC error: Re-insert for retransmission */
|
||||||
timeout = 10 * HZ;
|
timeout = 10 * HZ;
|
||||||
} else if (block->b_done) {
|
|
||||||
/* Block already removed, kill it for real */
|
|
||||||
timeout = 0;
|
|
||||||
} else {
|
} else {
|
||||||
/* Call was successful, now wait for client callback */
|
/* Call was successful, now wait for client callback */
|
||||||
timeout = 60 * HZ;
|
timeout = 60 * HZ;
|
||||||
@ -709,13 +706,10 @@ nlmsvc_retry_blocked(void)
|
|||||||
break;
|
break;
|
||||||
if (time_after(block->b_when,jiffies))
|
if (time_after(block->b_when,jiffies))
|
||||||
break;
|
break;
|
||||||
dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n",
|
dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
|
||||||
block, block->b_when, block->b_done);
|
block, block->b_when);
|
||||||
kref_get(&block->b_count);
|
kref_get(&block->b_count);
|
||||||
if (block->b_done)
|
nlmsvc_grant_blocked(block);
|
||||||
nlmsvc_unlink_block(block);
|
|
||||||
else
|
|
||||||
nlmsvc_grant_blocked(block);
|
|
||||||
nlmsvc_release_block(block);
|
nlmsvc_release_block(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ char *nfs_path(const char *base, const struct dentry *dentry,
|
|||||||
namelen = dentry->d_name.len;
|
namelen = dentry->d_name.len;
|
||||||
buflen -= namelen + 1;
|
buflen -= namelen + 1;
|
||||||
if (buflen < 0)
|
if (buflen < 0)
|
||||||
goto Elong;
|
goto Elong_unlock;
|
||||||
end -= namelen;
|
end -= namelen;
|
||||||
memcpy(end, dentry->d_name.name, namelen);
|
memcpy(end, dentry->d_name.name, namelen);
|
||||||
*--end = '/';
|
*--end = '/';
|
||||||
@ -68,6 +68,8 @@ char *nfs_path(const char *base, const struct dentry *dentry,
|
|||||||
end -= namelen;
|
end -= namelen;
|
||||||
memcpy(end, base, namelen);
|
memcpy(end, base, namelen);
|
||||||
return end;
|
return end;
|
||||||
|
Elong_unlock:
|
||||||
|
spin_unlock(&dcache_lock);
|
||||||
Elong:
|
Elong:
|
||||||
return ERR_PTR(-ENAMETOOLONG);
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfs_readdata_free(struct nfs_read_data *p)
|
static void nfs_readdata_free(struct nfs_read_data *p)
|
||||||
{
|
{
|
||||||
if (p && (p->pagevec != &p->page_array[0]))
|
if (p && (p->pagevec != &p->page_array[0]))
|
||||||
kfree(p->pagevec);
|
kfree(p->pagevec);
|
||||||
|
@ -137,7 +137,7 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfs_writedata_free(struct nfs_write_data *p)
|
static void nfs_writedata_free(struct nfs_write_data *p)
|
||||||
{
|
{
|
||||||
if (p && (p->pagevec != &p->page_array[0]))
|
if (p && (p->pagevec != &p->page_array[0]))
|
||||||
kfree(p->pagevec);
|
kfree(p->pagevec);
|
||||||
|
@ -123,7 +123,6 @@ struct nlm_block {
|
|||||||
unsigned int b_id; /* block id */
|
unsigned int b_id; /* block id */
|
||||||
unsigned char b_queued; /* re-queued */
|
unsigned char b_queued; /* re-queued */
|
||||||
unsigned char b_granted; /* VFS granted lock */
|
unsigned char b_granted; /* VFS granted lock */
|
||||||
unsigned char b_done; /* callback complete */
|
|
||||||
struct nlm_file * b_file; /* file in question */
|
struct nlm_file * b_file; /* file in question */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -476,10 +476,9 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate and free nfs_write_data structures
|
* Allocate nfs_write_data structures
|
||||||
*/
|
*/
|
||||||
extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount);
|
extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount);
|
||||||
extern void nfs_writedata_free(struct nfs_write_data *p);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* linux/fs/nfs/read.c
|
* linux/fs/nfs/read.c
|
||||||
@ -491,10 +490,9 @@ extern int nfs_readpage_result(struct rpc_task *, struct nfs_read_data *);
|
|||||||
extern void nfs_readdata_release(void *data);
|
extern void nfs_readdata_release(void *data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate and free nfs_read_data structures
|
* Allocate nfs_read_data structures
|
||||||
*/
|
*/
|
||||||
extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount);
|
extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount);
|
||||||
extern void nfs_readdata_free(struct nfs_read_data *p);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* linux/fs/nfs3proc.c
|
* linux/fs/nfs3proc.c
|
||||||
|
@ -229,7 +229,7 @@ int xprt_reserve_xprt(struct rpc_task *task);
|
|||||||
int xprt_reserve_xprt_cong(struct rpc_task *task);
|
int xprt_reserve_xprt_cong(struct rpc_task *task);
|
||||||
int xprt_prepare_transmit(struct rpc_task *task);
|
int xprt_prepare_transmit(struct rpc_task *task);
|
||||||
void xprt_transmit(struct rpc_task *task);
|
void xprt_transmit(struct rpc_task *task);
|
||||||
void xprt_abort_transmit(struct rpc_task *task);
|
void xprt_end_transmit(struct rpc_task *task);
|
||||||
int xprt_adjust_timeout(struct rpc_rqst *req);
|
int xprt_adjust_timeout(struct rpc_rqst *req);
|
||||||
void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
|
void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||||
void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
|
void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||||
|
@ -921,26 +921,43 @@ call_transmit(struct rpc_task *task)
|
|||||||
task->tk_status = xprt_prepare_transmit(task);
|
task->tk_status = xprt_prepare_transmit(task);
|
||||||
if (task->tk_status != 0)
|
if (task->tk_status != 0)
|
||||||
return;
|
return;
|
||||||
|
task->tk_action = call_transmit_status;
|
||||||
/* Encode here so that rpcsec_gss can use correct sequence number. */
|
/* Encode here so that rpcsec_gss can use correct sequence number. */
|
||||||
if (rpc_task_need_encode(task)) {
|
if (rpc_task_need_encode(task)) {
|
||||||
task->tk_rqstp->rq_bytes_sent = 0;
|
BUG_ON(task->tk_rqstp->rq_bytes_sent != 0);
|
||||||
call_encode(task);
|
call_encode(task);
|
||||||
/* Did the encode result in an error condition? */
|
/* Did the encode result in an error condition? */
|
||||||
if (task->tk_status != 0)
|
if (task->tk_status != 0)
|
||||||
goto out_nosend;
|
return;
|
||||||
}
|
}
|
||||||
task->tk_action = call_transmit_status;
|
|
||||||
xprt_transmit(task);
|
xprt_transmit(task);
|
||||||
if (task->tk_status < 0)
|
if (task->tk_status < 0)
|
||||||
return;
|
return;
|
||||||
if (!task->tk_msg.rpc_proc->p_decode) {
|
/*
|
||||||
task->tk_action = rpc_exit_task;
|
* On success, ensure that we call xprt_end_transmit() before sleeping
|
||||||
rpc_wake_up_task(task);
|
* in order to allow access to the socket to other RPC requests.
|
||||||
}
|
*/
|
||||||
return;
|
call_transmit_status(task);
|
||||||
out_nosend:
|
if (task->tk_msg.rpc_proc->p_decode != NULL)
|
||||||
/* release socket write lock before attempting to handle error */
|
return;
|
||||||
xprt_abort_transmit(task);
|
task->tk_action = rpc_exit_task;
|
||||||
|
rpc_wake_up_task(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 5a. Handle cleanup after a transmission
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
call_transmit_status(struct rpc_task *task)
|
||||||
|
{
|
||||||
|
task->tk_action = call_status;
|
||||||
|
/*
|
||||||
|
* Special case: if we've been waiting on the socket's write_space()
|
||||||
|
* callback, then don't call xprt_end_transmit().
|
||||||
|
*/
|
||||||
|
if (task->tk_status == -EAGAIN)
|
||||||
|
return;
|
||||||
|
xprt_end_transmit(task);
|
||||||
rpc_task_force_reencode(task);
|
rpc_task_force_reencode(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,18 +1009,7 @@ call_status(struct rpc_task *task)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 6a. Handle transmission errors.
|
* 6a. Handle RPC timeout
|
||||||
*/
|
|
||||||
static void
|
|
||||||
call_transmit_status(struct rpc_task *task)
|
|
||||||
{
|
|
||||||
if (task->tk_status != -EAGAIN)
|
|
||||||
rpc_task_force_reencode(task);
|
|
||||||
call_status(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 6b. Handle RPC timeout
|
|
||||||
* We do not release the request slot, so we keep using the
|
* We do not release the request slot, so we keep using the
|
||||||
* same XID for all retransmits.
|
* same XID for all retransmits.
|
||||||
*/
|
*/
|
||||||
|
@ -667,10 +667,11 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
|
|||||||
RPCAUTH_info, RPCAUTH_EOF);
|
RPCAUTH_info, RPCAUTH_EOF);
|
||||||
if (error)
|
if (error)
|
||||||
goto err_depopulate;
|
goto err_depopulate;
|
||||||
|
dget(dentry);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dir->i_mutex);
|
mutex_unlock(&dir->i_mutex);
|
||||||
rpc_release_path(&nd);
|
rpc_release_path(&nd);
|
||||||
return dget(dentry);
|
return dentry;
|
||||||
err_depopulate:
|
err_depopulate:
|
||||||
rpc_depopulate(dentry);
|
rpc_depopulate(dentry);
|
||||||
__rpc_rmdir(dir, dentry);
|
__rpc_rmdir(dir, dentry);
|
||||||
@ -731,10 +732,11 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
|
|||||||
rpci->flags = flags;
|
rpci->flags = flags;
|
||||||
rpci->ops = ops;
|
rpci->ops = ops;
|
||||||
inode_dir_notify(dir, DN_CREATE);
|
inode_dir_notify(dir, DN_CREATE);
|
||||||
|
dget(dentry);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dir->i_mutex);
|
mutex_unlock(&dir->i_mutex);
|
||||||
rpc_release_path(&nd);
|
rpc_release_path(&nd);
|
||||||
return dget(dentry);
|
return dentry;
|
||||||
err_dput:
|
err_dput:
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
dentry = ERR_PTR(-ENOMEM);
|
dentry = ERR_PTR(-ENOMEM);
|
||||||
|
@ -707,12 +707,9 @@ out_unlock:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void xprt_end_transmit(struct rpc_task *task)
|
||||||
xprt_abort_transmit(struct rpc_task *task)
|
|
||||||
{
|
{
|
||||||
struct rpc_xprt *xprt = task->tk_xprt;
|
xprt_release_write(task->tk_xprt, task);
|
||||||
|
|
||||||
xprt_release_write(xprt, task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -761,8 +758,6 @@ void xprt_transmit(struct rpc_task *task)
|
|||||||
task->tk_status = -ENOTCONN;
|
task->tk_status = -ENOTCONN;
|
||||||
else if (!req->rq_received)
|
else if (!req->rq_received)
|
||||||
rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
|
rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
|
||||||
|
|
||||||
xprt->ops->release_xprt(xprt, task);
|
|
||||||
spin_unlock_bh(&xprt->transport_lock);
|
spin_unlock_bh(&xprt->transport_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -772,18 +767,8 @@ void xprt_transmit(struct rpc_task *task)
|
|||||||
* schedq, and being picked up by a parallel run of rpciod().
|
* schedq, and being picked up by a parallel run of rpciod().
|
||||||
*/
|
*/
|
||||||
task->tk_status = status;
|
task->tk_status = status;
|
||||||
|
if (status == -ECONNREFUSED)
|
||||||
switch (status) {
|
|
||||||
case -ECONNREFUSED:
|
|
||||||
rpc_sleep_on(&xprt->sending, task, NULL, NULL);
|
rpc_sleep_on(&xprt->sending, task, NULL, NULL);
|
||||||
case -EAGAIN:
|
|
||||||
case -ENOTCONN:
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
xprt_release_write(xprt, task);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void do_xprt_reserve(struct rpc_task *task)
|
static inline void do_xprt_reserve(struct rpc_task *task)
|
||||||
|
@ -413,6 +413,33 @@ static int xs_tcp_send_request(struct rpc_task *task)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xs_tcp_release_xprt - clean up after a tcp transmission
|
||||||
|
* @xprt: transport
|
||||||
|
* @task: rpc task
|
||||||
|
*
|
||||||
|
* This cleans up if an error causes us to abort the transmission of a request.
|
||||||
|
* In this case, the socket may need to be reset in order to avoid confusing
|
||||||
|
* the server.
|
||||||
|
*/
|
||||||
|
static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
|
||||||
|
{
|
||||||
|
struct rpc_rqst *req;
|
||||||
|
|
||||||
|
if (task != xprt->snd_task)
|
||||||
|
return;
|
||||||
|
if (task == NULL)
|
||||||
|
goto out_release;
|
||||||
|
req = task->tk_rqstp;
|
||||||
|
if (req->rq_bytes_sent == 0)
|
||||||
|
goto out_release;
|
||||||
|
if (req->rq_bytes_sent == req->rq_snd_buf.len)
|
||||||
|
goto out_release;
|
||||||
|
set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state);
|
||||||
|
out_release:
|
||||||
|
xprt_release_xprt(xprt, task);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xs_close - close a socket
|
* xs_close - close a socket
|
||||||
* @xprt: transport
|
* @xprt: transport
|
||||||
@ -1250,7 +1277,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
|
|||||||
|
|
||||||
static struct rpc_xprt_ops xs_tcp_ops = {
|
static struct rpc_xprt_ops xs_tcp_ops = {
|
||||||
.reserve_xprt = xprt_reserve_xprt,
|
.reserve_xprt = xprt_reserve_xprt,
|
||||||
.release_xprt = xprt_release_xprt,
|
.release_xprt = xs_tcp_release_xprt,
|
||||||
.set_port = xs_set_port,
|
.set_port = xs_set_port,
|
||||||
.connect = xs_connect,
|
.connect = xs_connect,
|
||||||
.buf_alloc = rpc_malloc,
|
.buf_alloc = rpc_malloc,
|
||||||
|
Loading…
Reference in New Issue
Block a user