X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsmfs%2Fsmfs_cow.c;fp=lustre%2Fsmfs%2Fsmfs_cow.c;h=0000000000000000000000000000000000000000;hb=113303973ec9f8484eb2355a1a6ef3c4c7fd6a56;hp=3d36182140e1cbd445cba94b298c6af1f1e1f673;hpb=272294dfa235dac803ed2d2b2ee8e0bd402622bb;p=fs%2Flustre-release.git diff --git a/lustre/smfs/smfs_cow.c b/lustre/smfs/smfs_cow.c deleted file mode 100644 index 3d36182..0000000 --- a/lustre/smfs/smfs_cow.c +++ /dev/null @@ -1,1541 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * - * Copyright (C) 2004 Cluster File Systems, Inc. - * - * This file is part of Lustre, http://www.lustre.org. - * - * Lustre is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * Lustre is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Lustre; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#define DEBUG_SUBSYSTEM S_SM - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "smfs_internal.h" - -#define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + \ - size * sizeof(struct snap)) - -int smfs_cleanup_snap_info(struct snap_info *snap_info); - -static int smfs_init_snap_super_info(struct smfs_super_info *smfs_info) -{ - struct snap_super_info *snap_sinfo; - int rc = 0; - - ENTRY; - - OBD_ALLOC(smfs_info->smsi_snap_info, - sizeof(struct snap_super_info)); - - if (!smfs_info->smsi_snap_info) - GOTO(exit, rc = -ENOMEM); - - snap_sinfo = smfs_info->smsi_snap_info; - - /*init snap fsfilt operations*/ - if (!snap_sinfo->snap_cache_fsfilt) { - char *snap_cache_ftype = NULL; - int tmp = strlen(smfs_info->smsi_cache_ftype) + strlen("_snap"); - - OBD_ALLOC(snap_cache_ftype, tmp + 1); - if (!snap_cache_ftype) - GOTO(exit, rc = -ENOMEM); - - sprintf(snap_cache_ftype, "%s_snap", smfs_info->smsi_cache_ftype); - snap_sinfo->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype); - OBD_FREE(snap_cache_ftype, tmp + 1); - if (!snap_sinfo->snap_cache_fsfilt) { - CERROR("Can not get %s fsfilt ops needed by snap\n", - snap_cache_ftype); - GOTO(exit, rc = -EINVAL); - } - } - if (!snap_sinfo->snap_fsfilt) { - char *snap_ftype = NULL; - int tmp = strlen(smfs_info->smsi_ftype) + strlen("_snap"); - - OBD_ALLOC(snap_ftype, tmp + 1); - if (!snap_ftype) - GOTO(exit, rc = -ENOMEM); - - sprintf(snap_ftype, "%s_snap", smfs_info->smsi_ftype); - snap_sinfo->snap_fsfilt = fsfilt_get_ops(snap_ftype); - OBD_FREE(snap_ftype, tmp + 1); - if (!snap_sinfo->snap_fsfilt) { - CERROR("Can not get %s fsfilt ops needed by snap\n", - snap_ftype); - GOTO(exit, rc = -EINVAL); - } - } - INIT_LIST_HEAD(&snap_sinfo->snap_list); -exit: - if (rc && smfs_info->smsi_snap_info) - OBD_FREE(snap_sinfo, sizeof(struct snap_super_info)); - RETURN(rc); -} -/*FIXME-wangdi Should remove it when integrated it with lustre*/ -static struct dentry *smfs_simple_mkdir(struct dentry *dir, char *name, - int mode, int fix) -{ - struct dentry *dchild; - int err = 0; - - dchild = ll_lookup_one_len(name, dir, strlen(name)); - if (IS_ERR(dchild)) - GOTO(out_up, dchild); - - if (dchild->d_inode) { - int old_mode = dchild->d_inode->i_mode; - if (!S_ISDIR(old_mode)) - GOTO(out_err, err = -ENOTDIR); - - /* Fixup directory permissions if necessary */ - if (fix && (old_mode & S_IALLUGO) != (mode & S_IALLUGO)) { - CWARN("fixing permissions on %s from %o to %o\n", - name, old_mode, mode); - dchild->d_inode->i_mode = (mode & S_IALLUGO) | - (old_mode & ~S_IALLUGO); - mark_inode_dirty(dchild->d_inode); - } - GOTO(out_up, dchild); - } - err = vfs_mkdir(dir->d_inode, dchild, mode); - if (err) - GOTO(out_err, err); - RETURN(dchild); -out_err: - dput(dchild); - dchild = ERR_PTR(err); -out_up: - return dchild; - -} -static struct snap_info *smfs_find_snap_info(struct inode *inode) -{ - struct snap_inode_info *snap_iinfo = I2SNAPI(inode); - struct snap_super_info *snap_sinfo = S2SNAPI(inode->i_sb); - struct snap_info *snap_info = NULL, *tmp; - - ENTRY; - list_for_each_entry_safe(snap_info, tmp, &snap_sinfo->snap_list, - sni_list) { - if (snap_info->sni_root_ino == snap_iinfo->sn_root_ino) - RETURN(snap_info); - } - RETURN(NULL); -} - -#if 0 -static int smfs_dotsnap_dir_size(struct inode *inode) -{ - struct snap_super_info *snap_sinfo = S2SNAPI(inode->i_sb); - struct fsfilt_operations *snapops = snap_sinfo->snap_cache_fsfilt; - int size = 0, dir_size = 0, blocks, i = 0; - struct snap_table *snap_table = NULL; - struct snap_info *snap_info = NULL; - ENTRY; - - snap_info = smfs_find_snap_info(inode); - - if (!snap_info) { - CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode); - RETURN(0); - } - snap_table = snap_info->sni_table; - for (i = 0; i < snap_table->sntbl_count; i++) { - char *name = snap_table->sntbl_items[i].sn_name; - size += snapops->fs_dir_ent_size(name); - } - /*FIXME this is only for ext3 dir format, may need fix for other FS*/ - blocks = (size + inode->i_sb->s_blocksize - 1) >> - inode->i_sb->s_blocksize_bits; - - dir_size = blocks * inode->i_sb->s_blocksize; - RETURN(dir_size); - -} -#endif - -static int smfs_init_snap_inode_info(struct inode *inode, struct inode *dir, int index) -{ - int rc = 0; - ENTRY; - - if (!inode) - RETURN(0); - - if (dir) { - I2SNAPI(inode)->sn_flags = I2SNAPI(dir)->sn_flags; - I2SNAPI(inode)->sn_gen = I2SNAPI(dir)->sn_gen; - I2SNAPI(inode)->sn_root_ino = I2SNAPI(dir)->sn_root_ino; - I2SNAPI(inode)->sn_index = I2SNAPI(inode)->sn_index; - } else { - I2SNAPI(inode)->sn_flags = 0; - I2SNAPI(inode)->sn_gen = 0; - } - - I2SNAPI(inode)->sn_index = index; - - if (smfs_dotsnap_inode(inode)) { - struct snap_info *snap_info; - - snap_info = smfs_find_snap_info(inode); - if (!snap_info) { - RETURN(-EIO); - } - /*init dot_snap inode info*/ -// inode->i_size = (loff_t)smfs_dotsnap_dir_size(inode); - inode->i_size = snap_info->sni_table->sntbl_count; - inode->i_nlink = snap_info->sni_table->sntbl_count + 2; - inode->i_uid = 0; - inode->i_gid = 0; - } else if (SMFS_DO_COW(S2SMI(inode->i_sb)) && - (I2SMI(inode)->smi_flags & SM_DO_COW) && - smfs_primary_inode(inode)) { - struct snap_inode_info *sni_info = I2SNAPI(inode); - struct fsfilt_operations *sops = I2SNAPCOPS(inode); - int vallen = 0; - - vallen = sizeof(sni_info->sn_gen); - - rc = sops->fs_get_snap_info(I2CI(inode), SNAP_GENERATION, - strlen(SNAP_GENERATION), - &sni_info->sn_gen, &vallen); - } - RETURN(rc); -} - -#define COWED_NAME_LEN (7 + 8 + 1) -static int smfs_init_cowed_dir(struct snap_info *snap_info, struct inode* inode) -{ - struct dentry *dentry = NULL; - char name[COWED_NAME_LEN]; - int rc = 0; - ENTRY; - - sprintf(name, ".cowed_%08x", (__u32)inode->i_ino); - /*FIXME-WANGDI: will use simple_mkdir, when integrating snap to lustre*/ - dentry = smfs_simple_mkdir(inode->i_sb->s_root, name, 0777, 1); - if (IS_ERR(dentry)) { - rc = PTR_ERR(dentry); - CERROR("create cowed directory: rc = %d\n", rc); - RETURN(rc); - } - snap_info->sni_cowed_dentry = dentry; - /*cleanup cowed inode attr for cowed dir*/ - SMFS_CLEAN_INODE_COWED(dentry->d_inode); - RETURN(rc); -} - -static int smfs_init_dotinfo(struct snap_info *snap_info) -{ - struct snap_dot_info *dot_info = NULL; - int rc = 0; - ENTRY; - - if (snap_info->sni_dot_info) - RETURN(-EEXIST); - - OBD_ALLOC(snap_info->sni_dot_info, sizeof(struct snap_dot_info)); - - if (!snap_info->sni_dot_info) - RETURN(-ENOMEM); - - dot_info = snap_info->sni_dot_info; - - OBD_ALLOC(dot_info->dot_name, strlen(DOT_SNAP_NAME) + 1); - - if (!dot_info->dot_name) { - OBD_FREE(snap_info->sni_dot_info, sizeof(struct snap_dot_info)); - RETURN(-ENOMEM); - } - memcpy(dot_info->dot_name, DOT_SNAP_NAME, strlen(DOT_SNAP_NAME)); - - dot_info->dot_name_len = strlen(DOT_SNAP_NAME); - dot_info->dot_snap_enable = 1; - - RETURN(rc); -} - -static int smfs_init_snap_info(struct smfs_super_info *smb, - struct snap_info *snap_info, struct inode *inode) -{ - struct snap_table *snap_table = NULL; - struct fsfilt_operations *snapcops; - int rc = 0, size, table_size, vallen, i; - - ENTRY; - - snapcops = smb->smsi_snap_info->snap_cache_fsfilt; - /*Initialized table */ - /*get the maxsize of snaptable*/ - vallen = sizeof(int); - rc = snapcops->fs_get_snap_info(I2CI(inode), MAX_SNAPTABLE_COUNT, - strlen(MAX_SNAPTABLE_COUNT), &size, - &vallen); - if (size == 0) { - CERROR("the Max snaptable count should not be zero\n"); - GOTO(exit, rc); - } - table_size = SNAPTABLE_SIZE(size); - - OBD_ALLOC(snap_info->sni_table, table_size); - - if (!snap_info->sni_table) { - CERROR("No MEM\n"); - RETURN(-ENOMEM); - } - snap_table = snap_info->sni_table; - - snap_table->sntbl_magic = cpu_to_le32((__u32)SNAPTABLE_MAGIC); - snap_table->sntbl_max_count = size; - /*init sn_index to -1*/ - for (i = 0; i < snap_table->sntbl_max_count; i++) - snap_table->sntbl_items[i].sn_index = -1; - /*get snaptable info*/ - rc = snapcops->fs_get_snap_info(I2CI(inode), SNAPTABLE_INFO, - strlen(SNAPTABLE_INFO), - snap_table, &table_size); - if (rc < 0) { - if (rc == -ENODATA) { - snap_table->sntbl_count = 0; - rc = 0; - } else { - CERROR("Can not retrive the snaptable from this filesystem\n"); - GOTO(exit, rc); - } - } else { - if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) { - CERROR("On disk snaptable is not right \n"); - GOTO(exit, rc = -EIO); - } - } - init_MUTEX(&snap_info->sni_sema); - snap_info->sni_root_ino = inode->i_ino; - rc = smfs_init_cowed_dir(snap_info, inode); - if (rc) { - CERROR("Init cowed dir error rc=%d\n", rc); - GOTO(exit, rc); - } - rc = smfs_init_dotinfo(snap_info); -exit: - if (rc && snap_table) - OBD_FREE(snap_table, table_size); - RETURN(rc); -} - -static struct snap_info *smfs_create_snap_info(struct smfs_super_info *sinfo, - struct inode *inode) -{ - struct snap_info *snap_info = NULL; - int rc = 0; - ENTRY; - - OBD_ALLOC(snap_info, sizeof(struct snap_info)); - if (!snap_info) - RETURN(ERR_PTR(-ENOMEM)); - rc = smfs_init_snap_info(sinfo, snap_info, inode); - if (rc) - GOTO(exit, rc); - - /*set cow flags for the snap root inode*/ - I2SMI(inode)->smi_flags |= SM_DO_COW; - I2SNAPI(inode)->sn_root_ino = inode->i_ino; -exit: - if (rc) { - OBD_FREE(snap_info, sizeof(struct snap_info)); - snap_info = ERR_PTR(rc); - } - RETURN(snap_info); -} - -static int smfs_cow_pre(struct inode *dir, void *dentry, void *new_dir, - void *new_dentry, int op); - -static int smfs_cow_post(struct inode *dir, void *dentry, void *new_dir, - void *new_dentry, int op); -#define COW_HOOK "cow_hook" -static int smfs_cow_pre_hook(struct inode *inode, void *dentry, void *data1, - void *data2, int op, void *handle) -{ - int rc = 0; - ENTRY; - - if (smfs_do_cow(inode)) { - /*FIXME:WANGDI, get index from the dentry*/ - #if 0 - int index = 0; - smfs_get_dentry_name_index(dentry, &name, index); - smfs_free_dentry_name(&name); - #endif - rc = smfs_cow_pre(inode, dentry, data1, data2, op); - } - RETURN(rc); -} -static int smfs_cow_post_hook(struct inode *inode, void *dentry, void *data1, - void *data2, int op, void *handle) -{ - int rc = 0; - ENTRY; - - if (smfs_do_cow(inode)) { - rc = smfs_cow_post(inode, dentry, data1, data2, op); - } - RETURN(rc); -} - -int smfs_cow_cleanup(struct smfs_super_info *smb) -{ - struct snap_super_info *snap_sinfo = smb->smsi_snap_info; - struct list_head *snap_list = &snap_sinfo->snap_list; - struct smfs_hook_ops *cow_hops; - int rc = 0; - ENTRY; - - while (!list_empty(snap_list)) { - struct snap_info *snap_info; - - snap_info = list_entry(snap_list->next, struct snap_info, - sni_list); - rc = smfs_cleanup_snap_info(snap_info); - if (rc) - CERROR("cleanup snap_info error rc=%d\n", rc); - list_del(&snap_info->sni_list); - OBD_FREE(snap_info, sizeof(struct snap_info)); - } - - if (snap_sinfo->snap_fsfilt) - fsfilt_put_ops(snap_sinfo->snap_fsfilt); - if (snap_sinfo->snap_cache_fsfilt) - fsfilt_put_ops(snap_sinfo->snap_cache_fsfilt); - - cow_hops = smfs_unregister_hook_ops(smb, COW_HOOK); - smfs_free_hook_ops(cow_hops); - - SMFS_CLEAN_COW(smb); - if (snap_sinfo) - OBD_FREE(snap_sinfo, sizeof(struct snap_super_info)); - RETURN(rc); -} - -int smfs_cow_init(struct super_block *sb) -{ - struct smfs_super_info *smfs_info = S2SMI(sb); - struct smfs_hook_ops *cow_hops = NULL; - struct fsfilt_operations *sops; - struct inode *root_inode = smfs_info->smsi_sb->s_root->d_inode; - int snap_count = 0, rc = 0, vallen; - - ENTRY; - - SMFS_SET_COW(smfs_info); - - cow_hops = smfs_alloc_hook_ops(COW_HOOK, smfs_cow_pre_hook, - smfs_cow_post_hook); - if (!cow_hops) { - RETURN(-ENOMEM); - } - - rc = smfs_register_hook_ops(smfs_info, cow_hops); - if (rc) { - smfs_free_hook_ops(cow_hops); - RETURN(rc); - } - - rc = smfs_init_snap_super_info(smfs_info); - if (rc && cow_hops) { - smfs_unregister_hook_ops(smfs_info, cow_hops->smh_name); - smfs_free_hook_ops(cow_hops); - RETURN(rc); - } - sops = smfs_info->smsi_snap_info->snap_cache_fsfilt; - - vallen = sizeof(int); - rc = sops->fs_get_snap_info(root_inode, SNAP_COUNT, strlen(SNAP_COUNT), - &snap_count, &vallen); - if (rc < 0) - GOTO(exit, rc); - - if (snap_count > 0) { - int snap_root_size = snap_count * sizeof(ino_t); - ino_t *snap_root; - int i; - - OBD_ALLOC(snap_root, snap_root_size); - - if (!snap_root) - GOTO(exit, rc = -ENOMEM); - - rc = sops->fs_get_snap_info(root_inode, SNAP_ROOT_INO, - strlen(SNAP_ROOT_INO), snap_root, - &snap_root_size); - if (rc < 0) { - OBD_FREE(snap_root, sizeof(int) * snap_count); - GOTO(exit, rc); - } - for (i = 0; i < snap_count; i++) { - ino_t root_ino = le32_to_cpu(snap_root[i]); - struct snap_info *snap_info; - - root_inode = smfs_get_inode(sb, root_ino, NULL, 0); - smfs_init_snap_inode_info(root_inode, NULL, 0); - snap_info = smfs_create_snap_info(S2SMI(sb), root_inode); - iput(root_inode); - if (IS_ERR(snap_info)) { - OBD_FREE(snap_root, sizeof(int) * snap_count); - GOTO(exit, rc = PTR_ERR(snap_info)); - } - list_add(&snap_info->sni_list, - &(S2SNAPI(sb)->snap_list)); - } - } - smfs_info->smsi_snap_info->snap_count = snap_count; -exit: - if (rc) - smfs_cow_cleanup(smfs_info); - RETURN(rc); -} - -static int smfs_cleanup_dotinfo(struct snap_info *snap_info) -{ - struct snap_dot_info *dot_info = NULL; - int rc = 0; - ENTRY; - - if (!snap_info->sni_dot_info) - RETURN(rc); - - dot_info = snap_info->sni_dot_info; - - if (dot_info->dot_name) { - OBD_FREE(dot_info->dot_name, dot_info->dot_name_len + 1); - } - - OBD_FREE(dot_info, sizeof(struct snap_dot_info)); - - RETURN(rc); -} - -int smfs_cleanup_snap_info(struct snap_info *snap_info) -{ - struct snap_table *snap_table = snap_info->sni_table; - int rc = 0, table_size; - ENTRY; - - l_dput(snap_info->sni_cowed_dentry); - //d_unalloc(snap_info->sni_cowed_dentry); - if (snap_table) { - table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); - OBD_FREE(snap_info->sni_table, table_size); - } - smfs_cleanup_dotinfo(snap_info); - RETURN(rc); -} - -int smfs_snap_test_inode(struct inode *inode, void *args) -{ - struct smfs_iget_args *sargs = (struct smfs_iget_args*)args; - struct inode *dir; - - LASSERT(sargs); - - dir = sargs->s_inode; - - if (sargs->s_index > 0) { - if (I2SNAPI(inode)->sn_index != sargs->s_index) - return 0; - }else { - if (dir && I2SNAPI(inode)->sn_index != I2SNAPI(dir)->sn_index) - return 0; - } - return 1; -} -/* latest snap: returns - - the index of the latest snapshot before NOW - - hence it returns 0 in case all the volume snapshots lie in the future - - this is the index where a COW will land (will be created) -*/ -void snap_last(struct inode *inode, struct snap *snap) -{ - time_t now = LTIME_S(CURRENT_TIME); - struct snap_table *snap_table; - struct snap_info *snap_info; - int i ; - - ENTRY; - - snap_info = smfs_find_snap_info(inode); - if (!snap_info) { - CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode); - EXIT; - return; - } - snap_table = snap_info->sni_table; - /* start at the highest index in the superblock snaptime array */ - if (snap_table->sntbl_count == 0) { - memset(snap, 0, sizeof(struct snap)); - } else { - i = snap_table->sntbl_count - 1; - snap->sn_index = snap_table->sntbl_items[i].sn_index; - snap->sn_time = snap_table->sntbl_items[i].sn_time; - snap->sn_gen = snap_table->sntbl_items[i].sn_gen; - } - CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n", - snap->sn_index, snap->sn_time, now); - EXIT; - return; -} - -static inline int get_index_of_item(struct snap_table *table, char *name) -{ - int count = table->sntbl_count; - int i, j; - ENTRY; - - for (i = 0; i < table->sntbl_max_count; i++) { - if (!strcmp(name, table->sntbl_items[i].sn_name)) { - CERROR("Duplicate name %s in snaptable\n", name); - RETURN(-EINVAL); - } - } - - for (i = 1; i <= table->sntbl_max_count; i++) { - int found = 0; - for (j = 0; j < (count + 1); j++) { - if (table->sntbl_items[j].sn_index == i) { - found = 1; - break; - } - } - if (!found) - RETURN(i); - } - CERROR("snaptable Full\n"); - RETURN(-ENOSPC); -} - -static struct dentry *smfs_find_snap_root(struct super_block *sb, - char *path_name) -{ - struct dentry *dentry = NULL; - struct nameidata nd; - ENTRY; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) - if (path_init(path_name, LOOKUP_FOLLOW, &nd)) { - int error = path_walk(path_name, &nd); - if (error) { - path_release(&nd); - RETURN(NULL); - } - } else { - RETURN(NULL); - } -#else - if (path_lookup(path_name, LOOKUP_FOLLOW, &nd)) - RETURN(NULL); -#endif - dentry = dget(nd.dentry); - path_release(&nd); - RETURN(dentry); -} - -static int snap_add_item(struct smfs_super_info *smb, - struct snap_info *snap_info, - char *name) -{ - struct fsfilt_operations *snapops; - struct snap_table *snap_table = snap_info->sni_table; - struct inode *root_inode = NULL; - int table_size, count = 0, index = 0, rc = 0; - struct snap *snap_item; - ENTRY; - - count = snap_table->sntbl_count; - root_inode = iget(smb->smsi_sb, snap_info->sni_root_ino); - if (!root_inode || is_bad_inode(root_inode)) - RETURN(-EIO); - /* XXX Is down this sema necessary*/ - down_interruptible(&snap_info->sni_sema); - snap_item = &snap_table->sntbl_items[count]; - snapops = smb->smsi_snap_info->snap_cache_fsfilt; - /*add item in snap_table set generation*/ - snap_item->sn_time = LTIME_S(CURRENT_TIME); - /* find table index */ - index = get_index_of_item(snap_table, name); - if (index < 0) - GOTO(exit, rc = index); - - snap_item->sn_index = index; - snap_item->sn_flags = 0; - snap_item->sn_gen = snap_table->sntbl_generation + 1; - memcpy(snap_item->sn_name, name, SNAP_MAX_NAMELEN); - /* Wrote the whole snap_table to disk */ - table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); - - snap_table->sntbl_count++; - snap_table->sntbl_generation++; - rc = snapops->fs_set_snap_info(root_inode, SNAPTABLE_INFO, - strlen(SNAPTABLE_INFO), - snap_table, &table_size); - if (rc) { - snap_table->sntbl_count--; - snap_table->sntbl_generation--; - CERROR("Set snaptable error rc=%d\n", rc); - GOTO(exit, rc); - } -exit: - up(&snap_info->sni_sema); - if (root_inode) - iput(root_inode); - RETURN(rc); -} - -static struct snap_info * smfs_find_create_snap_info(struct super_block *sb, - struct inode *inode) -{ - struct snap_super_info *snap_sinfo = S2SNAPI(sb); - struct fsfilt_operations *sops = snap_sinfo->snap_cache_fsfilt; - struct snap_info *snap_info, *tmp; - ino_t *snap_root = NULL; - int rino_size, snap_count_size, rc = 0; - ENTRY; - - list_for_each_entry_safe(snap_info, tmp, &snap_sinfo->snap_list, - sni_list) { - if (snap_info->sni_root_ino == inode->i_ino) { - RETURN(snap_info); - } - } - - CDEBUG(D_INFO, "create a new snap info root ino %lu\n", inode->i_ino); - - snap_info = smfs_create_snap_info(S2SMI(sb), inode); - - if (IS_ERR(snap_info)) - RETURN(snap_info); - - snap_sinfo->snap_count++; - - rino_size = snap_sinfo->snap_count * sizeof(ino_t); - - OBD_ALLOC(snap_root, rino_size); - - if (!snap_root) - GOTO(exit, rc = -ENOMEM); - - rc = sops->fs_get_snap_info(I2CI(inode), SNAP_ROOT_INO, - strlen(SNAP_ROOT_INO), snap_root, - &rino_size); - if (rc < 0) { - if (rc == -ENODATA) { - rc = 0; - } else { - GOTO(exit, rc); - } - } - snap_root[snap_sinfo->snap_count - 1] = inode->i_ino; - - snap_count_size = sizeof(int); - rc = sops->fs_set_snap_info(I2CI(inode), SNAP_COUNT, strlen(SNAP_COUNT), - &snap_sinfo->snap_count, &snap_count_size); - if (rc) - GOTO(exit, rc); - - rc = sops->fs_set_snap_info(I2CI(inode), SNAP_ROOT_INO, - strlen(SNAP_ROOT_INO), snap_root, - &rino_size); - - if (rc) - GOTO(exit, rc); - - list_add(&snap_info->sni_list, &snap_sinfo->snap_list); -exit: - if (rc) { - smfs_cleanup_snap_info(snap_info); - OBD_FREE(snap_info, sizeof(struct snap_info)); - } - if (snap_root) - OBD_FREE(snap_root, rino_size); - RETURN(snap_info); -} - -int smfs_add_snap_item(struct super_block *sb, char *path_name, char *name) -{ - struct dentry *dentry = NULL; - struct snap_info *snap_info; - int rc = 0; - ENTRY; - - if (!SMFS_DO_COW(S2SMI(sb))) { - RETURN(0); - } - - if (!path_name || !name) { - CERROR("patch_name and snapshot_name is NULL"); - RETURN(-EINVAL); - } - dentry = smfs_find_snap_root(sb, path_name); - if (IS_ERR(dentry)) { - CERROR("can not find snap_shot root by %s\n", path_name); - RETURN(PTR_ERR(dentry)); - } - snap_info = smfs_find_create_snap_info(sb, dentry->d_inode); - if (IS_ERR(snap_info)) { - CERROR("can not find snap_info by %s rc=%lu\n", path_name, - PTR_ERR(snap_info)); - GOTO(exit, rc = PTR_ERR(snap_info)); - } - - rc = snap_add_item(S2SMI(sb), snap_info, name); -exit: - dput(dentry); - RETURN(rc); -} -//EXPORT_SYMBOL(smfs_add_snap_item); -/* - * Note: this function should be differnet with snap_do_cow. - * In smfs_do_cow, we check the EA for whether do cow for that inode. - * In smfs_needs_cow, we check whether we do need to do cow. - */ -int smfs_needs_cow(struct inode *inode) -{ - struct smfs_inode_info *smi_info = I2SMI(inode); - struct snap_inode_info *snap_info = NULL; - struct snap snap; - int index = -1; - ENTRY; - - snap_info = &(smi_info->sm_sninfo); - - snap_last(inode, &snap); - /* decision .... if the snapshot is more recent than the object, - * then any change to the object should cause a COW. - */ - if (snap_info->sn_gen < snap.sn_gen ) - index = snap.sn_index; - - CDEBUG(D_INFO, "snap_needs_cow, ino %lu , get index %d\n", - inode->i_ino, index); - - RETURN(index); -} /* snap_needs_cow */ - -static int link_cowed_inode(struct inode *inode) -{ - struct dentry *cowed_dir = NULL; - char idname[LL_ID_NAMELEN]; - struct snap_info *snap_info; - int idlen = 0, rc = 0; - struct dentry *dchild = NULL; - struct dentry *tmp = NULL; - unsigned mode; - - snap_info = smfs_find_snap_info(inode); - if (!snap_info) { - CERROR("can not find snap info for inode %p\n", inode); - RETURN(-EINVAL); - } - - cowed_dir = snap_info->sni_cowed_dentry; - - down(&cowed_dir->d_inode->i_sem); - - idlen = ll_id2str(idname, inode->i_ino, inode->i_generation); - dchild = lookup_one_len(idname, cowed_dir, idlen); - if (IS_ERR(dchild)) { - rc = PTR_ERR(dchild); - if (rc != -EPERM && rc != -EACCES) - CERROR("child lookup error %d\n", rc); - GOTO(out_lock, rc); - } - if (dchild->d_inode != NULL) { - CERROR("re-cowed file %s?\n", dchild->d_name.name); - LASSERT(dchild->d_inode == inode); - GOTO(out_dput, rc = 0); - } - tmp = pre_smfs_dentry(NULL, inode, cowed_dir); - /* link() is semanticaly-wrong for S_IFDIR, so we set S_IFREG - * for linking and return real mode back then -bzzz */ - mode = inode->i_mode; - inode->i_mode = S_IFREG; - - rc = cowed_dir->d_inode->i_op->link(tmp, cowed_dir->d_inode, dchild); - - post_smfs_dentry(tmp); - if (rc) { - CERROR("error linking cowed inode %s to COWED: rc = %d\n", - idname, rc); - } - inode->i_mode = mode; - if ((mode & S_IFMT) == S_IFDIR) { - dchild->d_inode->i_nlink++; - cowed_dir->d_inode->i_nlink++; - mark_inode_dirty(cowed_dir->d_inode); - mark_inode_dirty(dchild->d_inode); - } -out_dput: - up(&cowed_dir->d_inode->i_sem); - dput(dchild); -out_lock: - RETURN(rc); -} -/* - * Make a copy of the data and plug a redirector in between if there - * is no redirector yet. - */ -int snap_do_cow(struct inode *inode, struct dentry *dparent, int del) -{ - struct fsfilt_operations *snapops = I2SNAPCOPS(inode); - struct snap snap; - struct inode *cache_ind = NULL; - ENTRY; - - if (!snapops || !snapops->fs_create_indirect) - RETURN(-EINVAL); - - snap_last(inode, &snap); - cache_ind = snapops->fs_create_indirect(I2CI(inode), snap.sn_index, - snap.sn_gen, I2CI(dparent->d_inode), - del); - if(cache_ind && IS_ERR(cache_ind)) { - CERROR("Create ind inode %lu index %d gen %d del %d rc%lu\n", - inode->i_ino, snap.sn_index, snap.sn_gen, del, - PTR_ERR(cache_ind)); - RETURN(PTR_ERR(cache_ind)); - } - if (cache_ind) { - iput(cache_ind); - if (!SMFS_DO_INODE_COWED(inode)) { - /*insert the inode to cowed inode*/ - SMFS_SET_INODE_COWED(inode); - link_cowed_inode(inode); - } - } - RETURN(0); -} -/*Dir inode will do cow*/ -int smfs_cow_create_pre(struct inode *dir, void *de, void *data1, void *data2) -{ - struct dentry *dparent; - struct dentry *dentry = (struct dentry *)de; - int rc = 0; - ENTRY; - - if (smfs_needs_cow(dir) != -1) { - CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); - LASSERT(dentry->d_parent && dentry->d_parent->d_parent); - dparent = dentry->d_parent->d_parent; - if ((rc = snap_do_cow(dir, dparent, 0))) { - CERROR("Do cow error %d\n", rc); - RETURN(-EINVAL); - } - } - RETURN(rc); -} - -int smfs_cow_setattr_pre(struct inode *dir, void *de, void *data1, void *data2) -{ - struct dentry *dentry = (struct dentry *)de; - int rc = 0; - ENTRY; - if (smfs_needs_cow(dir) != -1) { - CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); - if ((snap_do_cow(dir, dentry->d_parent, 0))) { - CERROR("Do cow error\n"); - RETURN(-EINVAL); - } - } - RETURN(rc); -} - -int smfs_cow_link_pre(struct inode *dir, void *de, void *data1, void *data2) -{ - struct dentry *dparent; - struct dentry *dentry = (struct dentry *)de; - int rc = 0; - ENTRY; - - if (smfs_needs_cow(dir) != -1) { - CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); - LASSERT(dentry->d_parent && dentry->d_parent->d_parent); - dparent = dentry->d_parent->d_parent; - if ((snap_do_cow(dir, dparent, 0))) { - CERROR("Do cow error\n"); - RETURN(-EINVAL); - } - if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 0))) { - CERROR("Do cow error\n"); - RETURN(-EINVAL); - } - } - RETURN(rc); -} - -int smfs_cow_unlink_pre(struct inode *dir, void *de, void *data1, void *data2) -{ - struct dentry *dentry = (struct dentry *)de; - struct dentry *dparent; - int rc = 0; - ENTRY; - - if (smfs_needs_cow(dir) != -1) { - CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); - LASSERT(dentry->d_parent && dentry->d_parent->d_parent); - dparent = dentry->d_parent->d_parent; - if ((snap_do_cow(dir, dparent, 0))) { - CERROR("Do cow error\n"); - RETURN(-EINVAL); - } - if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 1))) { - CERROR("Do cow error\n"); - RETURN(-EINVAL); - } - - } - RETURN(rc); -} - -int smfs_cow_rename_pre(struct inode *dir, void *de, void *data1, void *data2) -{ - struct dentry *dentry = (struct dentry*)de; - struct inode *new_dir = (struct inode *)data1; - struct dentry *new_dentry = (struct dentry *)data2; - struct dentry *dparent; - int rc = 0; - ENTRY; - - LASSERT(new_dir); - LASSERT(new_dentry); - if (smfs_needs_cow(dir) != -1) { - CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n", dir->i_ino); - LASSERT(dentry->d_parent && dentry->d_parent->d_parent); - dparent = dentry->d_parent->d_parent; - if ((snap_do_cow(dir, dparent, 0))) { - CERROR("Do cow error\n"); - RETURN(-EINVAL); - } - if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 0))) { - CERROR("Do cow error\n"); - RETURN(-EINVAL); - } - } - if (smfs_needs_cow(new_dir) != -1) { - CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n", new_dir->i_ino); - LASSERT(new_dentry->d_parent && new_dentry->d_parent->d_parent); - dparent = new_dentry->d_parent->d_parent; - if ((new_dir != dir) && (snap_do_cow(new_dir, dparent, 0))){ - CERROR("Do cow error\n"); - RETURN(-EINVAL); - } - if (new_dentry->d_inode && new_dentry->d_inode->i_nlink == 1) { - if ((snap_do_cow(new_dentry->d_inode, - new_dentry->d_parent, 0))) { - CERROR("Do cow error\n"); - RETURN(-EINVAL); - } - } - } - RETURN(rc); -} - -int smfs_cow_write_pre(struct inode *inode, void *de, void *data1, void *data2) -{ - struct dentry *dentry = (struct dentry*)de; - struct snap_info *snap_info = NULL; - struct snap_table *table; - long blocks[2]={-1,-1}; - int index = 0, i, rc = 0; - size_t count; - loff_t pos; - - ENTRY; - - snap_info = smfs_find_snap_info(inode); - if (!snap_info) { - CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode); - RETURN(0); - } - table = snap_info->sni_table; - - LASSERT(data1); - LASSERT(data2); - - count = *(size_t *)data1; - pos = *(loff_t*)data2; - - down(&inode->i_sem); - - if (smfs_needs_cow(inode) != -1 ) { - CDEBUG(D_INFO, "snap_needs_cow for ino %lu \n",inode->i_ino); - snap_do_cow(inode, dentry->d_parent, 0); - } - - CDEBUG(D_INFO, "write offset %lld count %u \n", pos, count); - - if(pos & (PAGE_CACHE_SIZE - 1)){ - blocks[0] = pos >> inode->i_sb->s_blocksize_bits; - } - pos += count - 1; - if((pos + 1) & (PAGE_CACHE_SIZE - 1)){ - blocks[1] = pos >> inode->i_sb->s_blocksize_bits; - } - - if (blocks[0] == blocks[1]) - blocks[1] = -1; - - for (i = 0; i < 2; i++) { - int slot = 0; - if (blocks[i] == -1) - continue; - /*Find the nearest page in snaptable and copy back it*/ - for (slot = table->sntbl_count - 1; slot >= 0; slot--) { - struct fsfilt_operations *sops = I2SNAPCOPS(inode); - struct inode *cind = NULL; - int result = 0; - - index = table->sntbl_items[slot].sn_index; - cind = sops->fs_get_indirect(I2CI(inode), NULL, index); - if (!cind) continue; - - CDEBUG(D_INFO, "find cache_ino %lu\n", cind->i_ino); - - result = sops->fs_copy_block(I2CI(inode), cind, - blocks[i]); - if (result == 1) { - iput(cind); - result = 0; - break; - } - if (result < 0) { - iput(cind); - up(&inode->i_sem); - GOTO(exit, rc = result); - } - iput(cind); - } - } -exit: - up(&inode->i_sem); - RETURN(rc); -} -EXPORT_SYMBOL(smfs_cow_write_pre); -/*lookup inode in dotsnap inode */ -static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry, - struct snap_info *snap_info) -{ - if (dentry->d_name.len == 1 && - !strcmp(dentry->d_name.name, ".")) { - d_add(dentry, iget(dir->i_sb, dir->i_ino)); - } else if (dentry->d_name.len == 2 && - !strcmp(dentry->d_name.name, "..")) { - struct inode *inode; - struct dentry *dparent = dentry->d_parent; - if (dparent->d_inode) { - inode = iget(dir->i_sb, dparent->d_inode->i_ino); - if (inode) { - if (!is_bad_inode(inode)) - d_add(dentry, inode); - else - iput(inode); - } - } - } else { - /*find the name from the snaptable*/ - struct fsfilt_operations *sops = I2SNAPCOPS(dir); - struct snap_table *table; - struct inode *inode; - ino_t cino; - int i = 0, index = -1; - - table = snap_info->sni_table; - - for (i = 0; i < table->sntbl_count; i++) { - char *name = table->sntbl_items[i].sn_name; - if ((dentry->d_name.len == strlen(name)) && - (memcmp(dentry->d_name.name, name, - dentry->d_name.len) == 0)) { - index = table->sntbl_items[i].sn_index; - break; - } - } - if (index == -1) { - CERROR("No such %s in this .snap dir \n", - dentry->d_name.name); - RETURN(-ENOENT); - } - cino = sops->fs_get_indirect_ino(S2CSB(dir->i_sb), dir->i_ino, - index); - if (cino == 0) - cino = dir->i_ino; - inode = smfs_get_inode(dir->i_sb, cino, dir, index); - if (!inode || is_bad_inode(inode)) { - CERROR("Can not find cino %lu inode\n", cino); - RETURN(-ENOENT); - } - smfs_init_snap_inode_info(inode, dir, index); - d_add(dentry, inode); - } - RETURN(0); -} -int smfs_cow_lookup_pre(struct inode *inode, void *de, void *data1, - void *data2) -{ - struct dentry *dentry = (struct dentry*)de; - struct snap_info *snap_info; - struct snap_dot_info *dot_info; - int rc = 0; - ENTRY; - - snap_info = smfs_find_snap_info(inode); - if (!snap_info) { - CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode); - RETURN(0); - } - - dot_info = snap_info->sni_dot_info; - - if (smfs_primary_inode(inode) && - dentry->d_name.len == dot_info->dot_name_len && - memcmp(dentry->d_name.name, dot_info->dot_name, - strlen(dot_info->dot_name)) == 0) { - struct inode *dot_inode = NULL; - - dot_inode = smfs_get_inode(inode->i_sb, inode->i_ino, inode, - DOT_SNAP_INDEX); - smfs_init_snap_inode_info(dot_inode, inode, DOT_SNAP_INDEX); - d_add(dentry, dot_inode); - rc = 1; - RETURN(rc); - } else if (smfs_dotsnap_inode(inode)) { - rc = smfs_dotsnap_lookup(inode, dentry, snap_info); - if (rc == 0) - rc = 1; - RETURN(rc); - } else { - /*HERE: will replace ino in dentry->d_name according to index, - *For iopen, will fix it in integrating snapfs to Lustre*/ -#if 0 - struct fsfilt_operations *snapops = I2SNAPOPS(inode); - char *name = (char *)dentry->d_name.name; - unsigned long ino, hash, ind_ino; - int len = sizeof(ind_ino); - - ino = simple_strtoul(name, 0, 0); - - ind_ino = snapops->fs_get_indirect_ino(inode->i_sb, ino, index); - - snprintf(name, strlen(name), "0x%lx", ind_ino); - - hash = init_name_hash(); - while (len--) { - unsigned char c; - c = *(const unsigned char *)name++; - if (c == '\0') break; - hash = partial_name_hash(c, hash); - } - dentry->d_name.hash = end_name_hash(hash); -#endif - } - RETURN(rc); -} - -struct inode *smfs_cow_get_ind(struct inode *inode, int index) -{ - long block=(index << PAGE_CACHE_SHIFT) >> inode->i_sb->s_blocksize_bits; - struct fsfilt_operations *sops = I2SNAPCOPS(inode); - struct snap_info *snap_info = NULL; - struct snap_table *table = NULL; - int slot; - - ENTRY; - - snap_info = smfs_find_snap_info(inode); - if (!snap_info) { - CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode); - RETURN(NULL); - } - - table = snap_info->sni_table; - - for (slot = table->sntbl_count - 1; slot >= 0; slot--) { - struct address_space_operations *aops = inode->i_mapping->a_ops; - struct inode *cache_inode = NULL; - int index = 0; - - index = table->sntbl_items[slot].sn_index; - cache_inode = sops->fs_get_indirect(I2CI(inode), NULL, index); - - if (!cache_inode ) continue; - - if (aops->bmap(cache_inode->i_mapping, block)) - RETURN(cache_inode); - iput(cache_inode); - } - - RETURN(NULL); -} -EXPORT_SYMBOL(smfs_cow_get_ind); - -static int smfs_cow_readdir_pre(struct inode *dir, void *de, void *data1, - void *data2) -{ - struct file *filp = (struct file*)de; - void *dirent = data1; - filldir_t filldir = (filldir_t)data2; - struct snap_info *snap_info = NULL; - - if (smfs_under_dotsnap_inode(dir)) - RETURN(0); - - snap_info = smfs_find_snap_info(dir); - - if (!snap_info) { - CDEBUG(D_INFO, "can not find snap info for ino %lu\n", - dir->i_ino); - RETURN(-EINVAL); - } - - if (smfs_primary_inode(dir)) { - if (filp->f_pos == 0) { - struct snap_dot_info *dot = snap_info->sni_dot_info; - if (filldir(dirent, dot->dot_name, dot->dot_name_len, - filp->f_pos, -1, 0)) { - CERROR("fill .snap error \n"); - RETURN(-EINVAL); - } - } else { - filp->f_pos -= 1; - } - } else if (smfs_dotsnap_inode(dir)) { - struct snap_table *table = snap_info->sni_table; - int i = 0; - - if (filp->f_pos < 0) - RETURN(-EINVAL); - - if ((filp->f_pos == 0) && filldir(dirent, ".", 1, - filp->f_pos++, - dir->i_ino, 0) < 0) - RETURN(-EIO); - if ((filp->f_pos == 1) && filldir(dirent, "..", 2, - filp->f_pos++, - dir->i_ino, 0) < 0) - RETURN(-EIO); - - for (i = filp->f_pos - 2; i < table->sntbl_count; i++, - filp->f_pos++) { - int slot = table->sntbl_count - i - 1; - - if (filldir(dirent, table->sntbl_items[slot].sn_name, - strlen(table->sntbl_items[slot].sn_name), - filp->f_pos, dir->i_ino, 0)) - break; - - } - RETURN(1); - } - - RETURN(0); -} - - -typedef int (*cow_funcs)(struct inode *dir, void *dentry, void *new_dir, - void *new_dentry); - -static cow_funcs smfs_cow_pre_funcs[HOOK_MAX + 1] = { - [HOOK_CREATE] smfs_cow_create_pre, - [HOOK_LOOKUP] smfs_cow_lookup_pre, - [HOOK_LINK] smfs_cow_link_pre, - [HOOK_UNLINK] smfs_cow_unlink_pre, - [HOOK_SYMLINK] smfs_cow_create_pre, - [HOOK_MKDIR] smfs_cow_create_pre, - [HOOK_RMDIR] smfs_cow_unlink_pre, - [HOOK_MKNOD] smfs_cow_create_pre, - [HOOK_RENAME] smfs_cow_rename_pre, - [HOOK_SETATTR] smfs_cow_setattr_pre, - [HOOK_WRITE] smfs_cow_write_pre, - [HOOK_READDIR] smfs_cow_readdir_pre, -}; - -static int smfs_revalidate_dotsnap_dentry(struct dentry *dentry, - struct inode *dir, int index) -{ - struct inode *inode = dentry->d_inode; - ENTRY; - - if (!inode) - RETURN(0); - - if (index > 0 && index != DOT_SNAP_INDEX) { - struct fsfilt_operations *sops = I2SNAPCOPS(inode); - struct inode *cache_ind = NULL; - - cache_ind = sops->fs_get_indirect(I2CI(inode), NULL, index); - - if (cache_ind) { - struct inode *ind_inode = NULL; - - LASSERT(cache_ind->i_ino != I2CI(inode)->i_ino); - - ind_inode = smfs_get_inode(inode->i_sb, cache_ind->i_ino, - dir, index); - list_del_init(&dentry->d_alias); - iput(inode); - d_instantiate(dentry, ind_inode); - iput(cache_ind); - } - } - RETURN(0); -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -static int -smfs_revalidate_nd(struct dentry *de, struct nameidata *nd) -{ - struct inode *inode = de->d_inode; - ENTRY; - - if (!inode) - RETURN(0); - - if (smfs_under_dotsnap_inode(inode)) { - struct inode *dir = de->d_parent->d_inode; - int index = I2SNAPI(inode)->sn_index; - - smfs_revalidate_dotsnap_dentry(de, dir, index); - smfs_init_snap_inode_info(de->d_inode, dir, index); - } - - RETURN(0); -} -#else -static int -smfs_revalidate_it(struct dentry *de, int flags, - struct nameidata *nd, - struct lookup_intent *it) -{ - struct inode *inode = de->d_inode; - ENTRY; - - if (!inode) - RETURN(0); - - if (smfs_under_dotsnap_inode(inode)) { - struct inode *dir = de->d_parent->d_inode; - int index = I2SNAPI(inode)->sn_index; - - smfs_revalidate_dotsnap_dentry(de, dir, index); - smfs_init_snap_inode_info(de->d_inode, dir, index); - } - - RETURN(0); -} -#endif - -static int smfs_delete_dentry(struct dentry *dentry) -{ - dentry->d_op = NULL; - return 0; -} - -struct dentry_operations smfs_cow_dops = { -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - .d_revalidate = smfs_revalidate_nd, -#else - .d_revalidate_it = smfs_revalidate_it, -#endif - .d_delete = smfs_delete_dentry, -}; - -int smfs_cow_lookup_post(struct inode *dir, void *de, void *data1, - void *data2) -{ - struct dentry *dentry = (struct dentry*)de; - struct inode *inode = dentry->d_inode; - ENTRY; - - if (inode && smfs_under_dotsnap_inode(inode)) { - int index = I2SNAPI(dir)->sn_index; - - smfs_revalidate_dotsnap_dentry(dentry, dir, index); - smfs_init_snap_inode_info(inode, dir, index); - } - dentry->d_op = &smfs_cow_dops; - RETURN(0); -} - -static int smfs_cow_readdir_post(struct inode *dir, void *de, void *data1, - void *data2) -{ - struct file *filp = (struct file*)de; - - if (smfs_primary_inode(dir)) { - filp->f_pos += 1; - } - RETURN(0); -} - - -static cow_funcs smfs_cow_post_funcs[HOOK_MAX + 1] = { - [HOOK_CREATE] NULL, - [HOOK_LOOKUP] smfs_cow_lookup_post, - [HOOK_LINK] NULL, - [HOOK_UNLINK] NULL, - [HOOK_SYMLINK] NULL, - [HOOK_MKDIR] NULL, - [HOOK_RMDIR] NULL, - [HOOK_MKNOD] NULL, - [HOOK_RENAME] NULL, - [HOOK_SETATTR] NULL, - [HOOK_WRITE] NULL, - [HOOK_READDIR] smfs_cow_readdir_post, -}; - -static int smfs_cow_pre(struct inode *dir, void *dentry, void *new_dir, - void *new_dentry, int op) -{ - if (smfs_cow_pre_funcs[op]) { - return smfs_cow_pre_funcs[op](dir, dentry, new_dir, new_dentry); - } - return 0; -} - -static int smfs_cow_post(struct inode *dir, void *dentry, void *new_dir, - void *new_dentry, int op) -{ - if (smfs_cow_post_funcs[op]) { - return smfs_cow_post_funcs[op](dir, dentry, new_dir, new_dentry); - } - return 0; -} -