From 72afa19c19d5acc359e3304f474ff3b1830672e4 Mon Sep 17 00:00:00 2001 From: Swapnil Pimpale Date: Tue, 27 Aug 2013 17:55:46 +0530 Subject: [PATCH] LU-3807 dcache: Unsafe error handling arnd ll_splice_alias Callers of ll_splice_alias() should not assign the returned pointer to the dentry since it can be an err pointer. Fixed the above bug using a temporary dentry pointer. This temporary pointer is assigned to dentry only if ll_splice_alias has not returned an err pointer. Signed-off-by: Swapnil Pimpale Change-Id: I0cfdeb53b09fa5642ff01a919ded41aed32aad6d Reviewed-on: http://review.whamcloud.com/7460 Tested-by: Hudson Reviewed-by: Fan Yong Tested-by: Maloo Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin --- lustre/llite/namei.c | 21 ++++++++++++--------- lustre/llite/statahead.c | 29 ++++++++++++++++------------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 1aebd26..c01e2e4 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -434,12 +434,12 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de) int ll_lookup_it_finish(struct ptlrpc_request *request, struct lookup_intent *it, void *data) { - struct it_cb_data *icbd = data; - struct dentry **de = icbd->icbd_childp; - struct inode *parent = icbd->icbd_parent; - struct inode *inode = NULL; - __u64 bits = 0; - int rc; + struct it_cb_data *icbd = data; + struct dentry **de = icbd->icbd_childp; + struct inode *parent = icbd->icbd_parent; + struct inode *inode = NULL; + __u64 bits = 0; + int rc; ENTRY; /* NB 1 request reference will be taken away by ll_intent_lock() @@ -467,9 +467,12 @@ int ll_lookup_it_finish(struct ptlrpc_request *request, * Atoimc_open may passin hashed dentries for open. */ if (d_unhashed(*de)) { - *de = ll_splice_alias(inode, *de); - if (IS_ERR(*de)) - RETURN(PTR_ERR(*de)); + struct dentry *alias; + + alias = ll_splice_alias(inode, *de); + if (IS_ERR(alias)) + RETURN(PTR_ERR(alias)); + *de = alias; } if (!it_disposition(it, DISP_LOOKUP_NEG)) { diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c index 6b69c9e45..26efc32 100644 --- a/lustre/llite/statahead.c +++ b/lustre/llite/statahead.c @@ -1529,15 +1529,15 @@ ll_sai_unplug(struct ll_statahead_info *sai, struct ll_sa_entry *entry) int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug) { - struct ll_inode_info *lli = ll_i2info(dir); - struct ll_statahead_info *sai = lli->lli_sai; - struct dentry *parent; - struct ll_sa_entry *entry; - struct ptlrpc_thread *thread; - struct l_wait_info lwi = { 0 }; - int rc = 0; - struct ll_inode_info *plli; - ENTRY; + struct ll_inode_info *lli = ll_i2info(dir); + struct ll_statahead_info *sai = lli->lli_sai; + struct dentry *parent; + struct ll_sa_entry *entry; + struct ptlrpc_thread *thread; + struct l_wait_info lwi = { 0 }; + int rc = 0; + struct ll_inode_info *plli; + ENTRY; LASSERT(lli->lli_opendir_pid == current_pid()); @@ -1615,12 +1615,15 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, ll_inode2fid(inode), &bits); if (rc == 1) { if ((*dentryp)->d_inode == NULL) { - *dentryp = ll_splice_alias(inode, - *dentryp); - if (IS_ERR(*dentryp)) { + struct dentry *alias; + + alias = ll_splice_alias(inode, + *dentryp); + if (IS_ERR(alias)) { ll_sai_unplug(sai, entry); - RETURN(PTR_ERR(*dentryp)); + RETURN(PTR_ERR(alias)); } + *dentryp = alias; } else if ((*dentryp)->d_inode != inode) { /* revalidate, but inode is recreated */ CDEBUG(D_READA, -- 1.8.3.1