5 * A snap shot file system.
9 #define DEBUG_SUBSYSTEM S_SNAP
11 #include <linux/kmod.h>
12 #include <linux/init.h>
14 #include <linux/slab.h>
15 #include <linux/string.h>
16 #include <linux/snap.h>
17 #include "snapfs_internal.h"
20 * Return true if the inode is a redirector inode.
22 int snap_is_redirector(struct inode *cache_inode)
24 struct snap_cache *cache;
25 struct snapshot_operations *snapops;
27 cache = snap_find_cache(cache_inode->i_dev);
31 snapops = filter_c2csnapops(cache->cache_filter);
32 if (!snapops || !snapops->is_redirector) {
36 CDEBUG(D_SNAP, "ino %ld\n", cache_inode->i_ino);
37 return snapops->is_redirector(cache_inode);
41 * Using a cache inode and clone super block find the real one.
43 struct inode *snap_redirect(struct inode *cache_inode,
44 struct super_block *clone_sb)
46 struct snap_clone_info *clone_info;
47 struct snap_table *table;
48 struct inode *redirected;
49 struct snap_cache *cache;
50 struct snapshot_operations *snapops;
52 int my_table[SNAP_MAX];
57 cache = snap_find_cache(cache_inode->i_dev);
61 snapops = filter_c2csnapops(cache->cache_filter);
62 if (!snapops || !snapops->get_indirect) {
66 CDEBUG(D_SNAP, "cache ino %ld\n", cache_inode->i_ino);
67 clone_info = (struct snap_clone_info *)&clone_sb->u.generic_sbp;
69 table = &snap_tables[clone_info->clone_cache->cache_snap_tableno];
71 /* first find if there are indirected at the clone_index */
72 redirected = snapops->get_indirect(cache_inode, NULL,
73 clone_info->clone_index);
74 /* if not found, get the FIRST index after this and before NOW */
75 /* XXX fix this later, now use tbl_count, not NOW */
79 memset(my_table, 0, sizeof(my_table));
80 clone_slot = snap_index2slot(table, clone_info->clone_index);
81 for (slot = table->tbl_count-1; slot >= clone_slot; slot --) {
82 my_table[slot - clone_slot + 1] = table->snap_items[slot].index;
84 index = table->tbl_count - clone_slot;
85 redirected = snapops->get_indirect(cache_inode, my_table, index);
89 CDEBUG(D_SNAP,"redirected ino %ld\n",redirected->i_ino);
95 * Make a copy of the data and plug a redirector in between if there
96 * is no redirector yet.
98 int snap_do_cow(struct inode *inode, ino_t parent_ino, int del)
100 struct snap_cache *cache;
102 struct inode *ind = NULL;
103 struct snapshot_operations *snapops;
106 CDEBUG(D_SNAP, "snap_do_cow, ino %ld\n", inode->i_ino);
108 cache = snap_find_cache(inode->i_dev);
112 snapops = filter_c2csnapops(cache->cache_filter);
113 if (!snapops || !snapops->create_indirect) {
117 snap_last(cache, &snap);
118 ind = snapops->create_indirect(inode, snap.index, snap.gen, parent_ino, del);
121 init_filter_data(ind, 0);
122 set_filter_ops(cache, ind);
127 int snap_iterate(struct super_block *sb,
128 int (*repeat)(struct inode *inode, void *priv),
129 struct inode **start, void *priv, int flag)
131 struct inode *inode = sb->s_root->d_inode;
132 struct snap_cache *cache;
133 struct snapshot_operations *snapops;
137 cache = snap_find_cache(inode->i_dev);
141 snapops = filter_c2csnapops(cache->cache_filter);
142 if (!snapops || !snapops->iterate) {
146 return snapops->iterate(sb, repeat, start, priv, flag);
149 int snap_destroy_indirect(struct inode *pri, int index, struct inode *next_ind )
151 struct snap_cache *cache;
152 struct snapshot_operations *snapops;
155 cache = snap_find_cache(pri->i_dev);
158 snapops = filter_c2csnapops(cache->cache_filter);
159 if (!snapops || !snapops->destroy_indirect)
162 return snapops->destroy_indirect(pri, index, next_ind);
165 int snap_restore_indirect(struct inode *pri, int index )
167 struct snap_cache *cache;
168 struct snapshot_operations *snapops;
172 cache = snap_find_cache(pri->i_dev);
176 snapops = filter_c2csnapops(cache->cache_filter);
177 if (!snapops || !snapops->restore_indirect)
180 return snapops->restore_indirect(pri, index);
183 struct inode *snap_get_indirect(struct inode *pri, int *table, int slot)
185 struct snap_cache *cache;
186 struct snapshot_operations *snapops;
190 cache = snap_find_cache(pri->i_dev);
194 snapops = filter_c2csnapops(cache->cache_filter);
195 if (!snapops || !snapops->get_indirect)
198 return snapops->get_indirect(pri, table, slot);
201 int snap_set_indirect(struct inode *pri, ino_t ind_ino, int index, ino_t parent_ino)
203 struct snap_cache *cache;
204 struct snapshot_operations *snapops;
208 cache = snap_find_cache(pri->i_dev);
212 snapops = filter_c2csnapops(cache->cache_filter);
213 if (!snapops || !snapops->set_indirect)
217 return snapops->set_indirect(pri, ind_ino, index, parent_ino);