From fd75f8595ece2e27d9f22ca2c28dbac9ff1cb105 Mon Sep 17 00:00:00 2001 From: wangdi Date: Wed, 9 Aug 2006 08:31:08 +0000 Subject: [PATCH] Branch: b_new_cmd 1)merge some fixes from b1_5 *only client has parent update lock, then hash the child dentry, it could fix bad inode problems *when ll_inode_revaldate_it can not match lock locally, it should try to retrieve from remote server 2)re-phase comments in mdd_lov_create 3)remove LUSTRE_POSIX_MAX_ACL_SIZE from liblustre.h, it is not needed. --- lustre/include/liblustre.h | 4 -- lustre/llite/dcache.c | 99 +++++++++++++++++++++++++++++-------------- lustre/llite/file.c | 31 +++++++++++++- lustre/llite/llite_internal.h | 2 + lustre/llite/namei.c | 12 ++++-- lustre/mdc/mdc_locks.c | 11 +++-- lustre/mdc/mdc_request.c | 2 +- lustre/mdd/mdd_lov.c | 8 ++-- 8 files changed, 122 insertions(+), 47 deletions(-) diff --git a/lustre/include/liblustre.h b/lustre/include/liblustre.h index e0b5c0f..aaa369d 100644 --- a/lustre/include/liblustre.h +++ b/lustre/include/liblustre.h @@ -883,10 +883,6 @@ void posix_acl_release(struct posix_acl *acl) { } -#define LUSTRE_POSIX_ACL_MAX_ENTRIES (32) -#define LUSTRE_POSIX_ACL_MAX_SIZE \ - (sizeof(xattr_acl_header) + 32 * sizeof(xattr_acl_entry)) - #ifndef ENOTSUPP #define ENOTSUPP ENOTSUP #endif diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index ad53c20..ad565ae 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -141,6 +141,64 @@ void ll_intent_release(struct lookup_intent *it) EXIT; } +/* Drop dentry if it is not used already, unhash otherwise. + Should be called with dcache lock held! + Returns: 1 if dentry was dropped, 0 if unhashed. */ +int ll_drop_dentry(struct dentry *dentry) +{ + lock_dentry(dentry); + CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p " + "inode %p flags %d\n", dentry->d_name.len, + dentry->d_name.name, dentry, dentry->d_parent, + dentry->d_inode, dentry->d_flags); + + if (atomic_read(&dentry->d_count) == 0) { + CDEBUG(D_DENTRY, "deleting dentry %.*s (%p) parent %p " + "inode %p\n", dentry->d_name.len, + dentry->d_name.name, dentry, dentry->d_parent, + dentry->d_inode); + dget_locked(dentry); + __d_drop(dentry); + unlock_dentry(dentry); + spin_unlock(&dcache_lock); + dput(dentry); + spin_lock(&dcache_lock); + return 1; + } + +#ifdef LUSTRE_KERNEL_VERSION + if (!(dentry->d_flags & DCACHE_LUSTRE_INVALID)) { +#else + if (!d_unhashed(dentry)) { + struct inode *inode = dentry->d_inode; +#endif + CDEBUG(D_DENTRY, "unhashing dentry %.*s (%p) parent %p " + "inode %p refc %d\n", dentry->d_name.len, + dentry->d_name.name, dentry, dentry->d_parent, + dentry->d_inode, atomic_read(&dentry->d_count)); + /* actually we don't unhash the dentry, rather just + * mark it inaccessible for to __d_lookup(). otherwise + * sys_getcwd() could return -ENOENT -bzzz */ +#ifdef LUSTRE_KERNEL_VERSION + dentry->d_flags |= DCACHE_LUSTRE_INVALID; +#else + if (!inode || !S_ISDIR(inode->i_mode)) + __d_drop(dentry); +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + __d_drop(dentry); + if (inode) { + /* Put positive dentries to orphan list */ + hlist_add_head(&dentry->d_hash, + &ll_i2sbi(inode)->ll_orphan_dentry_list); + } +#endif + } + unlock_dentry(dentry); + return 0; +} + void ll_unhash_aliases(struct inode *inode) { struct list_head *tmp, *head; @@ -151,16 +209,21 @@ void ll_unhash_aliases(struct inode *inode) return; } - CDEBUG(D_INODE, "marking dentries for ino %lu/%u(%p) invalid\n", + CDEBUG(D_INODE, "marking dentries for 111 ino %lu/%u(%p) invalid\n", inode->i_ino, inode->i_generation, inode); head = &inode->i_dentry; -restart: spin_lock(&dcache_lock); +restart: tmp = head; while ((tmp = tmp->next) != head) { struct dentry *dentry = list_entry(tmp, struct dentry, d_alias); + CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p " + "inode %p flags %d\n", dentry->d_name.len, + dentry->d_name.name, dentry, dentry->d_parent, + dentry->d_inode, dentry->d_flags); + if (dentry->d_name.len == 1 && dentry->d_name.name[0] == '/') { CERROR("called on root (?) dentry=%p, inode=%p " "ino=%lu\n", dentry, inode, inode->i_ino); @@ -178,35 +241,9 @@ restart: continue; } - - lock_dentry(dentry); - if (atomic_read(&dentry->d_count) == 0) { - CDEBUG(D_DENTRY, "deleting dentry %.*s (%p) parent %p " - "inode %p\n", dentry->d_name.len, - dentry->d_name.name, dentry, dentry->d_parent, - dentry->d_inode); - dget_locked(dentry); - __d_drop(dentry); - unlock_dentry(dentry); - spin_unlock(&dcache_lock); - dput(dentry); - goto restart; - } else if (!(dentry->d_flags & DCACHE_LUSTRE_INVALID)) { - CDEBUG(D_DENTRY, "unhashing dentry %.*s (%p) parent %p " - "inode %p refc %d\n", dentry->d_name.len, - dentry->d_name.name, dentry, dentry->d_parent, - dentry->d_inode, atomic_read(&dentry->d_count)); - /* actually we don't unhash the dentry, rather just - * mark it inaccessible for to __d_lookup(). otherwise - * sys_getcwd() could return -ENOENT -bzzz */ - dentry->d_flags |= DCACHE_LUSTRE_INVALID; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) - __d_drop(dentry); - hlist_add_head(&dentry->d_hash, - &ll_i2sbi(inode)->ll_orphan_dentry_list); -#endif - } - unlock_dentry(dentry); + + if (ll_drop_dentry(dentry)) + goto restart; } spin_unlock(&dcache_lock); EXIT; diff --git a/lustre/llite/file.c b/lustre/llite/file.c index f4e1078..4fb7200 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1929,6 +1929,29 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) RETURN(rc); } +int ll_have_md_lock(struct inode *inode, __u64 bits) +{ + struct lustre_handle lockh; + ldlm_policy_data_t policy = { .l_inodebits = {bits}}; + struct lu_fid *fid; + int flags; + ENTRY; + + if (!inode) + RETURN(0); + + fid = &ll_i2info(inode)->lli_fid; + CDEBUG(D_INFO, "trying to match res "DFID3"\n", PFID3(fid)); + + flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK; + if (md_lock_match(ll_i2mdexp(inode), flags, fid, LDLM_IBITS, &policy, + LCK_CR|LCK_CW|LCK_PR, &lockh)) { + RETURN(1); + } + + RETURN(0); +} + int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it) { struct lookup_intent oit = { .it_op = IT_GETATTR }; @@ -1969,7 +1992,13 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it) rc = ll_revalidate_it_finish(req, 1, &oit, dentry); if (rc) GOTO(out, rc); - + + if (!dentry->d_inode->i_nlink) { + spin_lock(&dcache_lock); + ll_drop_dentry(dentry); + spin_unlock(&dcache_lock); + } + ll_lookup_finish_locks(&oit, dentry); /* object is allocated, validate size */ diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index c41502f..92a1927 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -382,6 +382,7 @@ extern struct file_operations ll_file_operations; extern struct file_operations ll_file_operations_flock; extern struct inode_operations ll_file_inode_operations; extern int ll_inode_revalidate_it(struct dentry *, struct lookup_intent *); +extern int ll_have_md_lock(struct inode *inode, __u64 bits); int ll_extent_lock(struct ll_file_data *, struct inode *, struct lov_stripe_md *, int mode, ldlm_policy_data_t *, struct lustre_handle *, int ast_flags); @@ -411,6 +412,7 @@ int ll_inode_permission(struct inode *inode, int mask); /* llite/dcache.c */ void ll_intent_drop_lock(struct lookup_intent *); void ll_intent_release(struct lookup_intent *); +int ll_drop_dentry(struct dentry *dentry); extern void ll_set_dd(struct dentry *de); void ll_unhash_aliases(struct inode *); void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft); diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 9c27050..6e83eea 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -355,9 +355,15 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset, *de = ll_find_alias(inode, *de); } else { ENTRY; - spin_lock(&dcache_lock); - ll_d_add(*de, inode); - spin_unlock(&dcache_lock); + /* Check that parent has UPDATE lock. If there is none, we + * cannot afford to hash this dentry (done by ll_d_add) as it + * might get picked up later when UPDATE lock will appear */ + if (ll_have_md_lock(parent, MDS_INODELOCK_UPDATE)) { + spin_lock(&dcache_lock); + ll_d_add(*de, inode); + spin_unlock(&dcache_lock); + } else + (*de)->d_inode = NULL; } ll_set_dd(*de); diff --git a/lustre/mdc/mdc_locks.c b/lustre/mdc/mdc_locks.c index 6d23228..252fe91 100644 --- a/lustre/mdc/mdc_locks.c +++ b/lustre/mdc/mdc_locks.c @@ -32,11 +32,11 @@ # include # include # include -#include #else # include #endif +#include #include #include #include @@ -617,7 +617,9 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, sizeof(lockh)); it->d.lustre.it_lock_mode = mode; } - RETURN(rc); + + if (rc || op_data->namelen != 0) + RETURN(rc); } /* lookup_it may be called only after revalidate_it has run, because @@ -676,10 +678,11 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, /* If we were revalidating a fid/name pair, mark the intent in * case we fail and get called again from lookup */ if (fid_is_sane(&op_data->fid2) && - !it_disposition(it, DISP_OPEN_CREATE)) { + !it_disposition(it, DISP_OPEN_CREATE) && + !(it->it_op & IT_GETATTR)) { it_set_disposition(it, DISP_ENQ_COMPLETE); /* Also: did we find the same inode? */ - if (!((it->it_create_mode & O_CREAT) || it->it_op & IT_CREAT) + if (!(it->it_create_mode & O_CREAT || it->it_op & IT_CREAT) && memcmp(&op_data->fid2, &mdt_body->fid1, sizeof(op_data->fid2))) RETURN(-ESTALE); diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 9b02718..496a5f5 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -31,12 +31,12 @@ # include # include # include -# include # include #else # include #endif +#include #include #include #include diff --git a/lustre/mdd/mdd_lov.c b/lustre/mdd/mdd_lov.c index 8bd37fb..058f82a 100644 --- a/lustre/mdd/mdd_lov.c +++ b/lustre/mdd/mdd_lov.c @@ -442,9 +442,11 @@ int mdd_lov_create(const struct lu_context *ctxt, struct mdd_device *mdd, } lsm->lsm_object_id = oa->o_id; } - /*after creating the object, if the la_size is not zero. - *since truncate when no lsm, we should set the size to - *ost object*/ + /*Sometimes, we may truncate some object(without lsm) + *then open (with write flags)it, so creating lsm above. + *The Nonzero(truncated) size should tell ost. since size + *attr is in charged by OST. + */ if (la->la_size) { oa->o_size = la->la_size; obdo_from_la(oa, la, OBD_MD_FLTYPE | OBD_MD_FLATIME | -- 1.8.3.1