Whamcloud - gitweb
some fix about snapfs
authorwangdi <wangdi>
Mon, 26 Jan 2004 17:42:03 +0000 (17:42 +0000)
committerwangdi <wangdi>
Mon, 26 Jan 2004 17:42:03 +0000 (17:42 +0000)
1)add clonefs check before snap delete
2)some fix about orphan list
3)initialize inode in mknod, mkdir symlink ...
4)some fix about symlinks
5)add some snapshot filter operations (listxattr, getxattr)
6)some fix about sparse files
7)fix page buffer problems in snap delete and snap_do_cow
8)adding some functions  in snapconf.
: ----------------------------------------------------------------------

lustre/snapfs/cache.c
lustre/snapfs/clonefs.c
lustre/snapfs/dir.c
lustre/snapfs/file.c
lustre/snapfs/filter.c
lustre/snapfs/inode.c
lustre/snapfs/snapfs_internal.h
lustre/snapfs/snaptable.c
lustre/snapfs/utils/snapctl.c

index 68efe98..62cb15b 100644 (file)
@@ -58,7 +58,7 @@ struct snap_cache *snap_find_cache(kdev_t dev)
 
        lh = &(snap_caches[snap_cache_hash(dev)]);
         list_for_each_entry(cache, lh, cache_chain) { 
-               if ( cache->cache_dev == dev )
+               if (cache->cache_dev == dev)
                        return cache;
        }
        return NULL;
index b4f136c..2292c49 100644 (file)
@@ -422,19 +422,17 @@ struct address_space_operations clonefs_file_address_ops = {
 
 static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 {
-       int res;
        struct inode * cache_inode;
        struct inode * old_inode;
+       int rc = -ENOENT;
 
        ENTRY;
 
        cache_inode = clonefs_get_inode(dentry->d_inode); 
 
-       res = -ENOENT;
-
-       if ( ! cache_inode ) {
+       if (!cache_inode) {
                CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-               RETURN(res);    
+               RETURN(rc);     
        }
        
        /* XXX: shall we allocate a new dentry ? 
@@ -446,8 +444,8 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
        /* set dentry inode to cache inode */
        dentry->d_inode = cache_inode;
 
-       if ( cache_inode->i_op->readlink ) {
-               res = cache_inode->i_op->readlink(dentry, buf, len); 
+       if (cache_inode->i_op->readlink) {
+               rc = cache_inode->i_op->readlink(dentry, buf, len); 
        }else {
                CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino);
        }
@@ -457,21 +455,21 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 
        iput(cache_inode);
 
-       RETURN(res);
+       RETURN(rc);
 }
 
 static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
 {
        struct inode * cache_inode;
        struct inode * old_inode;
-       int    res;
+       int    rc = -ENOENT;
 
        ENTRY;
 
        cache_inode = clonefs_get_inode(dentry->d_inode); 
-       if ( ! cache_inode ) {
+       if (!cache_inode) {
                CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-               RETURN(-ENOENT);        
+               RETURN(rc);     
        }
 
        /* XXX: shall we allocate a new dentry ? 
@@ -483,8 +481,8 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
        /* set dentry inode to cache inode */
        dentry->d_inode = cache_inode;
 
-       if ( cache_inode->i_op->follow_link ) {
-               res = cache_inode->i_op->follow_link(dentry, nd); 
+       if (cache_inode->i_op->follow_link) {
+               rc = cache_inode->i_op->follow_link(dentry, nd); 
        }
 
        /* restore the old inode */
@@ -492,16 +490,103 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
 
        iput(cache_inode);
 
-       RETURN(res);
+       RETURN(rc);
 }
+static ssize_t
+clonefs_getxattr(struct dentry *dentry, const char *name,
+                 void *buffer, size_t size)
+{
+       struct inode * cache_inode;
+       struct inode * old_inode;
+       int    rc = -ENOENT;
+
+       ENTRY;
+
+       cache_inode = clonefs_get_inode(dentry->d_inode); 
+       if (!cache_inode) {
+               CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
+               RETURN(rc);     
+       }
+
+       /* XXX: shall we allocate a new dentry ? 
+               The following is safe for ext2, etc. because ext2_follow_link 
+               only use the inode info */
 
+       /* save the old dentry inode */ 
+       old_inode = dentry->d_inode;
+       /* set dentry inode to cache inode */
+       dentry->d_inode = cache_inode;
+
+       if (cache_inode->i_op->getxattr) {
+               rc = cache_inode->i_op->getxattr(dentry, name, buffer, size); 
+       }
+
+       /* restore the old inode */
+       dentry->d_inode = old_inode;
+
+       iput(cache_inode);
+
+       RETURN(rc);
+}
+static ssize_t
+clonefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+       struct inode * cache_inode;
+       struct inode * old_inode;
+       int    rc = -ENOENT;
+
+       ENTRY;
+
+       cache_inode = clonefs_get_inode(dentry->d_inode); 
+       if (!cache_inode) {
+               CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
+               RETURN(rc);     
+       }
+
+       /* XXX: shall we allocate a new dentry ? 
+               The following is safe for ext2, etc. because ext2_follow_link 
+               only use the inode info */
+
+       /* save the old dentry inode */ 
+       old_inode = dentry->d_inode;
+       /* set dentry inode to cache inode */
+       dentry->d_inode = cache_inode;
+
+       if (cache_inode->i_op->listxattr) {
+               rc = cache_inode->i_op->listxattr(dentry, buffer, size); 
+       }
+
+       /* restore the old inode */
+       dentry->d_inode = old_inode;
+
+       iput(cache_inode);
+
+       RETURN(rc);
+
+}
 struct inode_operations clonefs_symlink_inode_ops =
 {
        /*FIXME later getxattr, listxattr, 
         * other method need to be replaced too 
         * */  
-       readlink:       clonefs_readlink,   /* readlink */              
-       follow_link:    clonefs_follow_link,/* follow_link */             
+       readlink:       clonefs_readlink,       /* readlink */              
+       follow_link:    clonefs_follow_link,    /* follow_link */             
+       getxattr:       clonefs_getxattr,       /* get xattr */
+        listxattr:      clonefs_listxattr,      /* list xattr */
 };
 
 
+int clonefs_mounted(struct snap_cache *cache, int index)
+{
+       struct snap_clone_info *clone_sb;
+       struct list_head *list, *end;
+
+       end = list = &cache->cache_clone_list;
+       
+       list_for_each_entry(clone_sb, list, clone_list_entry) {
+               if (clone_sb->clone_index == index)
+                       return 1;       
+       }       
+       return 0;       
+}
+
index 4db0908..d139d20 100644 (file)
@@ -37,10 +37,13 @@ static ino_t get_parent_ino(struct inode * inode)
 
 static void d_unadd_iput(struct dentry *dentry)
 {
+       spin_lock(&dcache_lock);
        list_del(&dentry->d_alias);
        INIT_LIST_HEAD(&dentry->d_alias);
        list_del(&dentry->d_hash);
        INIT_LIST_HEAD(&dentry->d_hash);
+       spin_unlock(&dcache_lock);
+       
        iput(dentry->d_inode);
        dentry->d_inode = NULL;
 }
@@ -76,7 +79,8 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 
                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);
+               CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n", 
+                      snap->i_ino, snap->i_mode);
                d_add(dentry, snap);
                RETURN(NULL);
        }
