Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 307085 Details for
Bug 448929
[RHEL5 U1] Kernel NFS Connectathon Test#12, 12.1 Failing
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Proposed patch
448929.rhel-5 (text/plain), 12.58 KB, created by
Peter Staubach
on 2008-05-29 15:12:19 UTC
(
hide
)
Description:
Proposed patch
Filename:
MIME Type:
Creator:
Peter Staubach
Created:
2008-05-29 15:12:19 UTC
Size:
12.58 KB
patch
obsolete
>--- linux-2.6.18.i686/fs/lockd/clntproc.c.org >+++ linux-2.6.18.i686/fs/lockd/clntproc.c >@@ -153,8 +153,6 @@ nlmclnt_proc(struct inode *inode, int cm > { > struct nlm_host *host; > struct nlm_rqst *call; >- sigset_t oldset; >- unsigned long flags; > int status, proto, vers; > > vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1; >@@ -178,22 +176,6 @@ nlmclnt_proc(struct inode *inode, int cm > /* Set up the argument struct */ > nlmclnt_setlockargs(call, fl); > >- /* Keep the old signal mask */ >- spin_lock_irqsave(¤t->sighand->siglock, flags); >- oldset = current->blocked; >- >- /* If we're cleaning up locks because the process is exiting, >- * perform the RPC call asynchronously. */ >- if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) >- && fl->fl_type == F_UNLCK >- && (current->flags & PF_EXITING)) { >- sigfillset(¤t->blocked); /* Mask all signals */ >- recalc_sigpending(); >- >- call->a_flags = RPC_TASK_ASYNC; >- } >- spin_unlock_irqrestore(¤t->sighand->siglock, flags); >- > if (IS_SETLK(cmd) || IS_SETLKW(cmd)) { > if (fl->fl_type != F_UNLCK) { > call->a_args.block = IS_SETLKW(cmd) ? 1 : 0; >@@ -208,11 +190,6 @@ nlmclnt_proc(struct inode *inode, int cm > fl->fl_ops->fl_release_private(fl); > fl->fl_ops = NULL; > >- spin_lock_irqsave(¤t->sighand->siglock, flags); >- current->blocked = oldset; >- recalc_sigpending(); >- spin_unlock_irqrestore(¤t->sighand->siglock, flags); >- > dprintk("lockd: clnt proc returns %d\n", status); > return status; > } >@@ -231,6 +208,7 @@ struct nlm_rqst *nlm_alloc_call(struct n > for(;;) { > call = kzalloc(sizeof(*call), GFP_KERNEL); > if (call != NULL) { >+ atomic_set(&call->a_count, 1); > locks_init_lock(&call->a_args.lock.fl); > locks_init_lock(&call->a_res.lock.fl); > call->a_host = host; >@@ -247,6 +225,8 @@ struct nlm_rqst *nlm_alloc_call(struct n > > void nlm_release_call(struct nlm_rqst *call) > { >+ if (!atomic_dec_and_test(&call->a_count)) >+ return; > nlm_release_host(call->a_host); > nlmclnt_release_lockargs(call); > kfree(call); >@@ -277,7 +257,7 @@ static int nlm_wait_on_grace(wait_queue_ > * Generic NLM call > */ > static int >-nlmclnt_call(struct nlm_rqst *req, u32 proc) >+nlmclnt_call(struct rpc_cred *cred, struct nlm_rqst *req, u32 proc) > { > struct nlm_host *host = req->a_host; > struct rpc_clnt *clnt; >@@ -286,6 +266,7 @@ nlmclnt_call(struct nlm_rqst *req, u32 p > struct rpc_message msg = { > .rpc_argp = argp, > .rpc_resp = resp, >+ .rpc_cred = cred, > }; > int status; > >@@ -353,10 +334,12 @@ in_grace_period: > /* > * Generic NLM call, async version. > */ >-static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops) >+static struct rpc_task *__nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops) > { > struct nlm_host *host = req->a_host; > struct rpc_clnt *clnt; >+ struct rpc_task *task; >+ int status = -ENOLCK; > > dprintk("lockd: call procedure %d on %s (async)\n", > (int)proc, host->h_name); >@@ -365,13 +348,42 @@ static int __nlm_async_call(struct nlm_r > clnt = nlm_bind_host(host); > if (clnt == NULL) > goto out_err; >+ status = -EIO; >+ if (clnt->cl_dead) >+ goto out_err; > msg->rpc_proc = &clnt->cl_procinfo[proc]; > > /* bootstrap and kick off the async RPC call */ >- return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req); >+ >+ status = -ENOMEM; >+ task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, req); >+ if (task == NULL) >+ goto out_err; >+ >+ rpc_call_setup(task, msg, 0); >+ >+ status = task->tk_status; >+ if (status != 0) >+ goto out_free; >+ atomic_inc(&task->tk_count); >+ rpc_execute(task); >+ return task; >+out_free: >+ rpc_put_task(task); > out_err: >- tk_ops->rpc_release(req); >- return -ENOLCK; >+ nlm_release_call(req); >+ return ERR_PTR(status); >+} >+ >+static int nlm_do_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops) >+{ >+ struct rpc_task *task; >+ >+ task = __nlm_async_call(req, proc, msg, tk_ops); >+ if (IS_ERR(task)) >+ return PTR_ERR(task); >+ rpc_put_task(task); >+ return 0; > } > > int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) >@@ -380,7 +392,7 @@ int nlm_async_call(struct nlm_rqst *req, > .rpc_argp = &req->a_args, > .rpc_resp = &req->a_res, > }; >- return __nlm_async_call(req, proc, &msg, tk_ops); >+ return nlm_do_async_call(req, proc, &msg, tk_ops); > } > > int nlm_async_reply(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) >@@ -388,7 +400,33 @@ int nlm_async_reply(struct nlm_rqst *req > struct rpc_message msg = { > .rpc_argp = &req->a_res, > }; >- return __nlm_async_call(req, proc, &msg, tk_ops); >+ return nlm_do_async_call(req, proc, &msg, tk_ops); >+} >+ >+/* >+ * NLM client asynchronous call. >+ * >+ * Note that although the calls are asynchronous, and are therefore >+ * guaranteed to complete, we still always attempt to wait for >+ * completion in order to be able to correctly track the lock >+ * state. >+ */ >+static int nlmclnt_async_call(struct rpc_cred *cred, struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) >+{ >+ struct rpc_message msg = { >+ .rpc_argp = &req->a_args, >+ .rpc_resp = &req->a_res, >+ .rpc_cred = cred, >+ }; >+ struct rpc_task *task; >+ int err; >+ >+ task = __nlm_async_call(req, proc, &msg, tk_ops); >+ if (IS_ERR(task)) >+ return PTR_ERR(task); >+ err = rpc_wait_for_completion_task(task); >+ rpc_put_task(task); >+ return err; > } > > /* >@@ -399,7 +437,7 @@ nlmclnt_test(struct nlm_rqst *req, struc > { > int status; > >- status = nlmclnt_call(req, NLMPROC_TEST); >+ status = nlmclnt_call(nfs_file_cred(fl->fl_file), req, NLMPROC_TEST); > if (status < 0) > goto out; > >@@ -490,10 +528,12 @@ static int do_vfs_lock(struct file_lock > static int > nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) > { >+ struct rpc_cred *cred = nfs_file_cred(fl->fl_file); > struct nlm_host *host = req->a_host; > struct nlm_res *resp = &req->a_res; > struct nlm_wait *block = NULL; > unsigned char fl_flags = fl->fl_flags; >+ unsigned char fl_type; > int status = -ENOLCK; > > if (!host->h_monitored && nsm_monitor(host) < 0) { >@@ -503,18 +543,22 @@ nlmclnt_lock(struct nlm_rqst *req, struc > } > fl->fl_flags |= FL_ACCESS; > status = do_vfs_lock(fl); >+ fl->fl_flags = fl_flags; > if (status < 0) > goto out; > > block = nlmclnt_prepare_block(host, fl); > again: >+ /* >+ * Initialise resp->status to a valid non-zero value, >+ * since 0 == nlm_lck_granted >+ */ >+ resp->status = nlm_lck_blocked; > for(;;) { > /* Reboot protection */ > fl->fl_u.nfs_fl.state = host->h_state; >- status = nlmclnt_call(req, NLMPROC_LOCK); >+ status = nlmclnt_call(cred, req, NLMPROC_LOCK); > if (status < 0) >- goto out_unblock; >- if (!req->a_args.block) > break; > /* Did a reclaimer thread notify us of a server reboot? */ > if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) >@@ -523,15 +567,22 @@ again: > break; > /* Wait on an NLM blocking lock */ > status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT); >- /* if we were interrupted. Send a CANCEL request to the server >- * and exit >- */ > if (status < 0) >- goto out_unblock; >+ break; > if (resp->status != NLM_LCK_BLOCKED) > break; > } > >+ /* if we were interrupted while blocking, then cancel the lock request >+ * and exit >+ */ >+ if (resp->status == nlm_lck_blocked) { >+ if (!req->a_args.block) >+ goto out_unlock; >+ if (nlmclnt_cancel(host, req->a_args.block, fl) == 0) >+ goto out_unblock; >+ } >+ > if (resp->status == NLM_LCK_GRANTED) { > down_read(&host->h_rwsem); > /* Check whether or not the server has rebooted */ >@@ -540,20 +591,33 @@ again: > goto again; > } > /* Ensure the resulting lock will get added to granted list */ >- fl->fl_flags = fl_flags | FL_SLEEP; >+ fl->fl_flags |= FL_SLEEP; > if (do_vfs_lock(fl) < 0) > printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); > up_read(&host->h_rwsem); >+ fl->fl_flags = fl_flags; >+ status = 0; > } >+ if (status < 0) >+ goto out_unlock; > status = nlm_stat_to_errno(resp->status); > out_unblock: > nlmclnt_finish_block(block); >- /* Cancel the blocked request if it is still pending */ >- if (resp->status == NLM_LCK_BLOCKED) >- nlmclnt_cancel(host, req->a_args.block, fl); > out: > nlm_release_call(req); >- fl->fl_flags = fl_flags; >+ return status; >+out_unlock: >+ /* Fatal error: ensure that we remove the lock altogether */ >+ dprintk("lockd: lock attempt ended in fatal error.\n" >+ " Attempting to unlock.\n"); >+ nlmclnt_finish_block(block); >+ fl_type = fl->fl_type; >+ fl->fl_type = F_UNLCK; >+ down_read(&host->h_rwsem); >+ do_vfs_lock(fl); >+ up_read(&host->h_rwsem); >+ fl->fl_type = fl_type; >+ nlmclnt_async_call(cred, req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops); > return status; > } > >@@ -577,8 +641,8 @@ nlmclnt_reclaim(struct nlm_host *host, s > nlmclnt_setlockargs(req, fl); > req->a_args.reclaim = 1; > >- if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0 >- && req->a_res.status == NLM_LCK_GRANTED) >+ status = nlmclnt_call(nfs_file_cred(fl->fl_file), req, NLMPROC_LOCK); >+ if (status >= 0 && req->a_res.status == NLM_LCK_GRANTED) > return 0; > > printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d " >@@ -608,7 +672,10 @@ nlmclnt_unlock(struct nlm_rqst *req, str > { > struct nlm_host *host = req->a_host; > struct nlm_res *resp = &req->a_res; >- int status = 0; >+ int status; >+ unsigned char fl_flags = fl->fl_flags; >+ unsigned long flags; >+ sigset_t oldset; > > /* > * Note: the server is supposed to either grant us the unlock >@@ -617,16 +684,30 @@ nlmclnt_unlock(struct nlm_rqst *req, str > */ > fl->fl_flags |= FL_EXISTS; > down_read(&host->h_rwsem); >- if (do_vfs_lock(fl) == -ENOENT) { >- up_read(&host->h_rwsem); >+ status = do_vfs_lock(fl); >+ up_read(&host->h_rwsem); >+ fl->fl_flags = fl_flags; >+ if (status == -ENOENT) { >+ status = 0; > goto out; > } >- up_read(&host->h_rwsem); > >- if (req->a_flags & RPC_TASK_ASYNC) >- return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops); >+ /* Block all signals while setting up call */ >+ spin_lock_irqsave(¤t->sighand->siglock, flags); >+ oldset = current->blocked; >+ sigfillset(¤t->blocked); >+ recalc_sigpending(); >+ spin_unlock_irqrestore(¤t->sighand->siglock, flags); >+ >+ atomic_inc(&req->a_count); >+ status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req, >+ NLMPROC_UNLOCK, &nlmclnt_unlock_ops); >+ >+ spin_lock_irqsave(¤t->sighand->siglock, flags); >+ current->blocked = oldset; >+ recalc_sigpending(); >+ spin_unlock_irqrestore(¤t->sighand->siglock, flags); > >- status = nlmclnt_call(req, NLMPROC_UNLOCK); > if (status < 0) > goto out; > >@@ -681,16 +762,10 @@ static const struct rpc_call_ops nlmclnt > static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl) > { > struct nlm_rqst *req; >- unsigned long flags; >- sigset_t oldset; >- int status; >+ int status; > >- /* Block all signals while setting up call */ >- spin_lock_irqsave(¤t->sighand->siglock, flags); >- oldset = current->blocked; >- sigfillset(¤t->blocked); >- recalc_sigpending(); >- spin_unlock_irqrestore(¤t->sighand->siglock, flags); >+ dprintk("lockd: blocking lock attempt was interrupted by a signal.\n" >+ " Attempting to cancel lock.\n"); > > req = nlm_alloc_call(nlm_get_host(host)); > if (!req) >@@ -700,13 +775,12 @@ static int nlmclnt_cancel(struct nlm_hos > nlmclnt_setlockargs(req, fl); > req->a_args.block = block; > >- status = nlm_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); >- >- spin_lock_irqsave(¤t->sighand->siglock, flags); >- current->blocked = oldset; >- recalc_sigpending(); >- spin_unlock_irqrestore(¤t->sighand->siglock, flags); >- >+ atomic_inc(&req->a_count); >+ status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req, >+ NLMPROC_CANCEL, &nlmclnt_cancel_ops); >+ if (status == 0 && req->a_res.status == nlm_lck_denied) >+ status = -ENOLCK; >+ nlm_release_call(req); > return status; > } > >--- linux-2.6.18.i686/fs/nfs/nfs4proc.c.org >+++ linux-2.6.18.i686/fs/nfs/nfs4proc.c >@@ -3332,6 +3332,7 @@ static int nfs4_proc_unlck(struct nfs4_s > struct nfs4_lock_state *lsp; > struct rpc_task *task; > int status = 0; >+ unsigned char fl_flags = request->fl_flags; > > status = nfs4_set_lock_state(state, request); > /* Unlock _before_ we do the RPC call */ >@@ -3355,6 +3356,7 @@ static int nfs4_proc_unlck(struct nfs4_s > status = nfs4_wait_for_completion_rpc_task(task); > rpc_put_task(task); > out: >+ request->fl_flags = fl_flags; > return status; > } > >--- linux-2.6.18.i686/include/linux/lockd/lockd.h.org >+++ linux-2.6.18.i686/include/linux/lockd/lockd.h >@@ -82,6 +82,7 @@ struct nlm_wait; > */ > #define NLMCLNT_OHSIZE (sizeof(system_utsname.nodename)+10) > struct nlm_rqst { >+ atomic_t a_count; > unsigned int a_flags; /* initial RPC task flags */ > struct nlm_host * a_host; /* host handle */ > struct nlm_args a_args; /* arguments */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 448929
: 307085