X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsnapfs%2Fclonefs.c;h=2292c495d8277342602ec8656e7e2f2f967ac29c;hb=63de3bfeb1a127bbc8e47c0391c98029394ff411;hp=66d38624996ec6c00cc7ad7c2a7976513405638a;hpb=c955653af59279f2c772c8bdcdafbf825e8bd10a;p=fs%2Flustre-release.git diff --git a/lustre/snapfs/clonefs.c b/lustre/snapfs/clonefs.c index 66d3862..2292c49 100644 --- a/lustre/snapfs/clonefs.c +++ b/lustre/snapfs/clonefs.c @@ -106,6 +106,7 @@ static void clonefs_read_inode(struct inode *inode) inode->i_op = &clonefs_file_inode_ops; if (inode->i_mapping) inode->i_mapping->a_ops = &clonefs_file_address_ops; + inode->i_fop = &clonefs_file_file_ops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &clonefs_dir_inode_ops; inode->i_fop = &clonefs_dir_file_ops; @@ -141,6 +142,8 @@ static void clonefs_put_super(struct super_block *sb) clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp; dput(clone_sb->clone_cache->cache_sb->s_root); list_del(&clone_sb->clone_list_entry); + + put_snap_current_mnt(clone_sb->clone_cache->cache_sb); EXIT; } @@ -182,6 +185,20 @@ static void d_unalloc(struct dentry *dentry) dput(dentry); /* this will free the dentry memory */ } +static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode) +{ + atomic_set(&dentry->d_count, 1); + dentry->d_vfs_flags = 0; + dentry->d_flags = 0; + dentry->d_inode = inode; + dentry->d_op = NULL; + dentry->d_fsdata = NULL; + dentry->d_mounted = 0; + INIT_LIST_HEAD(&dentry->d_hash); + INIT_LIST_HEAD(&dentry->d_lru); + INIT_LIST_HEAD(&dentry->d_subdirs); + INIT_LIST_HEAD(&dentry->d_alias); +} /* * Return the underlying fs dentry with name in 'dentry' that points * to the right inode. 'dir' is the clone fs directory to search for @@ -189,18 +206,25 @@ static void d_unalloc(struct dentry *dentry) */ struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry) { - struct inode *cache_dir; - struct dentry *cache_dentry; + struct inode *cache_dir = NULL; + struct dentry *cache_dentry = NULL; struct inode *cache_inode; struct dentry *result; + struct dentry tmp; struct inode *inode; struct snap_clone_info *clone_sb; ENTRY; cache_dir = clonefs_get_inode(dir); - - cache_dentry = d_alloc(dentry->d_parent, &dentry->d_name); + if (!cache_dir) + RETURN(ERR_PTR(-ENOENT)); + /*FIXME later, we make parent dentry here + *there may some problems in lookup + */ + prepare_parent_dentry(&tmp, cache_dir); + cache_dentry = d_alloc(&tmp, &dentry->d_name); + if (!cache_dentry) { iput(cache_dir); RETURN(ERR_PTR(-ENOENT)); @@ -307,7 +331,7 @@ static int clonefs_readdir(struct file *file, void *dirent, struct inode *cache_inode; struct file open_file; struct dentry open_dentry; - struct inode *inode=file->f_dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; ENTRY; @@ -370,13 +394,14 @@ static int clonefs_readpage(struct file *file, struct page *page) &open_dentry); /* tell currentfs_readpage the primary inode number */ open_dentry.d_fsdata = (void*)inode->i_ino; - + page->mapping->host = cache_inode; /* potemkin case: we are handed a directory inode */ down(&cache_inode->i_sem); /* XXX - readpage NULL on directories... */ result = cache_inode->i_mapping->a_ops->readpage(&open_file, page); up(&cache_inode->i_sem); + page->mapping->host = inode; clonefs_restore_snapfile(inode, file, cache_inode, &open_file); iput(cache_inode); RETURN(result); @@ -397,19 +422,17 @@ struct address_space_operations clonefs_file_address_ops = { static int clonefs_readlink(struct dentry *dentry, char *buf, int len) { - int res; struct inode * cache_inode; struct inode * old_inode; + int rc = -ENOENT; ENTRY; cache_inode = clonefs_get_inode(dentry->d_inode); - res = -ENOENT; - - if ( ! cache_inode ) { + if (!cache_inode) { CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); - RETURN(res); + RETURN(rc); } /* XXX: shall we allocate a new dentry ? @@ -421,8 +444,8 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len) /* set dentry inode to cache inode */ dentry->d_inode = cache_inode; - if ( cache_inode->i_op->readlink ) { - res = cache_inode->i_op->readlink(dentry, buf, len); + if (cache_inode->i_op->readlink) { + rc = cache_inode->i_op->readlink(dentry, buf, len); }else { CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino); } @@ -432,21 +455,21 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len) iput(cache_inode); - RETURN(res); + RETURN(rc); } static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd) { struct inode * cache_inode; struct inode * old_inode; - int res; + int rc = -ENOENT; ENTRY; cache_inode = clonefs_get_inode(dentry->d_inode); - if ( ! cache_inode ) { + if (!cache_inode) { CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); - RETURN(-ENOENT); + RETURN(rc); } /* XXX: shall we allocate a new dentry ? @@ -458,8 +481,8 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd) /* set dentry inode to cache inode */ dentry->d_inode = cache_inode; - if ( cache_inode->i_op->follow_link ) { - res = cache_inode->i_op->follow_link(dentry, nd); + if (cache_inode->i_op->follow_link) { + rc = cache_inode->i_op->follow_link(dentry, nd); } /* restore the old inode */ @@ -467,16 +490,103 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd) iput(cache_inode); - RETURN(res); + RETURN(rc); } +static ssize_t +clonefs_getxattr(struct dentry *dentry, const char *name, + void *buffer, size_t size) +{ + struct inode * cache_inode; + struct inode * old_inode; + int rc = -ENOENT; + + ENTRY; + + cache_inode = clonefs_get_inode(dentry->d_inode); + if (!cache_inode) { + CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); + RETURN(rc); + } + + /* XXX: shall we allocate a new dentry ? + The following is safe for ext2, etc. because ext2_follow_link + only use the inode info */ + + /* save the old dentry inode */ + old_inode = dentry->d_inode; + /* set dentry inode to cache inode */ + dentry->d_inode = cache_inode; + + if (cache_inode->i_op->getxattr) { + rc = cache_inode->i_op->getxattr(dentry, name, buffer, size); + } + + /* restore the old inode */ + dentry->d_inode = old_inode; + + iput(cache_inode); + RETURN(rc); +} +static ssize_t +clonefs_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + struct inode * cache_inode; + struct inode * old_inode; + int rc = -ENOENT; + + ENTRY; + + cache_inode = clonefs_get_inode(dentry->d_inode); + if (!cache_inode) { + CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); + RETURN(rc); + } + + /* XXX: shall we allocate a new dentry ? + The following is safe for ext2, etc. because ext2_follow_link + only use the inode info */ + + /* save the old dentry inode */ + old_inode = dentry->d_inode; + /* set dentry inode to cache inode */ + dentry->d_inode = cache_inode; + + if (cache_inode->i_op->listxattr) { + rc = cache_inode->i_op->listxattr(dentry, buffer, size); + } + + /* restore the old inode */ + dentry->d_inode = old_inode; + + iput(cache_inode); + + RETURN(rc); + +} struct inode_operations clonefs_symlink_inode_ops = { /*FIXME later getxattr, listxattr, * other method need to be replaced too * */ - readlink: clonefs_readlink, /* readlink */ - follow_link: clonefs_follow_link,/* follow_link */ + readlink: clonefs_readlink, /* readlink */ + follow_link: clonefs_follow_link, /* follow_link */ + getxattr: clonefs_getxattr, /* get xattr */ + listxattr: clonefs_listxattr, /* list xattr */ }; +int clonefs_mounted(struct snap_cache *cache, int index) +{ + struct snap_clone_info *clone_sb; + struct list_head *list, *end; + + end = list = &cache->cache_clone_list; + + list_for_each_entry(clone_sb, list, clone_list_entry) { + if (clone_sb->clone_index == index) + return 1; + } + return 0; +} +