X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsnapfs%2Fclonefs.c;h=2292c495d8277342602ec8656e7e2f2f967ac29c;hb=62a0d77038f9c69119fad5d76491edf986c5efbb;hp=1ef807807698b09a80f7d60d8186466672466ce2;hpb=86dcbf50773b4429e2710f709fa0fb9ebb6dcd3d;p=fs%2Flustre-release.git diff --git a/lustre/snapfs/clonefs.c b/lustre/snapfs/clonefs.c index 1ef8078..2292c49 100644 --- a/lustre/snapfs/clonefs.c +++ b/lustre/snapfs/clonefs.c @@ -13,45 +13,33 @@ * */ -#define __NO_VERSION__ +#define DEBUG_SUBSYSTEM S_SNAP + #include #include -#include #include +#include #include -#include -#include #include +#include +#include +#include +#include "snapfs_internal.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include /* Clone is a simple file system, read only that just follows redirectors we have placed the entire implementation except clone_read_super in this file */ -struct inode_operations clonefs_dir_inode_operations; -struct inode_operations clonefs_file_inode_operations; -struct inode_operations clonefs_symlink_inode_operations; -struct inode_operations clonefs_special_inode_operations; -struct file_operations clonefs_dir_file_operations; -struct file_operations clonefs_file_file_operations; -struct file_operations clonefs_special_file_operations; +struct inode_operations clonefs_dir_inode_ops; +struct inode_operations clonefs_file_inode_ops; +struct inode_operations clonefs_symlink_inode_ops; +//struct inode_operations clonefs_special_inode_operations; +struct file_operations clonefs_dir_file_ops; +struct file_operations clonefs_file_file_ops; +//struct file_operations clonefs_special_file_operations; +struct address_space_operations clonefs_file_address_ops; /* support routines for following redirectors */ @@ -82,14 +70,14 @@ struct inode *clonefs_get_inode(struct inode *inode) redirected_inode = snap_redirect(cache_inode, inode->i_sb); CDEBUG(D_SNAP, "redirected_inode: %lx, cache_inode %lx\n", - (ulong) redirected_inode, (ulong) cache_inode); + (unsigned long) redirected_inode, (unsigned long) cache_inode); CDEBUG(D_SNAP, "cache_inode: %lx, ino %ld, sb %lx, count %d\n", - (ulong) cache_inode, cache_inode->i_ino, - (ulong) cache_inode->i_sb, cache_inode->i_count); - + (unsigned long) cache_inode, cache_inode->i_ino, + (unsigned long) cache_inode->i_sb, atomic_read(&cache_inode->i_count)); + iput(cache_inode); - EXIT; + return redirected_inode; } @@ -102,39 +90,45 @@ static void clonefs_read_inode(struct inode *inode) ENTRY; CDEBUG(D_SNAP, "inode: %lx, ino %ld, sb %lx, count %d\n", - (ulong) inode , inode->i_ino, (long) inode->i_sb, - inode->i_count); + (unsigned long)inode, inode->i_ino, (long) inode->i_sb, + atomic_read(&inode->i_count)); /* redirecting inode in the cache */ cache_inode = clonefs_get_inode(inode); if (!cache_inode) { make_bad_inode(inode); - EXIT; return; } /* copy attrs of that inode to our clone inode */ snapfs_cpy_attrs(inode, cache_inode); - if (S_ISREG(inode->i_mode)) - inode->i_op = &clonefs_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) - inode->i_op = &clonefs_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &clonefs_symlink_inode_operations; - else if (S_ISCHR(inode->i_mode)) - inode->i_op = &chrdev_inode_operations; - else if (S_ISBLK(inode->i_mode)) - inode->i_op = &blkdev_inode_operations; - else if (S_ISFIFO(inode->i_mode)) - init_fifo(inode); - + if (S_ISREG(inode->i_mode)) { + 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; + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &clonefs_symlink_inode_ops; + } else { + /* init special inode + * FIXME whether we should replace special inode ops*/ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) + init_special_inode(inode, inode->i_mode, + kdev_t_to_nr(inode->i_rdev)); +#else + init_special_inode(inode, inode->i_mode, inode->i_rdev); +#endif + } iput(cache_inode); CDEBUG(D_SNAP, "cache_inode: %lx ino %ld, sb %lx, count %d\n", - (ulong) cache_inode, cache_inode->i_ino, - (ulong) cache_inode->i_sb, cache_inode->i_count); - EXIT; - return; + (unsigned long) cache_inode, cache_inode->i_ino, + (unsigned long) cache_inode->i_sb, + atomic_read(&cache_inode->i_count)); + EXIT; } @@ -144,18 +138,17 @@ static void clonefs_put_super(struct super_block *sb) ENTRY; CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n", - (ulong) sb, (ulong) &sb->u.generic_sbp); + (unsigned long) sb, (unsigned long) &sb->u.generic_sbp); clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp; - dput( clone_sb->clone_cache->cache_sb->s_root ); + dput(clone_sb->clone_cache->cache_sb->s_root); list_del(&clone_sb->clone_list_entry); - - MOD_DEC_USE_COUNT; + + put_snap_current_mnt(clone_sb->clone_cache->cache_sb); EXIT; } -static int clonefs_statfs(struct super_block *sb, struct statfs *buf, - int bufsiz) +static int clonefs_statfs(struct super_block *sb, struct statfs *buf) { struct snap_clone_info *clone_sb; struct snap_cache *cache; @@ -165,26 +158,19 @@ static int clonefs_statfs(struct super_block *sb, struct statfs *buf, cache = clone_sb->clone_cache; if (!cache) { - printk("clone_statfs: no cache\n"); - return -EINVAL; + CERROR("clone_statfs: no cache\n"); + RETURN(-EINVAL); } - EXIT; return cache->cache_filter->o_caops.cache_sops->statfs - (cache->cache_sb, buf, bufsiz); + (cache->cache_sb, buf); } struct super_operations clone_super_ops = { - clonefs_read_inode, /* read_inode */ - NULL, /* write_inode */ - NULL, /* put_inode */ - NULL, /* delete_inode */ - NULL, /* notify_change */ - clonefs_put_super, /* put_super */ - NULL, /* write_super */ - clonefs_statfs, /* statfs */ - NULL /* remount_fs */ + read_inode: clonefs_read_inode, /* read_inode */ + put_super: clonefs_put_super, /* put_super */ + statfs: clonefs_statfs, /* statfs */ }; @@ -199,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 @@ -206,22 +206,28 @@ 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); - EXIT; - return ERR_PTR(-ENOENT); + RETURN(ERR_PTR(-ENOENT)); } /* Lock cache directory inode. */ @@ -239,8 +245,7 @@ struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry) up(&cache_dir->i_sem); iput(cache_dir); dentry->d_inode = NULL; - EXIT; - return ERR_PTR(-ENOENT); + RETURN(ERR_PTR(-ENOENT)); } /* Unlock cache directory inode. */ up(&cache_dir->i_sem); @@ -268,8 +273,8 @@ struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry) if ( cache_inode != NULL ) { CDEBUG(D_INODE, "cache ino %ld, count %d, dir %ld, count %d\n", - cache_inode->i_ino, cache_inode->i_count, cache_dir->i_ino, - cache_dir->i_count); + cache_inode->i_ino, atomic_read(&cache_inode->i_count), + cache_dir->i_ino, atomic_read(&cache_dir->i_count)); } d_unalloc(cache_dentry); @@ -280,8 +285,7 @@ struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry) */ d_add(dentry, inode); - EXIT; - return NULL; + RETURN(NULL); } @@ -293,16 +297,17 @@ static void clonefs_prepare_snapfile(struct inode *i, struct dentry *cache_dentry) { ENTRY; - cache_file->f_pos = clone_file->f_pos; + + cache_file->f_pos = clone_file->f_pos; cache_file->f_mode = clone_file->f_mode; cache_file->f_flags = clone_file->f_flags; cache_file->f_count = clone_file->f_count; cache_file->f_owner = clone_file->f_owner; - cache_file->f_op = cache_inode->i_op->default_file_ops; + cache_file->f_op = cache_inode->i_fop; cache_file->f_dentry = cache_dentry; cache_file->f_dentry->d_inode = cache_inode; + EXIT; - return ; } /* update the clonefs file struct after IO in cache file */ @@ -312,10 +317,11 @@ static void clonefs_restore_snapfile(struct inode *cache_inode, struct file *clone_file) { ENTRY; - cache_file->f_pos = clone_file->f_pos; + + cache_file->f_pos = clone_file->f_pos; cache_inode->i_size = clone_inode->i_size; + EXIT; - return; } static int clonefs_readdir(struct file *file, void *dirent, @@ -325,20 +331,18 @@ 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; if(!inode) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } cache_inode = clonefs_get_inode(inode); if (!cache_inode) { make_bad_inode(inode); - EXIT; - return -ENOMEM; + RETURN(-ENOMEM); } CDEBUG(D_INODE,"clone ino %ld\n",cache_inode->i_ino); @@ -354,56 +358,22 @@ static int clonefs_readdir(struct file *file, void *dirent, } clonefs_restore_snapfile(inode, file, cache_inode, &open_file); iput(cache_inode); - EXIT; - return result; + RETURN(result); } -struct file_operations clonefs_dir_file_operations = { - NULL, /* lseek */ - NULL, /* read -- bad */ - NULL, /* write */ - clonefs_readdir, /* readdir */ - NULL, /* select */ - NULL, /* ioctl */ - NULL, /* mmap */ - NULL, /* open */ - NULL, - NULL, /* release */ - NULL, /* fsync */ - NULL, - NULL, - NULL +struct file_operations clonefs_dir_file_ops = { + readdir: clonefs_readdir, /* readdir */ }; -struct inode_operations clonefs_dir_inode_operations = -{ - &clonefs_dir_file_operations, - NULL, /* create */ - clonefs_lookup, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* bmap */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL, /* update page */ - NULL, /* revalidate */ +struct inode_operations clonefs_dir_inode_ops = { + lookup: clonefs_lookup, /* lookup */ }; /* ***************** end of clonefs dir ops ******************* */ /* ***************** begin clonefs file ops ******************* */ -int clonefs_readpage(struct file *file, struct page *page) +static int clonefs_readpage(struct file *file, struct page *page) { int result = 0; struct inode *cache_inode; @@ -417,96 +387,56 @@ int clonefs_readpage(struct file *file, struct page *page) cache_inode = clonefs_get_inode(file->f_dentry->d_inode); if (!cache_inode) { make_bad_inode(file->f_dentry->d_inode); - EXIT; - return -ENOMEM; + RETURN(-ENOMEM); } clonefs_prepare_snapfile(inode, file, cache_inode, &open_file, &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... */ - if (cache_inode->i_op->readpage == NULL) - printk("Yes, Grigori, directories are a problem.\n"); - else - cache_inode->i_op->readpage(&open_file, page); + 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); - EXIT; - return result; + RETURN(result); } - -struct file_operations clonefs_file_file_operations = { - NULL, /* lseek */ - generic_file_read, /* read -- bad */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* select */ - NULL, /* ioctl */ - generic_file_mmap, /* mmap */ - NULL, /* open */ - NULL, - NULL, /* release */ - NULL, /* fsync */ - NULL, - NULL, - NULL +struct file_operations clonefs_file_file_ops = { + read: generic_file_read, /* read -- bad */ + mmap: generic_file_mmap, /* mmap */ }; -struct inode_operations clonefs_file_inode_operations = -{ - &clonefs_file_file_operations, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - clonefs_readpage, /* readpage */ - NULL, /* writepage */ - NULL, /* bmap */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL, /* update page */ - NULL, /* revalidate */ +struct address_space_operations clonefs_file_address_ops = { + readpage: clonefs_readpage }; - /* ***************** end of clonefs file ops ******************* */ /* ***************** begin clonefs symlink ops ******************* */ -int clonefs_readlink(struct dentry *dentry, char *buf, int len) +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"); - EXIT; - return res; + RETURN(rc); } /* XXX: shall we allocate a new dentry ? - The following is safe for ext2, etc. because ext2_readlink only + The following is safe for ext3, etc. because ext2_readlink only use the inode info */ /* save the old dentry inode */ @@ -514,8 +444,8 @@ 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); } @@ -525,26 +455,21 @@ int clonefs_readlink(struct dentry *dentry, char *buf, int len) iput(cache_inode); - EXIT; - return res; + RETURN(rc); } -struct dentry * clonefs_follow_link(struct dentry * dentry, - struct dentry *base, - unsigned int follow) +static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd) { - struct dentry * res; struct inode * cache_inode; struct inode * old_inode; + int rc = -ENOENT; ENTRY; - res = ERR_PTR(-ENOENT); cache_inode = clonefs_get_inode(dentry->d_inode); - if ( ! cache_inode ) { + if (!cache_inode) { CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); - EXIT; - return res; + RETURN(rc); } /* XXX: shall we allocate a new dentry ? @@ -556,8 +481,8 @@ struct dentry * clonefs_follow_link(struct dentry * dentry, /* 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, base, follow); + if (cache_inode->i_op->follow_link) { + rc = cache_inode->i_op->follow_link(dentry, nd); } /* restore the old inode */ @@ -565,32 +490,103 @@ struct dentry * clonefs_follow_link(struct dentry * dentry, iput(cache_inode); - EXIT; - 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 */ -struct inode_operations clonefs_symlink_inode_operations = + /* 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 = { - NULL, /* no file operations */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - clonefs_readlink, /* readlink */ - clonefs_follow_link,/* follow_link */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* bmap */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL, /* update page */ - NULL, /* revalidate */ + /*FIXME later getxattr, listxattr, + * other method need to be replaced too + * */ + 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; +} +