struct snap_cache *snap_find_cache(kdev_t dev)
{
struct snap_cache *cache;
- struct list_head *lh, *tmp;
+ struct list_head *lh;
- lh = tmp = &(snap_caches[snap_cache_hash(dev)]);
+ lh = &(snap_caches[snap_cache_hash(dev)]);
list_for_each_entry(cache, lh, cache_chain) {
if ( cache->cache_dev == dev )
return cache;
}
return cache;
}
+/*walk through the cache structure*/
+int snap_cache_process(snap_cache_cb_t cb, void* in, unsigned long* out)
+{
+ int i = 0;
+
+ for (i = 0; i < CACHES_SIZE; i++) {
+ struct snap_cache *cache;
+ struct list_head *lh = &(snap_caches[i]);
+ list_for_each_entry(cache, lh, cache_chain) {
+ if (cb(cache, in, out))
+ goto exit;
+ }
+ }
+exit:
+ return 0;
+}
+
/* free a cache structure and all of the memory it is pointing to */
inline void snap_free_cache(struct snap_cache *cache)
inode->i_mapping->a_ops = &clonefs_file_address_ops;
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &clonefs_dir_inode_ops;
+ inode->i_fop = &clonefs_dir_file_ops;
} else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &clonefs_symlink_inode_ops;
} else {
{
struct snap_cache *cache;
struct inode_operations *iops;
- struct snapshot_operations *snapops;
void *handle = NULL;
int rc;
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 ) {
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))) {
+ if ((snap_do_cow(dir, get_parent_ino(dir), 0))) {
CERROR("Do cow error\n");
RETURN(-EINVAL);
}
}
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);
- init_filter_data(dentry->d_inode, snapops, 0); exit:
+ init_filter_data(dentry->d_inode, 0);
+exit:
snap_trans_commit(cache, handle);
RETURN(rc);
}
for( i=0; i<2; 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 - 1; slot >= 1; slot--) {
struct address_space_operations *c_aops =
cache_inode->i_mapping->a_ops;
cache_inode = NULL;
table = &snap_tables[cache->cache_snap_tableno];
- for (slot = table->tbl_count ; slot >= 1; slot--)
+ for (slot = table->tbl_count - 1; slot >= 1; slot--)
{
struct address_space_operations *c_aops =
cache_inode->i_mapping->a_ops;
void init_filter_data(struct inode *inode,
- struct snapshot_operations *snapops,
int flag)
{
struct filter_inode_info *i;
+ struct snap_cache *cache;
+ struct snapshot_operations *snapops;
- if (inode->i_filterdata){
+ if (inode->i_filterdata || inode->i_ino & 0xF0000000)
return;
- }
+ cache = snap_find_cache(inode->i_dev);
+ if (!cache) {
+ CERROR("currentfs_read_inode: cannot find cache\n");
+ make_bad_inode(inode);
+ return;
+ }
+ snapops = filter_c2csnapops(cache->cache_filter);
+
inode->i_filterdata = (struct filter_inode_info *) \
kmem_cache_alloc(filter_info_cache, SLAB_KERNEL);
i = inode->i_filterdata;
}
/*init filter_data struct
* FIXME flag should be set future*/
- init_filter_data(inode, snapops, 0);
+ init_filter_data(inode, 0);
return;
}
if (!redirected) {
int index;
clone_slot = snap_index2slot(table, clone_info->clone_index);
- for (slot = table->tbl_count; slot >= clone_slot; slot --) {
+ for (slot = table->tbl_count-1; slot >= clone_slot; slot --) {
my_table[slot-clone_slot+1] = table->snap_items[slot].index;
}
index = table->tbl_count - clone_slot + 1;
}
snap_last(cache, &snap);
- ind = snapops->create_indirect(inode, snap.index, 0, parent_ino, del);
+ ind = snapops->create_indirect(inode, snap.index, snap.gen, parent_ino, del);
if(!ind)
RETURN(-EINVAL);
iput(ind);
/* cache.c */
inline void snap_free_cache(struct snap_cache *cache);
struct snap_cache *snap_find_cache(kdev_t dev);
+typedef int (*snap_cache_cb_t)(struct snap_cache*, void *in, unsigned long *out);
+int snap_cache_process(snap_cache_cb_t cb, void* in, unsigned long* out);
/* snaptable.c */
extern struct snap_table snap_tables[SNAP_MAX_TABLES];
extern struct super_operations currentfs_super_ops;
void cleanup_filter_info_cache(void);
int init_filter_info_cache(void);
-void init_filter_data(struct inode *inode, struct snapshot_operations *snapops,
- int flag);
+extern void init_filter_data(struct inode *inode, int flag);
/* dir.c */
extern struct inode_operations currentfs_dir_iops;
{
int slot;
- for ( slot=0 ; slot<snap_table->tbl_count ; slot++ )
+ for ( slot=0 ; slot < snap_table->tbl_count ; slot++ )
if ( snap_table->snap_items[slot].index == snap_index )
return slot;
return -1;
table = &snap_tables[tableno];
stbl_out = (struct ioc_snap_tbl_data *)buf;
- stbl_out->count = table->tbl_count;
+ stbl_out->count = table->tbl_count - 1;
stbl_out->no = tableno;
buf_ptr = (char*)stbl_out->snaps;
nleft -= buf_ptr - buf;
- for (i = 0; i < table->tbl_count; i++) {
- memcpy(buf_ptr, &table->snap_items[i+1], sizeof(struct snap));
+ for (i = 1; i < table->tbl_count; i++) {
+ memcpy(buf_ptr, &table->snap_items[i], sizeof(struct snap));
nleft -= sizeof(struct snap);
if(nleft < 0) {
/* 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;
+ /*add item in snap_table set generation*/
+ table->snap_items[count].gen = table->generation + 1;
+ table->snap_items[count].time = CURRENT_TIME;
/* find table index */
index = get_index_of_item(table, data->snaps[0].name);
if (index < 0)
- RETURN(-EINVAL);
+ GOTO(exit, rc = -EINVAL);
- table->snap_items[count+1].index = index;
- table->snap_items[count+1].flags = 0;
- memcpy(&table->snap_items[count + 1].name[0],
+ table->snap_items[count].index = index;
+ table->snap_items[count].flags = 0;
+ memcpy(&table->snap_items[count].name[0],
data->snaps[0].name, 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);
+ GOTO(exit, rc = -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->count = cpu_to_le32((__u32)table->tbl_count) - 1;
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 + 1; i++) {
+ 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);
+ disk_snap_table->snap_items[i-1].time = cpu_to_le64((__u64)item->time);
+ disk_snap_table->snap_items[i-1].gen = cpu_to_le32((__u32)item->gen);
+ disk_snap_table->snap_items[i-1].flags = cpu_to_le32((__u32)item->flags);
+ disk_snap_table->snap_items[i-1].index = cpu_to_le32((__u32)item->index);
+ memcpy(&disk_snap_table->snap_items[i-1].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++;
-
+exit:
up(&table->tbl_sema);
-
- return 0;
+ RETURN(rc);
}
static int delete_inode(struct inode *primary, void *param)
memset(table, 0, sizeof(struct snap_table));
init_MUTEX(&table->tbl_sema);
-
+
+ /*Initialized table */
+ table->tbl_count = 1;
rc = snapops->get_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
(char*)disk_snap_table, &size);
if (rc < 0) {
RETURN(rc);
}
table->generation = le32_to_cpu(disk_snap_table->generation);
- table->tbl_count = le32_to_cpu(disk_snap_table->count);
+ 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);
int slot;
if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
- CDEBUG(D_SNAP, ": invalid table number %d\n", tableno);
+ CERROR("invalid table number %d\n", tableno);
return -EINVAL;
}
#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>
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;
}