Whamcloud - gitweb
- grrr, they are unsigned ...
[fs/lustre-release.git] / lustre / snapfs / super.c
index 8b68cff..bfeecde 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/loop.h>
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
 #include <linux/snap.h>
@@ -43,6 +44,42 @@ static void put_filesystem(struct file_system_type *fs)
                __MOD_DEC_USE_COUNT(fs->owner);
 }
 
+static struct vfsmount* get_vfsmount(struct super_block *sb)
+{
+       struct vfsmount *rootmnt, *mnt, *ret = NULL;
+       struct list_head *end, *list;
+
+       rootmnt = mntget(current->fs->rootmnt);
+       end = list = &rootmnt->mnt_list;
+       do {
+               mnt = list_entry(list, struct vfsmount, mnt_list);
+               if (mnt->mnt_sb == sb) {
+                       ret = mnt;
+                       break;
+               }
+               list = list->next;
+       } while (end != list);
+       mntput(current->fs->rootmnt);
+       return ret;
+}
+
+void get_snap_current_mnt(struct super_block *sb)
+{
+       struct vfsmount *mnt;
+
+       mnt = get_vfsmount(sb);
+       if (mnt) 
+               mntget(mnt);
+}
+void put_snap_current_mnt(struct super_block *sb)
+{
+       struct vfsmount *mnt;
+
+       mnt = get_vfsmount(sb);
+       if (mnt) 
+               mntput(mnt);
+}
+
 /* In get_opt we get options in opt, value in opt_value
  * we must remember to free opt and opt_value*/
 static char * snapfs_options(char *options, char **cache_type, 
@@ -223,6 +260,7 @@ snapfs_read_super (
                                        sb->s_root->d_op, 
                                        &currentfs_dentry_ops);
                sb->s_root->d_op = filter_c2udops(cache->cache_filter);
+               init_filter_data(sb->s_root->d_inode, 0); 
        }
         /*
          * Save a pointer to the snap_cache structure in the
@@ -268,7 +306,31 @@ static char *clonefs_options(char *options, char **devstr, char **namestr)
        }
        return pos;
 }
-
+static int snap_cache_lookup_ino_cb(struct snap_cache *cache, void *in, unsigned long *out)
+{
+       ino_t ino = *((unsigned long*)in);
+
+       if (cache) {
+               struct super_block *sb = cache->cache_sb;
+               kdev_t dev = sb->s_dev;
+
+               if (MAJOR(dev) != LOOP_MAJOR) 
+                       return 0;
+               if (sb->s_bdev->bd_op && sb->s_bdev->bd_op->ioctl) {
+                       struct inode *inode = sb->s_bdev->bd_inode;
+                       struct loop_info loop_info;
+
+                       sb->s_bdev->bd_op->ioctl(inode, NULL, LOOP_GET_INFO, 
+                                                (unsigned long)&loop_info);
+                       
+                       if(loop_info.lo_inode == ino) {
+                               *out = sb->s_dev; 
+                               return 1;
+                       }
+               }
+       }
+       return 0;       
+}
 static int snapfs_path2dev(char *dev_path, kdev_t *dev)
 {
        struct dentry *dentry;
@@ -290,8 +352,19 @@ static int snapfs_path2dev(char *dev_path, kdev_t *dev)
                path_release(&nd);
                return -ENODEV;
        }
-
-       *dev = kdev_t_to_nr(dentry->d_inode->i_rdev);
+       if (S_ISBLK(dentry->d_inode->i_mode)) {
+               *dev = kdev_t_to_nr(dentry->d_inode->i_rdev);
+       } else {
+               /*here we must walk through all the snap cache to 
+                *find the loop device */
+               kdev_t tmp;
+
+               if (snap_cache_process(snap_cache_lookup_ino_cb,
+                                      &dentry->d_inode->i_ino, 
+                                      (unsigned long*)&tmp))
+                       return -EINVAL;
+               *dev = tmp;
+       }
        path_release(&nd);
        return 0;
 }
@@ -386,6 +459,8 @@ clone_read_super(
 
        CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
                 (ulong) sb, (ulong) &sb->u.generic_sbp);
+       
+       get_snap_current_mnt(snap_cache->cache_sb);
  out_err:
        cleanup_option();
        if (err)