X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsmfs%2Fdir.c;h=6be2ddd0770f2c355b8b9fb78c51f5255c192ce9;hb=a5f098b37fff7f32c238fdfaae82b9f56e1b72b7;hp=e3ce2ab323edb47ba210e1b03a1c280f8e10a43b;hpb=1a39214bb49e82c2a3410392c0fce5258dbac64d;p=fs%2Flustre-release.git diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index e3ce2ab..6be2ddd 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -35,10 +35,11 @@ #include #include #include - +#include +#include #include "smfs_internal.h" -#define NAME_ALLOC_LEN(len) ((len+16) & ~15) +//#define NAME_ALLOC_LEN(len) ((len+16) & ~15) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) static int smfs_create(struct inode *dir, struct dentry *dentry, @@ -48,253 +49,379 @@ static int smfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) #endif { - struct inode *inode = NULL; - struct inode *cache_dir = NULL; + struct inode *inode = NULL; + struct inode *parent = I2CI(dentry->d_parent->d_inode); + struct inode *cache_dir = I2CI(dir); struct dentry *cache_dentry = NULL; struct dentry *cache_parent = NULL; void *handle = NULL; + struct hook_msg msg = { + .dentry = dentry, + }; int rc = 0; - + ENTRY; - cache_dir = I2CI(dir); - if (!cache_dir) - RETURN(-ENOENT); - - handle = smfs_trans_start(dir, FSFILT_OP_CREATE, NULL); - if (IS_ERR(handle)) - RETURN(-ENOSPC); - - SMFS_CACHE_HOOK_PRE(CACHE_HOOK_CREATE, handle, dir, rc); + LASSERT(cache_dir); + LASSERT(cache_dir->i_op->create); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); + //lock_kernel(); + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); - - lock_kernel(); - if (!cache_dentry || !cache_parent) - GOTO(exit, rc = -ENOMEM); + if (!cache_dentry || !cache_parent) { + rc = -ENOMEM; + goto exit; + } + + handle = smfs_trans_start(dir, FSFILT_OP_CREATE, NULL); + if (IS_ERR(handle)) { + rc = -ENOSPC; + goto exit; + } + + SMFS_PRE_HOOK(dir, HOOK_CREATE, &msg); pre_smfs_inode(dir, cache_dir); - SMFS_PRE_COW(dir, dentry, REINT_CREATE, "create", rc, exit); - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) - if (cache_dir && cache_dir->i_op->create) - rc = cache_dir->i_op->create(cache_dir, cache_dentry, - mode); + rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode); #else - if (cache_dir && cache_dir->i_op->create) - rc = cache_dir->i_op->create(cache_dir, cache_dentry, - mode, nd); + rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode, nd); #endif - if (rc) - GOTO(exit, rc); - - inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); - if (!inode) - GOTO(exit, rc = -ENOMEM); + if (!rc) { + inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, + dir, 0); + if (inode) { + d_instantiate(dentry, inode); + } + else + rc = -ENOENT; + } + + SMFS_POST_HOOK(dir, HOOK_CREATE, &msg, rc); - d_instantiate(dentry, inode); - sm_set_inode_ops(cache_dentry->d_inode, inode); post_smfs_inode(dir, cache_dir); + smfs_trans_commit(dir, handle, 0); - /*Do KML post hook*/ - - SMFS_KML_POST(dir, dentry, NULL, NULL, REINT_CREATE, - "create", rc, exit); - SMFS_CACHE_HOOK_POST(CACHE_HOOK_CREATE, handle, dir, dentry, - NULL, NULL, rc, exit); exit: - unlock_kernel(); + //unlock_kernel(); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); - smfs_trans_commit(dir, handle, 0); RETURN(rc); } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry) -#else -static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *nd) -#endif +static struct dentry * iopen_connect_dentry(struct dentry * dentry, + struct inode *inode, int rehash) { - struct inode *cache_dir; - struct inode *cache_inode; - struct inode *inode = NULL; + struct dentry *tmp, *goal = NULL; + struct list_head *lp; + + /* verify this dentry is really new */ + LASSERT(dentry->d_inode == NULL); + LASSERT(list_empty(&dentry->d_alias)); /* d_instantiate */ + if (rehash) + LASSERT(d_unhashed(dentry)); /* d_rehash */ + LASSERT(list_empty(&dentry->d_subdirs)); + + spin_lock(&dcache_lock); + if (!inode) + goto do_rehash; + + /* preferrably return a connected dentry */ + list_for_each(lp, &inode->i_dentry) { + tmp = list_entry(lp, struct dentry, d_alias); + if (tmp->d_flags & DCACHE_DISCONNECTED) { + LASSERT(tmp->d_alias.next == &inode->i_dentry); + LASSERT(tmp->d_alias.prev == &inode->i_dentry); + goal = tmp; + dget_locked(goal); + break; + } + } + + if (!goal) + goto do_instantiate; + + /* Move the goal to the de hash queue */ + goal->d_flags &= ~ DCACHE_DISCONNECTED; + security_d_instantiate(goal, inode); + __d_rehash(dentry); + __d_move(goal, dentry); + spin_unlock(&dcache_lock); + iput(inode); + + RETURN(goal); + + /* d_add(), but don't drop dcache_lock before adding dentry to inode */ +do_instantiate: + list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */ + dentry->d_inode = inode; +do_rehash: + if (rehash) + __d_rehash(dentry); + spin_unlock(&dcache_lock); + + RETURN(NULL); + +} + +static int smfs_do_lookup (struct inode * dir, + struct dentry * dentry, + struct nameidata *nd, + struct inode **inode) +{ + struct inode *cache_dir = I2CI(dir); + struct inode *parent = I2CI(dentry->d_parent->d_inode); struct dentry *cache_dentry = NULL; struct dentry *cache_parent = NULL; - struct dentry *rc = NULL; - void *handle = NULL; - int rc2 = 0; + struct dentry *rdentry = NULL, *tmp = NULL; + int rc = 0; + struct hook_msg msg = { + .dentry = dentry, + }; ENTRY; - - if (!(cache_dir = I2CI(dir))) - RETURN(ERR_PTR(-ENOENT)); - - SMFS_CACHE_HOOK_PRE(CACHE_HOOK_LOOKUP, handle, dir, rc2); - if (rc2) - RETURN(ERR_PTR(rc2)); + cache_dir = I2CI(dir); + if (!cache_dir) + RETURN(-ENOENT); + + LASSERT(cache_dir->i_op->lookup); /* preparing artificial backing fs dentries. */ - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent); + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); - - if (!cache_dentry || !cache_parent) - GOTO(exit, rc = ERR_PTR(-ENOMEM)); - - if (!cache_dir && cache_dir->i_op->lookup) - GOTO(exit, rc = ERR_PTR(-ENOENT)); - + if (!cache_dentry || !cache_parent) { + rc = -ENOMEM; + goto exit; + } + + SMFS_PRE_HOOK(dir, HOOK_LOOKUP, &msg); + /* perform lookup in backing fs. */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) - rc = cache_dir->i_op->lookup(cache_dir, cache_dentry); -#else - rc = cache_dir->i_op->lookup(cache_dir, cache_dentry, nd); -#endif - - if (rc && IS_ERR(rc)) - GOTO(exit, rc); - - if ((cache_inode = rc ? rc->d_inode : cache_dentry->d_inode)) { - if (IS_ERR(cache_inode)) { - dentry->d_inode = cache_inode; - GOTO(exit, rc = NULL); + rdentry = cache_dir->i_op->lookup(cache_dir, cache_dentry, nd); + if (rdentry) { + if (IS_ERR(rdentry)) { + rc = PTR_ERR(rdentry); + rdentry = NULL; } - inode = iget4(dir->i_sb, cache_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); - } else { - d_add(dentry, NULL); - GOTO(exit, rc); + else { + tmp = rdentry; + //copy fields if DCACHE_CROSS_REF + smfs_update_dentry(dentry, tmp); + } + } 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; } - - d_add(dentry, inode); - rc = NULL; - - SMFS_CACHE_HOOK_POST(CACHE_HOOK_LOOKUP, handle, dir, dentry, - NULL, NULL, rc2, exit); + + if (rdentry) { + LASSERT(atomic_read(&rdentry->d_count) > 0); + dput(rdentry); + } + exit: - if (rc2) - rc = ERR_PTR(rc2); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); - smfs_trans_commit(dir, handle, 0); + RETURN(rc); } -static int smfs_link(struct dentry * old_dentry, - struct inode * dir, struct dentry *dentry) +static struct dentry * smfs_iopen_lookup(struct inode * dir, + struct dentry *dentry, + struct nameidata *nd) { - struct inode *cache_old_inode = NULL; - struct inode *cache_dir = I2CI(dir); - struct inode *inode = NULL; - struct dentry *cache_dentry = NULL; - struct dentry *cache_old_dentry = NULL; - struct dentry *cache_parent = NULL; - void *handle = NULL; - int rc = 0; + struct dentry * alternate = NULL; + struct inode *inode = NULL; + int rc = 0; + ENTRY; + + rc = smfs_do_lookup(dir, dentry, nd, &inode); + if (rc) + RETURN(ERR_PTR(rc)); + + LASSERT(inode); + /* preferrably return a connected dentry */ + spin_lock(&dcache_lock); + list_for_each_entry(alternate, &inode->i_dentry, d_alias) { + LASSERT(!(alternate->d_flags & DCACHE_DISCONNECTED)); + } + + list_for_each_entry(alternate, &inode->i_dentry, d_alias) { + dget_locked(alternate); + spin_lock(&alternate->d_lock); + alternate->d_flags |= DCACHE_REFERENCED; + spin_unlock(&alternate->d_lock); + iput(inode); + spin_unlock(&dcache_lock); + RETURN(alternate); + } + + dentry->d_flags |= DCACHE_DISCONNECTED; - inode = old_dentry->d_inode; + /* d_add(), but don't drop dcache_lock before adding dentry to inode */ + list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */ + dentry->d_inode = inode; - cache_old_inode = I2CI(inode); + __d_rehash(dentry); /* d_rehash */ + spin_unlock(&dcache_lock); - handle = smfs_trans_start(dir, FSFILT_OP_LINK, NULL); - if (IS_ERR(handle)) - RETURN(-ENOSPC); + return NULL; +} - SMFS_CACHE_HOOK_PRE(CACHE_HOOK_LINK, handle, dir, rc); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry) +#else +static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +#endif +{ + struct dentry * rdentry = NULL; + struct inode * inode = NULL; + int rc; - lock_kernel(); + rc = smfs_do_lookup(dir, dentry, nd, &inode); + if (rc) + RETURN(ERR_PTR(rc)); - SMFS_PRE_COW(dir, old_dentry, REINT_LINK, "link", rc, exit); + //lmv stuff. Special dentry that has no inode. + if (dentry->d_flags & DCACHE_CROSS_REF) { + d_add(dentry, NULL); + RETURN(NULL); + } + //TODO: should flags be checked and copied before? + rdentry = iopen_connect_dentry(dentry, inode, 1); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); - cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + RETURN(rdentry); +} - if (!cache_parent || !cache_dentry) - GOTO(exit, rc = -ENOMEM); +static int smfs_link(struct dentry *old_dentry, + struct inode *dir, struct dentry *dentry) +{ + struct inode *parent = I2CI(dentry->d_parent->d_inode); + struct inode *cache_dir = I2CI(dir); + struct inode *old_inode = old_dentry->d_inode; + struct inode *cache_old_inode = I2CI(old_inode); + struct dentry *cache_old_dentry = NULL; + struct dentry *cache_dentry = NULL; + struct dentry *cache_parent = NULL; + void *handle = NULL; + int rc = 0; + struct hook_link_msg msg = { + .dentry = old_dentry, + .new_dentry = dentry + }; - cache_old_dentry = pre_smfs_dentry(NULL, cache_old_inode, - old_dentry); - if (!cache_old_dentry) - GOTO(exit, rc = -ENOMEM); + ENTRY; + + if (!cache_dir) + RETURN(-ENOENT); + + if (!cache_old_inode) + RETURN(-ENOENT); + + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); + cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + cache_old_dentry = pre_smfs_dentry(NULL, cache_old_inode, old_dentry); + if (!cache_old_dentry || !cache_dentry || !cache_parent) { + rc = -ENOMEM; + goto exit; + } + + handle = smfs_trans_start(dir, FSFILT_OP_LINK, NULL); + if (IS_ERR(handle)) { + rc = -ENOSPC; + goto exit; + } pre_smfs_inode(dir, cache_dir); - pre_smfs_inode(inode, cache_old_dentry->d_inode); + pre_smfs_inode(old_inode, cache_old_inode); - if (cache_dir->i_op->link) - rc = cache_dir->i_op->link(cache_old_dentry, cache_dir, - cache_dentry); - if (rc) - GOTO(exit, rc); + //lock_kernel(); + SMFS_PRE_HOOK(dir, HOOK_LINK, &msg); - atomic_inc(&inode->i_count); - post_smfs_inode(inode, cache_old_dentry->d_inode); - d_instantiate(dentry, inode); - post_smfs_inode(dir, cache_dir); + rc = cache_dir->i_op->link(cache_old_dentry, cache_dir, cache_dentry); + if (!rc) { + atomic_inc(&old_inode->i_count); + dput(iopen_connect_dentry(dentry, old_inode, 0)); + } - SMFS_KML_POST(dir, old_dentry, dentry, NULL, - REINT_LINK, "link", rc, exit); + SMFS_POST_HOOK(dir, HOOK_LINK, &msg, rc); + + post_smfs_inode(old_inode, cache_old_inode); + post_smfs_inode(dir, cache_dir); - SMFS_CACHE_HOOK_POST(CACHE_HOOK_LINK, handle, - dir, old_dentry, NULL, NULL, rc, exit); + smfs_trans_commit(dir, handle, 0); + exit: - unlock_kernel(); + //unlock_kernel(); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); post_smfs_dentry(cache_old_dentry); - smfs_trans_commit(dir, handle, 0); + RETURN(rc); } -static int smfs_unlink(struct inode * dir, - struct dentry *dentry) +static int smfs_unlink(struct inode * dir, struct dentry *dentry) { struct inode *cache_dir = I2CI(dir); struct inode *cache_inode = I2CI(dentry->d_inode); - struct dentry *cache_dentry; - struct dentry *cache_parent; + struct inode *parent = I2CI(dentry->d_parent->d_inode); + struct dentry *cache_dentry = NULL; + struct dentry *cache_parent = NULL; void *handle = NULL; int rc = 0; - int mode = 0; - - if (!cache_dir || !cache_inode) - RETURN(-ENOENT); - - handle = smfs_trans_start(dir, FSFILT_OP_UNLINK, NULL); - if (IS_ERR(handle)) - RETURN(-ENOSPC); - - SMFS_CACHE_HOOK_PRE(CACHE_HOOK_UNLINK, handle, dir, rc); + //int mode = 0; + struct hook_unlink_msg msg = { + .dentry = dentry, + .mode = 0 + }; - SMFS_PRE_COW(dir, dentry, REINT_UNLINK, "unlink", rc, exit); + ENTRY; + + LASSERT(cache_dir); + LASSERT(cache_inode); + LASSERT(cache_dir->i_op->unlink); + LASSERT(parent); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry); - - if (!cache_parent || !cache_dentry) - GOTO(exit, rc = -ENOMEM); + if (!cache_dentry || !cache_parent) { + rc = -ENOMEM; + goto exit; + } - lock_kernel(); + //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); - if (cache_dir->i_op->unlink) - rc = cache_dir->i_op->unlink(cache_dir, cache_dentry); + + SMFS_PRE_HOOK(dir, HOOK_UNLINK, &msg); + + 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(); - SMFS_KML_POST(dir, dentry, &mode, NULL, REINT_UNLINK, - "unlink", rc, exit); - - SMFS_CACHE_HOOK_POST(CACHE_HOOK_UNLINK, handle, dir, dentry, - NULL, NULL, rc, exit); + //unlock_kernel(); + + smfs_trans_commit(dir, handle, 0); exit: post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); - smfs_trans_commit(dir, handle, 0); RETURN(rc); } @@ -303,105 +430,118 @@ static int smfs_symlink(struct inode *dir, struct dentry *dentry, { struct inode *cache_dir = I2CI(dir); struct inode *inode = NULL; - struct dentry *cache_dentry; - struct dentry *cache_parent; + struct inode *parent = I2CI(dentry->d_parent->d_inode); + struct dentry *cache_dentry = NULL; + struct dentry *cache_parent = NULL; void *handle = NULL; - int rc = 0, tgt_len; + int rc = 0; + struct hook_symlink_msg msg = { + .dentry = dentry, + .tgt_len = strlen(symname) + 1, + .symname = (char*)symname + }; - if (!cache_dir) - RETURN(-ENOENT); + ENTRY; + + LASSERT(cache_dir); + LASSERT(cache_dir->i_op->symlink); + LASSERT(parent); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); - - if (!cache_parent || !cache_dentry) - GOTO(exit, rc = -ENOMEM); - + if (!cache_parent || !cache_dentry) { + rc = -ENOMEM; + goto exit; + } + handle = smfs_trans_start(dir, FSFILT_OP_SYMLINK, NULL); - if (IS_ERR(handle)) - RETURN(-ENOSPC); - - SMFS_CACHE_HOOK_PRE(CACHE_HOOK_SYMLINK, handle, dir, rc); - + if (IS_ERR(handle)) { + rc = -ENOSPC; + goto exit; + } + + //lock_kernel(); pre_smfs_inode(dir, cache_dir); - lock_kernel(); - if (cache_dir->i_op->symlink) - rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname); - inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); + 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); + if (inode) { + //smfs_update_dentry(dentry, cache_dentry); + d_instantiate(dentry, inode); + } + else + rc = -ENOENT; + } + + SMFS_POST_HOOK(dir, HOOK_SYMLINK, &msg, rc); + post_smfs_inode(dir, cache_dir); - if (inode) - d_instantiate(dentry, inode); - else - rc = -ENOENT; - - tgt_len = strlen(symname) + 1; - SMFS_KML_POST(dir, dentry, (char*)symname, &tgt_len, REINT_CREATE, - "symlink", rc, exit); + smfs_trans_commit(dir, handle, 0); - SMFS_CACHE_HOOK_POST(CACHE_HOOK_SYMLINK, handle, dir, dentry, - NULL, NULL, rc, exit); exit: - unlock_kernel(); + //unlock_kernel(); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); - smfs_trans_commit(dir, handle, 0); RETURN(rc); } -static int smfs_mkdir(struct inode *dir, struct dentry *dentry, - int mode) +static int smfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { struct inode *cache_dir = I2CI(dir); + struct inode *parent = I2CI(dentry->d_parent->d_inode); struct inode *inode = NULL; - struct dentry *cache_dentry; - struct dentry *cache_parent; + struct dentry *cache_dentry = NULL; + struct dentry *cache_parent = NULL; void *handle = NULL; int rc = 0; + struct hook_msg msg = { + .dentry = dentry, + }; - if (!cache_dir) - RETURN(-ENOENT); - - handle = smfs_trans_start(dir, FSFILT_OP_MKDIR, NULL); - if (IS_ERR(handle)) - RETURN(-ENOSPC); - - SMFS_CACHE_HOOK_PRE(CACHE_HOOK_MKDIR, handle, dir, rc); - - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); + ENTRY; + + LASSERT(cache_dir); + LASSERT(parent); + + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + if (!cache_parent || !cache_dentry) { + rc = -ENOMEM; + goto exit; + } - lock_kernel(); - if (!cache_parent || !cache_dentry) - GOTO(exit, rc = -ENOMEM); - + handle = smfs_trans_start(dir, FSFILT_OP_MKDIR, NULL); + if (IS_ERR(handle)) { + rc = -ENOSPC; + goto exit; + } + pre_smfs_inode(dir, cache_dir); + SMFS_PRE_HOOK(dir, HOOK_MKDIR, &msg); + + 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); + if (inode) { + //smsf_update_dentry(dentry, cache_dentry); + d_instantiate(dentry, inode); + } + else + rc = -ENOENT; + } - if (cache_dir->i_op->mkdir) - rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode); - - if (rc) - GOTO(exit, rc); - - inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); - if (!inode) - GOTO(exit, rc = -ENOENT); - - d_instantiate(dentry, inode); + SMFS_POST_HOOK(dir, HOOK_MKDIR, &msg, rc); post_smfs_inode(dir, cache_dir); + smfs_trans_commit(dir, handle, 0); - SMFS_KML_POST(dir, dentry, NULL, NULL, - REINT_CREATE, "mkdir", rc, exit); - - SMFS_CACHE_HOOK_POST(CACHE_HOOK_MKDIR, handle, - dir, dentry, NULL, NULL, rc, exit); exit: - unlock_kernel(); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); - smfs_trans_commit(dir, handle, 0); RETURN(rc); } @@ -409,47 +549,55 @@ static int smfs_rmdir(struct inode *dir, struct dentry *dentry) { struct inode *cache_dir = I2CI(dir); struct inode *cache_inode = I2CI(dentry->d_inode); + struct inode *parent = I2CI(dentry->d_parent->d_inode); struct dentry *cache_dentry = NULL; struct dentry *cache_parent = NULL; void *handle = NULL; - int rc = 0, mode = S_IFDIR; + int rc = 0; + struct hook_unlink_msg msg = { + .dentry = dentry, + .mode = S_IFDIR + }; - if (!cache_dir) - RETURN(-ENOENT); + ENTRY; + + LASSERT(cache_dir); + LASSERT(cache_dir->i_op->rmdir); + LASSERT(parent); + + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); + cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry); + if (!cache_parent || !cache_dentry) { + rc = -ENOMEM; + goto exit; + } handle = smfs_trans_start(dir, FSFILT_OP_RMDIR, NULL); if (IS_ERR(handle) ) { - CERROR("smfs_do_mkdir: no space for transaction\n"); - RETURN(-ENOSPC); + rc = -ENOSPC; + goto exit; } - SMFS_CACHE_HOOK_PRE(CACHE_HOOK_RMDIR, handle, dir, rc); - - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); - cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry); - - lock_kernel(); - if (!cache_parent || !cache_dentry) - GOTO(exit, rc = -ENOMEM); - pre_smfs_inode(dir, cache_dir); pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode); - if (cache_dir->i_op->rmdir) - rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry); - + + 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); - unlock_kernel(); + //like vfs_rmdir is doing with inode + if (!rc) + cache_dentry->d_inode->i_flags |= S_DEAD; - SMFS_KML_POST(dir, dentry, &mode, NULL, - REINT_UNLINK, "rmdir", rc, exit); + smfs_trans_commit(dir, handle, 0); - SMFS_CACHE_HOOK_POST(CACHE_HOOK_RMDIR, handle, dir, dentry, - NULL, NULL, rc, exit); exit: post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); - smfs_trans_commit(dir, handle, 0); RETURN(rc); } @@ -463,122 +611,140 @@ static int smfs_mknod(struct inode *dir, struct dentry *dentry, { struct inode *cache_dir = I2CI(dir); struct inode *inode = NULL; + struct inode *parent = I2CI(dentry->d_parent->d_inode); struct dentry *cache_dentry = NULL; struct dentry *cache_parent = NULL; void *handle = NULL; int rc = 0; + struct hook_msg msg = { + .dentry = dentry, + }; + + ENTRY; + + LASSERT(parent); + LASSERT(cache_dir); + LASSERT(cache_dir->i_op->mknod); - if (!cache_dir) - RETURN(-ENOENT); + cache_parent = pre_smfs_dentry(NULL, parent, dentry->d_parent); + cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); + if (!cache_parent || !cache_dentry) { + rc = -ENOMEM; + goto exit; + } handle = smfs_trans_start(dir, FSFILT_OP_MKNOD, NULL); if (IS_ERR(handle)) { - CERROR("smfs_do_mkdir: no space for transaction\n"); - RETURN(-ENOSPC); + rc = -ENOSPC; + goto exit; } - SMFS_CACHE_HOOK_PRE(CACHE_HOOK_MKNOD, handle, dir, rc); - - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent); - cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); - lock_kernel(); - if (!cache_parent || !cache_dentry) - GOTO(exit, rc = -ENOMEM); - - pre_smfs_inode(dir, cache_dir); - pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode); - - if (!cache_dir->i_op->mknod) - RETURN(-ENOENT); - - if ((rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, - mode, rdev))) - GOTO(exit, rc); - - inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL, - &I2SMI(dir)->smi_flags); - d_instantiate(dentry, inode); - + pre_smfs_inode(dir, cache_dir); - pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode); + + SMFS_PRE_HOOK(dir, HOOK_MKNOD, &msg); + + 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); + if (inode) { + //smsf_update_dentry(dentry, cache_dentry); + d_instantiate(dentry, inode); + } + else + rc = -ENOENT; + } - SMFS_KML_POST(dir, dentry, NULL, NULL, - REINT_CREATE, "mknod", rc, exit); + SMFS_POST_HOOK(dir, HOOK_MKNOD, &msg, rc); + + post_smfs_inode(dir, cache_dir); + + smfs_trans_commit(dir, handle, 0); - SMFS_CACHE_HOOK_POST(CACHE_HOOK_MKNOD, handle, dir, - dentry, NULL, NULL, rc, exit); exit: - unlock_kernel(); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); - smfs_trans_commit(dir, handle, 0); RETURN(rc); } -static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry, - struct inode * new_dir,struct dentry *new_dentry) +static int smfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir,struct dentry *new_dentry) { struct inode *cache_old_dir = I2CI(old_dir); struct inode *cache_new_dir = I2CI(new_dir); struct inode *cache_old_inode = I2CI(old_dentry->d_inode); - - struct inode *cache_new_inode = new_dentry->d_inode ? - I2CI(new_dentry->d_inode) : NULL; - + struct inode *old_parent = I2CI(old_dentry->d_parent->d_inode); + struct inode *new_parent = I2CI(new_dentry->d_parent->d_inode); + struct inode *cache_new_inode = NULL; struct dentry *cache_old_dentry = NULL; struct dentry *cache_new_dentry = NULL; struct dentry *cache_new_parent = NULL; struct dentry *cache_old_parent = NULL; void *handle = NULL; int rc = 0; + struct hook_rename_msg msg = { + .dentry = old_dentry, + .new_dir = new_dir, + .new_dentry = new_dentry + }; + ENTRY; + if (!cache_old_dir || !cache_new_dir || !cache_old_inode) RETURN(-ENOENT); - handle = smfs_trans_start(old_dir, FSFILT_OP_RENAME, NULL); - if (IS_ERR(handle)) { - CERROR("smfs_do_mkdir: no space for transaction\n"); - RETURN(-ENOSPC); + if (new_dentry->d_inode) { + cache_new_inode = I2CI(new_dentry->d_inode); + if (!cache_new_inode) + RETURN(-ENOENT); } - lock_kernel(); - - SMFS_CACHE_HOOK_PRE(CACHE_HOOK_RENAME, handle, old_dir, rc); - - cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry); + + cache_old_parent = pre_smfs_dentry(NULL, old_parent, old_dentry->d_parent); cache_old_dentry = pre_smfs_dentry(cache_old_parent, cache_old_inode, old_dentry); - if (!cache_old_parent || !cache_old_dentry) - GOTO(exit, rc = -ENOMEM); - - cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry); + if (!cache_old_parent || !cache_old_dentry) { + rc = -ENOMEM; + goto exit; + } + + cache_new_parent = pre_smfs_dentry(NULL, new_parent, new_dentry->d_parent); cache_new_dentry = pre_smfs_dentry(cache_new_parent, cache_new_inode, new_dentry); - if (!cache_new_parent || !cache_new_dentry) - GOTO(exit, rc = -ENOMEM); + if (!cache_new_parent || !cache_new_dentry) { + rc = -ENOMEM; + goto exit; + } + handle = smfs_trans_start(old_dir, FSFILT_OP_RENAME, NULL); + if (IS_ERR(handle)) { + rc = -ENOSPC; + goto exit; + } + 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); - if (cache_old_dir->i_op->rename) - rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry, - cache_new_dir, cache_new_dentry); + SMFS_PRE_HOOK(old_dir, HOOK_RENAME, &msg); + + rc = cache_old_dir->i_op->rename(cache_old_dir, cache_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); - - SMFS_KML_POST(old_dir, old_dentry, new_dir, - new_dentry, REINT_RENAME, "rename", rc, exit); if (new_dentry->d_inode) post_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode); - - SMFS_CACHE_HOOK_POST(CACHE_HOOK_RENAME, handle, old_dir, old_dentry, - new_dir, new_dentry, rc, exit); + + smfs_trans_commit(old_dir, handle, 0); + exit: - unlock_kernel(); post_smfs_dentry(cache_old_dentry); post_smfs_dentry(cache_old_parent); post_smfs_dentry(cache_new_dentry); post_smfs_dentry(cache_new_parent); - smfs_trans_commit(old_dir, handle, 0); RETURN(rc); } @@ -598,6 +764,10 @@ struct inode_operations smfs_dir_iops = { removexattr: smfs_removexattr, /* BKL held */ }; +struct inode_operations smfs_iopen_iops = { + lookup: smfs_iopen_lookup, +}; + static ssize_t smfs_read_dir(struct file *filp, char *buf, size_t size, loff_t *ppos) { @@ -605,29 +775,35 @@ static ssize_t smfs_read_dir(struct file *filp, char *buf, struct inode *cache_inode = NULL; struct smfs_file_info *sfi = NULL; loff_t tmp_ppos; - loff_t *cache_ppos; + loff_t *cache_ppos = NULL; int rc = 0; + ENTRY; + cache_inode = I2CI(dentry->d_inode); - if (!cache_inode) + if (!cache_inode || !cache_inode->i_fop->read) RETURN(-EINVAL); sfi = F2SMFI(filp); - if (sfi->magic != SMFS_FILE_MAGIC) BUG(); + if (sfi->magic != SMFS_FILE_MAGIC) + BUG(); if (ppos != &(filp->f_pos)) cache_ppos = &tmp_ppos; else cache_ppos = &sfi->c_file->f_pos; + *cache_ppos = *ppos; - if (cache_inode->i_fop->read) - rc = cache_inode->i_fop->read(sfi->c_file, buf, size, - cache_ppos); + rc = cache_inode->i_fop->read(sfi->c_file, buf, size, cache_ppos); + if (rc) + RETURN(rc); *ppos = *cache_ppos; + duplicate_file(filp, sfi->c_file); + RETURN(rc); } @@ -637,26 +813,42 @@ static int smfs_readdir(struct file *filp, void *dirent, filldir_t filldir) struct inode *cache_inode = NULL; struct smfs_file_info *sfi = NULL; int rc = 0; + struct hook_readdir_msg msg = { + .dentry = dentry, + .filp = filp, + .dirent = dirent, + .filldir = filldir + }; + ENTRY; + cache_inode = I2CI(dentry->d_inode); - if (!cache_inode) + if (!cache_inode || !cache_inode->i_fop->readdir) RETURN(-EINVAL); sfi = F2SMFI(filp); if (sfi->magic != SMFS_FILE_MAGIC) BUG(); - if (cache_inode->i_fop->readdir) - rc = cache_inode->i_fop->readdir(sfi->c_file, dirent, filldir); - + SMFS_PRE_HOOK(dentry->d_inode, HOOK_READDIR, &msg); + + rc = cache_inode->i_fop->readdir(sfi->c_file, dirent, filldir); + + SMFS_POST_HOOK(dentry->d_inode, HOOK_READDIR, &msg, rc); duplicate_file(filp, sfi->c_file); + RETURN(rc); } struct file_operations smfs_dir_fops = { - read: smfs_read_dir, - readdir: smfs_readdir, /* BKL held */ - ioctl: smfs_ioctl, /* BKL held */ - fsync: smfs_fsync, /* BKL held */ - open: smfs_open, - release: smfs_release, + .read = smfs_read_dir, + .readdir = smfs_readdir, /* BKL held */ + .ioctl = smfs_ioctl, /* BKL held */ + .fsync = smfs_fsync, /* BKL held */ + .open = smfs_open, + .release = smfs_release, +}; + +struct file_operations smfs_iopen_fops = { + .read = smfs_read_dir, }; +