@@ -87,10 +91,14 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
        }
 
        rc = iops->lookup(dir, dentry);
-       if ( rc || !dentry->d_inode) {
+       if (rc || !dentry->d_inode || 
+            is_bad_inode(dentry->d_inode) ||
+           IS_ERR(dentry->d_inode)) {
                RETURN(NULL);
        }
-       
+
+       CDEBUG(D_INODE, "cache inode ino %lu, mode %o\n", 
+              dentry->d_inode->i_ino, dentry->d_inode->i_mode);
        /*
         * If we are under dotsnap, we need save extra data into
         * dentry->d_fsdata:  For dir, we only need _this_ snapshot's index; 
@@ -160,13 +168,13 @@ static int currentfs_create(struct inode *dir, struct dentry *dentry, int mode)
        }
 
        cache = snap_find_cache(dir->i_dev);
-       if ( !cache ) { 
+       if (!cache) { 
                RETURN(-EINVAL);
        }
 
        handle = snap_trans_start(cache, dir, SNAP_OP_CREATE);
 
-       if ( snap_needs_cow(dir) != -1 ) {
+       if (snap_needs_cow(dir) != -1) {
                CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
                snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 1);
                if ((snap_do_cow(dir, get_parent_ino(dir), 0))) {
@@ -242,7 +250,12 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                 CERROR("Error in currentfs_mkdir, dentry->d_inode is NULL\n");
         }
 
-       snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 3);
+       set_filter_ops(cache, dentry->d_inode);
+       init_filter_data(dentry->d_inode, 0); 
+       
+       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:
        snap_trans_commit(cache, handle);
@@ -320,8 +333,11 @@ static int currentfs_symlink(struct inode *dir, struct dentry *dentry,
 
        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);
        
+       set_filter_ops(cache, dentry->d_inode);
+       init_filter_data(dentry->d_inode, 0); 
+       
+       snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3);
 exit:
        snap_trans_commit(cache, handle);
        RETURN(rc);
@@ -360,6 +376,9 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 
        snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 2);
        rc = iops->mknod(dir, dentry, mode, rdev);
+       
+       set_filter_ops(cache, dentry->d_inode);
+       init_filter_data(dentry->d_inode, 0); 
        snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 3);
        
        /* XXX do we need to set the correct snap_{*}_iops */
@@ -380,7 +399,6 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
        off_t   i_size = 0;
        ino_t ino = 0;
        int keep_inode = 0;
-//     struct dentry_operations *save_dop = NULL;
        void *handle = NULL;
 
        ENTRY;
@@ -416,23 +434,10 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
        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 (dir, get_parent_ino(dir), SNAP_CREATE_IND_DEL_PRI);
+               snap_do_cow (dentry->d_inode, get_parent_ino(dentry->d_inode), 
+                            SNAP_CREATE_IND_DEL_PRI);
                keep_inode = 1;
        }
