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 156380 Details for
Bug 242975
A number of NFS oops, memory leaks found in upstream.
[?]
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]
he back ported jumbo patch.
linux-2.6.18-nfs-oops-1.patch (text/plain), 14.37 KB, created by
Steve Dickson
on 2007-06-06 19:07:05 UTC
(
hide
)
Description:
he back ported jumbo patch.
Filename:
MIME Type:
Creator:
Steve Dickson
Created:
2007-06-06 19:07:05 UTC
Size:
14.37 KB
patch
obsolete
>--- linux-2.6.18.i686/include/linux/sunrpc/sched.h.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/include/linux/sunrpc/sched.h 2007-06-06 13:26:41.000000000 -0400 >@@ -254,6 +254,7 @@ void rpc_init_task(struct rpc_task *tas > void *data); > void rpc_put_task(struct rpc_task *); > void rpc_exit_task(struct rpc_task *); >+void rpc_release_calldata(const struct rpc_call_ops *, void *); > void rpc_killall_tasks(struct rpc_clnt *); > int rpc_execute(struct rpc_task *); > void rpc_run_child(struct rpc_task *parent, struct rpc_task *child, >--- linux-2.6.18.i686/fs/nfs/read.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/fs/nfs/read.c 2007-06-06 13:22:24.000000000 -0400 >@@ -147,12 +147,12 @@ static int nfs_readpage_sync(struct nfs_ > { > unsigned int rsize = NFS_SERVER(inode)->rsize; > unsigned int count = PAGE_CACHE_SIZE; >- int result; >+ int result = -ENOMEM; > struct nfs_read_data *rdata; > > rdata = nfs_readdata_alloc(count); > if (!rdata) >- return -ENOMEM; >+ goto out_unlock; > > memset(rdata, 0, sizeof(*rdata)); > rdata->flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); >@@ -225,8 +225,9 @@ static int nfs_readpage_sync(struct nfs_ > return result; > > io_error: >- unlock_page(page); > nfs_readdata_free(rdata); >+out_unlock: >+ unlock_page(page); > return result; > } > >@@ -639,9 +640,10 @@ int nfs_readpage(struct file *file, stru > goto out_error; > > if (file == NULL) { >+ error = -EBADF; > ctx = nfs_find_open_context(inode, NULL, FMODE_READ); > if (ctx == NULL) >- return -EBADF; >+ goto out_error; > } else > ctx = get_nfs_open_context((struct nfs_open_context *) > file->private_data); >--- linux-2.6.18.i686/fs/nfs/direct.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/fs/nfs/direct.c 2007-06-06 13:42:34.000000000 -0400 >@@ -122,19 +122,25 @@ ssize_t nfs_direct_IO(int rw, struct kio > return -EINVAL; > } > >-static void nfs_direct_dirty_pages(struct page **pages, int npages) >+static void nfs_direct_dirty_pages(struct page **pages, unsigned int pgbase, size_t count) > { >- int i; >+ unsigned int npages; >+ unsigned int i; >+ >+ if (count == 0) >+ return; >+ pages += (pgbase >> PAGE_SHIFT); >+ npages = (count + (pgbase & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT; > for (i = 0; i < npages; i++) { > struct page *page = pages[i]; > if (!PageCompound(page)) >- set_page_dirty_lock(page); >+ set_page_dirty(page); > } > } > >-static void nfs_direct_release_pages(struct page **pages, int npages) >+static void nfs_direct_release_pages(struct page **pages, unsigned int npages) > { >- int i; >+ unsigned int i; > for (i = 0; i < npages; i++) > page_cache_release(pages[i]); > } >@@ -162,7 +168,7 @@ static inline struct nfs_direct_req *nfs > return dreq; > } > >-static void nfs_direct_req_release(struct kref *kref) >+static void nfs_direct_req_free(struct kref *kref) > { > struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); > >@@ -171,6 +177,11 @@ static void nfs_direct_req_release(struc > kmem_cache_free(nfs_direct_cachep, dreq); > } > >+static void nfs_direct_req_release(struct nfs_direct_req *dreq) >+{ >+ kref_put(&dreq->kref, nfs_direct_req_free); >+} >+ > /* > * Collects and returns the final error value/byte-count. > */ >@@ -190,7 +201,6 @@ static ssize_t nfs_direct_wait(struct nf > result = dreq->count; > > out: >- kref_put(&dreq->kref, nfs_direct_req_release); > return (ssize_t) result; > } > >@@ -208,7 +218,7 @@ static void nfs_direct_complete(struct n > } > complete_all(&dreq->completion); > >- kref_put(&dreq->kref, nfs_direct_req_release); >+ nfs_direct_req_release(dreq); > } > > /* >@@ -224,17 +234,18 @@ static void nfs_direct_read_result(struc > if (nfs_readpage_result(task, data) != 0) > return; > >- nfs_direct_dirty_pages(data->pagevec, data->npages); >- nfs_direct_release_pages(data->pagevec, data->npages); >- > spin_lock(&dreq->lock); >- >- if (likely(task->tk_status >= 0)) >- dreq->count += data->res.count; >- else >+ if (unlikely(task->tk_status < 0)) { > dreq->error = task->tk_status; >- >- spin_unlock(&dreq->lock); >+ spin_unlock(&dreq->lock); >+ } else { >+ dreq->count += data->res.count; >+ spin_unlock(&dreq->lock); >+ nfs_direct_dirty_pages(data->pagevec, >+ data->args.pgbase, >+ data->res.count); >+ } >+ nfs_direct_release_pages(data->pagevec, data->npages); > > if (put_dreq(dreq)) > nfs_direct_complete(dreq); >@@ -279,9 +290,12 @@ static ssize_t nfs_direct_read_schedule( > result = get_user_pages(current, current->mm, user_addr, > data->npages, 1, 0, data->pagevec, NULL); > up_read(¤t->mm->mmap_sem); >- if (unlikely(result < data->npages)) { >- if (result > 0) >- nfs_direct_release_pages(data->pagevec, result); >+ if (result < 0) { >+ nfs_readdata_release(data); >+ break; >+ } >+ if ((unsigned)result < data->npages) { >+ nfs_direct_release_pages(data->pagevec, result); > nfs_readdata_release(data); > break; > } >@@ -360,6 +374,7 @@ static ssize_t nfs_direct_read(struct ki > if (!result) > result = nfs_direct_wait(dreq); > rpc_clnt_sigunmask(clnt, &oldset); >+ nfs_direct_req_release(dreq); > > return result; > } >@@ -433,10 +448,10 @@ static void nfs_direct_commit_result(str > if (NFS_PROTO(data->inode)->commit_done(task, data) != 0) > return; > if (unlikely(task->tk_status < 0)) { >- dreq->error = task->tk_status; >+ dprintk("NFS: %5u commit failed with error %d.\n", >+ task->tk_pid, task->tk_status); > dreq->flags = NFS_ODIRECT_RESCHED_WRITES; >- } >- if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) { >+ } else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) { > dprintk("NFS: %5u commit verify failed\n", task->tk_pid); > dreq->flags = NFS_ODIRECT_RESCHED_WRITES; > } >@@ -532,9 +547,12 @@ static void nfs_direct_write_result(stru > > spin_lock(&dreq->lock); > >+ if (unlikely(dreq->error != 0)) >+ goto out_unlock; > if (unlikely(status < 0)) { >+ /* An error has occured, so we should not commit */ >+ dreq->flags = 0; > dreq->error = status; >- goto out_unlock; > } > > dreq->count += data->res.count; >@@ -608,9 +626,12 @@ static ssize_t nfs_direct_write_schedule > result = get_user_pages(current, current->mm, user_addr, > data->npages, 0, 0, data->pagevec, NULL); > up_read(¤t->mm->mmap_sem); >- if (unlikely(result < data->npages)) { >- if (result > 0) >- nfs_direct_release_pages(data->pagevec, result); >+ if (result < 0) { >+ nfs_writedata_release(data); >+ break; >+ } >+ if ((unsigned)result < data->npages) { >+ nfs_direct_release_pages(data->pagevec, result); > nfs_writedata_release(data); > break; > } >@@ -702,6 +723,7 @@ static ssize_t nfs_direct_write(struct k > if (!result) > result = nfs_direct_wait(dreq); > rpc_clnt_sigunmask(clnt, &oldset); >+ nfs_direct_req_release(dreq); > > return result; > } >--- linux-2.6.18.i686/fs/nfs/getroot.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/fs/nfs/getroot.c 2007-06-06 13:39:02.000000000 -0400 >@@ -135,17 +135,15 @@ int nfs4_path_walk(struct nfs_server *se > struct nfs_fh lastfh; > struct qstr name; > int ret; >- //int referral_count = 0; > > dprintk("--> nfs4_path_walk(,,%s)\n", path); > > fsinfo.fattr = &fattr; > nfs_fattr_init(&fattr); > >- if (*path++ != '/') { >- dprintk("nfs4_get_root: Path does not begin with a slash\n"); >- return -EINVAL; >- } >+ /* Eat leading slashes */ >+ while (*path == '/') >+ path++; > > /* Start by getting the root filehandle from the server */ > ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); >@@ -160,6 +158,7 @@ int nfs4_path_walk(struct nfs_server *se > return -ENOTDIR; > } > >+ /* FIXME: It is quite valid for the server to return a referral here */ > if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { > printk(KERN_ERR "nfs4_get_root:" > " getroot obtained referral\n"); >@@ -187,6 +186,7 @@ eat_dot_dir: > goto eat_dot_dir; > } > >+ /* FIXME: Why shouldn't the user be able to use ".." in the path? */ > if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2]) > ) { > printk(KERN_ERR "nfs4_get_root:" >@@ -212,6 +212,7 @@ eat_dot_dir: > return -ENOTDIR; > } > >+ /* FIXME: Referrals are quite valid here too */ > if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { > printk(KERN_ERR "nfs4_get_root:" > " lookupfh obtained referral\n"); >--- linux-2.6.18.i686/fs/nfs/nfs3proc.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/fs/nfs/nfs3proc.c 2007-06-06 13:21:32.000000000 -0400 >@@ -369,7 +369,7 @@ again: > > /* If the server doesn't support the exclusive creation semantics, > * try again with simple 'guarded' mode. */ >- if (status == NFSERR_NOTSUPP) { >+ if (status == -ENOTSUPP) { > switch (arg.createmode) { > case NFS3_CREATE_EXCLUSIVE: > arg.createmode = NFS3_CREATE_GUARDED; >--- linux-2.6.18.i686/fs/nfs/nfs4xdr.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/fs/nfs/nfs4xdr.c 2007-06-06 13:31:18.000000000 -0400 >@@ -387,8 +387,10 @@ static int nfs4_stat_to_errno(int); > decode_putfh_maxsz + \ > op_decode_hdr_maxsz + 12) > #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ >+ encode_putfh_maxsz + \ > encode_getattr_maxsz) > #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ >+ decode_putfh_maxsz + \ > decode_getattr_maxsz) > #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ > encode_putfh_maxsz + \ >--- linux-2.6.18.i686/fs/nfs/dir.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/fs/nfs/dir.c 2007-06-06 13:37:49.000000000 -0400 >@@ -1114,8 +1114,21 @@ static struct dentry *nfs_readdir_lookup > } > name.hash = full_name_hash(name.name, name.len); > dentry = d_lookup(parent, &name); >- if (dentry != NULL) >- return dentry; >+ if (dentry != NULL) { >+ /* Is this a positive dentry that matches the readdir info? */ >+ if (dentry->d_inode != NULL && >+ (NFS_FILEID(dentry->d_inode) == entry->ino || >+ d_mountpoint(dentry))) { >+ if (!desc->plus || entry->fh->size == 0) >+ return dentry; >+ if (nfs_compare_fh(NFS_FH(dentry->d_inode), >+ entry->fh) == 0) >+ goto out_renew; >+ } >+ /* No, so d_drop to allow one to be created */ >+ d_drop(dentry); >+ dput(dentry); >+ } > if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) > return NULL; > /* Note: caller is already holding the dir->i_mutex! */ >@@ -1137,6 +1150,7 @@ static struct dentry *nfs_readdir_lookup > dentry = alias; > } > >+out_renew: > nfs_renew_times(dentry); > nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); > return dentry; >--- linux-2.6.18.i686/fs/lockd/clntproc.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/fs/lockd/clntproc.c 2007-06-06 13:28:44.000000000 -0400 >@@ -357,7 +357,6 @@ static int __nlm_async_call(struct nlm_r > { > struct nlm_host *host = req->a_host; > struct rpc_clnt *clnt; >- int status = -ENOLCK; > > dprintk("lockd: call procedure %d on %s (async)\n", > (int)proc, host->h_name); >@@ -369,12 +368,10 @@ static int __nlm_async_call(struct nlm_r > msg->rpc_proc = &clnt->cl_procinfo[proc]; > > /* bootstrap and kick off the async RPC call */ >- status = rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req); >- if (status == 0) >- return 0; >+ return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req); > out_err: >- nlm_release_call(req); >- return status; >+ tk_ops->rpc_release(req); >+ return -ENOLCK; > } > > int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) >--- linux-2.6.18.i686/fs/lockd/svclock.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/fs/lockd/svclock.c 2007-06-06 13:28:44.000000000 -0400 >@@ -611,9 +611,7 @@ callback: > > /* Call the client */ > kref_get(&block->b_count); >- if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, >- &nlmsvc_grant_ops) < 0) >- nlmsvc_release_block(block); >+ nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops); > } > > /* >--- linux-2.6.18.i686/net/sunrpc/clnt.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/net/sunrpc/clnt.c 2007-06-06 14:05:20.000000000 -0400 >@@ -154,7 +154,11 @@ rpc_new_client(struct rpc_xprt *xprt, ch > clnt->cl_prot = xprt->prot; > clnt->cl_stats = program->stats; > clnt->cl_metrics = rpc_alloc_iostats(clnt); >+ err = -ENOMEM; >+ if (clnt->cl_metrics == NULL) >+ goto out_no_stats; > clnt->cl_program = program; >+ > rpc_init_wait_queue(&clnt->cl_pmap_default.pm_bindwait, "bindwait"); > > if (!clnt->cl_port) >@@ -188,6 +192,8 @@ out_no_auth: > rpc_put_mount(); > } > out_no_path: >+ rpc_free_iostats(clnt->cl_metrics); >+out_no_stats: > if (clnt->cl_server != clnt->cl_inline_name) > kfree(clnt->cl_server); > kfree(clnt); >@@ -244,6 +250,9 @@ rpc_clone_client(struct rpc_clnt *clnt) > memcpy(new, clnt, sizeof(*new)); > atomic_set(&new->cl_count, 1); > atomic_set(&new->cl_users, 0); >+ new->cl_metrics = rpc_alloc_iostats(clnt); >+ if (new->cl_metrics == NULL) >+ goto out_no_stats; > if (clnt->cl_server != clnt->cl_inline_name) { > new->cl_server = kstrdup(clnt->cl_server, GFP_KERNEL); > if (new->cl_server == NULL) { >@@ -274,8 +283,9 @@ rpc_clone_client(struct rpc_clnt *clnt) > if (new->cl_auth) > atomic_inc(&new->cl_auth->au_count); > new->cl_pmap = &new->cl_pmap_default; >- new->cl_metrics = rpc_alloc_iostats(clnt); > return new; >+out_no_stats: >+ kfree(new); > out_no_clnt: > printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); > return ERR_PTR(-ENOMEM); >@@ -529,8 +539,7 @@ rpc_call_async(struct rpc_clnt *clnt, st > rpc_restore_sigmask(&oldset); > return status; > out_release: >- if (tk_ops->rpc_release != NULL) >- tk_ops->rpc_release(data); >+ rpc_release_calldata(tk_ops, data); > return status; > } > >--- linux-2.6.18.i686/net/sunrpc/sched.c.save 2007-06-06 13:20:50.000000000 -0400 >+++ linux-2.6.18.i686/net/sunrpc/sched.c 2007-06-06 13:26:41.000000000 -0400 >@@ -630,6 +630,15 @@ void rpc_exit_task(struct rpc_task *task > } > EXPORT_SYMBOL(rpc_exit_task); > >+void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) >+{ >+ if (ops->rpc_release != NULL) { >+ lock_kernel(); >+ ops->rpc_release(calldata); >+ unlock_kernel(); >+ } >+} >+ > /* > * This is the RPC `scheduler' (or rather, the finite state machine). > */ >@@ -905,8 +914,7 @@ void rpc_put_task(struct rpc_task *task) > } > if (task->tk_flags & RPC_TASK_DYNAMIC) > call_rcu_bh(&task->u.tk_rcu, rpc_free_task); >- if (tk_ops->rpc_release) >- tk_ops->rpc_release(calldata); >+ rpc_release_calldata(tk_ops, calldata); > } > EXPORT_SYMBOL(rpc_put_task); > >@@ -950,8 +958,7 @@ struct rpc_task *rpc_run_task(struct rpc > struct rpc_task *task; > task = rpc_new_task(clnt, flags, ops, data); > if (task == NULL) { >- if (ops->rpc_release != NULL) >- ops->rpc_release(data); >+ rpc_release_calldata(ops, data); > return ERR_PTR(-ENOMEM); > } > atomic_inc(&task->tk_count);
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 242975
: 156380