diff --git a/lustre/snapfs/cache.c b/lustre/snapfs/cache.c index d0c8f1bb49d142069702de57ea5e69fdecffc92d..bb1ed305309d21a09099b66b153c1dd8f768fee7 100644 --- a/lustre/snapfs/cache.c +++ b/lustre/snapfs/cache.c @@ -1,56 +1,35 @@ -/* - * - * - * Copyright (C) 2000 Stelias Computing, Inc. - * Copyright (C) 2000 Red Hat, Inc. - * - * +/* + * snapfs/cache.c */ +#define DEBUG_SUBSYSTEM S_SNAP -#include <stdarg.h> - -#include <asm/bitops.h> -#include <asm/uaccess.h> -#include <asm/system.h> - -#include <linux/errno.h> +#include <linux/kmod.h> +#include <linux/init.h> #include <linux/fs.h> -#include <linux/ext2_fs.h> -#include <linux/malloc.h> -#include <linux/vmalloc.h> -#include <linux/sched.h> -#include <linux/stat.h> +#include <linux/slab.h> #include <linux/string.h> -#include <linux/locks.h> -#include <linux/blkdev.h> -#include <linux/init.h> -#define __NO_VERSION__ -#include <linux/module.h> - -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> - +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> +#include <portals/list.h> +#include "snapfs_internal.h" /* * XXX - Not sure for snapfs that the cache functions are even needed. * Can't all lookups be done by an inode->superblock->u.generic_sbp * lookup? */ -/* - This file contains the routines associated with managing a - cache of files . These caches need to be found - fast so they are hashed by the device, with an attempt to have - collision chains of length 1. -*/ +extern struct snap_table snap_tables[SNAP_MAX_TABLES]; /* the intent of this hash is to have collision chains of length 1 */ #define CACHES_BITS 8 #define CACHES_SIZE (1 << CACHES_BITS) #define CACHES_MASK CACHES_SIZE - 1 + static struct list_head snap_caches[CACHES_SIZE]; + static inline int snap_cache_hash(kdev_t dev) { return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8)); @@ -78,68 +57,39 @@ struct snap_cache *snap_find_cache(kdev_t dev) struct list_head *lh, *tmp; lh = tmp = &(snap_caches[snap_cache_hash(dev)]); - while ( (tmp = lh->next) != lh ) { - cache = list_entry(tmp, struct snap_cache, cache_chain); + list_for_each_entry(cache, lh, cache_chain) { if ( cache->cache_dev == dev ) return cache; } return NULL; } - -/* map an inode to a cache */ -struct snap_cache *snap_get_cache(struct inode *inode) -{ - struct snap_cache *cache; - - /* find the correct snap_cache here, based on the device */ - cache = snap_find_cache(inode->i_dev); - if ( !cache ) { - printk("WARNING: no cache for dev %d, ino %ld\n", - inode->i_dev, inode->i_ino); - return NULL; - } - - return cache; -} - - -/* another debugging routine: check fs is InterMezzo fs */ -int snap_ispresto(struct inode *inode) -{ - struct snap_cache *cache; - - if ( !inode ) - return 0; - cache = snap_get_cache(inode); - if ( !cache ) - return 0; - return (inode->i_dev == cache->cache_dev); -} - /* setup a cache structure when we need one */ struct snap_cache *snap_init_cache(void) { struct snap_cache *cache; /* make a snap_cache structure for the hash */ - SNAP_ALLOC(cache, struct snap_cache *, sizeof(struct snap_cache)); + SNAP_ALLOC(cache, sizeof(struct snap_cache)); if ( cache ) { - memset(cache, 0, sizeof(struct snap_cache)); + int i; + + memset(cache, 0, sizeof(struct snap_cache)); INIT_LIST_HEAD(&cache->cache_chain); INIT_LIST_HEAD(&cache->cache_clone_list); - } + + for (i = 0; i < SNAP_MAX_TABLES; i++) { + init_MUTEX(&snap_tables[i].tbl_sema); + } + } return cache; } - /* free a cache structure and all of the memory it is pointing to */ inline void snap_free_cache(struct snap_cache *cache) { if (!cache) return; - - SNAP_FREE(cache, sizeof(struct snap_cache)); } diff --git a/lustre/snapfs/clonefs.c b/lustre/snapfs/clonefs.c index 1ef807807698b09a80f7d60d8186466672466ce2..708b083b4aa863189246485f65b5fdcf95ff69e3 100644 --- a/lustre/snapfs/clonefs.c +++ b/lustre/snapfs/clonefs.c @@ -13,45 +13,33 @@ * */ -#define __NO_VERSION__ +#define DEBUG_SUBSYSTEM S_SNAP + #include <linux/module.h> #include <linux/kernel.h> -#include <linux/mm.h> #include <linux/string.h> +#include <linux/slab.h> #include <linux/stat.h> -#include <linux/errno.h> -#include <linux/locks.h> #include <linux/unistd.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> +#include "snapfs_internal.h" -#include <asm/system.h> -#include <asm/uaccess.h> - -#include <linux/fs.h> -#include <linux/stat.h> -#include <linux/errno.h> -#include <linux/locks.h> -#include <linux/string.h> -#include <asm/uaccess.h> -#include <linux/malloc.h> -#include <linux/vmalloc.h> -#include <asm/segment.h> - -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> /* 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,43 @@ 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; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &clonefs_dir_inode_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 +136,15 @@ 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; - 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 +154,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 */ }; @@ -220,8 +202,7 @@ struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry) cache_dentry = d_alloc(dentry->d_parent, &dentry->d_name); if (!cache_dentry) { iput(cache_dir); - EXIT; - return ERR_PTR(-ENOENT); + RETURN(ERR_PTR(-ENOENT)); } /* Lock cache directory inode. */ @@ -239,8 +220,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 +248,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 +260,7 @@ struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry) */ d_add(dentry, inode); - EXIT; - return NULL; + RETURN(NULL); } @@ -293,16 +272,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 +292,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, @@ -330,15 +311,13 @@ static int clonefs_readdir(struct file *file, void *dirent, 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 +333,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,8 +362,7 @@ 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, @@ -429,65 +373,28 @@ int clonefs_readpage(struct file *file, struct page *page) /* 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); 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; @@ -501,12 +408,11 @@ int clonefs_readlink(struct dentry *dentry, char *buf, int len) if ( ! cache_inode ) { CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); - EXIT; - return res; + RETURN(res); } /* 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 */ @@ -525,26 +431,21 @@ int clonefs_readlink(struct dentry *dentry, char *buf, int len) iput(cache_inode); - EXIT; - return res; + RETURN(res); } -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 res; ENTRY; - res = ERR_PTR(-ENOENT); cache_inode = clonefs_get_inode(dentry->d_inode); if ( ! cache_inode ) { CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); - EXIT; - return res; + RETURN(-ENOENT); } /* XXX: shall we allocate a new dentry ? @@ -557,7 +458,7 @@ struct dentry * clonefs_follow_link(struct dentry * dentry, dentry->d_inode = cache_inode; if ( cache_inode->i_op->follow_link ) { - res = cache_inode->i_op->follow_link(dentry, base, follow); + res = cache_inode->i_op->follow_link(dentry, nd); } /* restore the old inode */ @@ -565,32 +466,16 @@ struct dentry * clonefs_follow_link(struct dentry * dentry, iput(cache_inode); - EXIT; - return res; + RETURN(res); } -struct inode_operations clonefs_symlink_inode_operations = +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 */ }; diff --git a/lustre/snapfs/dcache.c b/lustre/snapfs/dcache.c index 88ce4bb54c37400d3a8a2a9369eeab3a88ebc342..cf4337d46be4ffd5ffac9bb39a25912c74641284 100644 --- a/lustre/snapfs/dcache.c +++ b/lustre/snapfs/dcache.c @@ -2,20 +2,20 @@ * Directory operations for SnapFS filesystem */ -#include <linux/types.h> +#define DEBUG_SUBSYSTEM S_SNAP + +#include <linux/module.h> #include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/stat.h> -#include <linux/errno.h> -#include <linux/locks.h> -#include <asm/segment.h> -#include <asm/uaccess.h> #include <linux/string.h> +#include <linux/slab.h> +#include <linux/stat.h> +#include <linux/unistd.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> + +#include "snapfs_internal.h" -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> /* called when a cache lookup succeeds */ @@ -45,7 +45,7 @@ static int currentfs_dentry_revalidate(struct dentry *de, int flag) return 0; } #else - return 1; + RETURN(1); #endif } diff --git a/lustre/snapfs/dir.c b/lustre/snapfs/dir.c index 0b83fa147c616d1a464297d2510900ba3268efd6..a1636f2bc32432ceb6c4af50e727848f8e055082 100644 --- a/lustre/snapfs/dir.c +++ b/lustre/snapfs/dir.c @@ -1,30 +1,19 @@ /* * dir.c */ +#define DEBUG_SUBSYSTEM S_SNAP -#define EXPORT_SYMTAB - - -#define __NO_VERSION__ #include <linux/module.h> -#include <asm/uaccess.h> -#include <linux/sched.h> -#include <linux/stat.h> +#include <linux/kernel.h> #include <linux/string.h> -#include <linux/locks.h> -#include <linux/quotaops.h> -#include <linux/list.h> -#include <linux/file.h> -#include <asm/bitops.h> -#include <asm/byteorder.h> +#include <linux/slab.h> +#include <linux/stat.h> +#include <linux/unistd.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> - -#ifdef CONFIG_SNAPFS_EXT3 -void ext3_orphan_del(handle_t *handle, struct inode *inode); -#endif +#include "snapfs_internal.h" static ino_t get_parent_ino(struct inode * inode) { @@ -32,7 +21,7 @@ static ino_t get_parent_ino(struct inode * inode) struct dentry * dentry; if (list_empty(&inode->i_dentry)) { - printk("snapfs ERROR: no dentry for ino %lu\n", inode->i_ino); + CERROR("No dentry for ino %lu\n", inode->i_ino); return 0; } @@ -69,8 +58,7 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry) cache = snap_find_cache(dir->i_dev); if ( !cache ) { - EXIT; - return ERR_PTR(-EINVAL); + RETURN(ERR_PTR(-EINVAL)); } if ( dentry->d_name.len == strlen(".snap") && @@ -80,30 +68,27 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry) /* Don't permit .snap in clonefs */ if( dentry->d_sb != cache->cache_sb ) - return ERR_PTR(-ENOENT); + RETURN(ERR_PTR(-ENOENT)); /* Don't permit .snap under .snap */ if( currentfs_is_under_dotsnap(dentry) ) - return ERR_PTR(-ENOENT); + RETURN(ERR_PTR(-ENOENT)); ino = 0xF0000000 | dir->i_ino; snap = iget(dir->i_sb, ino); CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n", snap->i_ino, snap->i_mode); d_add(dentry, snap); - EXIT; - return NULL; + RETURN(NULL); } iops = filter_c2cdiops(cache->cache_filter); if (!iops || !iops->lookup) { - EXIT; - return ERR_PTR(-EINVAL); + RETURN(ERR_PTR(-EINVAL)); } rc = iops->lookup(dir, dentry); if ( rc || !dentry->d_inode) { - EXIT; - return NULL; + RETURN(NULL); } /* @@ -144,8 +129,7 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry) dentry->d_fsdata = (void*)pri_ino; } - EXIT; - return NULL; + RETURN(NULL); #if 0 /* XXX: PJB these need to be set up again. See dcache.c */ @@ -159,70 +143,71 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry) err_out: d_unadd_iput(dentry); - EXIT; - return ERR_PTR(-EINVAL); + RETURN(ERR_PTR(-EINVAL)); } static int currentfs_create(struct inode *dir, struct dentry *dentry, int mode) { - struct snap_cache *cache; - int rc; + struct snap_cache *cache; struct inode_operations *iops; - void *handle = NULL; + struct snapshot_operations *snapops; + void *handle = NULL; + int rc; ENTRY; if (currentfs_is_under_dotsnap(dentry)) { - EXIT; - return -EPERM; + RETURN(-EPERM); } cache = snap_find_cache(dir->i_dev); if ( !cache ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } + snapops = filter_c2csnapops(cache->cache_filter); + if (!snapops || !snapops->get_generation) + RETURN(-EINVAL); + handle = snap_trans_start(cache, dir, SNAP_OP_CREATE); if ( snap_needs_cow(dir) != -1 ) { - printk("snap_needs_cow for ino %lu \n",dir->i_ino); + CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 1); - snap_do_cow(dir, get_parent_ino(dir), 0); + if (!(snap_do_cow(dir, get_parent_ino(dir), 0))) { + CERROR("Do cow error\n"); + RETURN(-EINVAL); + } } iops = filter_c2cdiops(cache->cache_filter); - if (!iops || - !iops->create) { - rc = -EINVAL; - goto exit; + if (!iops || !iops->create) { + RETURN(-EINVAL); } snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 2); rc = iops->create(dir, dentry, mode); /* XXX now set the correct snap_{file,dir,sym}_iops */ - if ( ! dentry->d_inode) { - printk("Error in currentfs_create, dentry->d_inode is NULL\n"); - goto exit; + if (!dentry->d_inode) { + CERROR("Error in currentfs_create, dentry->d_inode is NULL\n"); + GOTO(exit, 0); } - if ( S_ISDIR(dentry->d_inode->i_mode) ) + if (S_ISDIR(dentry->d_inode->i_mode)) dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter); - else if ( S_ISREG(dentry->d_inode->i_mode) ) { - if ( !filter_c2cfiops(cache->cache_filter) ) { - filter_setup_file_ops(cache->cache_filter, - dentry->d_inode->i_op, ¤tfs_file_iops); + else if (S_ISREG(dentry->d_inode->i_mode)) { + if (!filter_c2cfiops(cache->cache_filter)) { + filter_setup_file_ops(cache->cache_filter, dentry->d_inode, + ¤tfs_file_iops, ¤tfs_file_fops, + ¤tfs_file_aops); } dentry->d_inode->i_op = filter_c2ufiops(cache->cache_filter); } - printk("inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op); - + CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op); snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 3); - -exit: + init_filter_data(dentry->d_inode, snapops, 0); exit: snap_trans_commit(cache, handle); - EXIT; - return rc; + RETURN(rc); } static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) @@ -235,27 +220,24 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ENTRY; if (currentfs_is_under_dotsnap(dentry)) { - EXIT; - return -EPERM; + RETURN(-EPERM); } cache = snap_find_cache(dir->i_dev); if ( !cache ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } handle = snap_trans_start(cache, dir, SNAP_OP_MKDIR); if ( snap_needs_cow(dir) != -1 ) { - CDEBUG(D_FILE, "snap_needs_cow for ino %lu \n",dir->i_ino); + CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 1); snap_do_cow(dir, get_parent_ino(dir), 0); } iops = filter_c2cdiops(cache->cache_filter); - if (!iops || - !iops->mkdir) { + if (!iops || !iops->mkdir) { rc = -EINVAL; goto exit; } @@ -269,17 +251,16 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) /* XXX now set the correct snap_{file,dir,sym}_iops */ if ( dentry->d_inode) { dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter); - printk("inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op); + CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op); } else { - printk("Error in currentfs_mkdir, dentry->d_inode is NULL\n"); + CERROR("Error in currentfs_mkdir, dentry->d_inode is NULL\n"); } snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 3); exit: snap_trans_commit(cache, handle); - EXIT; - return rc; + RETURN(rc); } static int currentfs_link (struct dentry * old_dentry, struct inode * dir, @@ -292,44 +273,37 @@ static int currentfs_link (struct dentry * old_dentry, struct inode * dir, ENTRY; - if (currentfs_is_under_dotsnap(dentry)) { - EXIT; - return -EPERM; - } + if (currentfs_is_under_dotsnap(dentry)) + RETURN(-EPERM); cache = snap_find_cache(dir->i_dev); - if ( !cache ) { - EXIT; - return -EINVAL; - } + if ( !cache ) + RETURN(-EINVAL); handle = snap_trans_start(cache, dir, SNAP_OP_LINK); if ( snap_needs_cow(dir) != -1 ) { - printk("snap_needs_cow for ino %lu \n",dir->i_ino); + CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 1); snap_do_cow(dir, get_parent_ino(dir), 0); } if ( snap_needs_cow(old_dentry->d_inode) != -1 ) { - printk("snap_needs_cow for ino %lu \n",old_dentry->d_inode->i_ino); + CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",old_dentry->d_inode->i_ino); snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2); snap_do_cow(old_dentry->d_inode, dir->i_ino, 0); } iops = filter_c2cdiops(cache->cache_filter); - if (!iops || - !iops->link) { - rc = -EINVAL; - goto exit; - } + + if (!iops || !iops->link) + GOTO(exit, rc = -EINVAL); + snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2); rc = iops->link(old_dentry,dir, dentry); snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 3); - exit: snap_trans_commit(cache, handle); - EXIT; - return rc; + RETURN(rc); } static int currentfs_symlink(struct inode *dir, struct dentry *dentry, @@ -343,33 +317,28 @@ static int currentfs_symlink(struct inode *dir, struct dentry *dentry, ENTRY; cache = snap_find_cache(dir->i_dev); - if ( !cache ) { - EXIT; - return -EINVAL; - } + if (!cache) + RETURN(-EINVAL); handle = snap_trans_start(cache, dir, SNAP_OP_SYMLINK); if ( snap_needs_cow(dir) != -1 ) { - printk("snap_needs_cow for ino %lu \n",dir->i_ino); + CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 1); snap_do_cow(dir, get_parent_ino(dir), 0); } iops = filter_c2cdiops(cache->cache_filter); - if (!iops || - !iops->symlink) { - rc = -EINVAL; - goto exit; - } + if (!iops || !iops->symlink) + GOTO(exit, rc = -EINVAL); + snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 2); rc = iops->symlink(dir, dentry, symname); snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3); exit: snap_trans_commit(cache, handle); - EXIT; - return rc; + RETURN(rc); } static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode, @@ -383,30 +352,26 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode, ENTRY; if (currentfs_is_under_dotsnap(dentry)) { - EXIT; - return -EPERM; + RETURN(-EPERM); } cache = snap_find_cache(dir->i_dev); if ( !cache ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } handle = snap_trans_start(cache, dir, SNAP_OP_MKNOD); if ( snap_needs_cow(dir) != -1 ) { - printk("snap_needs_cow for ino %lu \n",dir->i_ino); + CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 1); snap_do_cow(dir, get_parent_ino(dir), 0); } iops = filter_c2cdiops(cache->cache_filter); - if (!iops || - !iops->mknod) { - rc = -EINVAL; - goto exit; - } + if (!iops || !iops->mknod) + GOTO(exit, rc = -EINVAL); + snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 2); rc = iops->mknod(dir, dentry, mode, rdev); snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 3); @@ -415,8 +380,7 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode, exit: snap_trans_commit(cache, handle); - EXIT; - return rc; + RETURN(rc); } static int currentfs_rmdir(struct inode *dir, struct dentry *dentry) @@ -436,30 +400,25 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry) ENTRY; if (currentfs_is_under_dotsnap(dentry)) { - EXIT; - return -EPERM; + RETURN(-EPERM); } cache = snap_find_cache(dir->i_dev); if ( !cache ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } handle = snap_trans_start(cache, dir, SNAP_OP_RMDIR); if ( snap_needs_cow(dir) != -1 ) { - printk("snap_needs_cow for ino %lu \n",dir->i_ino); + CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 1); snap_do_cow(dir, get_parent_ino(dir), 0); } iops = filter_c2cdiops(cache->cache_filter); - if (!iops || - !iops->rmdir) { - rc = -EINVAL; - goto exit; - } + if (!iops || !iops->rmdir) + GOTO(exit, rc = -EINVAL); /* XXX : there are two cases that we can't remove this inode from disk. 1. the inode needs to be cowed. @@ -468,17 +427,12 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry) will not be deleted after rmdir, will only remove dentry */ - if( snap_needs_cow(dentry->d_inode) != -1) { + if (snap_needs_cow(dentry->d_inode) != -1 || + snap_is_redirector(dentry->d_inode)) { snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 2); - snap_do_cow (dentry->d_inode, dir->i_ino, - SNAP_DEL_PRI_WITHOUT_IND); + snap_do_cow (dir, get_parent_ino(dir), SNAP_CREATE_IND_DEL_PRI); keep_inode = 1; } - else if( snap_is_redirector(dentry->d_inode) ) { - snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 3); - snap_do_cow(dentry->d_inode, dir->i_ino, SNAP_DEL_PRI_WITH_IND); - keep_inode = 1; - } #if 0 if ( keep_inode ) { printk("set up dentry ops, before %p\n",dentry->d_op); @@ -499,8 +453,7 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry) // i_ctime = dentry->d_inode->i_ctime; i_nlink = dentry->d_inode->i_nlink; i_size = dentry->d_inode->i_size; - -} + } snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 4); rc = iops->rmdir(dir, dentry); @@ -534,7 +487,6 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry) snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 6); } } - exit: snap_trans_commit(cache, handle); EXIT; @@ -552,27 +504,24 @@ static int currentfs_unlink(struct inode *dir, struct dentry *dentry) ENTRY; if (currentfs_is_under_dotsnap(dentry)) { - EXIT; - return -EPERM; + RETURN(-EPERM); } cache = snap_find_cache(dir->i_dev); if ( !cache ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } handle = snap_trans_start(cache, dir, SNAP_OP_UNLINK); if ( snap_needs_cow(dir) != -1 ) { - printk("snap_needs_cow for ino %lu \n",dir->i_ino); + CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 1); snap_do_cow(dir, get_parent_ino(dir), 0); } iops = filter_c2cdiops(cache->cache_filter); - if (!iops || - !iops->unlink) { + if (!iops || !iops->unlink) { rc = -EINVAL; goto exit; } @@ -588,18 +537,17 @@ static int currentfs_unlink(struct inode *dir, struct dentry *dentry) if( snap_needs_cow (inode) != -1) { /* call snap_do_cow with DEL_WITHOUT_IND option */ snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 2); - snap_do_cow(inode, dir->i_ino,SNAP_DEL_PRI_WITHOUT_IND); + snap_do_cow(inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI); if( inode->i_nlink == 1 ) inode->i_nlink++; - } - else if( snap_is_redirector (inode) && inode->i_nlink == 1 ) { + } else if (snap_is_redirector (inode) && inode->i_nlink == 1) { /* call snap_do_cow with DEL_WITH_IND option * just free the blocks of inode, not really delete it */ snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 3); - snap_do_cow (inode, dir->i_ino, SNAP_DEL_PRI_WITH_IND); + snap_do_cow (inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI); inode->i_nlink++; - } + } snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 4); rc = iops->unlink(dir, dentry); @@ -607,8 +555,7 @@ static int currentfs_unlink(struct inode *dir, struct dentry *dentry) exit: snap_trans_commit(cache, handle); - EXIT; - return rc; + RETURN(rc); } static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry, @@ -623,26 +570,24 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry, if (currentfs_is_under_dotsnap(old_dentry) || currentfs_is_under_dotsnap(new_dentry)) { - EXIT; - return -EPERM; + RETURN(-EPERM); } cache = snap_find_cache(old_dir->i_dev); if ( !cache ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } handle = snap_trans_start(cache, old_dir, SNAP_OP_RENAME); /* Always cow the old dir and old dentry->d_inode */ if ( snap_needs_cow(old_dir) != -1 ) { - printk("rename: needs_cow for old_dir %lu\n",old_dir->i_ino); + CDEBUG(D_INODE, "rename: needs_cow for old_dir %lu\n",old_dir->i_ino); snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 1); snap_do_cow(old_dir, get_parent_ino(old_dir), 0); } if( snap_needs_cow (old_dentry->d_inode) != -1) { - printk("rename: needs_cow for old_dentry, ino %lu\n", + CDEBUG(D_INODE, "rename: needs_cow for old_dentry, ino %lu\n", old_dentry->d_inode->i_ino); snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 2); snap_do_cow(old_dentry->d_inode, old_dir->i_ino,0); @@ -654,10 +599,10 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry, */ if(( old_dir != new_dir) ) { if( snap_needs_cow(new_dir) !=-1 ){ - printk("rename:snap_needs_cow for new_dir %lu\n", + CDEBUG(D_INODE, "rename:snap_needs_cow for new_dir %lu\n", new_dir->i_ino); snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,3); - snap_do_cow(new_dir, get_parent_ino(new_dir),0); + snap_do_cow(new_dir, get_parent_ino(new_dir), 0); } } @@ -681,7 +626,7 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry, /* call snap_do_cow with DEL_WITHOUT_IND option */ snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4); snap_do_cow(new_dentry->d_inode, new_dir->i_ino, - SNAP_DEL_PRI_WITHOUT_IND); + SNAP_CREATE_IND_DEL_PRI); new_dentry->d_inode->i_nlink++; } else if( snap_is_redirector (new_dentry->d_inode) ) { @@ -690,14 +635,13 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry, */ snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4); snap_do_cow (new_dentry->d_inode, new_dir->i_ino, - SNAP_DEL_PRI_WITH_IND); + SNAP_CREATE_IND_DEL_PRI); new_dentry->d_inode->i_nlink++; } } iops = filter_c2cdiops(cache->cache_filter); - if (!iops || - !iops->rename) { + if (!iops || !iops->rename) { rc = -EINVAL; goto exit; } @@ -708,8 +652,7 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry, exit: snap_trans_commit(cache, handle); - EXIT; - return rc; + RETURN(rc); } static int currentfs_readdir(struct file *filp, void *dirent, @@ -721,19 +664,16 @@ static int currentfs_readdir(struct file *filp, void *dirent, ENTRY; if( !filp || !filp->f_dentry || !filp->f_dentry->d_inode ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } cache = snap_find_cache(filp->f_dentry->d_inode->i_dev); if ( !cache ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } fops = filter_c2cdfops( cache->cache_filter ); if( !fops ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } /* @@ -745,7 +685,7 @@ static int currentfs_readdir(struct file *filp, void *dirent, if( filp->f_pos == 0 ){ if( filldir(dirent, ".snap", strlen(".snap")+1, filp->f_pos, - 0xF0000000|filp->f_dentry->d_inode->i_ino) ){ + -1, 0) ){ return -EINVAL; } filp->f_pos += strlen(".snap")+1; @@ -756,7 +696,7 @@ static int currentfs_readdir(struct file *filp, void *dirent, }else rc = fops->readdir(filp, dirent, filldir); - return rc; + RETURN(rc); } struct file_operations currentfs_dir_fops = { @@ -764,14 +704,13 @@ struct file_operations currentfs_dir_fops = { }; struct inode_operations currentfs_dir_iops = { - default_file_ops: ¤tfs_dir_fops, - create: currentfs_create, - mkdir: currentfs_mkdir, - link: currentfs_link, - symlink: currentfs_symlink, - mknod: currentfs_mknod, - rmdir: currentfs_rmdir, - unlink: currentfs_unlink, - rename: currentfs_rename, - lookup: currentfs_lookup + create: currentfs_create, + mkdir: currentfs_mkdir, + link: currentfs_link, + symlink: currentfs_symlink, + mknod: currentfs_mknod, + rmdir: currentfs_rmdir, + unlink: currentfs_unlink, + rename: currentfs_rename, + lookup: currentfs_lookup }; diff --git a/lustre/snapfs/dotsnap.c b/lustre/snapfs/dotsnap.c index 19dfc1ca2dc7f02409a6ffca9bbafdc3809150be..62c026de016a8fde3d653a41937b6741ce301fa7 100644 --- a/lustre/snapfs/dotsnap.c +++ b/lustre/snapfs/dotsnap.c @@ -2,25 +2,19 @@ * dotsnap.c - support for .snap directories */ -#define EXPORT_SYMTAB +#define DEBUG_SUBSYSTEM S_SNAP - -#define __NO_VERSION__ #include <linux/module.h> -#include <asm/uaccess.h> -#include <linux/sched.h> -#include <linux/stat.h> +#include <linux/kernel.h> #include <linux/string.h> -#include <linux/locks.h> -#include <linux/quotaops.h> -#include <linux/list.h> -#include <linux/file.h> -#include <asm/bitops.h> -#include <asm/byteorder.h> +#include <linux/slab.h> +#include <linux/stat.h> +#include <linux/unistd.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> +#include "snapfs_internal.h" struct inode_operations dotsnap_inode_operations; struct file_operations dotsnap_file_operations; @@ -38,8 +32,7 @@ int currentfs_is_under_dotsnap(struct dentry *de) de = de->d_parent; } - EXIT; - return 0; + RETURN(0); } void currentfs_dotsnap_read_inode(struct snap_cache *cache, @@ -76,41 +69,39 @@ struct dentry *dotsnap_lookup(struct inode *dir, struct dentry *dentry) cache = snap_find_cache(dir->i_dev); if ( !cache ) { - printk("dotsnap_readdir: cannot find cache\n"); + CERROR("dotsnap_readdir: cannot find cache\n"); make_bad_inode(dir); - EXIT; - return ERR_PTR(-EINVAL); + RETURN(ERR_PTR(-EINVAL)); } snapops = filter_c2csnapops(cache->cache_filter); if (!snapops || !snapops->get_indirect_ino) { - EXIT; - return ERR_PTR(-EINVAL); + RETURN(ERR_PTR(-EINVAL)); } tableno = cache->cache_snap_tableno; table = &snap_tables[tableno]; if( table->tbl_count <= 1 ) - return NULL; + RETURN(NULL); - index = table->tbl_index[0]; + index = table->snap_items[0].index;; for ( i = 1 ; i < table->tbl_count ; i++ ) { - if ( (dentry->d_name.len == strlen(table->tbl_name[i])) && - (memcmp(dentry->d_name.name, table->tbl_name[i], + if ( (dentry->d_name.len == strlen(table->snap_items[i].name)) && + (memcmp(&dentry->d_name.name[0], &table->snap_items[i].name[0], dentry->d_name.len) == 0) ) { - index = table->tbl_index[i]; + index = table->snap_items[i].index; break; } } if( i >= table->tbl_count ) - return ERR_PTR(-ENOENT); + RETURN(ERR_PTR(-ENOENT)); inode = iget(dir->i_sb, dir->i_ino & (~0xF0000000)); if ( !inode ) - return ERR_PTR(-EINVAL); + RETURN(ERR_PTR(-EINVAL)); ino = snapops->get_indirect_ino(inode, index); iput(inode); @@ -120,15 +111,15 @@ struct dentry *dotsnap_lookup(struct inode *dir, struct dentry *dentry) } if ( ino == -EINVAL ) { - return ERR_PTR(-EINVAL); + RETURN(ERR_PTR(-EINVAL)); } -CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino); + CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino); inode = iget(dir->i_sb, ino); d_add(dentry, inode); dentry->d_fsdata = (void*)index; inode->i_op = dentry->d_parent->d_parent->d_inode->i_op; - return NULL; + RETURN(NULL); } @@ -145,55 +136,47 @@ static int dotsnap_readdir(struct file * filp, cache = snap_find_cache(filp->f_dentry->d_inode->i_dev); if ( !cache ) { - printk("dotsnap_readdir: cannot find cache\n"); + CDEBUG(D_INODE, "dotsnap_readdir: cannot find cache\n"); make_bad_inode(filp->f_dentry->d_inode); - EXIT; - return -EINVAL; + RETURN(-EINVAL); } snapops = filter_c2csnapops(cache->cache_filter); if (!snapops || !snapops->get_indirect_ino) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } tableno = cache->cache_snap_tableno; table = &snap_tables[tableno]; - CDEBUG(D_INODE, "\n"); for (i = filp->f_pos ; i < table->tbl_count -1 ; i++) { int index; struct inode *inode; ino_t ino; - CDEBUG(D_INODE, "%d\n",i); inode = filp->f_dentry->d_inode; - index = table->tbl_index[i+1]; + index = table->snap_items[i+1].index; ino = snapops->get_indirect_ino (filp->f_dentry->d_inode, index); - CDEBUG(D_INODE, "\n"); - if ( ino == -ENOATTR || ino == 0 ) { ino = filp->f_dentry->d_parent->d_inode->i_ino; } - - CDEBUG(D_INODE, "\n"); + if ( ino == -EINVAL ) { return -EINVAL; } - CDEBUG(D_INODE, "Listing %s\n", table->tbl_name[i+1]); - if (filldir(dirent, table->tbl_name[i+1], - strlen(table->tbl_name[i+1]), - filp->f_pos, ino) < 0){ + CDEBUG(D_INODE, "Listing %s\n", &table->snap_items[i+1].name[0]); + if (filldir(dirent, &table->snap_items[i+1].name[0], + strlen(&table->snap_items[i+1].name[0]), + filp->f_pos, ino, 0) < 0){ CDEBUG(D_INODE, "\n"); break; } filp->f_pos++; } - EXIT; - return 0; + RETURN(0); } @@ -203,6 +186,5 @@ struct file_operations dotsnap_file_operations = { struct inode_operations dotsnap_inode_operations = { - default_file_ops: &dotsnap_file_operations, lookup: dotsnap_lookup }; diff --git a/lustre/snapfs/file.c b/lustre/snapfs/file.c index 38c5652c5016e60e1e85bd891b1cd20dd229361c..c6795aa9fe490c8a321af817a5798f7f20efbe71 100644 --- a/lustre/snapfs/file.c +++ b/lustre/snapfs/file.c @@ -2,25 +2,19 @@ * file.c */ -#define EXPORT_SYMTAB +#define DEBUG_SUBSYSTEM S_SNAP - -#define __NO_VERSION__ #include <linux/module.h> -#include <asm/uaccess.h> -#include <linux/sched.h> -#include <linux/stat.h> +#include <linux/kernel.h> #include <linux/string.h> -#include <linux/locks.h> -#include <linux/quotaops.h> -#include <linux/list.h> -#include <linux/file.h> -#include <asm/bitops.h> -#include <asm/byteorder.h> +#include <linux/slab.h> +#include <linux/stat.h> +#include <linux/unistd.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> +#include "snapfs_internal.h" /* instantiate a file handle to the cache file */ static void currentfs_prepare_snapfile(struct inode *inode, @@ -29,17 +23,13 @@ static void currentfs_prepare_snapfile(struct inode *inode, struct file *cache_file, struct dentry *cache_dentry) { - ENTRY; 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_dentry = cache_dentry; cache_file->f_dentry->d_inode = cache_inode; - EXIT; - return ; } /* update the currentfs file struct after IO in cache file */ @@ -48,10 +38,7 @@ static void currentfs_restore_snapfile(struct inode *cache_inode, struct inode *clone_inode, struct file *clone_file) { - ENTRY; cache_file->f_pos = clone_file->f_pos; - EXIT; - return; } @@ -67,41 +54,34 @@ static ssize_t currentfs_write (struct file *filp, const char *buf, struct snap_table *table; int slot = 0; int index = 0; - struct inode_operations *ciops; + struct address_space_operations *aops; struct inode *cache_inode = NULL; struct snapshot_operations *snapops; ENTRY; - if (currentfs_is_under_dotsnap(filp->f_dentry)) { - EXIT; - return -ENOSPC; - } + if (currentfs_is_under_dotsnap(filp->f_dentry)) + RETURN(-ENOSPC); cache = snap_find_cache(inode->i_dev); - if ( !cache ) { - EXIT; - return -EINVAL; - } + if ( !cache ) + RETURN(-EINVAL); if ( snap_needs_cow(inode) != -1 ) { - CDEBUG(D_FILE, "snap_needs_cow for ino %lu \n",inode->i_ino); + CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino); snap_do_cow(inode, filp->f_dentry->d_parent->d_inode->i_ino, 0); } fops = filter_c2cffops(cache->cache_filter); - if (!fops || - !fops->write) { - EXIT; - return -EINVAL; - } + if (!fops || !fops->write) + RETURN(-EINVAL); if (filp->f_flags & O_APPEND) pos = inode->i_size; else { pos = *ppos; if (pos != *ppos) - return -EINVAL; + RETURN(-EINVAL); } /* @@ -115,41 +95,38 @@ static ssize_t currentfs_write (struct file *filp, const char *buf, block[1] = pos >> inode->i_sb->s_blocksize_bits; if( block[0] == block[1] ) block[1] = -1; - - ciops = filter_c2cfiops(cache->cache_filter); + + aops = filter_c2cfaops(cache->cache_filter); snapops = filter_c2csnapops(cache->cache_filter); for( i=0; i<2; i++ ){ - if( block[i]!=-1 && !ciops->bmap(inode, block[i]) ) { + if(block[i]!=-1 && aops->bmap(inode->i_mapping, block[i])) { table = &snap_tables[cache->cache_snap_tableno]; - for (slot = table->tbl_count ; slot >= 1; slot--) - { + for (slot = table->tbl_count ; slot >= 1; slot--) { + struct address_space_operations *c_aops = + cache_inode->i_mapping->a_ops; cache_inode = NULL; - index = table->tbl_index[slot]; + index = table->snap_items[slot].index; cache_inode = snap_get_indirect(inode, NULL, index); if ( !cache_inode ) continue; - if (cache_inode->i_op->bmap(cache_inode, block[i])) { - CDEBUG(D_FILE, "find cache_ino %lu\n", + if (c_aops->bmap(cache_inode->i_mapping, block[i])) { + CDEBUG(D_SNAP, "find cache_ino %lu\n", cache_inode->i_ino); if( snapops && snapops->copy_block) { - snapops->copy_block( inode, + snapops->copy_block(inode, cache_inode, block[i]); } - iput(cache_inode); break; } - iput(cache_inode); + iput(cache_inode); } } } - rc = fops->write(filp, buf, count, ppos); - - EXIT; - return rc; + RETURN(rc); } static int currentfs_readpage(struct file *file, struct page *page) @@ -161,7 +138,7 @@ static int currentfs_readpage(struct file *file, struct page *page) struct inode *cache_inode = NULL; struct file open_file; struct dentry open_dentry ; - struct inode_operations *ciops; + struct address_space_operations *c_aops; struct snap_cache *cache; long block; struct snap_table *table; @@ -173,21 +150,19 @@ static int currentfs_readpage(struct file *file, struct page *page) cache = snap_find_cache(inode->i_dev); if ( !cache ) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } + + c_aops = filter_c2cfaops(cache->cache_filter); - ciops = filter_c2cfiops(cache->cache_filter); - - block = page->offset >> inode->i_sb->s_blocksize_bits; + block = page->index >> inode->i_sb->s_blocksize_bits; /* if there is a block in the cache, return the cache readpage */ - if( inode->i_blocks && ciops->bmap(inode, block) ) { - CDEBUG(D_FILE, "block %lu in cache, ino %lu\n", + if( inode->i_blocks && c_aops->bmap(inode->i_mapping, block) ) { + CDEBUG(D_SNAP, "block %lu in cache, ino %lu\n", block, inode->i_ino); - result = ciops->readpage(file, page); - EXIT; - return result; + result = c_aops->readpage(file, page); + RETURN(result); } /* @@ -197,7 +172,7 @@ static int currentfs_readpage(struct file *file, struct page *page) if( file->f_dentry->d_fsdata ){ pri_inode = iget(inode->i_sb, (unsigned long)file->f_dentry->d_fsdata); if( !pri_inode ) - return -EINVAL; + RETURN(-EINVAL); inode = pri_inode; search_older = 1; } @@ -206,54 +181,55 @@ static int currentfs_readpage(struct file *file, struct page *page) for (slot = table->tbl_count ; slot >= 1; slot--) { + struct address_space_operations *c_aops = + cache_inode->i_mapping->a_ops; cache_inode = NULL; - index = table->tbl_index[slot]; + index = table->snap_items[slot].index; cache_inode = snap_get_indirect(inode, NULL, index); - if ( !cache_inode ) continue; + if (!cache_inode ) continue; /* we only want slots between cache_inode to the oldest one */ - if( search_older && cache_inode->i_ino == ind_ino ) + if(search_older && cache_inode->i_ino == ind_ino ) search_older = 0; - if ( !search_older && cache_inode->i_op->bmap(cache_inode, block)) { + if (!search_older && c_aops->bmap(cache_inode->i_mapping, block)) break; - } iput(cache_inode); } if( pri_inode ) iput(pri_inode); - if ( !cache_inode ) { - EXIT; - return -EINVAL; - } + if ( !cache_inode ) + RETURN(-EINVAL); currentfs_prepare_snapfile(inode, file, cache_inode, &open_file, &open_dentry); down(&cache_inode->i_sem); - if( ciops->readpage ) { - CDEBUG(D_FILE, "block %lu NOT in cache, use redirected ino %lu\n", block, cache_inode->i_ino ); - result = ciops->readpage(&open_file, page); + if( c_aops->readpage ) { + CDEBUG(D_SNAP, "block %lu NOT in cache, use redirected ino %lu\n", + block, cache_inode->i_ino ); + result = c_aops->readpage(&open_file, page); }else { - CDEBUG(D_FILE, "cache ino %lu, readpage is NULL\n", - cache_inode->i_ino); + CDEBUG(D_SNAP, "cache ino %lu, readpage is NULL\n", + cache_inode->i_ino); } - up(&cache_inode->i_sem); currentfs_restore_snapfile(inode, file, cache_inode, &open_file); iput(cache_inode); - EXIT; - return result; + RETURN(result); } - +struct address_space_operations currentfs_file_aops = { + readpage: currentfs_readpage, +}; + struct file_operations currentfs_file_fops = { - write:currentfs_write, + write: currentfs_write, }; - + struct inode_operations currentfs_file_iops = { - default_file_ops: ¤tfs_file_fops, - readpage: currentfs_readpage, + revalidate: NULL, }; + diff --git a/lustre/snapfs/filter.c b/lustre/snapfs/filter.c index c63caac5cd1d7ab9b5f4fa758e9653a0a31933b1..263029c8881ce40aeb553835d98ceb14ad93ac5a 100644 --- a/lustre/snapfs/filter.c +++ b/lustre/snapfs/filter.c @@ -1,37 +1,21 @@ /* - * - * - * Copyright (C) 2000 Stelias Computing, Inc. - * Copyright (C) 2000 Red Hat, Inc. - * Copyright (C) 2000 Mountain View Data, Inc. - * - * + * filter.c */ +#define DEBUG_SUBSYSTEM S_SNAP -#include <stdarg.h> - -#include <asm/bitops.h> -#include <asm/uaccess.h> -#include <asm/system.h> - -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/ext2_fs.h> -#include <linux/malloc.h> -#include <linux/vmalloc.h> -#include <linux/sched.h> -#include <linux/stat.h> -#include <linux/string.h> -#include <linux/locks.h> -#include <linux/blkdev.h> -#include <linux/init.h> -#define __NO_VERSION__ #include <linux/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/stat.h> +#include <linux/unistd.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> + +#include "snapfs_internal.h" -#include <linux/filter.h> -int filter_print_entry = 1; -int filter_debug = 0xfffffff; /* * The function in this file are responsible for setting up the * correct methods layered file systems like InterMezzo and SnapFS @@ -71,6 +55,11 @@ inline struct file_operations *filter_c2uffops(struct filter_fs *cache) return &cache->o_fops.filter_file_fops; } +inline struct address_space_operations *filter_c2ufaops(struct filter_fs *cache) +{ + return &cache->o_fops.filter_file_aops; +} + inline struct file_operations *filter_c2usfops(struct filter_fs *cache) { return &cache->o_fops.filter_sym_fops; @@ -97,6 +86,11 @@ inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache) return cache->o_caops.cache_file_iops; } +inline struct address_space_operations *filter_c2cfaops(struct filter_fs *cache) +{ + return cache->o_caops.cache_file_aops; +} + inline struct inode_operations *filter_c2csiops(struct filter_fs *cache) { return cache->o_caops.cache_sym_iops; @@ -131,50 +125,51 @@ inline struct snapshot_operations *filter_c2csnapops(struct filter_fs *cache) struct filter_fs *filter_get_filter_fs(const char *cache_type) { struct filter_fs *ops = NULL; - FENTRY; + ENTRY; if ( strlen(cache_type) == strlen("ext2") && memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) { ops = &filter_oppar[FILTER_FS_EXT2]; - FDEBUG(D_SUPER, "ops at %p\n", ops); + CDEBUG(D_SUPER, "ops at %p\n", ops); } if ( strlen(cache_type) == strlen("ext3") && memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) { ops = &filter_oppar[FILTER_FS_EXT3]; - FDEBUG(D_SUPER, "ops at %p\n", ops); + CDEBUG(D_SUPER, "ops at %p\n", ops); } if ( strlen(cache_type) == strlen("reiser") && memcmp(cache_type, "reiser", strlen("reiser")) == 0 ) { ops = &filter_oppar[FILTER_FS_REISER]; - FDEBUG(D_SUPER, "ops at %p\n", ops); + CDEBUG(D_SUPER, "ops at %p\n", ops); } if (ops == NULL) { - printk("prepare to die: unrecognized cache type for Filter\n"); + CERROR("prepare to die: unrecognized cache type for Filter\n"); } - FEXIT; + EXIT; return ops; } - /* * Frobnicate the InterMezzo/SnapFS operations * this establishes the link between the InterMezzo/SnapFS file system * and the underlying file system used for the cache. */ -void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_sops, struct super_operations *filter_sops) +void filter_setup_super_ops(struct filter_fs *cache, + struct super_operations *cache_sops, + struct super_operations *filter_sops) { /* Get ptr to the shared struct snapfs_ops structure. */ struct filter_ops *uops = &cache->o_fops; /* Get ptr to the shared struct cache_ops structure. */ struct cache_ops *caops = &cache->o_caops; - FENTRY; + ENTRY; if ( cache->o_flags & FILTER_DID_SUPER_OPS ) { - FEXIT; + EXIT; return; } cache->o_flags |= FILTER_DID_SUPER_OPS; @@ -182,7 +177,6 @@ void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *ca /* Set the cache superblock operations to point to the superblock operations of the underlying file system. */ caops->cache_sops = cache_sops; - /* * Copy the cache (real fs) superblock ops to the "filter" * superblock ops as defaults. Some will be changed below @@ -195,189 +189,163 @@ void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *ca } if (cache_sops->read_inode && uops->filter_sops.read_inode) { uops->filter_sops.read_inode = filter_sops->read_inode; - FDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n", + CDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n", cache, cache, uops->filter_sops.read_inode); } - if (cache_sops->notify_change && uops->filter_sops.notify_change) - uops->filter_sops.notify_change = filter_sops->notify_change; - if (cache_sops->remount_fs && uops->filter_sops.remount_fs) - uops->filter_sops.remount_fs = filter_sops->remount_fs; - FEXIT; + uops->filter_sops.clear_inode = filter_sops->clear_inode; + + EXIT; } - -void filter_setup_dir_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops) +void filter_setup_dir_ops(struct filter_fs *cache, + struct inode *inode, + struct inode_operations *filter_iops, + struct file_operations *filter_fops) { struct inode_operations *u_iops; - struct file_operations *u_fops, *c_fops, *f_fops; - FENTRY; + struct file_operations *u_fops; + + ENTRY; - if ( cache->o_flags & FILTER_DID_DIR_OPS ) { - FEXIT; + if (cache->o_flags & FILTER_DID_DIR_OPS) { + EXIT; return; } - FDEBUG(D_SUPER, "\n"); cache->o_flags |= FILTER_DID_DIR_OPS; /* steal the old ops */ - cache->o_caops.cache_dir_iops = cache_iops; - cache->o_caops.cache_dir_fops = - cache_iops->default_file_ops; - - FDEBUG(D_SUPER, "\n"); - /* abbreviate */ - u_iops = &cache->o_fops.filter_dir_iops; - - /* setup our dir iops: copy and modify */ - memcpy(u_iops, cache_iops, sizeof(*cache_iops)); - FDEBUG(D_SUPER, "\n"); + cache->o_caops.cache_dir_iops = inode->i_op; + cache->o_caops.cache_dir_fops = inode->i_fop; + + u_iops = filter_c2udiops(cache); + u_fops = filter_c2udfops(cache); + + /* setup our dir iops and fops: copy and modify */ + memcpy(u_iops, inode->i_op, sizeof(struct inode_operations)); + memcpy(u_fops, inode->i_fop, sizeof(struct file_operations)); /* methods that filter if cache filesystem has these ops */ - if ( cache_iops->lookup && filter_iops->lookup ) { - FDEBUG(D_SUPER, "\n"); - u_iops->lookup = filter_iops->lookup; - FDEBUG(D_SUPER, "lookup at %p\n", &filter_iops->lookup); + if (filter_iops) { + struct inode_operations *cache_iops = inode->i_op; + + if (cache_iops->lookup && filter_iops->lookup) + u_iops->lookup = filter_iops->lookup; + if (cache_iops->create && filter_iops->create) + u_iops->create = filter_iops->create; + if (cache_iops->link && filter_iops->link) + u_iops->link = filter_iops->link; + if (cache_iops->unlink && filter_iops->unlink) + u_iops->unlink = filter_iops->unlink; + if (cache_iops->mkdir && filter_iops->mkdir) + u_iops->mkdir = filter_iops->mkdir; + if (cache_iops->rmdir && filter_iops->rmdir) + u_iops->rmdir = filter_iops->rmdir; + if (cache_iops->symlink && filter_iops->symlink) + u_iops->symlink = filter_iops->symlink; + if (cache_iops->rename && filter_iops->rename) + u_iops->rename = filter_iops->rename; + if (cache_iops->mknod && filter_iops->mknod) + u_iops->mknod = filter_iops->mknod; + if (cache_iops->permission && filter_iops->permission) + u_iops->permission = filter_iops->permission; } - if (cache_iops->create && filter_iops->create) - u_iops->create = filter_iops->create; - FDEBUG(D_SUPER, "\n"); - if (cache_iops->link && filter_iops->link) - u_iops->link = filter_iops->link; - FDEBUG(D_SUPER, "\n"); - if (cache_iops->unlink && filter_iops->unlink) - u_iops->unlink = filter_iops->unlink; - FDEBUG(D_SUPER, "\n"); - if (cache_iops->mkdir && filter_iops->mkdir) - u_iops->mkdir = filter_iops->mkdir; - FDEBUG(D_SUPER, "\n"); - if (cache_iops->rmdir && filter_iops->rmdir) - u_iops->rmdir = filter_iops->rmdir; - FDEBUG(D_SUPER, "\n"); - if (cache_iops->symlink && filter_iops->symlink) - u_iops->symlink = filter_iops->symlink; - FDEBUG(D_SUPER, "\n"); - if (cache_iops->rename && filter_iops->rename) - u_iops->rename = filter_iops->rename; - FDEBUG(D_SUPER, "\n"); - if (cache_iops->mknod && filter_iops->mknod) - u_iops->mknod = filter_iops->mknod; - FDEBUG(D_SUPER, "\n"); - if (cache_iops->permission && filter_iops->permission) - u_iops->permission = filter_iops->permission; - /* copy dir fops */ - FDEBUG(D_SUPER, "\n"); - u_fops = &cache->o_fops.filter_dir_fops; - c_fops = cache_iops->default_file_ops; - f_fops = filter_iops->default_file_ops; - - memcpy(u_fops, c_fops, sizeof(*c_fops)); - - if( c_fops->readdir && f_fops->readdir ) - u_fops->readdir = f_fops->readdir; - - /* assign */ - FDEBUG(D_SUPER, "\n"); - filter_c2udiops(cache)->default_file_ops = filter_c2udfops(cache); - FDEBUG(D_SUPER, "\n"); - - /* unconditional filtering operations */ - if ( filter_iops->default_file_ops && - filter_iops->default_file_ops->open ) - filter_c2udfops(cache)->open = - filter_iops->default_file_ops->open; - - FEXIT; + + if (filter_fops) { + struct file_operations *cache_fops = inode->i_fop; + + if(cache_fops->readdir && filter_fops->readdir) + u_fops->readdir = filter_fops->readdir; + } + EXIT; } - -void filter_setup_file_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops) +void filter_setup_file_ops(struct filter_fs *cache, + struct inode *inode, + struct inode_operations *filter_iops, + struct file_operations *filter_fops, + struct address_space_operations *filter_aops) { struct inode_operations *u_iops; - FENTRY; + struct file_operations *u_fops; + struct address_space_operations *u_aops; + ENTRY; - if ( cache->o_flags & FILTER_DID_FILE_OPS ) { - FEXIT; + if (cache->o_flags & FILTER_DID_FILE_OPS || !inode ) { + EXIT; return; } + cache->o_flags |= FILTER_DID_FILE_OPS; /* steal the old ops */ - cache->o_caops.cache_file_iops = cache_iops; - cache->o_caops.cache_file_fops = - cache_iops->default_file_ops; + cache->o_caops.cache_file_iops = inode->i_op; + cache->o_caops.cache_file_fops = inode->i_fop; /* abbreviate */ u_iops = filter_c2ufiops(cache); - + u_fops = filter_c2uffops(cache); + u_aops = filter_c2ufaops(cache); + /* setup our dir iops: copy and modify */ - memcpy(u_iops, cache_iops, sizeof(*cache_iops)); + memcpy(u_iops, inode->i_op, sizeof(struct inode_operations)); + memcpy(u_fops, inode->i_fop, sizeof(struct file_operations)); - /* copy dir fops */ - memcpy(filter_c2uffops(cache), cache_iops->default_file_ops, - sizeof(*cache_iops->default_file_ops)); - /* assign */ - filter_c2ufiops(cache)->default_file_ops = filter_c2uffops(cache); - - /* unconditional filtering operations */ - if (filter_iops->default_file_ops && - filter_iops->default_file_ops->open ) - filter_c2uffops(cache)->open = - filter_iops->default_file_ops->open; - if (filter_iops->default_file_ops && - filter_iops->default_file_ops->release ) - filter_c2uffops(cache)->release = - filter_iops->default_file_ops->release; - if (filter_iops->default_file_ops && - filter_iops->default_file_ops->write ) - filter_c2uffops(cache)->write = - filter_iops->default_file_ops->write; - - /* set up readpage */ - if (filter_iops->readpage) - filter_c2ufiops(cache)->readpage = filter_iops->readpage; - - FEXIT; + if (inode->i_mapping && inode->i_mapping->a_ops) { + cache->o_caops.cache_file_aops = inode->i_mapping->a_ops; + memcpy(u_aops, inode->i_mapping->a_ops, + sizeof(struct address_space_operations)); + } + if (filter_iops) { + if (filter_iops->revalidate) + u_iops->revalidate = filter_iops->revalidate; + } + if (filter_fops) { + if (filter_fops->read) + u_fops->read = filter_fops->read; + } + if (filter_aops) { + if (filter_aops->readpage) + u_aops->readpage = filter_aops->readpage; + } + EXIT; } -/* XXX in 2.3 there are "fast" and "slow" symlink ops for ext2 XXX */ -void filter_setup_symlink_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops) +void filter_setup_symlink_ops(struct filter_fs *cache, + struct inode *inode, + struct inode_operations *filter_iops, + struct file_operations *filter_fops) { struct inode_operations *u_iops; - FENTRY; + struct file_operations *u_fops; + + ENTRY; - if ( cache->o_flags & FILTER_DID_SYMLINK_OPS ) { - FEXIT; + if (cache->o_flags & FILTER_DID_SYMLINK_OPS || !inode ) { + EXIT; return; } cache->o_flags |= FILTER_DID_SYMLINK_OPS; /* steal the old ops */ - cache->o_caops.cache_sym_iops = cache_iops; - cache->o_caops.cache_sym_fops = - cache_iops->default_file_ops; + cache->o_caops.cache_sym_iops = inode->i_op; + cache->o_caops.cache_sym_fops = inode->i_fop; /* abbreviate */ u_iops = filter_c2usiops(cache); + u_fops = filter_c2usfops(cache); /* setup our dir iops: copy and modify */ - memcpy(u_iops, cache_iops, sizeof(*cache_iops)); - - /* copy fops - careful for symlinks they might be NULL */ - if ( cache_iops->default_file_ops ) { - memcpy(filter_c2usfops(cache), cache_iops->default_file_ops, - sizeof(*cache_iops->default_file_ops)); + memcpy(u_iops, inode->i_op, sizeof(struct inode_operations)); + memcpy(u_fops, inode->i_fop, sizeof(struct file_operations)); + if (filter_iops) { + struct inode_operations *cache_iops = inode->i_op; + if (cache_iops->readlink && filter_iops->readlink) + u_iops->readlink = filter_iops->readlink; + if (cache_iops->follow_link && filter_iops->follow_link) + u_iops->follow_link = filter_iops->follow_link; } - - /* assign */ - filter_c2usiops(cache)->default_file_ops = filter_c2usfops(cache); - - if (cache_iops->readlink && filter_iops->readlink) - u_iops->readlink = filter_iops->readlink; - if (cache_iops->follow_link && filter_iops->follow_link) - u_iops->follow_link = filter_iops->follow_link; - - FEXIT; + EXIT; } void filter_setup_dentry_ops(struct filter_fs *cache, @@ -385,7 +353,7 @@ void filter_setup_dentry_ops(struct filter_fs *cache, struct dentry_operations *filter_dop) { if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) { - FEXIT; + EXIT; return; } cache->o_flags |= FILTER_DID_DENTRY_OPS; @@ -395,39 +363,40 @@ void filter_setup_dentry_ops(struct filter_fs *cache, filter_dop, sizeof(*filter_dop)); if (cache_dop && cache_dop != filter_dop && cache_dop->d_revalidate){ - printk("WARNING: filter overriding revalidation!\n"); + CWARN("filter overriding revalidation!\n"); } + EXIT; return; } /* snapfs : for snapshot operations */ void filter_setup_snapshot_ops (struct filter_fs *cache, struct snapshot_operations *cache_snapops) { - FENTRY; + ENTRY; if ( cache->o_flags & FILTER_DID_SNAPSHOT_OPS ) { - FEXIT; + EXIT; return; } cache->o_flags |= FILTER_DID_SNAPSHOT_OPS; cache->o_snapops = cache_snapops; - FEXIT; + EXIT; } void filter_setup_journal_ops (struct filter_fs *cache, struct journal_ops *cache_journal_ops) { - FENTRY; + ENTRY; if( cache->o_flags & FILTER_DID_JOURNAL_OPS ){ - FEXIT; + EXIT; return; } cache->o_flags |= FILTER_DID_JOURNAL_OPS; cache->o_trops = cache_journal_ops; - FEXIT; + EXIT; } diff --git a/lustre/snapfs/inode.c b/lustre/snapfs/inode.c index d6434f35402f7ea5d556f2854ec0d252dbb60cd9..9f43d0de868899107c4922250e61d52df40ad329 100644 --- a/lustre/snapfs/inode.c +++ b/lustre/snapfs/inode.c @@ -5,32 +5,17 @@ * */ -#define EXPORT_SYMTAB +#define DEBUG_SUBSYSTEM S_SNAP - -#define __NO_VERSION__ -#include <linux/module.h> -#include <asm/uaccess.h> -#include <linux/sched.h> -#include <linux/stat.h> -#include <linux/string.h> -#include <linux/locks.h> -#include <linux/quotaops.h> -#include <linux/list.h> -#include <linux/file.h> -#include <asm/bitops.h> -#include <asm/byteorder.h> - -#ifdef CONFIG_SNAPFS_EXT2 -#include <linux/ext2_fs.h> -#endif -#ifdef CONFIG_SNAPFS_EXT3 +#include <linux/kmod.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/jbd.h> #include <linux/ext3_fs.h> -#endif - -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> +#include <linux/string.h> +#include <linux/snap.h> +#include "snapfs_internal.h" extern int currentfs_remount(struct super_block * sb, int *flags, char *data); @@ -43,104 +28,100 @@ extern int currentfs_remount(struct super_block * sb, int *flags, char *data); extern void currentfs_dotsnap_read_inode(struct snap_cache *, struct inode *); +static kmem_cache_t *filter_info_cache = NULL; + +void cleanup_filter_info_cache() +{ + kmem_cache_destroy(filter_info_cache); +} + +int init_filter_info_cache() +{ + filter_info_cache = kmem_cache_create("snapfs_filter_info", + sizeof(struct filter_inode_info), + 0, 0, NULL, NULL); + if (!filter_info_cache) { + CERROR("unable to create snap_inode info cache\n"); + return -ENOMEM; + } + return 0; +} + + +void init_filter_data(struct inode *inode, + struct snapshot_operations *snapops, + int flag) +{ + struct filter_inode_info *i; + + if (inode->i_filterdata){ + return; + } + inode->i_filterdata = (struct filter_inode_info *) \ + kmem_cache_alloc(filter_info_cache, SLAB_KERNEL); + i = inode->i_filterdata; + i -> generation = snapops->get_generation(inode); + i -> flags = flag; +} /* Superblock operations. */ static void currentfs_read_inode(struct inode *inode) { struct snap_cache *cache; + struct snapshot_operations *snapops; ENTRY; if( !inode ) - { - EXIT; return; - } CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino); cache = snap_find_cache(inode->i_dev); - if ( !cache ) { - printk("currentfs_read_inode: cannot find cache\n"); + if (!cache) { + CERROR("currentfs_read_inode: cannot find cache\n"); make_bad_inode(inode); - EXIT; - return ; + return; } - if ( inode->i_ino & 0xF0000000 ) { - CDEBUG(D_INODE, "\n"); + if (inode->i_ino & 0xF0000000) { currentfs_dotsnap_read_inode(cache, inode); - EXIT; - return ; + return; } + snapops = filter_c2csnapops(cache->cache_filter); + + if (!snapops || !snapops->get_indirect) + return; - if( filter_c2csops(cache->cache_filter) ) + if(filter_c2csops(cache->cache_filter)) filter_c2csops(cache->cache_filter)->read_inode(inode); /* XXX now set the correct snap_{file,dir,sym}_iops */ - if ( S_ISDIR(inode->i_mode) ) + if (S_ISDIR(inode->i_mode)) inode->i_op = filter_c2udiops(cache->cache_filter); - else if ( S_ISREG(inode->i_mode) ) { + else if (S_ISREG(inode->i_mode)) { if ( !filter_c2cfiops(cache->cache_filter) ) { - filter_setup_file_ops(cache->cache_filter, - inode->i_op, ¤tfs_file_iops); + filter_setup_file_ops(cache->cache_filter, inode, + ¤tfs_file_iops, + ¤tfs_file_fops, + ¤tfs_file_aops); } - inode->i_op = filter_c2ufiops(cache->cache_filter); - printk("inode %lu, i_op at %p\n", inode->i_ino, inode->i_op); + CDEBUG(D_INODE, "inode %lu, i_op at %p\n", + inode->i_ino, inode->i_op); } - else if ( S_ISLNK(inode->i_mode) ) { + else if (S_ISLNK(inode->i_mode)) { if ( !filter_c2csiops(cache->cache_filter) ) { - filter_setup_symlink_ops(cache->cache_filter, - inode->i_op, ¤tfs_sym_iops); + filter_setup_symlink_ops(cache->cache_filter, inode, + ¤tfs_sym_iops, ¤tfs_sym_fops); } inode->i_op = filter_c2usiops(cache->cache_filter); - printk("inode %lu, i_op at %p\n", inode->i_ino, inode->i_op); + CDEBUG(D_INODE, "inode %lu, i_op at %p\n", + inode->i_ino, inode->i_op); } - - EXIT; + /*init filter_data struct + * FIXME flag should be set future*/ + init_filter_data(inode, snapops, 0); return; } - -static int currentfs_notify_change(struct dentry *dentry, struct iattr *iattr) -{ - struct snap_cache *cache; - int rc; - struct super_operations *sops; - - ENTRY; - - if (currentfs_is_under_dotsnap(dentry)) { - EXIT; - return -EPERM; - } - - cache = snap_find_cache(dentry->d_inode->i_dev); - if ( !cache ) { - EXIT; - return -EINVAL; - } - - /* XXX better alloc a new dentry */ - - if ( snap_needs_cow(dentry->d_inode) != -1 ) { - printk("notify_change:snap_needs_cow for ino %lu \n", - dentry->d_inode->i_ino); - snap_do_cow(dentry->d_inode, - dentry->d_parent->d_inode->i_ino, 0); - } - - sops = filter_c2csops(cache->cache_filter); - if (!sops || - !sops->notify_change) { - EXIT; - return -EINVAL; - } - rc = sops->notify_change(dentry, iattr); - - EXIT; - return rc; -} - - static void currentfs_put_super(struct super_block *sb) { @@ -150,10 +131,10 @@ static void currentfs_put_super(struct super_block *sb) CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n", (ulong) sb, (ulong) sb->u.generic_sbp); cache = snap_find_cache(sb->s_dev); - if (!cache) { - EXIT; - goto exit; - } + + if (!cache) + GOTO(exit, 0); + /* handle COMPAT_FEATUREs */ #ifdef CONFIG_SNAPFS_EXT2 else if( cache->cache_type == FILTER_FS_EXT2 ){ @@ -182,7 +163,7 @@ static void currentfs_put_super(struct super_block *sb) } if (!list_empty(&cache->cache_clone_list)) { - printk("Warning: snap_put_super: clones exist!\n"); + CWARN("snap_put_super: clones exist!\n"); } list_del(&cache->cache_chain); @@ -191,21 +172,32 @@ static void currentfs_put_super(struct super_block *sb) CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n", (ulong) sb, (ulong) sb->u.generic_sbp); exit: - CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n", - snap_kmemory, snap_vmemory); - MOD_DEC_USE_COUNT; EXIT; - return ; + return; +} +static void currentfs_clear_inode(struct inode *inode) +{ + struct snap_cache *cache; + struct super_operations *sops; + ENTRY; + cache = snap_find_cache(inode->i_dev); + if (!cache) { + CDEBUG(D_INODE, "inode has invalid dev\n"); + return; + } + + if (inode->i_filterdata) { + kmem_cache_free(filter_info_cache, inode->i_filterdata); + inode->i_filterdata = NULL; + } + + sops = filter_c2csops(cache->cache_filter); + if (sops && sops->clear_inode) + sops->clear_inode(inode); } struct super_operations currentfs_super_ops = { - currentfs_read_inode, - NULL, /* write inode */ - NULL, /* put inode */ - NULL, /* delete inode */ - currentfs_notify_change, - currentfs_put_super, - NULL, /* write super */ - NULL, - NULL, /* remount */ + read_inode: currentfs_read_inode, + put_super: currentfs_put_super, + clear_inode: currentfs_clear_inode, }; diff --git a/lustre/snapfs/journal_ext3.c b/lustre/snapfs/journal_ext3.c index 8171842e530299faf72ec753a64a01458a528d8b..7a4fa7ec578107083edf5121fe23a8ce7a535876 100644 --- a/lustre/snapfs/journal_ext3.c +++ b/lustre/snapfs/journal_ext3.c @@ -3,26 +3,21 @@ * Snapfs. (C) 2000 Peter J. Braam */ -#include <linux/types.h> +#define DEBUG_SUBSYSTEM S_SNAP + +#include <linux/module.h> #include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/malloc.h> -#include <linux/vmalloc.h> -#include <linux/stat.h> -#include <linux/errno.h> -#include <linux/locks.h> -#include <asm/segment.h> -#include <asm/uaccess.h> #include <linux/string.h> -#ifdef CONFIG_SNAPFS_EXT3 -#include <linux/ext3_jfs.h> -#endif -#include "linux/filter.h" -#include "linux/snapfs.h" -#include "linux/snapsupport.h" +#include <linux/slab.h> +#include <linux/stat.h> +#include <linux/unistd.h> +#include <linux/jbd.h> +#include <linux/ext3_jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> + +#include "snapfs_internal.h" -#ifdef CONFIG_SNAPFS_EXT3 #define EXT3_EA_TRANS_BLOCKS EXT3_DATA_TRANS_BLOCKS @@ -63,17 +58,17 @@ static void *snap_e3_trans_start(struct inode *inode, int op) jblocks = 4 * COW_CREDITS + 2 * EXT3_DATA_TRANS_BLOCKS + 2; break; default: - CDEBUG(D_JOURNAL, "invalid operation %d for journal\n", op); + CDEBUG(D_INODE, "invalid operation %d for journal\n", op); return NULL; } - CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks); - return journal_start(EXT3_JOURNAL(inode), jblocks); + CDEBUG(D_INODE, "creating journal handle (%d blocks)\n", jblocks); + return ext3_journal_start(inode, jblocks); } static void snap_e3_trans_commit(void *handle) { - journal_stop(current->j_handle); + journal_stop(handle); } struct journal_ops snap_ext3_journal_ops = { @@ -81,4 +76,3 @@ struct journal_ops snap_ext3_journal_ops = { snap_e3_trans_commit }; -#endif /* CONFIG_EXT3_FS */ diff --git a/lustre/snapfs/psdev.c b/lustre/snapfs/psdev.c index 424d32557daa66688636ffc9febfd140ac795dce..764adcc291b5946fb0ea501b684961ba60c34e50 100644 --- a/lustre/snapfs/psdev.c +++ b/lustre/snapfs/psdev.c @@ -12,46 +12,28 @@ #define EXPORT_SYMTAB -#include <linux/config.h> /* for CONFIG_PROC_FS */ + +#define DEBUG_SUBSYSTEM S_SNAP + #include <linux/module.h> -#include <linux/errno.h> #include <linux/kernel.h> -#include <linux/major.h> -/* #include <linux/kmod.h> for request_module() */ -#include <linux/sched.h> -#include <linux/lp.h> -#include <linux/malloc.h> -#include <linux/ioport.h> -#include <linux/fcntl.h> -#include <linux/delay.h> -#include <linux/skbuff.h> -#include <linux/proc_fs.h> -#include <linux/vmalloc.h> -#include <linux/fs.h> -#include <linux/poll.h> -#include <linux/init.h> -#include <linux/list.h> -#include <asm/io.h> -#include <asm/segment.h> -#include <asm/system.h> -#include <asm/poll.h> -#include <asm/uaccess.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/stat.h> +#include <linux/unistd.h> #include <linux/miscdevice.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> + +#include "snapfs_internal.h" -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> -#if 1 /* XXX - enable for debug messages */ int snap_print_entry = 1; -int snap_debug_level = ~D_INFO; -#else -int snap_print_entry = 0; int snap_debug_level = 0; -#endif int snap_inodes = 0; -long snap_memory = 0; - +long snap_kmemory = 0; +int snap_stack = 0; struct snap_control_device snap_dev; extern int snap_ioctl (struct inode * inode, struct file * filp, @@ -64,14 +46,12 @@ static int snap_psdev_open(struct inode * inode, struct file * file) ENTRY; if (!inode) - return -EINVAL; + RETURN(-EINVAL); dev = MINOR(inode->i_rdev); if (dev != SNAP_PSDEV_MINOR) - return -ENODEV; + RETURN(-ENODEV); - MOD_INC_USE_COUNT; - EXIT; - return 0; + RETURN(0); } /* called when closing /dev/device */ @@ -81,15 +61,12 @@ static int snap_psdev_release(struct inode * inode, struct file * file) ENTRY; if (!inode) - return -EINVAL; + RETURN(-EINVAL); dev = MINOR(inode->i_rdev); if (dev != SNAP_PSDEV_MINOR) - return -ENODEV; - - MOD_DEC_USE_COUNT; + RETURN(-ENODEV); - EXIT; - return 0; + RETURN(0); } /* XXX need ioctls here to do snap_delete and snap_restore, snap_backup */ @@ -97,19 +74,9 @@ static int snap_psdev_release(struct inode * inode, struct file * file) /* declare character device */ static struct file_operations snapcontrol_fops = { - NULL, /* llseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* presto_psdev_readdir */ - NULL, /* poll */ - snap_ioctl, /* ioctl */ - NULL, /* presto_psdev_mmap */ - snap_psdev_open, /* open */ - NULL, - snap_psdev_release, /* release */ - NULL, /* fsync */ - NULL, /* fasync */ - NULL /* lock */ + ioctl: snap_ioctl, /* ioctl */ + open: snap_psdev_open, /* open */ + release: snap_psdev_release, /* release */ }; @@ -117,14 +84,14 @@ static struct file_operations snapcontrol_fops = { #define SNAPFS_MINOR 240 static struct miscdevice snapcontrol_dev = { - SNAPFS_MINOR, - "snapcontrol", - &snapcontrol_fops + minor: SNAPFS_MINOR, + name: "snapcontrol", + fops: &snapcontrol_fops }; int init_snap_psdev(void) { - printk(KERN_INFO "SNAP psdev driver v0.01, braam@mountainviewdata.com\n"); + printk(KERN_INFO "SNAP psdev driver v0.01, braam@clusterfs.com\n"); misc_register( &snapcontrol_dev ); @@ -138,7 +105,6 @@ void snap_cleanup_psdev(void) EXIT; } -#ifdef MODULE MODULE_AUTHOR("Peter J. Braam <braam@cs.cmu.edu>"); MODULE_DESCRIPTION("Snapfs file system filters v0.01"); @@ -147,7 +113,7 @@ extern int cleanup_snapfs(void); extern int init_clonefs(void); extern int init_snap_sysctl(void); -int init_module(void) +static int __init snapfs_init(void) { int err; if ( (err = init_snap_psdev()) ) { @@ -164,17 +130,18 @@ int init_module(void) printk("Error initializing snapfs proc sys, %d\n", err); return -EINVAL; } - - + return 0; } -void cleanup_module(void) +static void __exit snapfs_cleanup(void) { cleanup_snapfs(); snap_cleanup_psdev(); } -#endif +module_init(snapfs_init); +module_exit(snapfs_cleanup); + diff --git a/lustre/snapfs/snap.c b/lustre/snapfs/snap.c index 463e0faae729bd2b004abd8e928eb1ae28d901d5..a5032a6ff8584db6909d00791aba8696cad37051 100644 --- a/lustre/snapfs/snap.c +++ b/lustre/snapfs/snap.c @@ -6,25 +6,15 @@ * */ -#define EXPORT_SYMTAB +#define DEBUG_SUBSYSTEM S_SNAP - -#define __NO_VERSION__ -#include <linux/module.h> -#include <asm/uaccess.h> -#include <linux/sched.h> -#include <linux/stat.h> +#include <linux/kmod.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/slab.h> #include <linux/string.h> -#include <linux/locks.h> -#include <linux/quotaops.h> -#include <linux/list.h> -#include <linux/file.h> -#include <asm/bitops.h> -#include <asm/byteorder.h> - -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> +#include <linux/snap.h> +#include "snapfs_internal.h" /* * Return true if the inode is a redirector inode. @@ -36,12 +26,10 @@ int snap_is_redirector(struct inode *cache_inode) cache = snap_find_cache(cache_inode->i_dev); if (!cache) { - EXIT; return 0; } snapops = filter_c2csnapops(cache->cache_filter); if (!snapops || !snapops->is_redirector) { - EXIT; return 0; } @@ -68,13 +56,11 @@ struct inode *snap_redirect(struct inode *cache_inode, cache = snap_find_cache(cache_inode->i_dev); if (!cache) { - EXIT; - return NULL; + RETURN(NULL); } snapops = filter_c2csnapops(cache->cache_filter); if (!snapops || !snapops->get_indirect) { - EXIT; - return NULL; + RETURN(NULL); } CDEBUG(D_SNAP, "cache ino %ld\n", cache_inode->i_ino); @@ -87,22 +73,19 @@ struct inode *snap_redirect(struct inode *cache_inode, clone_info->clone_index); /* if not found, get the FIRST index after this and before NOW */ /* XXX fix this later, now use tbl_count, not NOW */ - if(!redirected) { + if (!redirected) { + int index; clone_slot = snap_index2slot(table, clone_info->clone_index); - for(slot = table->tbl_count; slot >= clone_slot; slot --) - { - my_table[slot-clone_slot+1] = table->tbl_index[slot]; + for (slot = table->tbl_count; slot >= clone_slot; slot --) { + my_table[slot-clone_slot+1] = table->snap_items[slot].index; } - redirected = snapops->get_indirect - (cache_inode, my_table, table->tbl_count - clone_slot + 1); + index = table->tbl_count - clone_slot + 1; + redirected = snapops->get_indirect(cache_inode, my_table, index); } - /* old version - redirected = snapops->get_indirect - (cache_inode, table->tbl_index, - snap_index2slot(table, clone_info->clone_index)); - */ - if(redirected) CDEBUG(D_SNAP,"redirected ino %ld\n",redirected->i_ino); - EXIT; + + if (redirected) + CDEBUG(D_SNAP,"redirected ino %ld\n",redirected->i_ino); + return redirected; } @@ -122,23 +105,19 @@ int snap_do_cow(struct inode *inode, ino_t parent_ino, int del) cache = snap_find_cache(inode->i_dev); if (!cache) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } snapops = filter_c2csnapops(cache->cache_filter); if (!snapops || !snapops->create_indirect) { - EXIT; - return -EINVAL; + RETURN(-EINVAL); } + snap_last(cache, &snap); - ind = snapops->create_indirect(inode, parent_ino, snap.index, del); - EXIT; - if(ind) { - iput(ind); - return 0; - } - else - return -EINVAL; + ind = snapops->create_indirect(inode, snap.index, 0, parent_ino, del); + if(!ind) + RETURN(-EINVAL); + iput(ind); + RETURN(0); } int snap_iterate(struct super_block *sb, @@ -153,16 +132,13 @@ int snap_iterate(struct super_block *sb, cache = snap_find_cache(inode->i_dev); if (!cache) { - EXIT; - return 0; + RETURN(0); } snapops = filter_c2csnapops(cache->cache_filter); if (!snapops || !snapops->iterate) { - EXIT; - return 0; + RETURN(0); } - EXIT; return snapops->iterate(sb, repeat, start, priv, flag); } @@ -173,17 +149,12 @@ int snap_destroy_indirect(struct inode *pri, int index, struct inode *next_ind ) ENTRY; cache = snap_find_cache(pri->i_dev); - if (!cache) { - EXIT; - return 0; - } + if (!cache) + RETURN(0); snapops = filter_c2csnapops(cache->cache_filter); - if (!snapops || !snapops->destroy_indirect) { - EXIT; - return 0; - } + if (!snapops || !snapops->destroy_indirect) + RETURN(0); - EXIT; return snapops->destroy_indirect(pri, index, next_ind); } @@ -195,17 +166,13 @@ int snap_restore_indirect(struct inode *pri, int index ) ENTRY; cache = snap_find_cache(pri->i_dev); - if (!cache) { - EXIT; - return 0; - } + if (!cache) + RETURN(0); + snapops = filter_c2csnapops(cache->cache_filter); - if (!snapops || !snapops->restore_indirect) { - EXIT; - return 0; - } + if (!snapops || !snapops->restore_indirect) + RETURN(0); - EXIT; return snapops->restore_indirect(pri, index); } @@ -217,42 +184,16 @@ struct inode *snap_get_indirect(struct inode *pri, int *table, int slot) ENTRY; cache = snap_find_cache(pri->i_dev); - if (!cache) { - EXIT; - return NULL; - } + if (!cache) + RETURN(NULL); + snapops = filter_c2csnapops(cache->cache_filter); - if (!snapops || !snapops->get_indirect) { - EXIT; - return NULL; - } + if (!snapops || !snapops->get_indirect) + RETURN(NULL); - EXIT; return snapops->get_indirect(pri, table, slot); } -int snap_migrate_data(struct inode *dst, struct inode *src) -{ - struct snap_cache *cache; - struct snapshot_operations *snapops; - - ENTRY; - - cache = snap_find_cache(src->i_dev); - if (!cache) { - EXIT; - return 0; - } - snapops = filter_c2csnapops(cache->cache_filter); - if (!snapops || !snapops->migrate_data) { - EXIT; - return 0; - } - - EXIT; - return snapops->migrate_data(dst, src); -} - int snap_set_indirect(struct inode *pri, ino_t ind_ino, int index, ino_t parent_ino) { struct snap_cache *cache; @@ -261,15 +202,12 @@ int snap_set_indirect(struct inode *pri, ino_t ind_ino, int index, ino_t parent_ ENTRY; cache = snap_find_cache(pri->i_dev); - if (!cache) { - EXIT; - return -EINVAL; - } - snapops = filter_c2csnapops(cache->cache_filter); - if (!snapops || !snapops->set_indirect) { - EXIT; - return -EINVAL; - } + if (!cache) + RETURN(-EINVAL); + + snapops = filter_c2csnapops(cache->cache_filter); + if (!snapops || !snapops->set_indirect) + RETURN(-EINVAL); EXIT; return snapops->set_indirect(pri, ind_ino, index, parent_ino); diff --git a/lustre/snapfs/snaptable.c b/lustre/snapfs/snaptable.c index 058164b3491a187f306d02571c478f1b7ebf05a5..ac5b712fd2488034ce4664bc4aa9796e5c183df2 100644 --- a/lustre/snapfs/snaptable.c +++ b/lustre/snapfs/snaptable.c @@ -6,28 +6,18 @@ * */ -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/malloc.h> -#include <linux/locks.h> -#include <linux/errno.h> -#include <linux/swap.h> -#include <linux/smp_lock.h> -#include <linux/vmalloc.h> -#include <linux/blkdev.h> -#include <linux/sysrq.h> -#include <linux/file.h> -#include <linux/init.h> -#include <linux/quotaops.h> +#define DEBUG_SUBSYSTEM S_SNAP +#include <linux/module.h> +#include <linux/kmod.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/snap.h> #include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/bitops.h> -#include <asm/mmu_context.h> +#include "snapfs_internal.h" -#include <linux/filter.h> -#include <linux/snapsupport.h> -#include <linux/snapfs.h> struct snap_table snap_tables[SNAP_MAX_TABLES]; @@ -52,7 +42,7 @@ int snap_index2slot(struct snap_table *snap_table, int snap_index) int slot; for ( slot=0 ; slot<snap_table->tbl_count ; slot++ ) - if ( snap_table->tbl_index[slot] == snap_index ) + if ( snap_table->snap_items[slot].index == snap_index ) return slot; return -1; } @@ -63,7 +53,8 @@ int snap_index2slot(struct snap_table *snap_table, int snap_index) - 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 snap_cache *info, struct snap *snap) { int i ; @@ -73,9 +64,10 @@ void snap_last(struct snap_cache *info, struct snap *snap) ENTRY; if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) { - printk(__FUNCTION__ ": invalid table no %d\n", tableno); + CERROR("invalid table no %d\n", tableno); snap->index = -1; } + table = &snap_tables[tableno]; /* start at the highest index in the superblock @@ -83,16 +75,11 @@ void snap_last(struct snap_cache *info, struct snap *snap) i = table->tbl_count - 1; /* NOTE: i>0 is an unnecessary check */ - while ( table->tbl_times[i] > now && i > 0) { - CDEBUG(D_SNAP, "time: %ld, i: %d\n", table->tbl_times[i], i); - i--; - } - - snap->index = table->tbl_index[i]; - snap->time = table->tbl_times[i]; + snap->index = table->snap_items[i].index; + snap->time = table->snap_items[i].time; + snap->gen = table->snap_items[i].gen; CDEBUG(D_SNAP, "index: %d, time[i]: %ld, now: %ld\n", snap->index, snap->time, now); - EXIT; return; } @@ -104,117 +91,30 @@ int snap_needs_cow(struct inode *inode) { struct snap snap; struct snap_cache *cache; + struct filter_inode_info *filter_info; int index = -1; ENTRY; cache = snap_find_cache(inode->i_dev); if ( !cache ) { - EXIT; - return -1; + RETURN(index); } - + filter_info = (struct filter_inode_info *) inode->i_filterdata; /* here we find the time of the last snap to compare with */ - snap_last(cache, &snap); + snap_last(cache, &snap); /* decision .... if the snapshot is more recent than the object, * then any change to the object should cause a COW. */ - if (inode->i_mtime <= snap.time && inode->i_ctime <= snap.time) { + if (filter_info && filter_info->generation < snap.gen ) { index = snap.index; } - printk("snap_needs_cow, ino %lu , get index %d\n",inode->i_ino, index); - EXIT; - return index; -} /* snap_needs_cow */ + CDEBUG(D_SNAP, "snap_needs_cow, ino %lu , get index %d\n", + inode->i_ino, index); -#if 0 -int snap_obd2snap(struct snap_clone_info *info, struct snap *snap) -{ - struct snap_table *table; - int tableno = info->clone_cache->cache_snap_tableno; - int index = info->clone_index; - int slot; - - ENTRY; - if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) { - printk(__FUNCTION__ ": invalid table no %d\n", tableno); - snap->index = -1; - } - table = &snap_tables[tableno]; - slot = snap_index2slot(table, index); - - snap->index = index; - snap->time = table->tbl_times[slot]; - EXIT; - return slot; -} -#endif - -/* at what index is the current snapshot located */ -int snap_current(struct snap_cache *cache) -{ - int tableno = cache->cache_snap_tableno; - - return snap_tables[tableno].tbl_index[0]; -} - -int snap_is_used(int table_no, int snap_index) - -{ - /* ENTRY; */ - if ( snap_index < 0 || snap_index >= SNAP_MAX ) { - printk(__FUNCTION__ ": invalid snapno %d,table %d\n", - snap_index, table_no); - EXIT; - return -1; - } - if ( table_no < 0 || table_no > SNAP_MAX_TABLES ) { - printk(__FUNCTION__ ": invalid snapno %d,table %d\n", - snap_index, table_no); - EXIT; - return -1; - } - - /* EXIT; */ - return snap_tables[table_no].tbl_used & (1<<snap_index); -} - -void snap_use(int table_no, int snap_index) -{ - if ( snap_index < 0 || snap_index >= SNAP_MAX ) { - printk(__FUNCTION__ ": invalid snapno %d,table %d\n", - snap_index, table_no); - return; - } - if ( table_no < 0 || table_no > SNAP_MAX_TABLES ) { - printk(__FUNCTION__ ": invalid snapno %d,table %d\n", - snap_index, table_no); - return; - } - if ( snap_index2slot(&snap_tables[table_no], snap_index) < 0 ) - return; - - snap_tables[table_no].tbl_used |= (1<<snap_index); -} - -void snap_unuse(int table_no, int snap_index) -{ - if ( snap_index < 0 || snap_index >= SNAP_MAX ) { - printk(__FUNCTION__ ": invalid snapno %d,table %d\n", - snap_index, table_no); - return; - } - if ( table_no < 0 || table_no > SNAP_MAX_TABLES ) { - printk(__FUNCTION__ ": invalid snapno %d,table %d\n", - snap_index, table_no); - return; - } - if ( snap_index2slot(&snap_tables[table_no], snap_index) < 0 ) - return; - - snap_tables[table_no].tbl_used &= ~(1<<snap_index); -} + RETURN(index); +} /* snap_needs_cow */ static int nprint_buf(char *buf, int buflen, char *fmt, ...) { @@ -247,20 +147,18 @@ int snap_print_table(struct snap_table_data *data, char *buf, int *buflen) int nprint = 0; if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) { - printk(__FUNCTION__ ": invalid table number %d\n", tableno); - EXIT; - return -EINVAL; + CERROR("invalid table number %d\n", tableno); + RETURN(-EINVAL); } table = &snap_tables[tableno]; printk("------- snap table %d\n", tableno); printk(" -- snap count %d\n", table->tbl_count); - printk(" -- snap used 0x%x\n", table->tbl_used); for ( i = 0 ; i < SNAP_MAX ; i++ ) { printk(" -- slot %d, idx %d, time %ld, name %s\n", - i, table->tbl_index[i], table->tbl_times[i], - table->tbl_name[i]); + i, table->snap_items[i].index, table->snap_items[i].time, + &table->snap_items[i].name[0]); } buf_ptr = buf; @@ -272,15 +170,14 @@ int snap_print_table(struct snap_table_data *data, char *buf, int *buflen) nleft -= nprint; if( nleft > 0 ) buf_ptr += nprint; else goto exit; - nprint = nprint_buf(buf_ptr, nleft, " -- snap used 0x%x\n", table->tbl_used); - nleft -= nprint; + if( nleft > 0 ) buf_ptr += nprint; else goto exit; for ( i = 0 ; i < SNAP_MAX ; i++ ) { nprint = nprint_buf( buf_ptr, nleft, " -- slot %d, idx %d, time %ld, name %s\n", - i, table->tbl_index[i], table->tbl_times[i], - table->tbl_name[i]); + i, table->snap_items[i].index, table->snap_items[i].time, + &table->snap_items[i].name[0]); nleft -= nprint; if( nleft > 0 ) buf_ptr += nprint; else goto exit; @@ -291,153 +188,301 @@ exit: return 0; } - -int snap_install_table(int len, struct snap_table_data *data) +static int inline get_index_of_item(struct snap_table *table) { + int count = table->tbl_count; int i, j; - int tableno = data->tblcmd_no; -// int found_current; - struct snap_table *table; + for (i = 0; i < SNAP_MAX; i ++) { + for (j = 1; j < count; j++) { + if (table->snap_items[j].index == i) + break; + } + if (j >= count) + return i; + } + return -EINVAL; +} +/* This function will write one item(a snapshot) to snaptable + * and will also write to disk. + */ +int snaptable_add_item(struct snap_table_data *data) +{ + struct snap_table *table; + struct snap_disk_table *disk_snap_table; + struct snapshot_operations *snapops; + struct snap_cache *cache; + int tableno , index, i, count, rc; + + if (!(cache = snap_find_cache((kdev_t)data->dev))) + RETURN(-ENODEV); + + snapops = filter_c2csnapops(cache->cache_filter); + if (!snapops || !snapops->set_meta_attr) + RETURN(-EINVAL); + + tableno = data->tblcmd_no; if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) { - printk(__FUNCTION__ ": invalid table number %d\n", tableno); - EXIT; - return -EINVAL; + CERROR("invalid table number %d\n", tableno); + RETURN(-EINVAL); } table = &snap_tables[tableno]; + count = table->tbl_count; + + /* XXX Is down this sema necessary*/ + down_interruptible(&table->tbl_sema); + + /*add item in snap_table*/ + table->snap_items[count+1].gen = table->generation; + table->snap_items[count+1].time = CURRENT_TIME; + /* find table index */ + index = get_index_of_item(table); + if (index < 0) + RETURN(-EINVAL); + + table->snap_items[count+1].index = index; + table->snap_items[count+1].flags = 0; + memcpy(&table->snap_items[count + 1].name[0], + &data->tblcmd_snaps[0].name[0], SNAP_MAX_NAMELEN); + /* we will write the whole snap_table to disk */ + SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table)); + if (!disk_snap_table) + RETURN(-ENOMEM); + disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC); + disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count); + disk_snap_table->generation = cpu_to_le32((__u32)table->generation); + memset(&disk_snap_table->snap_items[0], 0, + SNAP_MAX * sizeof(struct snap_disk)); + for (i = 1; i <= count; i++) { + struct snap *item = &table->snap_items[i]; + disk_snap_table->snap_items[i].time = cpu_to_le64((__u64)item->time); + disk_snap_table->snap_items[i].gen = cpu_to_le32((__u32)item->gen); + disk_snap_table->snap_items[i].flags = cpu_to_le32((__u32)item->flags); + disk_snap_table->snap_items[i].index = cpu_to_le32((__u32)item->index); + memcpy(&disk_snap_table->snap_items[i].name , item->name, SNAP_MAX_NAMELEN); + } + rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR, + (char*)disk_snap_table, sizeof(struct snap_disk_table)); + + SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table)); + table->tbl_count++; + table->generation++; + + up(&table->tbl_sema); + + return 0; +} - /* for each index that is used by the current table - we need to make sure that the new table we are about - to put in contains that index too - */ - for ( i = 0; i < SNAP_MAX ; i++ ) { - int foundit; - int err; - - if ((err = snap_is_used(tableno, i)) < 0 ) { - printk(__FUNCTION__ ": table %d not used\n", tableno); - EXIT; - return -EINVAL; - } else if (err == 0) { - continue; - } +static int delete_inode(struct inode *primary, void *param) +{ + struct snap_iterdata * data; + int tableno = 0; + int index = 0; + int rc = 0; - foundit = 0; - for (j = 0 ; j<= data->tblcmd_count ; j++) { - if ( i == data->tblcmd_snaps[j].index ) { - foundit = 1; - break; - } - } - if ( !foundit ) { - printk(__FUNCTION__ ": index %d not in table %d\n", - i, tableno); - return -EINVAL; - } - } + struct inode *redirect; + ino_t old_ind = 0; + struct snap_table *table; + int slot; + int delete_slot; + int this_index; + struct inode *next_ind = NULL; + int my_table[SNAP_MAX]; - /* we must have: - - valid indices - - a current snapshot in the table - - increasing snapshot times - */ -// found_current = 0; - CDEBUG(D_SNAP, "snaplist: tblcmd_count %d\n", data->tblcmd_count); - for (i = 0 ; i < data->tblcmd_count ; i++) { - - if ( (data->tblcmd_snaps[i].index < 0) || - (data->tblcmd_snaps[i].index >= SNAP_MAX) ) { - printk(__FUNCTION__ ": snap_index out of range!\n"); - return -EINVAL; - } + if(!primary) return 0; - if (i>0 && data->tblcmd_snaps[i].time <= - data->tblcmd_snaps[i-1].time) { - printk(__FUNCTION__ ": times not increasing\n"); - return -EINVAL; - } + data = (struct snap_iterdata*) param; -// if ( 0 == data->tblcmd_snaps[i].time ) { -// found_current = 1; -// break; -// } + if(data) { + index = data->index; + tableno = data->tableno; } -// if ( !found_current ) { -// printk(__FUNCTION__ "no current snapshot in table\n"); -// return -EINVAL; -// } - - /* ready to go: over write the table */ -/* - for (i = 0 ; i < data->tblcmd_count ; i++) { - - table->tbl_times[i] = data->tblcmd_snaps[i].time; - table->tbl_index[i] = data->tblcmd_snaps[i].index; - memcpy(table->tbl_name[i], data->tblcmd_snaps[i].name, - SNAP_MAX_NAMELEN); - table->tbl_name[i][SNAP_MAX_NAMELEN - 1] = '\0'; - CDEBUG(D_SNAP, "snaplist: i %d, time %ld, idx %d, name %s\n", - i, table->tbl_times[i], table->tbl_index[i], - table->tbl_name[i]); - } -*/ - /* below : new, we don't need current snapshot for data - * current snapshot always has slot 0, index 0, name "current" - */ - table->tbl_times[0] = 0; - table->tbl_index[0] = 0; - strcpy(table->tbl_name[0], "current"); + CDEBUG(D_INODE, "delete_inode ino %lu, index %d\n", primary->i_ino, index); - i=0; - CDEBUG(D_SNAP, "snaplist: i %d, time %ld, idx %d, name %s\n", - i, table->tbl_times[i], table->tbl_index[i], - table->tbl_name[i]); + table = &snap_tables[tableno]; - for (i = 0 ; i < data->tblcmd_count ; i++) { + redirect = snap_get_indirect(primary, NULL, index); - table->tbl_times[i+1] = data->tblcmd_snaps[i].time; - table->tbl_index[i+1] = data->tblcmd_snaps[i].index; - memcpy(table->tbl_name[i+1], data->tblcmd_snaps[i].name, - SNAP_MAX_NAMELEN); - table->tbl_name[i+1][SNAP_MAX_NAMELEN - 1] = '\0'; + if(!redirect) + return 0; - CDEBUG(D_SNAP, "snaplist: i %d, time %ld, idx %d, name %s\n", - i+1, table->tbl_times[i+1], table->tbl_index[i+1], - table->tbl_name[i+1]); + old_ind = redirect->i_ino; + iput(redirect); + slot = snap_index2slot(table, index) - 1; + if( slot > 0 ) { + this_index = table->snap_items[slot].index; + redirect = snap_get_indirect(primary, NULL, this_index); + if(redirect) + iput(redirect); + else { + snap_set_indirect(primary, old_ind, this_index, 0); + snap_set_indirect(primary, 0, index, 0); + return 0; + } + } + + /* get the FIRST index after this and before NOW */ + /* used for destroy_indirect and block level cow */ + /* XXX fix this later, now use tbl_count, not NOW */ + delete_slot = snap_index2slot(table, index); + for(slot = table->tbl_count; slot > delete_slot; slot --) + { + my_table[slot - delete_slot] = table->snap_items[slot].index; + } + next_ind = snap_get_indirect + (primary, my_table, table->tbl_count - delete_slot ); + if( next_ind && (next_ind->i_ino == primary->i_ino) ) { + iput(next_ind); + next_ind = NULL; } - for ( i = data->tblcmd_count + 1 ; i < SNAP_MAX ; i++ ) { - table->tbl_times[i] = 0; - table->tbl_index[i] = 0; - memset(table->tbl_name[i], 0, SNAP_MAX_NAMELEN); + if( next_ind && (next_ind->i_ino == old_ind) ) { + iput(next_ind); + next_ind = NULL; } - /* set the table count */ -// table->tbl_count = data->tblcmd_count; - table->tbl_count = data->tblcmd_count + 1; + rc = snap_destroy_indirect(primary, index, next_ind); + + if(next_ind) iput(next_ind); + + if(rc != 0) + CERROR("snap_destroy_indirect(ino %lu,index %d),ret %d\n", + primary->i_ino, index, rc); return 0; } +static int snap_delete(struct super_block *sb, struct snap_iterdata *data) +{ + CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n", + data->dev, data->tableno, data->index, data->time ); -int snap_table_attach(int tableno, int snap_index) + snap_iterate(sb, &delete_inode, NULL, data, SNAP_ITERATE_COWED_INODE); + + return 0; +} + +/* This function will delete one item(a snapshot) in the snaptable + * and will also delete the item in the disk. + */ +int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data) { - struct snap_table *table; + struct snap_table *table; + struct snap_disk_table *disk_snap_table; + struct snapshot_operations *snapops; + struct snap_cache *cache; + int tableno = data->tableno, index, i, slot, rc, count; + + if (!(cache = snap_find_cache((kdev_t)data->dev))) + RETURN(-ENODEV); + + snapops = filter_c2csnapops(cache->cache_filter); + if (!snapops || !snapops->set_meta_attr) + RETURN(-EINVAL); + + if (tableno < 0 || tableno > SNAP_MAX_TABLES) { + CERROR("invalid table number %d\n", tableno); + RETURN(-EINVAL); + } + /*first delete the snapshot + * FIXME if snap delete error, how to handle this error*/ + rc = snap_delete(sb, data); + if (rc) + RETURN(-EINVAL); + /*delete item in snaptable */ + table = &snap_tables[tableno]; + index = data->index; - if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) { - printk(__FUNCTION__ ": invalid table number %d\n", tableno); - EXIT; - return -EINVAL; + slot = snap_index2slot(table, index); + if (slot < 0) + RETURN(-EINVAL); + + down_interruptible(&table->tbl_sema); + while(slot < table->tbl_count) { + struct snap *item = &table->snap_items[slot]; + item->time = table->snap_items[slot + 1].time; + item->flags = table->snap_items[slot + 1].flags; + item->gen = table->snap_items[slot + 1].gen; + item->index = table->snap_items[slot + 1].index; + memcpy(&item->name[0], &table->snap_items[slot + 1].name[0], + SNAP_MAX_NAMELEN); } - table = &snap_tables[tableno]; + + table->tbl_count --; - if ( snap_index2slot(table, snap_index) < 0 ) { - printk(__FUNCTION__ ": snap index %d not present in table %d\n", - snap_index, tableno); - return -EINVAL; + SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table)); + + if (!disk_snap_table) + RETURN(-ENOMEM); + /* we will delete the item snap_table to disk */ + + disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC); + disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count); + disk_snap_table->generation = cpu_to_le32((__u32)table->generation); + memset(&disk_snap_table->snap_items[0], 0, + SNAP_MAX * sizeof(struct snap_disk)); + + count = table->tbl_count; + + for (i = 1; i <= count; i++) { + struct snap *item = &table->snap_items[i]; + disk_snap_table->snap_items[i].time = cpu_to_le64((__u64)item->time); + disk_snap_table->snap_items[i].gen = cpu_to_le32((__u32)item->gen); + disk_snap_table->snap_items[i].flags = cpu_to_le32((__u32)item->flags); + disk_snap_table->snap_items[i].index = cpu_to_le32((__u32)item->index); + memcpy(&disk_snap_table->snap_items[i].name , item->name, SNAP_MAX_NAMELEN); + } + rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR, + (char*)disk_snap_table, sizeof(struct snap_disk_table)); + + SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table)); + + up(&table->tbl_sema); + + RETURN(0); +} + +int snapfs_read_snaptable(struct snap_cache *cache, int tableno) +{ + struct snap_table *table; + struct snap_disk_table *disk_snap_table; + struct snapshot_operations *snapops; + int i, rc; + int size = 0; + + + snapops = filter_c2csnapops(cache->cache_filter); + if (!snapops || !snapops->get_meta_attr) + RETURN(-EINVAL); + + SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table)); + + size = sizeof(struct snap_disk_table); + + rc = snapops->get_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR, + (char*)disk_snap_table, &size); + if (rc < 0) { + SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table)); + RETURN(rc); } + table = &snap_tables[tableno]; - snap_use(tableno, snap_index); + if (le32_to_cpu(disk_snap_table->magic) != DISK_SNAP_TABLE_MAGIC) { + CERROR("On disk snaptable is not right \n"); + RETURN(rc); + } + table->generation = le32_to_cpu(disk_snap_table->generation); + table->tbl_count = le32_to_cpu(disk_snap_table->count); + for ( i = 0; i < disk_snap_table->count; i++) { + struct snap *item = &table->snap_items[i + 1]; + item->time = le64_to_cpu(disk_snap_table->snap_items[i].time); + item->gen = le32_to_cpu(disk_snap_table->snap_items[i].gen); + item->flags = le32_to_cpu(disk_snap_table->snap_items[i].flags); + item->index = le32_to_cpu(disk_snap_table->snap_items[i].index); + memcpy(&item->name[0], &disk_snap_table->snap_items[i].name[0], + SNAP_MAX_NAMELEN); + } + SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table)); return 0; } @@ -450,16 +495,16 @@ static int getdata(int len, void **data) return 0; } - SNAP_ALLOC(tmp, void *, len); + SNAP_ALLOC(tmp, len); if ( !tmp ) return -ENOMEM; - CDEBUG(D_MALLOC, "snap_alloc:len %d, add %p\n", len, tmp); + CDEBUG(D_SNAP, "snap_alloc:len %d, add %p\n", len, tmp); memset(tmp, 0, len); if ( copy_from_user(tmp, *data, len)) { SNAP_FREE(tmp, len); - CDEBUG(D_MALLOC, "snap_free:len %d, add %p\n", len, tmp); + CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", len, tmp); return -EFAULT; } *data = tmp; @@ -469,7 +514,7 @@ static int getdata(int len, void **data) static void freedata(void *data, int len) { SNAP_FREE(data, len); - CDEBUG(D_MALLOC, "snap_free:len %d, add %p\n", len, data); + CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", len, data); } static int get_next_inode(struct inode *pri, void *ino) @@ -527,7 +572,7 @@ static int snap_get_next_inode(struct snap_ino_list_data *data, ino_t *found_ino *parent_ino = 0; inode = iget (cache->cache_sb, *found_ino); if (list_empty(&inode->i_dentry)) { - printk("No dentry for ino %lu, Error(XXX)! \n", inode->i_ino); + CERROR("No dentry for ino %lu, Error(XXX)! \n", inode->i_ino); iput(inode); return 0; } @@ -544,35 +589,6 @@ static int snap_get_next_inode(struct snap_ino_list_data *data, ino_t *found_ino return 0; } -/* -static int snap_get_inode_info(struct snap_ino_list_data *data, int index) -{ - kdev_t dev = data->dev; - ino_t pri = data->ino; - int index = data->index; - - struct snap_cache *cache; - - struct inode *pri; - struct inode *ind; - ino_t ind_ino = 0; - - ENTRY; - - cache = snap_find_cache(dev); - if ( !cache ) { - EXIT; - return -EINVAL; - } - pri = iget(cache->cache->sb, pri_ino); - ind = snap_get_indirect(pri, NULL, index); - if(ind) { - ind_ino = ind->i_ino; - iput(ind); - } - return ind_ino; -} -*/ static int print_inode(struct inode *pri,void *param) { @@ -586,94 +602,6 @@ static int snap_print(struct super_block *sb, void *data) return 0; } -static int delete_inode(struct inode *primary, void *param) -{ - struct snap_iterdata * data; - int tableno = 0; - int index = 0; - int rc = 0; - - struct inode *redirect; - ino_t old_ind = 0; - struct snap_table *table; - int slot; - int delete_slot; - int this_index; - struct inode *next_ind = NULL; - int my_table[SNAP_MAX]; - - if(!primary) return 0; - - data = (struct snap_iterdata*) param; - - if(data) { - index = data->index; - tableno = data->tableno; - } - - printk("delete_inode ino %lu, index %d\n", primary->i_ino, index); - - table = &snap_tables[tableno]; - - redirect = snap_get_indirect(primary, NULL, index); - - if(!redirect) - return 0; - - old_ind = redirect->i_ino; - iput(redirect); - slot = snap_index2slot(table, index) - 1; - if( slot > 0 ) { - this_index = table->tbl_index[slot]; - redirect = snap_get_indirect(primary, NULL, this_index); - if(redirect) - iput(redirect); - else { - snap_set_indirect(primary, old_ind, this_index, 0); - snap_set_indirect(primary, 0, index, 0); - return 0; - } - } - - /* get the FIRST index after this and before NOW */ - /* used for destroy_indirect and block level cow */ - /* XXX fix this later, now use tbl_count, not NOW */ - delete_slot = snap_index2slot(table, index); - for(slot = table->tbl_count; slot > delete_slot; slot --) - { - my_table[slot - delete_slot] = table->tbl_index[slot]; - } - next_ind = snap_get_indirect - (primary, my_table, table->tbl_count - delete_slot ); - if( next_ind && (next_ind->i_ino == primary->i_ino) ) { - iput(next_ind); - next_ind = NULL; - } - - if( next_ind && (next_ind->i_ino == old_ind) ) { - iput(next_ind); - next_ind = NULL; - } - - rc = snap_destroy_indirect(primary, index, next_ind); - - if(next_ind) iput(next_ind); - - if(rc != 0) - printk("ERROR:snap_destroy_indirect(ino %lu,index %d),ret %d\n", primary->i_ino, index, rc); - return 0; -} - -static int snap_delete(struct super_block *sb, struct snap_iterdata *data) -//static int snap_delete(struct super_block *sb, void *data) -{ - CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n", - data->dev, data->tableno, data->index, data->time ); - - snap_iterate(sb,&delete_inode,NULL, data, SNAP_ITERATE_COWED_INODE); - return 0; -} - static int delete_new_inode(struct inode *pri, void *param) { struct snap_iterdata * data; @@ -706,7 +634,6 @@ static int delete_new_inode(struct inode *pri, void *param) CDEBUG(D_SNAP, "snap_restore ino %lu is newer, delete \n",pri->i_ino); for( pos = head->next; pos != head; pos = pos->next ){ -// d_invalidate( list_entry(pos, struct dentry, d_alias) ); d_drop( list_entry(pos, struct dentry, d_alias) ); } pri->i_nlink = 0; @@ -728,7 +655,6 @@ static int restore_inode(struct inode *pri, void *param) int slot; int restore_slot; struct snap_table *table; -// int my_table[SNAP_MAX]; int restore_index; ENTRY; @@ -760,33 +686,18 @@ static int restore_inode(struct inode *pri, void *param) for(slot = restore_slot; slot <= table->tbl_count; slot++) { ind = snap_get_indirect (pri, NULL, - table->tbl_index[slot]); + table->snap_items[slot].index); if(ind) { - restore_index = table->tbl_index[slot]; + restore_index = table->snap_items[slot].index; break; } } -/* for(slot = table->tbl_count; slot >= restore_slot; - slot --) - { - my_table[slot - restore_slot + 1] = - table->tbl_index[slot]; - } - ind = snap_get_indirect (pri, my_table, - table->tbl_count - restore_slot + 1); - - if( ind && (ind->i_ino == pri->i_ino) ) { - iput(ind); - ind = NULL; - } -*/ } if(ind) { CDEBUG(D_SNAP, "restore ino %lu with index %d\n", pri->i_ino, restore_index); iput(ind); -// snap_restore_indirect(pri, index); snap_restore_indirect(pri, restore_index); /* XXX */ //delete_inode(pri, param); @@ -797,7 +708,7 @@ static int restore_inode(struct inode *pri, void *param) } } else { - printk("ino %lu is older, don't restore\n",pri->i_ino); + CDEBUG(D_SNAP, "ino %lu is older, don't restore\n", pri->i_ino); } EXIT; return 0; @@ -821,21 +732,16 @@ int snap_get_index_from_name(int tableno, char *name) int slot; if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) { - printk(__FUNCTION__ ": invalid table number %d\n", tableno); + CDEBUG(D_SNAP, ": invalid table number %d\n", tableno); return -EINVAL; } table = &snap_tables[tableno]; for ( slot = 0 ; slot < SNAP_MAX ; slot++ ) { -/* if(memcmp (table->tbl_name[slot], name, - strlen(table->tbl_name[slot]) ) == 0 ) { - return table->tbl_index[slot]; - } -*/ - if(strncmp (table->tbl_name[slot], name, + if(strncmp (&table->snap_items[slot].name[0], name, SNAP_MAX_NAMELEN) == 0 ) { - return table->tbl_index[slot]; + return table->snap_items[slot].index; } } return -EINVAL; @@ -844,27 +750,20 @@ int snap_get_index_from_name(int tableno, char *name) int snap_iterate_func(int len, struct snap_ioc_data *ioc_data, unsigned int cmd) { struct snap_iterdata data; - - kdev_t dev ; - char name[SNAP_MAX_NAMELEN]; - - int index ; - int tableno; - int name_len; - int slot; - struct super_block *sb; struct snap_cache *cache; struct snap_table *table; + char name[SNAP_MAX_NAMELEN]; + int index, tableno, name_len, slot, rc; + + kdev_t dev ; ENTRY; dev = ioc_data->dev; cache = snap_find_cache(dev); - if ( !cache ) { - EXIT; - return -EINVAL; - } + if ( !cache ) + RETURN(-EINVAL); sb = cache->cache_sb; tableno = cache->cache_snap_tableno; @@ -877,41 +776,37 @@ int snap_iterate_func(int len, struct snap_ioc_data *ioc_data, unsigned int cmd) if(name_len < 0 ) name_len = 0; memcpy(name, ioc_data->name, name_len); - if ( (index = snap_get_index_from_name (tableno, name)) < 0 ) { - EXIT; - return -EINVAL; - } + + if ((index = snap_get_index_from_name (tableno, name)) < 0) + RETURN(-EINVAL); data.dev = dev; data.index = index; data.tableno = tableno; slot = snap_index2slot (table, index); - if( slot < 0 ) { - EXIT; - return -EINVAL; - } - data.time = table->tbl_times[slot]; - + if( slot < 0 ) + RETURN(-EINVAL); + + data.time = table->snap_items[slot].time; CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n", data.dev, data.tableno, data.index, data.time ); switch (cmd) { case IOC_SNAP_DEBUG: - snap_print(sb, &data); + rc = snap_print(sb, &data); break; case IOC_SNAP_DELETE: - snap_delete(sb, &data); + rc = snaptable_delete_item(sb, &data); break; case IOC_SNAP_RESTORE: - snap_restore(sb, &data); + rc = snap_restore(sb, &data); break; default: - return -EINVAL; + CERROR("unrecognized cmd %d \n", cmd); + rc = -EINVAL; + break; } - - EXIT; - - return 0; + RETURN(0); } int snap_ioctl (struct inode * inode, struct file * filp, @@ -941,10 +836,12 @@ int snap_ioctl (struct inode * inode, struct file * filp, if ( _IOC_TYPE(cmd) != IOC_SNAP_TYPE || _IOC_NR(cmd) < IOC_SNAP_MIN_NR || _IOC_NR(cmd) > IOC_SNAP_MAX_NR ) { - CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n", + /*FIXME: Sometimes Gettimeof the day will come here + * Do not know the reason*/ + CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n", _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd)); EXIT; - return -EINVAL; + return 0; } /* get data structures */ @@ -964,8 +861,8 @@ int snap_ioctl (struct inode * inode, struct file * filp, } switch (cmd) { - case IOC_SNAP_SETTABLE: - rc = snap_install_table(len, karg); + case IOC_SNAP_ADD: + rc = snaptable_add_item(karg); break; case IOC_SNAP_PRINTTABLE: { struct output_data{ @@ -1064,9 +961,11 @@ int snap_ioctl (struct inode * inode, struct file * filp, case IOC_SNAP_DEBUG: rc = snap_iterate_func(len, karg, cmd); break; +#ifdef SNAP_DEBUG case IOC_SNAP_DEVFAIL: snap_debug_failcode = (unsigned int)arg; break; +#endif case IOC_SNAP_SHOW_DOTSNAP: { struct ioc_show_info{ kdev_t dev; diff --git a/lustre/snapfs/super.c b/lustre/snapfs/super.c index f1019771a87a67f086ab38d6b08e6c01858057e2..e4b4ef8b9a66ca62408fa48b3c92937d4c813a11 100644 --- a/lustre/snapfs/super.c +++ b/lustre/snapfs/super.c @@ -8,43 +8,22 @@ * * Author: Peter J. Braam <braam@mountainviewdata.com> */ +#define DEBUG_SUBSYSTEM S_SNAP - -#include <stdarg.h> - -#include <asm/bitops.h> -#include <asm/uaccess.h> -#include <asm/system.h> - -#include <linux/errno.h> +#include <linux/module.h> +#include <linux/kmod.h> +#include <linux/init.h> #include <linux/fs.h> -#include <linux/dcache.h> - -#ifdef CONFIG_SNAPFS_EXT2 -#include <linux/ext2_fs.h> -#endif -#ifdef CONFIG_SNAPFS_EXT3 -#include <linux/ext3_fs.h> -#endif - -#include <linux/malloc.h> -#include <linux/vmalloc.h> -#include <linux/sched.h> -#include <linux/stat.h> +#include <linux/slab.h> #include <linux/string.h> -#include <linux/locks.h> -#include <linux/blkdev.h> -#include <linux/init.h> -#define __NO_VERSION__ -#include <linux/module.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> +#include <linux/errno.h> +#include "snapfs_internal.h" -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> #ifdef SNAP_DEBUG -long snap_vmemory = 0; -long snap_kmemory = 0; unsigned int snap_debug_failcode = 0; #endif @@ -54,15 +33,16 @@ extern inline void snap_init_cache_hash(void); extern int snap_get_index_from_name (int tableno, char *name); -#ifdef CONFIG_SNAPFS_EXT2 -extern struct snapshot_operations ext2_snap_operations; -extern struct journal_ops snap_ext2_journal_ops; -#endif -#ifdef CONFIG_SNAPFS_EXT3 extern struct snapshot_operations ext3_snap_operations; extern struct journal_ops snap_ext3_journal_ops; -#endif + +static void put_filesystem(struct file_system_type *fs) +{ + if (fs->owner) + __MOD_DEC_USE_COUNT(fs->owner); +} + /* returns an allocated string, copied out from data if opt is found */ static char *read_opt(const char *opt, char *data) @@ -78,9 +58,9 @@ static char *read_opt(const char *opt, char *data) return NULL; value++; - SNAP_ALLOC(retval, char *, strlen(value) + 1); + SNAP_ALLOC(retval, strlen(value) + 1); if ( !retval ) { - printk("snapfs: Out of memory!\n"); + CERROR("snapfs: Out of memory!\n"); return NULL; } @@ -114,15 +94,15 @@ static char *snapfs_options(char *options, char *cache_data, /* set the defaults here */ if (cache_type && !*cache_type) { - SNAP_ALLOC(*cache_type, char *, strlen("ext2") + 1); - strcpy(*cache_type, "ext2"); + SNAP_ALLOC(*cache_type, strlen("ext3") + 1); + strcpy(*cache_type, "ext3"); } if (cow_type && !*cow_type) { - SNAP_ALLOC(*cow_type, char *, strlen("block") + 1); + SNAP_ALLOC(*cow_type, strlen("block") + 1); strcpy(*cow_type, "block"); } if (snaptable && !*snaptable) { - SNAP_ALLOC(*snaptable, char *, strlen("-1")+1); + SNAP_ALLOC(*snaptable, strlen("-1")+1); strcpy(*snaptable, "-1"); } @@ -167,25 +147,18 @@ int snapfs_remount(struct super_block * sb, int *flags, char *data) int err = 0; ENTRY; - CDEBUG(D_MALLOC, "before remount: kmem %ld, vmem %ld\n", - snap_kmemory, snap_vmemory); CDEBUG(D_SUPER, "remount opts: %s\n", data ? (char *)data : "(none)"); if (data) { /* reserve space for the cache's data */ - SNAP_ALLOC(cache_data, void *, PAGE_SIZE); - if ( !cache_data ) { - err = -ENOMEM; - EXIT; - goto out_err; - } + SNAP_ALLOC(cache_data, PAGE_SIZE); + if ( !cache_data ) + GOTO(out_err, err = -ENOMEM); } cache = snap_find_cache(sb->s_dev); if (!cache) { - printk(__FUNCTION__ ": cannot find cache on remount\n"); - err = -ENODEV; - EXIT; - goto out_err; + CERROR("cannot find cache on remount\n"); + GOTO(out_err, err = -ENODEV); } /* If an option has not yet been set, we allow it to be set on @@ -211,8 +184,6 @@ int snapfs_remount(struct super_block * sb, int *flags, char *data) err = sops->remount_fs(sb, flags, cache_data); } - CDEBUG(D_MALLOC, "after remount: kmem %ld, vmem %ld\n", - snap_kmemory, snap_vmemory); EXIT; out_err: if (cache_data) @@ -251,15 +222,12 @@ snapfs_read_super ( int tableno; ENTRY; - CDEBUG(D_MALLOC, "before parsing: kmem %ld, vmem %ld\n", - snap_kmemory, snap_vmemory); /* reserve space for the cache's data */ - SNAP_ALLOC(cache_data, void *, PAGE_SIZE); + SNAP_ALLOC(cache_data, PAGE_SIZE); if ( !cache_data ) { - printk("snapfs_read_super: Cannot allocate data page.\n"); - EXIT; - goto out_err; + CERROR("snapfs_read_super: Cannot allocate data page.\n"); + GOTO(out_err, 0); } CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)"); @@ -281,20 +249,21 @@ snapfs_read_super ( /* set up the cache */ cache = snap_init_cache(); if ( !cache ) { - printk("snapfs_read_super: failure allocating cache.\n"); - EXIT; - goto out_err; + CERROR("snapfs_read_super: failure allocating cache.\n"); + GOTO(out_err, 0); } fstype = get_fs_type(cache_type); if ( !fstype || !fstype->read_super) { - EXIT; - goto out_err; + GOTO(out_err, 0); } cache->cache_filter = filter_get_filter_fs((const char *)cache_type); - /* XXX if cache->cache_filter==NULL?although it's rare ***/ - + + if (!cache->cache_filter) { + CERROR("Unrecognized cache type %s \n", cache_type); + GOTO(out_err, 0); + } /* * Read the underlying file system superblock - ext2, ext3, reiser. @@ -303,20 +272,12 @@ snapfs_read_super ( * * Note: It's assumed that sb is always returned. */ - CDEBUG(D_SUPER, "\n"); if (fstype->read_super(sb, cache_data, silent) != sb) { - printk("snapfs: cache mount failure.\n"); - EXIT; - goto out_err; + CERROR("snapfs: cache mount failure.\n"); + GOTO(out_err, 0); } - /* XXX now look at the flags in the superblock and determine if this - is a block cow file system or a file cow fs. Then assign the - snap operations accordingly. This goes in the sections for ext2/ext3/xfs etc - */ - /* this might have been freed above */ - CDEBUG(D_SUPER, "\n"); if (cache_data) { SNAP_FREE(cache_data, PAGE_SIZE); cache_data = NULL; @@ -329,14 +290,13 @@ snapfs_read_super ( * 'cache' is the struct snap_cache allocated for this * snapfs mount. */ - CDEBUG(D_SUPER, "\n"); snap_cache_add(cache, sb->s_dev); tableno = simple_strtoul(snapno, &endptr, 0); cache->cache_snap_tableno = tableno; - CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno); + CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno); /* * make sure we have our own super operations * @@ -344,10 +304,8 @@ snapfs_read_super ( * struct snap_ops structure set based on the underlying * file system type. */ - CDEBUG(D_SUPER, "\n"); filter_setup_super_ops(cache->cache_filter, sb->s_op, ¤tfs_super_ops); - CDEBUG(D_SUPER, "\n"); sb->s_op = filter_c2usops(cache->cache_filter); /* * Save pointers in the snap_cache structure to the @@ -358,25 +316,6 @@ snapfs_read_super ( /* set up snapshot ops, handle COMPAT_FEATUREs */ if( 0 ){ } -#ifdef CONFIG_SNAPFS_EXT2 - else if ( strcmp (cache_type,"ext2") == 0 ){ - cache->cache_type = FILTER_FS_EXT2; - filter_setup_snapshot_ops(cache->cache_filter, - &ext2_snap_operations); - filter_setup_journal_ops(cache->cache_filter, - &snap_ext2_journal_ops); - if( !EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_SNAPFS) ){ - if( strcmp(cow_type, "block")==0 ){ - sb->u.ext2_sb.s_feature_compat |= - EXT2_FEATURE_COMPAT_BLOCKCOW; - sb->u.ext2_sb.s_es->s_feature_compat |= - cpu_to_le32(EXT2_FEATURE_COMPAT_BLOCKCOW); - } - } - sb->u.ext2_sb.s_last_cowed_ino = 0; - } -#endif -#ifdef CONFIG_SNAPFS_EXT3 else if ( strcmp (cache_type,"ext3") == 0 ){ cache->cache_type = FILTER_FS_EXT3; filter_setup_snapshot_ops(cache->cache_filter, @@ -389,37 +328,32 @@ snapfs_read_super ( cpu_to_le32(EXT3_FEATURE_COMPAT_BLOCKCOW); } } - sb->u.ext3_sb.s_last_cowed_ino = 0; + sb->u.ext3_sb.s_last_cowed_pri_ino = 0; + sb->u.ext3_sb.s_first_cowed_pri_ino = 0; } -#endif - - CDEBUG(D_SUPER, "\n"); /* now get our own directory operations */ if ( sb->s_root && sb->s_root->d_inode ) { - CDEBUG(D_SUPER, "\n"); filter_setup_dir_ops(cache->cache_filter, - sb->s_root->d_inode->i_op, - ¤tfs_dir_iops); - CDEBUG(D_SUPER, "\n"); + sb->s_root->d_inode, + ¤tfs_dir_iops, ¤tfs_dir_fops); sb->s_root->d_inode->i_op =filter_c2udiops(cache->cache_filter); -// CDEBUG(D_SUPER, "\n"); -// sb->s_root->d_inode->i_snapop = ext2_snapops(); CDEBUG(D_SUPER, "lookup at %p\n", sb->s_root->d_inode->i_op->lookup); -#if 0 - /* XXX is this needed ?? */ + /* XXX is this needed ?? ext3 do not have dentry operations*/ filter_setup_dentry_ops(cache->cache_filter, sb->s_root->d_op, ¤tfs_dentry_ops); sb->s_root->d_op = filter_c2udops(cache->cache_filter); -#endif } /* * Save a pointer to the snap_cache structure in the * "snap_current" superblock. */ (struct snap_cache *) sb->u.generic_sbp = cache; + + snapfs_read_snaptable(cache, tableno); + CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n", (ulong) sb, (ulong) sb->u.generic_sbp); @@ -436,12 +370,10 @@ snapfs_read_super ( SNAP_FREE(cow_type, strlen(cow_type) + 1); cow_type = NULL; } + /* Inc in get_fs_type, Dec in put_fs_type*/ - CDEBUG(D_MALLOC, "after mounting: kmem %ld, vmem %ld\n", - snap_kmemory, snap_vmemory); - - MOD_INC_USE_COUNT; - EXIT; + put_filesystem(fstype); + return sb; out_err: @@ -456,19 +388,13 @@ snapfs_read_super ( SNAP_FREE(cache_type, strlen(cache_type) + 1); if (cow_type) SNAP_FREE(cow_type, strlen(cow_type) + 1); + if (fstype) + put_filesystem(fstype); - CDEBUG(D_MALLOC, "mount error exit: kmem %ld, vmem %ld\n", - snap_kmemory, snap_vmemory); return NULL; } - -struct file_system_type snapfs_current_type = { - "snap_current", - FS_REQUIRES_DEV, /* can use Ibaskets when ext2 does */ - snapfs_read_super, - NULL -}; +static DECLARE_FSTYPE_DEV(snapfs_current_type, "snap_current", snapfs_read_super); /* Find the options for the clone. These consist of a cache device @@ -510,19 +436,26 @@ static char *clonefs_options(char *options, char *cache_data, static int snapfs_path2dev(char *dev_path, kdev_t *dev) { struct dentry *dentry; + struct nameidata nd; + int error = 0; + + if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) { + error = path_walk(dev_path, &nd); + if (error) + return error; + } else + return -EINVAL; - dentry = lookup_dentry(dev_path, NULL, 0); - if (IS_ERR(dentry)) - return PTR_ERR(dentry); + dentry = nd.dentry; - if (!dentry->d_inode) - return -ENODEV; - - if (!S_ISBLK(dentry->d_inode->i_mode)) + if (!dentry->d_inode || !S_ISBLK(dentry->d_inode->i_mode) || + is_bad_inode(dentry->d_inode) ) { + path_release(&nd); return -ENODEV; + } *dev = dentry->d_inode->i_rdev; - + path_release(&nd); return 0; } @@ -554,15 +487,12 @@ clone_read_super( ENTRY; - CDEBUG(D_MALLOC, "before parsing: kmem %ld, vmem %ld\n", - snap_kmemory, snap_vmemory); /* reserve space for the cache's data */ - SNAP_ALLOC(cache_data, void *, PAGE_SIZE); + SNAP_ALLOC(cache_data, PAGE_SIZE); if ( !cache_data ) { - printk("clone_read_super: Cannot allocate data page.\n"); - EXIT; - goto out_err; + CERROR("clone_read_super: Cannot allocate data page.\n"); + GOTO(out_err, 0); } CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)"); @@ -575,29 +505,25 @@ clone_read_super( SNAP_FREE(cache_data, PAGE_SIZE); cache_data = NULL; } else { - printk("clonefs: invalid mount option %s\n", cache_data); - EXIT; - goto out_err; + CERROR("clonefs: invalid mount option %s\n", cache_data); + GOTO(out_err, 0); } if (!namestr || !devstr) { - printk("snapfs: mount options name and dev mandatory\n"); - EXIT; - goto out_err; + CERROR("snapfs: mount options name and dev mandatory\n"); + GOTO(out_err, 0); } err = snapfs_path2dev(devstr, &dev); if ( err ) { - printk("snap: incorrect device option %s\n", devstr); - EXIT; - goto out_err; + CERROR("snap: incorrect device option %s\n", devstr); + GOTO(out_err, 0); } snap_cache = snap_find_cache(dev); if ( !snap_cache ) { - printk("snap: incorrect device option %s\n", devstr); - EXIT; - goto out_err; + CERROR("snap: incorrect device option %s\n", devstr); + GOTO(out_err, 0); } /*index = simple_strtoul(indexstr, &endptr, 0); @@ -614,9 +540,8 @@ clone_read_super( snap_cache->cache_snap_tableno, namestr, index); if(index < 0 ) { - printk("No valid index for name %s passed to mount\n",namestr); - EXIT; - goto out_err; + CERROR("No valid index for name %s passed to mount\n",namestr); + GOTO(out_err, 0); } /* @@ -640,13 +565,13 @@ clone_read_super( CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n", sb->s_op->read_inode, root_ino, root_inode); - sb->s_root = d_alloc_root(root_inode, NULL); + sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) { list_del(&clone_sb->clone_list_entry); sb = NULL; } - dget( snap_cache->cache_sb->s_root ); + dget(snap_cache->cache_sb->s_root); if (cache_data) SNAP_FREE(cache_data, PAGE_SIZE); @@ -656,39 +581,29 @@ clone_read_super( SNAP_FREE(namestr, strlen(namestr) + 1); CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n", (ulong) sb, (ulong) &sb->u.generic_sbp); - - MOD_INC_USE_COUNT; - EXIT; return sb; out_err: - CDEBUG(D_MALLOC, "mount error exit: kmem %ld, vmem %ld\n", - snap_kmemory, snap_vmemory); return NULL; } - -struct file_system_type snapfs_clone_type = { - "snap_clone", - 0, - clone_read_super, - NULL -}; - +static DECLARE_FSTYPE(snapfs_clone_type, "snap_clone", clone_read_super, 0); int init_snapfs(void) { int status; snap_init_cache_hash(); + init_filter_info_cache(); - status = register_filesystem(&snapfs_current_type); - if (status) { - printk("snapfs: failed in register current filesystem!\n"); - } status = register_filesystem(&snapfs_clone_type); if (status) { unregister_filesystem(&snapfs_current_type); - printk("snapfs: failed in register clone filesystem!\n"); + CERROR("snapfs: failed in register clone filesystem!\n"); + } + + status = register_filesystem(&snapfs_current_type); + if (status) { + CERROR("snapfs: failed in register current filesystem!\n"); } return status; } @@ -701,14 +616,14 @@ int cleanup_snapfs(void) ENTRY; + cleanup_filter_info_cache(); err = unregister_filesystem(&snapfs_clone_type); if ( err ) { - printk("snapfs: failed to unregister clone filesystem\n"); + CERROR("snapfs: failed to unregister clone filesystem\n"); } err = unregister_filesystem(&snapfs_current_type); if ( err ) { - printk("snapfs: failed to unregister filesystem\n"); + CERROR("snapfs: failed to unregister filesystem\n"); } - return 0; } diff --git a/lustre/snapfs/symlink.c b/lustre/snapfs/symlink.c index 41efbd1935f839cc67b1862c1d77dc9c8e45810b..cf4c99cbb174117a6040a98852b057b3694356f6 100644 --- a/lustre/snapfs/symlink.c +++ b/lustre/snapfs/symlink.c @@ -4,26 +4,19 @@ * A snap shot file system. * */ +#define DEBUG_SUBSYSTEM S_SNAP -#define EXPORT_SYMTAB - - -#define __NO_VERSION__ -#include <linux/module.h> -#include <asm/uaccess.h> -#include <linux/sched.h> -#include <linux/stat.h> +#include <linux/kmod.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/slab.h> #include <linux/string.h> -#include <linux/locks.h> -#include <linux/quotaops.h> -#include <linux/list.h> -#include <linux/file.h> -#include <asm/bitops.h> -#include <asm/byteorder.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> + +#include "snapfs_internal.h" -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> static inline int inode_has_ea(struct inode *inode) { @@ -92,19 +85,17 @@ static int cat_str_ahead(char *buf, int pos, const char* str) * (1) we are not lies in .snap * (2) we are already in the root's .snap */ -static struct dentry * dotsnap_follow_link(struct dentry *base, - struct dentry *dentry, - int follow) +static int dotsnap_follow_link(struct dentry *dentry, + struct nameidata *nd) { struct super_block *sb = dentry->d_inode->i_sb; - struct dentry *rc = NULL; struct dentry *de = dentry, *de_save1=NULL, *de_save2=NULL; char *buf = NULL; - int pos = D_MAXLEN; + int pos = D_MAXLEN, rc; - SNAP_ALLOC(buf, char*, D_MAXLEN); + SNAP_ALLOC(buf, D_MAXLEN); if( !buf ) - return ERR_PTR(-ENOMEM); + RETURN(-ENOMEM); /* * iterate upward to construct the path @@ -139,49 +130,50 @@ lookup: pos = cat_str_ahead(buf, pos, ".snap"); buf[D_MAXLEN-1] = 0; - CDEBUG(D_FILE, "constructed path: %s\n", &buf[pos]); + CDEBUG(D_SNAP, "constructed path: %s\n", &buf[pos]); /* FIXME lookup_dentry will never return NULL ?? */ +#if 0 rc = lookup_dentry(&buf[pos], dget(sb->s_root), follow); if( !rc ){ rc = ERR_PTR(-ENOENT); - CDEBUG(D_FILE, "lookup_dentry return NULL~!@#$^&*\n"); + CDEBUG(D_SNAP, "lookup_dentry return NULL~!@#$^&*\n"); } - dput(base); - +#else + if (path_init(&buf[pos], LOOKUP_FOLLOW, nd)) { + rc = path_walk(&buf[pos], nd); + if (rc) + GOTO(exit, rc); + } +#endif exit: SNAP_FREE(buf, D_MAXLEN); return rc; } -static struct dentry * currentfs_follow_link ( struct dentry *dentry, - struct dentry *base, - unsigned int follow) +static int currentfs_follow_link (struct dentry *dentry, struct nameidata *nd) { struct snap_cache *cache; - struct dentry * rc; struct inode_operations *iops; struct inode * inode = dentry->d_inode; int bpib = inode->i_sb->s_blocksize >> 9; __u32 save_i_blocks; - + int rc; ENTRY; cache = snap_find_cache(inode->i_dev); if ( !cache ) { - EXIT; - return ERR_PTR(-EINVAL); + RETURN(-EINVAL); } iops = filter_c2csiops(cache->cache_filter); if (!iops || !iops->follow_link) { - rc = ERR_PTR(-EINVAL); - goto exit; + GOTO(exit, rc = -EINVAL); } if( currentfs_is_under_dotsnap(dentry) ){ - rc = dotsnap_follow_link( base, dentry, follow ); + rc = dotsnap_follow_link(dentry, nd); if( rc ) goto exit; } @@ -193,7 +185,7 @@ static struct dentry * currentfs_follow_link ( struct dentry *dentry, if( inode_has_ea(inode) && inode->i_blocks == bpib ) { inode->i_blocks = 0; } - rc = iops->follow_link(dentry, base, follow); + rc = iops->follow_link(dentry, nd); if( inode->i_blocks != save_i_blocks ){ inode->i_blocks = save_i_blocks; @@ -201,13 +193,14 @@ static struct dentry * currentfs_follow_link ( struct dentry *dentry, } exit: - EXIT; - return rc; + RETURN(rc); } struct inode_operations currentfs_sym_iops = { readlink: currentfs_readlink, - follow_link: currentfs_follow_link + follow_link: currentfs_follow_link, }; -struct file_operations currentfs_sym_fops; +struct file_operations currentfs_sym_fops = { + ioctl: NULL, +}; diff --git a/lustre/snapfs/sysctl.c b/lustre/snapfs/sysctl.c index f7f88a6700a9efec406f8fe1e5d245c3562082a7..1969081dd17dd34d961d4eb7fb12665b7867b06f 100644 --- a/lustre/snapfs/sysctl.c +++ b/lustre/snapfs/sysctl.c @@ -2,53 +2,27 @@ * Sysctrl entries for Snapfs */ -#define __NO_VERSION__ -#include <linux/config.h> /* for CONFIG_PROC_FS */ +/* /proc entries */ + +#define DEBUG_SUBSYSTEM S_SNAP + #include <linux/module.h> -#include <linux/sched.h> -#include <linux/mm.h> +#include <linux/kmod.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/string.h> #include <linux/sysctl.h> -#include <linux/swapctl.h> #include <linux/proc_fs.h> -#include <linux/malloc.h> -#include <linux/vmalloc.h> -#include <linux/stat.h> -#include <linux/ctype.h> -#include <linux/init.h> -#include <asm/bitops.h> -#include <asm/segment.h> -#include <asm/uaccess.h> -#include <linux/utsname.h> -#include <linux/blk.h> - -#include <linux/filter.h> -#include <linux/snapfs.h> -#include <linux/snapsupport.h> +#include <linux/jbd.h> +#include <linux/ext3_fs.h> +#include <linux/snap.h> +#include "snapfs_internal.h" -/* /proc entries */ #ifdef CONFIG_PROC_FS - - -static void snapfs_proc_modcount(struct inode *inode, int fill) -{ - if (fill) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; -} - -struct proc_dir_entry proc_fs_snapfs = { - 0, 10, "snapfs", - S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, - 0, &proc_dir_inode_operations, - NULL, NULL, - NULL, - NULL, NULL -}; - - +static struct proc_dir_entry *proc_snapfs_root; #endif @@ -67,9 +41,11 @@ static struct ctl_table_header *snapfs_table_header = NULL; #define ENTRY_CNT 3 /* XXX - doesn't seem to be working in 2.2.15 */ -static struct ctl_table snapfs_ctltable[ENTRY_CNT] = +static struct ctl_table snapfs_ctltable[] = { +#ifdef SNAP_DEBUG {PSDEV_DEBUG, "debug", &snap_debug_level, sizeof(int), 0644, NULL, &proc_dointvec}, +#endif {PSDEV_TRACE, "trace", &snap_print_entry, sizeof(int), 0644, NULL, &proc_dointvec}, {0} }; @@ -80,31 +56,35 @@ static ctl_table snapfs_table[2] = { }; -int /* __init */ init_snapfs_proc_sys(void) +int __init init_snapfs_proc_sys(void) { +#ifdef CONFIG_PROC_FS + proc_snapfs_root = proc_mkdir("snapfs", proc_root_fs); + if (!proc_snapfs_root) { + printk(KERN_ERR "SNAPFS: error registering /proc/fs/snapfs\n"); + RETURN(-ENOMEM); + } + proc_snapfs_root->owner = THIS_MODULE; +#endif #ifdef CONFIG_SYSCTL if ( !snapfs_table_header ) snapfs_table_header = register_sysctl_table(snapfs_table, 0); -#endif -#ifdef CONFIG_PROC_FS - proc_register(&proc_root_fs, &proc_fs_snapfs); - proc_fs_snapfs.fill_inode = &snapfs_proc_modcount; #endif return 0; } -void cleanup_snapfs_proc_sys(void) { - +void cleanup_snapfs_proc_sys(void) +{ #ifdef CONFIG_SYSCTL if ( snapfs_table_header ) unregister_sysctl_table(snapfs_table_header); snapfs_table_header = NULL; #endif - #if CONFIG_PROC_FS - proc_unregister(&proc_root_fs, proc_fs_snapfs.low_ino); + remove_proc_entry("snapfs", proc_root_fs); #endif + }