-#if 0
-       if ( keep_inode ) {     
-                       printk("set up dentry ops, before %p\n",dentry->d_op);
-               save_dop = dentry->d_op;
-
-               filter_setup_dentry_ops(cache->cache_filter,
-                                dentry->d_op, &currentfs_dentry_ops);
-               dentry->d_op = filter_c2udops(cache->cache_filter);
-
-                       printk("set up dentry ops, after %p\n",dentry->d_op);
-
-       }
-
-#endif
 
        if( keep_inode && dentry->d_inode ) {
                ino = dentry->d_inode->i_ino;
@@ -445,31 +450,20 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
        rc = iops->rmdir(dir, dentry);
        snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 5);
 
-       /* XXX : check this */
-#if 0
-       if ( keep_inode ) {
-               dentry->d_op = save_dop;
-               printk("restore dentry ops, now at %p\n",dentry->d_op);
-       }
-
-#endif
-
        if( keep_inode && ino) {
-               inode = iget ( dir->i_sb, ino);
+               inode = iget (dir->i_sb, ino);
                if( inode) {
 //                     inode->i_ctime = i_ctime;
                        inode->i_nlink = i_nlink;
                        inode->i_size = i_size;
                        mark_inode_dirty(inode);
                        iput( inode);
-#ifdef CONFIG_SNAPFS_EXT3
                        /*
                         * In Ext3, rmdir() will put this inode into
                         * orphan list, we must remove it out. It's ugly!!
                         */
                        if( cache->cache_type == FILTER_FS_EXT3 )
                                ext3_orphan_del(handle, inode);
-#endif
                        snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 6);
                }
        }
@@ -698,5 +692,8 @@ struct inode_operations currentfs_dir_iops = {
        rmdir:          currentfs_rmdir,
        unlink:         currentfs_unlink,
        rename:         currentfs_rename,
-       lookup:         currentfs_lookup
+       lookup:         currentfs_lookup,
+       removexattr:    currentfs_removexattr,
+       setattr:        currentfs_setattr,
+       setxattr:       currentfs_setxattr,
 };
