Whamcloud - gitweb
Fix typo in patch.
[fs/lustre-release.git] / lustre / snapfs / snap.c
1
2 /*
3  *  fs/snap/snap.c
4  *
5  *  A snap shot file system.
6  *
7  */
8
9 #define DEBUG_SUBSYSTEM S_SNAP
10
11 #include <linux/kmod.h>
12 #include <linux/init.h>
13 #include <linux/fs.h>
14 #include <linux/slab.h>
15 #include <linux/string.h>
16 #include <linux/snap.h>
17 #include "snapfs_internal.h" 
18
19 /*
20  * Return true if the inode is a redirector inode.
21  */
22 int snap_is_redirector(struct inode *cache_inode)
23 {
24         struct snap_cache *cache;
25         struct snapshot_operations *snapops;
26
27         cache = snap_find_cache(cache_inode->i_dev);
28         if (!cache) {
29                 return 0;
30         }
31         snapops = filter_c2csnapops(cache->cache_filter);
32         if (!snapops || !snapops->is_redirector) {
33                 return 0;
34         }
35
36         CDEBUG(D_SNAP, "ino %ld\n", cache_inode->i_ino);
37         return snapops->is_redirector(cache_inode);
38 }
39
40 /*
41  * Using a cache inode and clone super block find the real one.
42  */
43 struct inode *snap_redirect(struct inode *cache_inode, 
44                             struct super_block *clone_sb)
45 {
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;
51         int slot = 0;
52         int my_table[SNAP_MAX];
53         int clone_slot;
54
55         ENTRY;
56
57         cache = snap_find_cache(cache_inode->i_dev);
58         if (!cache) {
59                 RETURN(NULL);
60         }
61         snapops = filter_c2csnapops(cache->cache_filter);
62         if (!snapops || !snapops->get_indirect) {
63                 RETURN(NULL);
64         }
65
66         CDEBUG(D_SNAP, "cache ino %ld\n", cache_inode->i_ino);
67         clone_info = (struct snap_clone_info *)&clone_sb->u.generic_sbp;
68
69         table = &snap_tables[clone_info->clone_cache->cache_snap_tableno];
70
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 */
76         if (!redirected) {
77                 int index;
78                 clone_slot = snap_index2slot(table, clone_info->clone_index);
79                 for (slot = table->tbl_count; slot >= clone_slot; slot --) {
80                         my_table[slot-clone_slot+1] = table->snap_items[slot].index;
81                 }
82                 index = table->tbl_count - clone_slot + 1;
83                 redirected = snapops->get_indirect(cache_inode, my_table, index);
84         }
85
86         if (redirected) 
87                 CDEBUG(D_SNAP,"redirected ino %ld\n",redirected->i_ino);
88
89         return redirected;
90 }
91
92 /*
93  * Make a copy of the data and plug a redirector in between if there
94  * is no redirector yet.
95  */
96 int snap_do_cow(struct inode *inode, ino_t parent_ino, int del)
97 {
98         struct snap_cache *cache;
99         struct snap snap;
100         struct inode *ind = NULL;
101         struct snapshot_operations *snapops;
102
103         ENTRY;
104         CDEBUG(D_SNAP, "snap_do_cow, ino %ld\n", inode->i_ino);
105
106         cache = snap_find_cache(inode->i_dev);
107         if (!cache) {
108                 RETURN(-EINVAL);
109         }
110         snapops = filter_c2csnapops(cache->cache_filter);
111         if (!snapops || !snapops->create_indirect) {
112                 RETURN(-EINVAL);
113         }
114
115         snap_last(cache, &snap);
116         ind = snapops->create_indirect(inode, snap.index, 0, parent_ino, del);
117         if(!ind)
118                 RETURN(-EINVAL);                
119         iput(ind);
120         RETURN(0);
121 }
122
123 int snap_iterate(struct super_block *sb,
124                 int (*repeat)(struct inode *inode, void *priv),
125                 struct inode **start, void *priv, int flag)
126 {
127         struct inode *inode = sb->s_root->d_inode;
128         struct snap_cache *cache;
129         struct snapshot_operations *snapops;
130
131         ENTRY;
132
133         cache = snap_find_cache(inode->i_dev);
134         if (!cache) {
135                 RETURN(0);
136         }
137         snapops = filter_c2csnapops(cache->cache_filter);
138         if (!snapops || !snapops->iterate) {
139                 RETURN(0);
140         }
141
142         return snapops->iterate(sb, repeat, start, priv, flag);
143 }
144
145 int snap_destroy_indirect(struct inode *pri, int index, struct inode *next_ind )
146 {
147         struct snap_cache *cache;
148         struct snapshot_operations *snapops;
149
150         ENTRY;
151         cache = snap_find_cache(pri->i_dev);
152         if (!cache) 
153                 RETURN(0);
154         snapops = filter_c2csnapops(cache->cache_filter);
155         if (!snapops || !snapops->destroy_indirect) 
156                 RETURN(0);
157
158         return snapops->destroy_indirect(pri, index, next_ind);
159 }
160
161 int snap_restore_indirect(struct inode *pri, int index )
162 {
163         struct snap_cache *cache;
164         struct snapshot_operations *snapops;
165
166         ENTRY;
167
168         cache = snap_find_cache(pri->i_dev);
169         if (!cache) 
170                 RETURN(0);
171
172         snapops = filter_c2csnapops(cache->cache_filter);
173         if (!snapops || !snapops->restore_indirect) 
174                 RETURN(0);
175
176         return snapops->restore_indirect(pri, index);
177 }
178
179 struct inode *snap_get_indirect(struct inode *pri, int *table, int slot)
180 {
181         struct snap_cache *cache;
182         struct snapshot_operations *snapops;
183
184         ENTRY;
185
186         cache = snap_find_cache(pri->i_dev);
187         if (!cache) 
188                 RETURN(NULL);
189         
190         snapops = filter_c2csnapops(cache->cache_filter);
191         if (!snapops || !snapops->get_indirect) 
192                 RETURN(NULL);
193
194         return snapops->get_indirect(pri, table, slot);
195 }
196
197 int snap_set_indirect(struct inode *pri, ino_t ind_ino, int index, ino_t parent_ino)
198 {
199         struct snap_cache *cache;
200         struct snapshot_operations *snapops;
201
202         ENTRY;
203
204         cache = snap_find_cache(pri->i_dev);
205         if (!cache) 
206                 RETURN(-EINVAL);
207         
208         snapops = filter_c2csnapops(cache->cache_filter);
209         if (!snapops || !snapops->set_indirect) 
210                 RETURN(-EINVAL);
211
212         EXIT;
213         return snapops->set_indirect(pri, ind_ino, index, parent_ino);
214 }
215
216