X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsmfs%2Fdir.c;h=296973b106dd0cbdf70cec4aa13107c3da75f10b;hb=55fbf48ae65fac7b891367691e8177dbccf524f7;hp=6be2ddd0770f2c355b8b9fb78c51f5255c192ce9;hpb=701322d0e64a6530e6263aaf8e852e6171c65de5;p=fs%2Flustre-release.git diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index 6be2ddd..296973b 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -61,11 +61,14 @@ static int smfs_create(struct inode *dir, struct dentry *dentry, int rc = 0; ENTRY; - + + CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n", + dentry->d_name.len, dentry->d_name.name, dentry, + dir->i_ino, dir->i_generation); + LASSERT(cache_dir); LASSERT(cache_dir->i_op->create); - - //lock_kernel(); + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); if (!cache_dentry || !cache_parent) { @@ -89,8 +92,8 @@ static int smfs_create(struct inode *dir, struct dentry *dentry, rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode, nd); #endif if (!rc) { - inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, - dir, 0); + inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode, + I2SMI(dir), 0); if (inode) { d_instantiate(dentry, inode); } @@ -102,9 +105,8 @@ static int smfs_create(struct inode *dir, struct dentry *dentry, post_smfs_inode(dir, cache_dir); smfs_trans_commit(dir, handle, 0); - + exit: - //unlock_kernel(); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); RETURN(rc); @@ -182,7 +184,10 @@ static int smfs_do_lookup (struct inode * dir, ENTRY; - cache_dir = I2CI(dir); + CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n", + dentry->d_name.len, dentry->d_name.name, dentry, + dir->i_ino, dir->i_generation); + if (!cache_dir) RETURN(-ENOENT); @@ -204,26 +209,43 @@ static int smfs_do_lookup (struct inode * dir, if (IS_ERR(rdentry)) { rc = PTR_ERR(rdentry); rdentry = NULL; - } - else { + } else { tmp = rdentry; - //copy fields if DCACHE_CROSS_REF - smfs_update_dentry(dentry, tmp); } - } else + } else { tmp = cache_dentry; - + } + SMFS_POST_HOOK(dir, HOOK_LOOKUP, &msg, rc); - if (tmp && tmp->d_inode) { - *inode = smfs_get_inode(dir->i_sb, tmp->d_inode->i_ino, - dir, 0); - if (!(*inode)) - rc = -ENOENT; + if (tmp) { + //copy fields if DCACHE_CROSS_REF + smfs_update_dentry(dentry, tmp); + + if (tmp->d_inode) { + *inode = smfs_get_inode(dir->i_sb, tmp->d_inode, + I2SMI(dir), 0); + if (!(*inode)) + rc = -ENOENT; + else { + if (!tmp->d_inode->i_nlink) { + struct inode * ind = tmp->d_inode; + + CWARN("inode #%lu (%*s) nlink is %i/%i\n", + ind->i_ino, tmp->d_name.len, + tmp->d_name.name, ind->i_nlink, + (*inode)->i_nlink); + CWARN("parent #%lu (%*s) nlink is %i\n", + dir->i_ino, tmp->d_parent->d_name.len, + tmp->d_parent->d_name.name, + cache_dir->i_nlink); + LBUG(); + } + } + } } if (rdentry) { - LASSERT(atomic_read(&rdentry->d_count) > 0); dput(rdentry); } @@ -286,6 +308,8 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, struct dentry * rdentry = NULL; struct inode * inode = NULL; int rc; + + ENTRY; rc = smfs_do_lookup(dir, dentry, nd, &inode); if (rc) @@ -302,6 +326,26 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, RETURN(rdentry); } +#if HAVE_LOOKUP_RAW +static int smfs_lookup_raw(struct inode *dir, const char *name, + int len, ino_t *data) +{ + struct inode *cache_dir = I2CI(dir); + int rc = 0; + + if (!cache_dir) + RETURN(-ENOENT); + + if (cache_dir->i_op->lookup_raw) { + rc = cache_dir->i_op->lookup_raw(cache_dir, name, len, data); + } else { + CWARN("do not have raw lookup ops in bottom fs\n"); + } + + RETURN(rc); +} +#endif + static int smfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { @@ -350,6 +394,7 @@ static int smfs_link(struct dentry *old_dentry, rc = cache_dir->i_op->link(cache_old_dentry, cache_dir, cache_dentry); if (!rc) { atomic_inc(&old_inode->i_count); + old_inode->i_nlink++; dput(iopen_connect_dentry(dentry, old_inode, 0)); } @@ -381,7 +426,7 @@ static int smfs_unlink(struct inode * dir, struct dentry *dentry) //int mode = 0; struct hook_unlink_msg msg = { .dentry = dentry, - .mode = 0 + .mode = dentry->d_inode->i_mode }; ENTRY; @@ -391,6 +436,10 @@ static int smfs_unlink(struct inode * dir, struct dentry *dentry) LASSERT(cache_dir->i_op->unlink); LASSERT(parent); + CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n", + dentry->d_name.len, dentry->d_name.name, dentry, + dir->i_ino, dir->i_generation); + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry); if (!cache_dentry || !cache_parent) { @@ -398,13 +447,12 @@ static int smfs_unlink(struct inode * dir, struct dentry *dentry) goto exit; } - //lock_kernel(); handle = smfs_trans_start(dir, FSFILT_OP_UNLINK, NULL); if (IS_ERR(handle)) { rc = -ENOSPC; goto exit; } - + pre_smfs_inode(dir, cache_dir); pre_smfs_inode(dentry->d_inode, cache_inode); @@ -413,10 +461,11 @@ static int smfs_unlink(struct inode * dir, struct dentry *dentry) rc = cache_dir->i_op->unlink(cache_dir, cache_dentry); SMFS_POST_HOOK(dir, HOOK_UNLINK, &msg, rc); - - post_smfs_inode(dentry->d_inode, cache_dentry->d_inode); - post_smfs_inode(dir, cache_dir); - //unlock_kernel(); + if (!rc) { + post_smfs_inode(dentry->d_inode, cache_inode); + dentry->d_inode->i_nlink--; + post_smfs_inode(dir, cache_dir); + } smfs_trans_commit(dir, handle, 0); exit: @@ -460,17 +509,15 @@ static int smfs_symlink(struct inode *dir, struct dentry *dentry, goto exit; } - //lock_kernel(); pre_smfs_inode(dir, cache_dir); SMFS_PRE_HOOK(dir, HOOK_SYMLINK, &msg); rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname); if (!rc) { - inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, - dir, 0); + inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode, + I2SMI(dir), 0); if (inode) { - //smfs_update_dentry(dentry, cache_dentry); d_instantiate(dentry, inode); } else @@ -483,7 +530,6 @@ static int smfs_symlink(struct inode *dir, struct dentry *dentry, smfs_trans_commit(dir, handle, 0); exit: - //unlock_kernel(); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); RETURN(rc); @@ -507,6 +553,11 @@ static int smfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) LASSERT(cache_dir); LASSERT(parent); + CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n", + dentry->d_name.len, dentry->d_name.name, dentry, + dir->i_ino, dir->i_generation); + + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); if (!cache_parent || !cache_dentry) { @@ -525,10 +576,10 @@ static int smfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode); if (!rc) { - inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, - dir, 0); + inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode, + I2SMI(dir), 0); if (inode) { - //smsf_update_dentry(dentry, cache_dentry); + dir->i_nlink++; d_instantiate(dentry, inode); } else @@ -552,6 +603,7 @@ static int smfs_rmdir(struct inode *dir, struct dentry *dentry) struct inode *parent = I2CI(dentry->d_parent->d_inode); struct dentry *cache_dentry = NULL; struct dentry *cache_parent = NULL; + struct inode * inode = dentry->d_inode; void *handle = NULL; int rc = 0; struct hook_unlink_msg msg = { @@ -561,6 +613,10 @@ static int smfs_rmdir(struct inode *dir, struct dentry *dentry) ENTRY; + CDEBUG(D_INODE, "VFS Op:name=%.*s (%p),dir=%lu/%u\n", + dentry->d_name.len, dentry->d_name.name, dentry, + dir->i_ino, dir->i_generation); + LASSERT(cache_dir); LASSERT(cache_dir->i_op->rmdir); LASSERT(parent); @@ -571,30 +627,36 @@ static int smfs_rmdir(struct inode *dir, struct dentry *dentry) rc = -ENOMEM; goto exit; } - + handle = smfs_trans_start(dir, FSFILT_OP_RMDIR, NULL); if (IS_ERR(handle) ) { rc = -ENOSPC; goto exit; } + dentry_unhash(cache_dentry); + pre_smfs_inode(dir, cache_dir); - pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode); + pre_smfs_inode(inode, cache_inode); SMFS_PRE_HOOK(dir, HOOK_RMDIR, &msg); rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry); SMFS_POST_HOOK(dir, HOOK_RMDIR, &msg, rc); - - post_smfs_inode(dir, cache_dir); - post_smfs_inode(dentry->d_inode, cache_dentry->d_inode); - //like vfs_rmdir is doing with inode - if (!rc) - cache_dentry->d_inode->i_flags |= S_DEAD; - + if (!rc) { + if (inode->i_nlink != 2) + CWARN("Directory #%lu under rmdir has %i nlinks\n", + inode->i_ino, inode->i_nlink); + inode->i_nlink = 0; + dir->i_nlink--; + post_smfs_inode(dir, cache_dir); + post_smfs_inode(inode, cache_inode); + //like vfs_rmdir is doing with inode + cache_inode->i_flags |= S_DEAD; + } smfs_trans_commit(dir, handle, 0); - + dput(cache_dentry); exit: post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); @@ -645,8 +707,8 @@ static int smfs_mknod(struct inode *dir, struct dentry *dentry, rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, mode, rdev); if (!rc) { - inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, - dir, 0); + inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode, + I2SMI(dir), 0); if (inode) { //smsf_update_dentry(dentry, cache_dentry); d_instantiate(dentry, inode); @@ -672,6 +734,7 @@ static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry, { struct inode *cache_old_dir = I2CI(old_dir); struct inode *cache_new_dir = I2CI(new_dir); + struct inode *new_inode = new_dentry->d_inode; struct inode *cache_old_inode = I2CI(old_dentry->d_inode); struct inode *old_parent = I2CI(old_dentry->d_parent->d_inode); struct inode *new_parent = I2CI(new_dentry->d_parent->d_inode); @@ -693,8 +756,8 @@ static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (!cache_old_dir || !cache_new_dir || !cache_old_inode) RETURN(-ENOENT); - if (new_dentry->d_inode) { - cache_new_inode = I2CI(new_dentry->d_inode); + if (new_inode) { + cache_new_inode = I2CI(new_inode); if (!cache_new_inode) RETURN(-ENOENT); } @@ -723,8 +786,9 @@ static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry, pre_smfs_inode(old_dir, cache_old_dir); pre_smfs_inode(new_dir, cache_new_dir); - if (new_dentry->d_inode) - pre_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode); + pre_smfs_inode(old_dentry->d_inode, cache_old_inode); + if (new_inode) + pre_smfs_inode(new_inode, cache_new_inode); SMFS_PRE_HOOK(old_dir, HOOK_RENAME, &msg); @@ -732,12 +796,24 @@ static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry, cache_new_dir, cache_new_dentry); SMFS_POST_HOOK(old_dir, HOOK_RENAME, &msg, rc); - - post_smfs_inode(old_dir, cache_old_dir); - post_smfs_inode(new_dir, cache_new_dir); - if (new_dentry->d_inode) - post_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode); - + if (!rc) { + post_smfs_inode(old_dir, cache_old_dir); + post_smfs_inode(new_dir, cache_new_dir); + post_smfs_inode(old_dentry->d_inode, cache_old_inode); + if (new_inode) { + post_smfs_inode(new_inode, cache_new_inode); + new_inode->i_nlink--; + } + //directory is renamed + if (S_ISDIR(old_dentry->d_inode->i_mode)) { + old_dir->i_nlink--; + if (new_inode) { + new_inode->i_nlink--; + } else { + new_dir->i_nlink++; + } + } + } smfs_trans_commit(old_dir, handle, 0); exit: @@ -749,23 +825,27 @@ exit: } struct inode_operations smfs_dir_iops = { - create: smfs_create, - lookup: smfs_lookup, - link: smfs_link, /* BKL held */ - unlink: smfs_unlink, /* BKL held */ - symlink: smfs_symlink, /* BKL held */ - mkdir: smfs_mkdir, /* BKL held */ - rmdir: smfs_rmdir, /* BKL held */ - mknod: smfs_mknod, /* BKL held */ - rename: smfs_rename, /* BKL held */ - setxattr: smfs_setxattr, /* BKL held */ - getxattr: smfs_getxattr, /* BKL held */ - listxattr: smfs_listxattr, /* BKL held */ - removexattr: smfs_removexattr, /* BKL held */ + .create = smfs_create, + .lookup = smfs_lookup, +#if HAVE_LOOKUP_RAW + .lookup_raw = smfs_lookup_raw, +#endif + .link = smfs_link, + .unlink = smfs_unlink, + .symlink = smfs_symlink, + .mkdir = smfs_mkdir, + .rmdir = smfs_rmdir, + .mknod = smfs_mknod, + .rename = smfs_rename, + .setxattr = smfs_setxattr, + .getxattr = smfs_getxattr, + .listxattr = smfs_listxattr, + .removexattr = smfs_removexattr, + .permission = smfs_permission, }; struct inode_operations smfs_iopen_iops = { - lookup: smfs_iopen_lookup, + .lookup = smfs_iopen_lookup, }; static ssize_t smfs_read_dir(struct file *filp, char *buf,