index 25eea66..a8a8860 100644 (file)
@@ -43,7 +43,7 @@ static int copy_back_page(struct inode *dst,
        char *kaddr_src, *kaddr_dst;
         struct snap_cache *cache;
        struct address_space_operations *c_aops;
-       struct page *src_page, *dst_page;
+       struct page *src_page = NULL, *dst_page = NULL;
        unsigned long index, offset, bytes;
        int    err = 0;
        ENTRY;
@@ -96,6 +96,8 @@ static int copy_back_page(struct inode *dst,
        flush_dcache_page(dst_page);
 
        err = c_aops->commit_write(NULL, dst_page, offset, offset + bytes);
+       CDEBUG(D_SNAP, "copy back pages %p index %lu src %lu dst %lu \n",
+              dst_page, dst_page->index, src->i_ino, dst->i_ino); 
        if (err) 
                goto unlock_dst_page; 
        err = 1;
@@ -132,28 +134,36 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
         if ( !cache ) 
                 RETURN(-EINVAL);
 
+       down(&inode->i_sem);
+
         if ( snap_needs_cow(inode) != -1 ) {
                 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) 
-                RETURN(-EINVAL);
-
+        if (!fops || !fops->write) { 
+                up(&inode->i_sem); 
+               RETURN(-EINVAL);
+       }
         if (filp->f_flags & O_APPEND)
                 pos = inode->i_size;
         else {
                 pos = *ppos;
-                if (pos != *ppos)
+                if (pos != *ppos){
+                       up(&inode->i_sem); 
                         RETURN(-EINVAL);
+               }
         }
-       if (pos & PAGE_CACHE_MASK) {
+       
+       CDEBUG(D_SNAP, "write offset %lld count %u \n", pos, count);
+       
+       if (pos & (PAGE_CACHE_SIZE - 1)) {
                start[0] = pos & PAGE_CACHE_MASK;
                end[0] = pos;
        }
        pos += count - 1;
-       if ((pos+1) & PAGE_CACHE_MASK) {
+       if ((pos+1) & (PAGE_CACHE_SIZE - 1)) {
                start[1] = pos;  
                end[1] = PAGE_CACHE_ALIGN(pos);
        }
@@ -161,7 +171,9 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
        if (((start[0] >> PAGE_CACHE_SHIFT) == (start[1] >> PAGE_CACHE_SHIFT)) ||
            pos > inode->i_size) 
                start[1] = -1;
-       
+
+       CDEBUG(D_SNAP, "copy back start[0] %ld end[0] %ld start[1] %ld end[1] %ld \n",
+              start[0], end[0], start[1], end[1]);     
        for (i = 0; i < 2; i++) {
                if (start[i] == -1) 
                        continue;
@@ -189,11 +201,14 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
                        if (result < 0) {
                                iput(cache_inode);
                                rc = result;
+                               up(&inode->i_sem);
                                goto exit;
                        }
                                iput(cache_inode);
                }
        }
+       
+        up(&inode->i_sem); 
        rc = fops->write(filp, buf, count, ppos);
 exit:
         RETURN(rc);
@@ -246,7 +261,6 @@ static int currentfs_readpage(struct file *file, struct page *page)
        table = &snap_tables[cache->cache_snap_tableno];
 
         for (slot = table->tbl_count - 1; slot >= 1; slot--) {
-               cache_inode = NULL;
                 index = table->snap_items[slot].index;
                cache_inode = snap_get_indirect(inode, NULL, index);
 
@@ -259,12 +273,19 @@ static int currentfs_readpage(struct file *file, struct page *page)
                 if (!search_older && c_aops->bmap(cache_inode->i_mapping, block)) 
                         break;
                 iput(cache_inode);
+               cache_inode = NULL;
         }
        if (pri_inode) iput(pri_inode);
 
-       if (!cache_inode )  
-               RETURN(-EINVAL);
-
+       if (!cache_inode) {
+               CDEBUG(D_SNAP, "block %lu is a hole of inode %lu \n", 
+                      block, inode->i_ino);
+               memset(kmap(page), 0, PAGE_CACHE_SIZE);
+               flush_dcache_page(page);
+               GOTO(exit, rc = 0);
+       }
+       CDEBUG(D_INODE, "readpage ino %lu icount %d \n", cache_inode->i_ino, 
+              atomic_read(&cache_inode->i_count));
        down(&cache_inode->i_sem);
 
        /*Here we have changed a file to read,
@@ -284,13 +305,14 @@ static int currentfs_readpage(struct file *file, struct page *page)
                GOTO(exit_release, rc = -EIO);
 
        memcpy(kmap(page), kmap(cache_page), PAGE_CACHE_SIZE);
+       flush_dcache_page(page);
 
        kunmap(cache_page);
        page_cache_release(cache_page);
 
        up(&cache_inode->i_sem);
        iput(cache_inode);
-       
+exit:  
        kunmap(page);
        SetPageUptodate(page);
        UnlockPage(page);
@@ -315,6 +337,8 @@ struct file_operations currentfs_file_fops = {
 };
                                                                                                                                                                                                      
 struct inode_operations currentfs_file_iops = {
-       revalidate:     NULL,
+       setattr:        currentfs_setattr,
+       setxattr:       currentfs_setxattr,
+       removexattr:    currentfs_removexattr,  
 };
 
index c17a499..f7d6f6f 100644 (file)
@@ -239,6 +239,13 @@ void filter_setup_dir_ops(struct filter_fs *cache,
                        u_iops->mknod = filter_iops->mknod;
                if (cache_iops->permission && filter_iops->permission)
                        u_iops->permission = filter_iops->permission;
+               if (cache_iops->setattr && filter_iops->setattr)
+                       u_iops->setattr = filter_iops->setattr;
+               if (cache_iops->setxattr && filter_iops->setxattr)
+                       u_iops->setxattr = filter_iops->setxattr;
+               if (cache_iops->removexattr && filter_iops->removexattr)
+                       u_iops->removexattr = filter_iops->removexattr;
+
        }
        /* copy dir fops */
        
@@ -290,6 +297,12 @@ void filter_setup_file_ops(struct filter_fs           *cache,
        if (filter_iops) {
                if (filter_iops->revalidate)
                        u_iops->revalidate = filter_iops->revalidate;
+               if (filter_iops->removexattr)
+                       u_iops->removexattr = filter_iops->removexattr;
+               if (filter_iops->setxattr)
+                       u_iops->setxattr = filter_iops->setxattr;
+               if (filter_iops->setattr)
+                       u_iops->setattr = filter_iops->setattr;
        }
        if (filter_fops) {
                if (filter_fops->read)
@@ -337,6 +350,11 @@ void filter_setup_symlink_ops(struct filter_fs *cache,
                        u_iops->readlink = filter_iops->readlink;
                if (cache_iops->follow_link && filter_iops->follow_link)
                        u_iops->follow_link = filter_iops->follow_link;
+               if (cache_iops->getxattr && filter_iops->getxattr) 
+                       u_iops->getxattr = filter_iops->getxattr;
+               if (cache_iops->listxattr && filter_iops->listxattr)
+                       u_iops->listxattr = filter_iops->listxattr;
+
        }
        EXIT;
 }
index 25619a8..97bfd46 100644 (file)
@@ -64,6 +64,8 @@ void init_filter_data(struct inode *inode,
                return;
        }
        snapops = filter_c2csnapops(cache->cache_filter);
+
+       if (inode->i_filterdata) return;
        
        inode->i_filterdata = (struct filter_inode_info *) \
                              kmem_cache_alloc(filter_info_cache, SLAB_KERNEL);
@@ -104,7 +106,95 @@ void set_filter_ops(struct snap_cache *cache, struct inode *inode)
                       inode->i_ino, inode->i_op);
        }
 }
+int currentfs_setxattr(struct dentry *dentry, const char *name, 
+                      const void *value, size_t size, int flags)
+{
+        struct snap_cache      *cache;
+       struct inode            *inode = dentry->d_inode;
+       struct inode_operations *iops;
+       int    rc;
+
+       ENTRY;
+       cache = snap_find_cache(inode->i_dev);
+       if (!cache) {
+               CERROR("currentfs_setxattr: cannot find cache\n");
+               RETURN(-EINVAL);
+       }
+
+       iops = filter_c2cfiops(cache->cache_filter);
+       if (!iops || !iops->setxattr) {
+               RETURN(-EINVAL);                
+       }
+        if ( snap_needs_cow(inode) != -1 ) {
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+       }
+
+       rc = iops->setxattr(dentry, name, value, size, flags);
+
+       RETURN(rc);
+}
+int currentfs_removexattr(struct dentry *dentry, const char *name)
+{
+        struct snap_cache      *cache;
+       struct inode            *inode = dentry->d_inode;
+       struct inode_operations *iops;
+       int    rc;
+
+       ENTRY;
+       cache = snap_find_cache(inode->i_dev);
+       if (!cache) {
+               CERROR("currentfs_setxattr: cannot find cache\n");
+               RETURN(-EINVAL);
+       }
+
+       iops = filter_c2cfiops(cache->cache_filter);
+       if (!iops || !iops->removexattr) {
+               RETURN(-EINVAL);                
+       }
+        
+       if (snap_needs_cow(inode) != -1) {
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+       }
+       rc = iops->removexattr(dentry, name);
+
+       RETURN(rc);
+}
+
+int currentfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+        struct snap_cache      *cache;
+       struct inode            *inode = dentry->d_inode;
+       struct inode_operations *iops;
+       int    rc;
+
+       ENTRY;
+       cache = snap_find_cache(inode->i_dev);
+       if (!cache) {
+               CERROR("currentfs_setxattr: cannot find cache\n");
+               RETURN(-EINVAL);
+       }
 
+       iops = filter_c2cfiops(cache->cache_filter);
+       if (!iops || !iops->setattr) {
+               RETURN(-EINVAL);                
+       }
+        if ( snap_needs_cow(inode) != -1 ) {
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+       }
+
+       rc = iops->setattr(dentry, attr);
+
+       RETURN(rc);
+}
 /* Superblock operations. */
 static void currentfs_read_inode(struct inode *inode)
 {
@@ -113,7 +203,6 @@ static void currentfs_read_inode(struct inode *inode)
 
        if( !inode ) 
                return;
-
        CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
 
        cache = snap_find_cache(inode->i_dev);
@@ -131,10 +220,14 @@ static void currentfs_read_inode(struct inode *inode)
        if(filter_c2csops(cache->cache_filter))
                filter_c2csops(cache->cache_filter)->read_inode(inode);
 
+       CDEBUG(D_INODE, "read_inode ino %lu icount %d \n", 
+              inode->i_ino, atomic_read(&inode->i_count));
        set_filter_ops(cache, inode);
        /*init filter_data struct 
         * FIXME flag should be set future*/
        init_filter_data(inode, 0); 
+       CDEBUG(D_INODE, "read_inode ino %lu icount %d \n", 
+              inode->i_ino, atomic_read(&inode->i_count));
        return; 
 }
 
