diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c index f50b9f68f2747bfbd0c002692c9978114f3bb3fd..65fe3f80106c877e55d3d107bc58b5c80be1a856 100644 --- a/lustre/lvfs/fsfilt_ext3.c +++ b/lustre/lvfs/fsfilt_ext3.c @@ -1261,6 +1261,53 @@ static int fsfilt_ext3_setup(struct obd_device *obd, struct super_block *sb) return 0; } +static inline int ext3_match (int len, const char * const name, + struct ext3_dir_entry_2 * de) +{ + if (len != de->name_len) + return 0; + if (!de->inode) + return 0; + return !memcmp(name, de->name, len); +} +static int fsfilt_ext3_scan_for_entry(struct dentry *dentry) +{ + struct inode *dir = dentry->d_parent->d_inode; + int blksize = dir->i_sb->s_blocksize; + int blk = 0, err, num = 0, de_len; + struct ext3_dir_entry_2 * de; + int count = dir->i_size; + struct qstr *name; + char *dlimit; + + name = &dentry->d_name; + while (count > 0) { + struct buffer_head *bh; + + bh = ext3_bread(NULL, dir, blk++, 0, &err); + if (bh == NULL) { + CERROR("error read dir %lu+%d: %d\n", + dir->i_ino, blk, err); + break; + } + + dlimit = bh->b_data + blksize; + de = (struct ext3_dir_entry_2 *) bh->b_data; + while ((char *) de < dlimit) { + if ((char *) de + name->len <= dlimit && + ext3_match(name->len, name->name, de)) + num++; + de_len = le16_to_cpu(de->rec_len); + de = (struct ext3_dir_entry_2 *) ((char *) de + de_len); + } + + count -= blksize; + brelse(bh); + } + + return num; +} + extern int ext3_add_dir_entry(struct dentry *dentry); extern int ext3_del_dir_entry(struct dentry *dentry); @@ -1273,6 +1320,7 @@ static int fsfilt_ext3_add_dir_entry(struct obd_device *obd, unsigned long fid) { #ifdef EXT3_FEATURE_INCOMPAT_MDSNUM + struct mds_obd *mdsobd = &obd->u.mds; struct dentry *dentry; int err; LASSERT(ino != 0); @@ -1297,6 +1345,14 @@ static int fsfilt_ext3_add_dir_entry(struct obd_device *obd, * it cross-ref by subsequent lookups */ d_drop(dentry); + if (parent->d_inode->i_ino == id_ino(&mdsobd->mds_rootid)) { + err = fsfilt_ext3_scan_for_entry(dentry); + if (err != 0) + CDEBUG(D_ERROR, "existing %d entry %*s in %lu/%u\n", + err, dentry->d_name.len, dentry->d_name.name, + parent->d_inode->i_ino, parent->d_inode->i_generation); + } + dentry->d_flags |= DCACHE_CROSS_REF; dentry->d_inum = ino; dentry->d_mdsnum = mds; @@ -1319,10 +1375,19 @@ static int fsfilt_ext3_del_dir_entry(struct obd_device *obd, struct dentry *dentry) { #ifdef EXT3_FEATURE_INCOMPAT_MDSNUM + struct inode *dir = dentry->d_parent->d_inode; + struct mds_obd *mdsobd = &obd->u.mds; int err; lock_24kernel(); err = ext3_del_dir_entry(dentry); unlock_24kernel(); + if (!err && dir->i_ino == id_ino(&mdsobd->mds_rootid)) { + int num = fsfilt_ext3_scan_for_entry(dentry); + if (num != 0) + CDEBUG(D_ERROR, "existing %d entry %*s in %lu/%u\n", + err, dentry->d_name.len, dentry->d_name.name, + dir->i_ino, dir->i_generation); + } if (err == 0) d_drop(dentry); return err; diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 8e4034298be9ca6c011a1423d42808f18bc98313..7ec76408780f19d99e4ca39df0ae7e3e96ef7ce2 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -2163,23 +2163,25 @@ cleanup: if (!IS_ERR(chkdentry)) { if (chkdentry->d_inode) { /* it was cross-ref before */ - CDEBUG(D_ERROR, "%lu/%u:%*s(%d,%p) -> %lu/%u, was %p\n", + CDEBUG(D_ERROR, "%lu/%u:%*s(%d,%x,%p) -> %lu/%u, was %p\n", dparent->d_inode->i_ino, dparent->d_inode->i_generation, chkdentry->d_name.len, chkdentry->d_name.name, atomic_read(&chkdentry->d_count), - chkdentry, chkdentry->d_inode->i_ino, + chkdentry->d_flags, chkdentry, + chkdentry->d_inode->i_ino, chkdentry->d_inode->i_generation, dchild); } else if (chkdentry->d_flags & DCACHE_CROSS_REF) { /* it's still in dcache? on a platter?! */ - CDEBUG(D_ERROR, "%lu/%u:%*s(%d,%p) -> %u/%u, was %p\n", + CDEBUG(D_ERROR, "%lu/%u:%*s(%d,%x,%p) -> %u/%u, was %p\n", dparent->d_inode->i_ino, dparent->d_inode->i_generation, chkdentry->d_name.len, chkdentry->d_name.name, atomic_read(&chkdentry->d_count), - chkdentry, chkdentry->d_inum, + chkdentry->d_flags, chkdentry, + chkdentry->d_inum, chkdentry->d_generation, dchild); } else { /* didn't find removed dir entry - fine! */