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