@@ -217,3 +310,8 @@ struct super_operations currentfs_super_ops = {
        put_super:      currentfs_put_super,
        clear_inode:    currentfs_clear_inode,
 };
+
+
+
+
+
index 6ce3e3e..da9d992 100644 (file)
@@ -209,7 +209,7 @@ struct snap_obd_data {
        unsigned int snap_index;/* which snapshot is ours */
        unsigned int snap_table;/* which table do we use */
 };
-#define DISK_SNAPTABLE_ATTR     "Snaptable"
+#define DISK_SNAPTABLE_ATTR     "Snaptable12"
 #define DISK_SNAP_TABLE_MAGIC  0x1976
 struct snap_disk_table {
        unsigned int            magic;
@@ -287,6 +287,10 @@ void cleanup_filter_info_cache(void);
 int init_filter_info_cache(void);
 extern void init_filter_data(struct inode *inode, int flag);
 extern void set_filter_ops(struct snap_cache *cache, struct inode *inode);
+extern int currentfs_setxattr(struct dentry *dentry, const char *name, 
+                      const void *value, size_t size, int flags);
+extern int currentfs_removexattr(struct dentry *dentry, const char *name);
+extern int currentfs_setattr(struct dentry *dentry, struct iattr *attr);
 /* dir.c */
 extern struct inode_operations currentfs_dir_iops;
 extern struct file_operations currentfs_dir_fops;
@@ -306,6 +310,8 @@ extern struct dentry_operations currentfs_dentry_ops;
 extern int init_option(char *data);
 extern void cleanup_option(void);
 extern int get_opt(struct option **opt, char **pos);
+/* clonefs.c */
+int clonefs_mounted(struct snap_cache *cache, int index);
 
 #define FILTER_DID_SUPER_OPS   0x1
 #define FILTER_DID_INODE_OPS   0x2
index 0af46c3..5759058 100644 (file)
 
 struct snap_table snap_tables[SNAP_MAX_TABLES];
 
-#if 0
-static void snap_lock_table(int table_no)
-{
-
-       spin_lock(snap_tables[table_no].tbl_lock);
-
-}
-
-static void snap_unlock_table(int table_no)
-{
-
-       spin_unlock(snap_tables[table_no].tbl_lock);
-
-}
-#endif
-
 int snap_index2slot(struct snap_table *snap_table, int snap_index)
 {
        int slot;
@@ -210,8 +194,10 @@ static int snaptable_add_item(struct ioc_snap_tbl_data *data)
        table->snap_items[count].time = CURRENT_TIME;
        /* find table index */
        index = get_index_of_item(table, data->snaps[0].name);
-       if (index < 0)
+       if (index < 0) {
+               CERROR("snaptable full Or Duplicate name in snaptable\n");
                GOTO(exit, rc = -EINVAL);
+       }
        
        table->snap_items[count].index = index;
        table->snap_items[count].flags = 0;
@@ -285,6 +271,9 @@ static int delete_inode(struct inode *primary, void *param)
        }
        old_ind = redirect->i_ino;
        iput(redirect);
+
+       /* In destroy indirect inode, we lock the primary inode here */
+       down(&primary->i_sem);  
        slot = snap_index2slot(table, index) - 1;
        if (slot > 0) {
                this_index = table->snap_items[slot].index;
@@ -294,33 +283,29 @@ static int delete_inode(struct inode *primary, void *param)
                } else {
                        snap_set_indirect(primary, old_ind, this_index, 0);
                        snap_set_indirect(primary, 0, index, 0);
+                       up(&primary->i_sem);            
                        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 --) {
+       for (slot = table->tbl_count - 1; 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;
-       }
+       
+       this_index = table->tbl_count - delete_slot - 1;
+       next_ind = snap_get_indirect(primary, my_table, this_index);
 
-       if (next_ind && (next_ind->i_ino == old_ind)) {
+       if (next_ind && (next_ind->i_ino == primary->i_ino)) {
                iput(next_ind);
                next_ind = NULL;
        }
-
        rc = snap_destroy_indirect(primary, index, next_ind);
 
+       up(&primary->i_sem);
+       
        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);
@@ -339,6 +324,7 @@ static int snap_delete(struct super_block *sb, struct snap_iterdata *data)
 
 /* This function will delete one item(a snapshot) in the snaptable  
  * and will also delete the item in the disk.
+ * FIXME later, this should be in a transaction.
  */
 int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
 {
@@ -346,19 +332,26 @@ int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
        struct snap_disk_table          *disk_snap_table;
        struct snapshot_operations      *snapops;
        struct snap_cache               *cache;
-       int                             tableno = data->tableno, index, i, slot, rc, count;
+       int                             tableno = data->tableno; 
+       int                             index, i, del_slot, 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);
-
        if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
                CERROR("invalid table number %d\n", tableno);
                RETURN(-EINVAL);
        }
+
+       snapops = filter_c2csnapops(cache->cache_filter);
+       if (!snapops || !snapops->set_meta_attr)
+               RETURN(-EINVAL);
+       
+       index = data->index;
+       if (clonefs_mounted(cache, index)) {
+               CERROR("Please first umount this clonefs \n");
+               RETURN(-EBUSY);         
+       }       
        /*first delete the snapshot
         * FIXME if snap delete error, how to handle this error*/
        rc = snap_delete(sb, data);
@@ -366,55 +359,63 @@ int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
                RETURN(-EINVAL);
        /*delete item in snaptable */
        table = &snap_tables[tableno];
-       index = data->index;
 
-       slot = snap_index2slot(table, index);
-       if (slot < 0)
+       del_slot = snap_index2slot(table, index);
+       if (del_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->tbl_count --;
        
        SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
 
-       if (!disk_snap_table)
+       if (!disk_snap_table) {
+               up(&table->tbl_sema);
                RETURN(-ENOMEM);
+       }
+
        /* we will delete the item  snap_table to disk */
-       
+
+       index = del_slot;
+       /*Move the items after the delete slot forward one step*/
+       memset(&table->snap_items[index], 0, sizeof(struct snap));
+       while(index < table->tbl_count - 1) {
+               struct snap *item = &table->snap_items[index];
+                       
+               item->time = table->snap_items[index + 1].time;
+               item->flags = table->snap_items[index + 1].flags;
+               item->gen = table->snap_items[index + 1].gen;
+               item->index = table->snap_items[index + 1].index;
+               memcpy(&item->name[0], &table->snap_items[index + 1].name[0],
+                      SNAP_MAX_NAMELEN);
+               index ++;
+       }
+
+       table->tbl_count --;
+               
        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);
+       disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count - 1);
+       disk_snap_table->generation = cpu_to_le32((__u32)table->generation + 1);
        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);
