X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsmfs%2Fdir.c;h=4130858f6bfa89a20f66444defbe015151b1208e;hb=da2e78ae73129188f1324615c6c78ee0dddb36ed;hp=685d6ffd303ecff1677a3532f312d4e094bfb42e;hpb=9d4b898b1c1c7c318fda5f0c345ed726c774c06a;p=fs%2Flustre-release.git diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index 685d6ff..4130858 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -36,10 +36,10 @@ #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, @@ -49,229 +49,402 @@ 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); + LASSERT(cache_dir); + LASSERT(cache_dir->i_op->create); - lock_kernel(); - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, - PRE_HOOK, rc, exit); - - 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_dentry || !cache_parent) - GOTO(exit, rc = -ENOMEM); + if (!cache_dentry || !cache_parent) { + rc = -ENOMEM; + goto exit; + } - pre_smfs_inode(dir, cache_dir); + 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); + #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); + 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_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, inode, - rc, exit); + SMFS_POST_HOOK(dir, HOOK_CREATE, &msg, rc); - d_instantiate(dentry, inode); post_smfs_inode(dir, cache_dir); + smfs_trans_commit(dir, handle, 0); - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, - POST_HOOK, rc, exit); exit: - 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) + RETURN(-ENOENT); - if (!(cache_dir = I2CI(dir))) - RETURN(ERR_PTR(-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) { + rc = -ENOMEM; + goto exit; + } + + SMFS_PRE_HOOK(dir, HOOK_LOOKUP, &msg); + + /* perform lookup in backing fs. */ + rdentry = cache_dir->i_op->lookup(cache_dir, cache_dentry, nd); + if (rdentry) { + if (IS_ERR(rdentry)) { + rc = PTR_ERR(rdentry); + rdentry = NULL; + } else { + tmp = rdentry; + } + } else { + tmp = cache_dentry; + } - if (!cache_dentry || !cache_parent) - GOTO(exit, rc = ERR_PTR(-ENOMEM)); + SMFS_POST_HOOK(dir, HOOK_LOOKUP, &msg, rc); + + if (tmp) { + //copy fields if DCACHE_CROSS_REF + smfs_update_dentry(dentry, tmp); + + if (tmp->d_inode) { + if (!tmp->d_inode->i_nlink) + CWARN("inode #%lu (%p) nlink is 0\n", + tmp->d_inode->i_ino, tmp->d_inode); + + *inode = smfs_get_inode(dir->i_sb, tmp->d_inode->i_ino, + dir, 0); + if (!(*inode)) + rc = -ENOENT; + } + } + + if (rdentry) { + dput(rdentry); + } + +exit: + post_smfs_dentry(cache_dentry); + post_smfs_dentry(cache_parent); + + RETURN(rc); +} - if (!cache_dir && cache_dir->i_op->lookup) - GOTO(exit, rc = ERR_PTR(-ENOENT)); +static struct dentry * smfs_iopen_lookup(struct inode * dir, + struct dentry *dentry, + struct nameidata *nd) +{ + 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; - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, - PRE_HOOK, rc2, exit); + /* 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; + + __d_rehash(dentry); /* d_rehash */ + spin_unlock(&dcache_lock); + + return NULL; +} - /* perform lookup in backing fs. */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) - rc = cache_dir->i_op->lookup(cache_dir, cache_dentry); +static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry) #else - rc = cache_dir->i_op->lookup(cache_dir, cache_dentry, nd); +static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) #endif - if (rc && IS_ERR(rc)) - GOTO(exit, rc); +{ + struct dentry * rdentry = NULL; + struct inode * inode = NULL; + int rc; + + ENTRY; - 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); - } - SMFS_GET_INODE(dir->i_sb, cache_inode, dir, inode, rc2, exit); + rc = smfs_do_lookup(dir, dentry, nd, &inode); + if (rc) + RETURN(ERR_PTR(rc)); + + //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); + + RETURN(rdentry); +} - d_add(dentry, inode); - rc = NULL; +#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"); + } - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, POST_HOOK, rc2, - exit); -exit: - if (rc2 < 0) - rc = ERR_PTR(rc2); - post_smfs_dentry(cache_dentry); - post_smfs_dentry(cache_parent); - smfs_trans_commit(dir, handle, 0); RETURN(rc); } +#endif static int smfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { - struct inode *cache_old_inode = NULL; + struct inode *parent = I2CI(dentry->d_parent->d_inode); struct inode *cache_dir = I2CI(dir); - struct inode *inode = NULL; - struct dentry *cache_dentry = NULL; + 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 + }; - inode = old_dentry->d_inode; - cache_old_inode = I2CI(inode); + ENTRY; - handle = smfs_trans_start(dir, FSFILT_OP_LINK, NULL); - if (IS_ERR(handle)) - RETURN(-ENOSPC); + if (!cache_dir) + RETURN(-ENOENT); - lock_kernel(); - SMFS_HOOK(dir, old_dentry, NULL, NULL, HOOK_LINK, handle, - PRE_HOOK, rc, exit); + if (!cache_old_inode) + RETURN(-ENOENT); - 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); - - cache_old_dentry = pre_smfs_dentry(NULL, cache_old_inode, - old_dentry); - if (!cache_old_dentry) - GOTO(exit, rc = -ENOMEM); + 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); + 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_POST_HOOK(dir, HOOK_LINK, &msg, rc); + + post_smfs_inode(old_inode, cache_old_inode); post_smfs_inode(dir, cache_dir); - SMFS_HOOK(dir, old_dentry, dentry, NULL, HOOK_LINK, handle, - POST_HOOK, 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); + //int mode = 0; + struct hook_unlink_msg msg = { + .dentry = dentry, + .mode = dentry->d_inode->i_mode + }; - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_UNLINK, handle, PRE_HOOK, 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(); + 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_HOOK(dir, dentry, &mode, NULL, HOOK_UNLINK, handle, POST_HOOK, - rc, exit); + 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); } @@ -280,99 +453,115 @@ 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; - - if (!cache_dir) - RETURN(-ENOENT); + int rc = 0; + struct hook_symlink_msg msg = { + .dentry = dentry, + .tgt_len = strlen(symname) + 1, + .symname = (char*)symname + }; - handle = smfs_trans_start(dir, FSFILT_OP_SYMLINK, NULL); - if (IS_ERR(handle)) - RETURN(-ENOSPC); + ENTRY; - lock_kernel(); - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_SYMLINK, handle, PRE_HOOK, rc, - exit); + 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)) { + rc = -ENOSPC; + goto exit; + } + pre_smfs_inode(dir, cache_dir); - if (cache_dir->i_op->symlink) - rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname); - post_smfs_inode(dir, cache_dir); + SMFS_PRE_HOOK(dir, HOOK_SYMLINK, &msg); - SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, inode, rc, exit); - if (inode) - d_instantiate(dentry, inode); - else - rc = -ENOENT; - - tgt_len = strlen(symname) + 1; + 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) { + d_instantiate(dentry, inode); + } + else + rc = -ENOENT; + } - SMFS_HOOK(dir, dentry, (char *)symname, &tgt_len, HOOK_SYMLINK, handle, - POST_HOOK, rc, exit); + SMFS_POST_HOOK(dir, HOOK_SYMLINK, &msg, rc); + + 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); - 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); - - lock_kernel(); + ENTRY; - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, PRE_HOOK, rc, - exit); + LASSERT(cache_dir); + 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) { + rc = -ENOMEM; + goto exit; + } - 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); - - SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, inode, rc, exit); - 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_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, POST_HOOK, rc, - exit); exit: - unlock_kernel(); post_smfs_dentry(cache_dentry); post_smfs_dentry(cache_parent); - smfs_trans_commit(dir, handle, 0); RETURN(rc); } @@ -380,46 +569,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; } - - lock_kernel(); - - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_RMDIR, handle, PRE_HOOK, rc, - exit); - - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry); - cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry); - - 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_HOOK(dir, dentry, &mode, NULL, HOOK_RMDIR, handle, POST_HOOK, - rc, exit); + 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); } @@ -433,54 +631,59 @@ 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; } - - lock_kernel(); - SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, PRE_HOOK, rc, - exit); - cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent); - cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry); - 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); - - SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, inode, rc, exit); - - 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_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, POST_HOOK, rc, - exit); + SMFS_POST_HOOK(dir, HOOK_MKNOD, &msg, rc); + 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); - smfs_trans_commit(dir, handle, 0); RETURN(rc); } @@ -490,75 +693,87 @@ 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 *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_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, - handle, PRE_HOOK, rc, exit); - - 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) { + rc = -ENOMEM; + goto exit; + } - if (!cache_old_parent || !cache_old_dentry) - GOTO(exit, rc = -ENOMEM); - - cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry); - + 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) { + rc = -ENOMEM; + goto exit; + } - if (!cache_new_parent || !cache_new_dentry) - GOTO(exit, rc = -ENOMEM); - + 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_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle, - POST_HOOK, rc, exit); - if (new_dentry->d_inode) post_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode); + + 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); } struct inode_operations smfs_dir_iops = { create: smfs_create, lookup: smfs_lookup, +#if HAVE_LOOKUP_RAW + lookup_raw: smfs_lookup_raw, +#endif link: smfs_link, /* BKL held */ unlink: smfs_unlink, /* BKL held */ symlink: smfs_symlink, /* BKL held */ @@ -572,6 +787,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) { @@ -579,28 +798,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); } @@ -610,27 +836,29 @@ 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(); - SMFS_HOOK(dentry->d_inode, filp, dirent, filldir, HOOK_READDIR, NULL, - PRE_HOOK, rc, exit); + SMFS_PRE_HOOK(dentry->d_inode, HOOK_READDIR, &msg); - if (cache_inode->i_fop->readdir) - rc = cache_inode->i_fop->readdir(sfi->c_file, dirent, filldir); - - SMFS_HOOK(dentry->d_inode, filp, dirent, filldir, HOOK_READDIR, NULL, - POST_HOOK, rc, exit); + 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); -exit: - if (rc > 0) - rc = 0; + RETURN(rc); } @@ -642,3 +870,8 @@ struct file_operations smfs_dir_fops = { .open = smfs_open, .release = smfs_release, }; + +struct file_operations smfs_iopen_fops = { + .read = smfs_read_dir, +}; +