X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Focfs2%2Fdcache.c;h=b1cc7c381e889b5d898ad5f3e2a9bddeb9b39fd1;hb=3a76e3716b4e571f5d91a20b6afb412560599083;hp=09efe240e652e3dd4e56601c61ebcb754b1cfc1a;hpb=80c05846f604bab6d61e9732c262420ee9f5f358;p=linux-2.6 diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 09efe240e6..b1cc7c381e 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -128,9 +128,9 @@ static int ocfs2_match_dentry(struct dentry *dentry, /* * Walk the inode alias list, and find a dentry which has a given * parent. ocfs2_dentry_attach_lock() wants to find _any_ alias as it - * is looking for a dentry_lock reference. The vote thread is looking - * to unhash aliases, so we allow it to skip any that already have - * that property. + * is looking for a dentry_lock reference. The downconvert thread is + * looking to unhash aliases, so we allow it to skip any that already + * have that property. */ struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, @@ -183,9 +183,6 @@ DEFINE_SPINLOCK(dentry_attach_lock); * The dir cluster lock (held at either PR or EX mode) protects us * from unlink and rename on other nodes. * - * The 'create' flag tells us whether we're doing this as a result of - * a file creation. - * * A dput() can happen asynchronously due to pruning, so we cover * attaching and detaching the dentry lock with a * dentry_attach_lock. @@ -199,16 +196,15 @@ DEFINE_SPINLOCK(dentry_attach_lock); */ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode, - u64 parent_blkno, - int create) + u64 parent_blkno) { int ret; struct dentry *alias; struct ocfs2_dentry_lock *dl = dentry->d_fsdata; - mlog(0, "Attach \"%.*s\", parent %llu, create %d, fsdata: %p\n", + mlog(0, "Attach \"%.*s\", parent %llu, fsdata: %p\n", dentry->d_name.len, dentry->d_name.name, - (unsigned long long)parent_blkno, create, dl); + (unsigned long long)parent_blkno, dl); /* * Negative dentry. We ignore these for now. @@ -242,10 +238,9 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, * since we have it pinned, so our reference is safe. */ dl = alias->d_fsdata; - mlog_bug_on_msg(!dl, "parent %llu, ino %llu, create %d\n", + mlog_bug_on_msg(!dl, "parent %llu, ino %llu\n", (unsigned long long)parent_blkno, - (unsigned long long)OCFS2_I(inode)->ip_blkno, - create); + (unsigned long long)OCFS2_I(inode)->ip_blkno); mlog_bug_on_msg(dl->dl_parent_blkno != parent_blkno, " \"%.*s\": old parent: %llu, new: %llu\n", @@ -271,7 +266,7 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, dl->dl_count = 0; /* * Does this have to happen below, for all attaches, in case - * the struct inode gets blown away by votes? + * the struct inode gets blown away by the downconvert thread? */ dl->dl_inode = igrab(inode); dl->dl_parent_blkno = parent_blkno; @@ -283,32 +278,17 @@ out_attach: dl->dl_count++; spin_unlock(&dentry_attach_lock); - /* - * Creation of a new file means that nobody can possibly have - * this name in the system, which means that acquiry of those - * locks can easily be optimized. - */ - if (create) { - ret = ocfs2_create_new_lock(OCFS2_SB(inode->i_sb), - &dl->dl_lockres, 0); - if (ret) - mlog_errno(ret); - goto out; - } - /* * This actually gets us our PRMODE level lock. From now on, * we'll have a notification if one of these names is * destroyed on another node. */ ret = ocfs2_dentry_lock(dentry, 0); - if (ret) { + if (!ret) + ocfs2_dentry_unlock(dentry, 0); + else mlog_errno(ret); - goto out; - } - ocfs2_dentry_unlock(dentry, 0); -out: dput(alias); return ret; @@ -338,9 +318,9 @@ out: static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, struct ocfs2_dentry_lock *dl) { + iput(dl->dl_inode); ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); ocfs2_lock_res_free(&dl->dl_lockres); - iput(dl->dl_inode); kfree(dl); } @@ -364,12 +344,24 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode) { struct ocfs2_dentry_lock *dl = dentry->d_fsdata; - mlog_bug_on_msg(!dl && !(dentry->d_flags & DCACHE_DISCONNECTED), - "dentry: %.*s\n", dentry->d_name.len, - dentry->d_name.name); + if (!dl) { + /* + * No dentry lock is ok if we're disconnected or + * unhashed. + */ + if (!(dentry->d_flags & DCACHE_DISCONNECTED) && + !d_unhashed(dentry)) { + unsigned long long ino = 0ULL; + if (inode) + ino = (unsigned long long)OCFS2_I(inode)->ip_blkno; + mlog(ML_ERROR, "Dentry is missing cluster lock. " + "inode: %llu, d_flags: 0x%x, d_name: %.*s\n", + ino, dentry->d_flags, dentry->d_name.len, + dentry->d_name.name); + } - if (!dl) goto out; + } mlog_bug_on_msg(dl->dl_count == 0, "dentry: %.*s, count: %u\n", dentry->d_name.len, dentry->d_name.name, @@ -396,7 +388,7 @@ out: * directory locks. The dentries have already been deleted on other * nodes via ocfs2_remote_dentry_delete(). * - * Normally, the VFS handles the d_move() for the file sytem, after + * Normally, the VFS handles the d_move() for the file system, after * the ->rename() callback. OCFS2 wants to handle this internally, so * the new lock can be created atomically with respect to the cluster. */ @@ -414,15 +406,17 @@ void ocfs2_dentry_move(struct dentry *dentry, struct dentry *target, * XXX: Is there any advantage to dropping the lock here? */ if (old_dir == new_dir) - return; + goto out_move; ocfs2_dentry_lock_put(osb, dentry->d_fsdata); dentry->d_fsdata = NULL; - ret = ocfs2_dentry_attach_lock(dentry, inode, - OCFS2_I(new_dir)->ip_blkno, 0); + ret = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(new_dir)->ip_blkno); if (ret) mlog_errno(ret); + +out_move: + d_move(dentry, target); } struct dentry_operations ocfs2_dentry_ops = {