+       for (i = 0; i < table->tbl_count - 1; i++) {
+               struct snap_disk *disk_item = &disk_snap_table->snap_items[i];
+               struct snap *item = &table->snap_items[i+1];
+               
+               disk_item[i].time = cpu_to_le64((__u64)item->time);
+               disk_item[i].gen = cpu_to_le32((__u32)item->gen);
+               disk_item[i].flags = cpu_to_le32((__u32)item->flags);
+               disk_item[i].index = cpu_to_le32((__u32)item->index);
+               memcpy(&disk_item[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);
+       RETURN(rc);
 }
 
 int snapfs_read_snaptable(struct snap_cache *cache, int tableno)
@@ -592,13 +593,12 @@ static int delete_new_inode(struct inode *pri, void *param)
 
        ENTRY; 
 
-       if(!pri) return 0;
-
-       if(snap_is_redirector(pri)){
-               EXIT;
-               return 0;
-       }
+       if(!pri) 
+               RETURN(0);
 
+       if(snap_is_redirector(pri))
+               RETURN(0);
+       
        data = (struct snap_iterdata*) param;
 
        if(data) {
@@ -619,14 +619,12 @@ static int delete_new_inode(struct inode *pri, void *param)
                }
                pri->i_nlink = 0;
        }
-       return 0;
-
+       RETURN(0);
 }
 
 static int restore_inode(struct inode *pri, void *param)
 {
        struct snap_iterdata * data;
-//     struct snap_cache *cache;
        int tableno = 0;
 
        int index = 1;
@@ -640,7 +638,7 @@ static int restore_inode(struct inode *pri, void *param)
        
        ENTRY; 
 
-       if(!pri) return 0;
+       if(!pri) RETURN(0);
 
        data = (struct snap_iterdata*) param;
 
@@ -690,8 +688,7 @@ static int restore_inode(struct inode *pri, void *param)
        else {
                CDEBUG(D_SNAP, "ino %lu is older, don't restore\n", pri->i_ino);
        }
-       EXIT;
-       return 0;
+       RETURN(0);
 }
 
 //int snap_restore(struct super_block *sb, void *data)
