#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>
__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,
sb->s_root->d_op,
¤tfs_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
}
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;
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;
}
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)