@@ -718,7 +715,7 @@ int snap_get_index_from_name(int tableno, char *name)
 
        table = &snap_tables[tableno];
 
-       for ( slot = 0 ; slot < SNAP_MAX ; slot++ ) {
+       for ( slot = 0 ; slot < table->tbl_count; slot++) {
                if (!strcmp(&table->snap_items[slot].name[0], name)) {
                        return table->snap_items[slot].index;
                }
@@ -754,9 +751,11 @@ int snap_iterate_func( struct ioc_snap_tbl_data *data, unsigned int cmd)
        table = &snap_tables[tableno];
        
        index = snap_get_index_from_name(tableno, data->snaps[0].name);
-       if (index < 0)
+       if (index < 0) {
+               CERROR("Could not find %s in snaptable\n", 
+                      data->snaps[0].name);
                RETURN(-EINVAL);
-       
+       }
        iterate_data.dev = (kdev_t)data->dev;
        iterate_data.index = index;
        iterate_data.tableno = tableno;
@@ -784,7 +783,7 @@ int snap_iterate_func( struct ioc_snap_tbl_data *data, unsigned int cmd)
                        rc = -EINVAL;
                        break;
        }
-       RETURN(0);
+       RETURN(rc);
 }
 
 #define BUF_SIZE 1024
@@ -873,7 +872,8 @@ int snap_ioctl (struct inode * inode, struct file * filp,
                }
                */
                memcpy(name, data->name, name_len);
-               printk("dev %d , len %d, name_len %d, find name is [%s]\n", dev, input.ioc_inlen, name_len, name);
+               printk("dev %d , len %d, name_len %d, find name is [%s]\n", 
+                       dev, input.ioc_inlen, name_len, name);
                cache = snap_find_cache(dev); 
                if ( !cache ) {
                        EXIT;
index 78415cc..f11bb05 100644 (file)
@@ -174,23 +174,13 @@ static int open_device(char *name, unsigned int dev)
        }
        return 0;
 }
-
-int snap_dev_open(int argc, char **argv)
+static  int open_snap_device(char *name)
 {
        struct snap_mnt *snaplist;
-       char *dev_name;
-       int rc;
-
-       if (argc != 2) { 
-               fprintf(stderr, "The argument count is not right \n");
-               return CMD_HELP;
-       }
-       
-       dev_name = argv[1];
-
+       int rc; 
        get_snaplist();
        list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
-               if (!strcmp(&snaplist->device.name[0], dev_name)) {
+               if (!strcmp(&snaplist->device.name[0], name)) {
                        rc = open_device(&snaplist->device.name[0], 
                                    snaplist->device.dev);
                        release_snap_list();    
@@ -198,9 +188,25 @@ int snap_dev_open(int argc, char **argv)
                }
        }
        release_snap_list();    
-       fprintf(stderr, "%s are not snapdevice\n", dev_name);
+       fprintf(stderr, "%s are not snapdevice\n", name);
        return (-EINVAL);
 }
+int snap_dev_open(int argc, char **argv)
+{
+       char *dev_name;
+       int rc;
+
+       if (argc != 2) { 
+               fprintf(stderr, "The argument count is not right \n");
+               return CMD_HELP;
+       }
+       
+       dev_name = argv[1];
+       rc = open_snap_device(dev_name);
+       if (rc)
+               fprintf(stderr, "%s are not snapdevice\n", dev_name);
+       return (rc);
+}
 int snap_dev_list(int argc, char **argv)
 {
        struct snap_mnt *snaplist;
@@ -244,6 +250,7 @@ static inline void print_snap_table(void * buf)
 }
 int snap_snap_list(int argc, char **argv)
 {
+       char *dev_name = NULL;
        int i, rc = 0;
 
        if (argc != 1 && argc != 2) {
@@ -251,10 +258,17 @@ int snap_snap_list(int argc, char **argv)
                return CMD_HELP;
        }
        if (open_device_table.count == 0) {
-               fprintf(stderr, "Please open a snapdevice first\n");
-               return (-EINVAL);
+               if (argc == 2) {
+                       dev_name = argv[1];             
+               }       
+               if (dev_name) {
+                       rc = open_snap_device(dev_name); 
+               }
+               if (!dev_name || rc) {  
+                       fprintf(stderr, "Please open a snapdevice first\n");
+                       return (-EINVAL);
+               }
        }
-       
        for (i = 0; i < open_device_table.count; i++) {
                struct ioc_snap_tbl_data *snap_ioc_data;
 
@@ -281,16 +295,26 @@ int snap_snap_list(int argc, char **argv)
 }
 int snap_snap_del(int argc, char **argv)
 {
+       char   *dev_name = NULL, *snap_name = NULL;     
        int    rc = 0, i;
        
        if (argc != 3 && argc !=2) {
                fprintf(stderr, "The argument count is not right \n");
                return CMD_HELP;
        }
-
        if (open_device_table.count == 0) {
-               fprintf(stderr, "Please open a snapdevice first\n");
-               return (-EINVAL);
+               if (argc == 3) {
+                       dev_name = argv[1];             
+               } else if (argc == 4) {
+                       dev_name = argv[2];
+               }
+               if (dev_name) {
+                       rc = open_snap_device(dev_name); 
+               }
+               if (!dev_name || rc) {  
+                       fprintf(stderr, "Please open a snapdevice first\n");
+                       return (-EINVAL);
+               }
        }
        for (i = 0; i < open_device_table.count; i++) {
                struct ioc_snap_tbl_data *snap_ioc_data;
@@ -302,38 +326,53 @@ int snap_snap_del(int argc, char **argv)
 
                if (argc == 3) { 
                        snap_ioc_data->no = atoi(argv[1]);
-                       memcpy(snap_ioc_data->snaps[0].name, 
-                              argv[2], strlen(argv[2]));
+                       if (!snap_name)
+                               snap_name = argv[2];
                } else { 
                        snap_ioc_data->no = 0;
-                       memcpy(snap_ioc_data->snaps[0].name, 
-                              argv[1], strlen(argv[1]));
+                       if (!snap_name)
+                               snap_name = argv[1];
                }
+               memcpy(snap_ioc_data->snaps[0].name, 
+                              snap_name, strlen(snap_name));
+
                snap_ioc_data->snaps[0].time = time(NULL);
                
                IOC_PACK(sizeof(struct ioc_snap_tbl_data) + sizeof(struct snap));
 
                if ((rc = ioctl(open_device_table.device[i].fd, 
                                        IOC_SNAP_DELETE, buf))) {
-                       fprintf(stderr, "del %s failed \n", argv[1]);
+                       fprintf(stderr, "del %s failed \n", snap_name);
                } else {
-                       fprintf(stderr, "del %s success\n", argv[1]);
+                       fprintf(stderr, "del %s success\n", snap_name);
                }
        }
        return rc;
 }
 int snap_snap_add(int argc, char **argv)
 {
+       char   *dev_name = NULL, *snap_name = NULL;     
        int    rc = 0, i;
        
-       if (argc != 3 && argc !=2) {
+       if (argc != 3 && argc !=2 && argc !=4) {
                fprintf(stderr, "The argument count is not right \n");
                return CMD_HELP;
        }
-
        if (open_device_table.count == 0) {
-               fprintf(stderr, "Please open a snapdevice first\n");
-               return (-EINVAL);
+               if (argc == 3) {
+                       dev_name = argv[1];             
+                       snap_name = argv[2];
+               } else if (argc == 4) {
+                       dev_name = argv[2];
+                       snap_name = argv[3];
+               }
+               if (dev_name) {
+                       rc = open_snap_device(dev_name); 
+               }
+               if (!dev_name || rc) {  
+                       fprintf(stderr, "Please open a snapdevice first\n");
+                       return (-EINVAL);
+               }
        }
        for (i = 0; i < open_device_table.count; i++) {
                struct ioc_snap_tbl_data *snap_ioc_data;
@@ -345,22 +384,24 @@ int snap_snap_add(int argc, char **argv)
 
                if (argc == 3) { 
                        snap_ioc_data->no = atoi(argv[1]);
-                       memcpy(snap_ioc_data->snaps[0].name, 
-                              argv[2], strlen(argv[2]));
+                       if (!snap_name)
+                               snap_name = argv[2];
                } else { 
                        snap_ioc_data->no = 0;
-                       memcpy(snap_ioc_data->snaps[0].name, 
-                              argv[1], strlen(argv[1]));
+                       if (!snap_name)
+                               snap_name = argv[1];
                }
+               memcpy(snap_ioc_data->snaps[0].name, 
+                              snap_name, strlen(snap_name));
                snap_ioc_data->snaps[0].time = time(NULL);
                
                IOC_PACK(sizeof(struct ioc_snap_tbl_data) + sizeof(struct snap));
 
                if ((rc = ioctl(open_device_table.device[i].fd, 
                                        IOC_SNAP_ADD, buf))) {
-                       fprintf(stderr, "add %s failed \n", argv[1]);
+                       fprintf(stderr, "add %s failed \n", snap_name);
                } else {
-                       fprintf(stderr, "add %s success\n", argv[1]);
+                       fprintf(stderr, "add %s success\n", snap_name);
                }
        }
        return rc;