Whamcloud - gitweb
b592087460da08f4ab1724c9819f8d7d81fc4c05
[fs/lustre-release.git] / lustre / smfs / smfs_cow.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #define DEBUG_SUBSYSTEM S_SM
24
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/string.h>
28 #include <linux/slab.h>
29 #include <linux/stat.h>
30 #include <linux/unistd.h>
31 #include <linux/smp_lock.h>
32 #include <linux/obd_class.h>
33 #include <linux/obd_support.h>
34 #include <linux/lustre_lib.h>
35 #include <linux/lustre_idl.h>
36 #include <linux/lustre_fsfilt.h>
37
38 #include <linux/lustre_snap.h>
39 #include <linux/lustre_smfs.h>
40
41 #include "smfs_internal.h"
42 #define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + size * sizeof(struct snap)) 
43 static int smfs_init_snaptabe(struct super_block *sb)
44 {
45         struct snap_info         *snap_info = S2SNAPI(sb);      
46         struct snap_table        *snap_table = NULL;       
47         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
48         int                      rc = 0, size, table_size, vallen;
49  
50         ENTRY;
51
52         init_MUTEX(&snap_info->sntbl_sema);
53         /*Initialized table */
54         /*get the maxsize of snaptable*/
55         vallen = sizeof(int);
56         rc = snapops->fs_get_snap_info(sb, NULL, MAX_SNAPTABLE_COUNT,
57                                        strlen(MAX_SNAPTABLE_COUNT), &size, 
58                                        &vallen);
59         if (size == 0) {
60                 CERROR("the Max snaptable count should not be zero\n");
61                 RETURN(-EINVAL);
62         }
63         
64         table_size = SNAPTABLE_SIZE(size);
65
66         OBD_ALLOC(snap_info->sntbl, table_size);
67
68         if (!snap_info->sntbl) {
69                 CERROR("No MEM\n");
70                 RETURN(-ENOMEM);
71         }
72         snap_table = snap_info->sntbl;
73          
74         snap_table->sntbl_magic = cpu_to_le32((__u32)SNAPTABLE_MAGIC); 
75         snap_table->sntbl_max_count = size;
76         /*get snaptable info*/
77
78         rc = snapops->fs_get_snap_info(sb, NULL, SNAPTABLE_INFO, 
79                                        strlen(SNAPTABLE_INFO), 
80                                        snap_table, &table_size);       
81         if (rc < 0) {
82                 if (rc == -ENOATTR) {
83                         snap_table->sntbl_count = 0;
84                         CDEBUG(D_INFO, "No snaptable here\n");
85                         RETURN(0);
86                 } else {
87                         CERROR("Can not retrive the snaptable from this filesystem\n");
88                         OBD_FREE(snap_table, table_size);
89                         RETURN(rc); 
90                 }
91         } 
92         if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) {
93                 CERROR("On disk snaptable is not right \n");
94                 OBD_FREE(snap_table, table_size);
95                 RETURN(-EIO);
96         }
97         RETURN(rc);
98 }
99
100 int smfs_cow_init(struct super_block *sb)
101 {
102         struct smfs_super_info *smfs_info = S2SMI(sb);
103         struct inode *inode = sb->s_root->d_inode;
104         int rc = 0;
105
106         SMFS_SET_COW(smfs_info);
107       
108         OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
109      
110         if (!smfs_info->smsi_snap_info) 
111                 RETURN(-ENOMEM);
112         
113         /*init snap fsfilt operations*/
114         if (!S2SNAPI(sb)->snap_cache_fsfilt) {
115                 char *snap_cache_ftype = NULL;
116                 int   tmp = strlen(S2SMI(sb)->smsi_cache_ftype) + strlen("_snap");
117                 
118                 OBD_ALLOC(snap_cache_ftype, tmp + 1);  
119                 sprintf(snap_cache_ftype, "%s_snap", S2SMI(sb)->smsi_cache_ftype);
120                 S2SNAPI(sb)->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
121                 OBD_FREE(snap_cache_ftype, tmp + 1);
122                 if (!S2SNAPI(sb)->snap_cache_fsfilt) {
123                         CERROR("Can not get %s fsfilt ops needed by snap\n",
124                                snap_cache_ftype);
125                         RETURN(-EINVAL);
126                 }
127         }
128         if (!S2SNAPI(sb)->snap_fsfilt) {
129                 char *snap_ftype = NULL;
130                 int   tmp = strlen(S2SMI(sb)->smsi_ftype) + strlen("_snap");
131                 
132                 OBD_ALLOC(snap_ftype, tmp + 1);  
133                 sprintf(snap_ftype, "%s_snap", S2SMI(sb)->smsi_ftype);
134                 S2SNAPI(sb)->snap_fsfilt = fsfilt_get_ops(snap_ftype);
135                 OBD_FREE(snap_ftype, tmp + 1);
136                 if (!S2SNAPI(sb)->snap_fsfilt) {
137                         CERROR("Can not get %s fsfilt ops needed by snap\n",
138                                snap_ftype);
139                         RETURN(-EINVAL);
140                 }
141         }
142         rc = smfs_init_snaptabe(sb); 
143         
144         RETURN(rc);
145 }
146
147 int smfs_cow_cleanup(struct super_block *sb)
148 {
149         struct smfs_super_info *smfs_info = S2SMI(sb);
150         struct snap_info       *snap_info = S2SNAPI(sb);        
151         struct snap_table      *snap_table = snap_info->sntbl;  
152         int rc = 0, table_size;
153         ENTRY;
154
155         SMFS_CLEAN_COW(smfs_info);
156        
157         if (snap_info->snap_fsfilt) 
158                 fsfilt_put_ops(snap_info->snap_fsfilt);
159         if (snap_info->snap_cache_fsfilt)
160                 fsfilt_put_ops(snap_info->snap_cache_fsfilt);
161
162         if (snap_table) {
163                 table_size =  SNAPTABLE_SIZE(snap_table->sntbl_max_count);
164                 OBD_FREE(snap_info->sntbl, table_size);
165         }
166         if (snap_info) 
167                OBD_FREE(snap_info, sizeof(*snap_info)); 
168         
169         RETURN(rc);
170 }
171
172 /*FIXME Note indirect and primary inode 
173 * should be recorgnized here*/
174 int smfs_init_snap_inode_info(struct inode *inode, int flags)
175 {
176         struct snap_inode_info *sni_info = I2SNAPI(inode);
177         struct fsfilt_operations *snapops = I2SNAPOPS(inode);
178         int vallen, rc = 0;
179         ENTRY;
180
181         if (SMFS_DO_COW(S2SMI(inode->i_sb)) &&
182             (flags & SM_DO_COW)) {
183                 sni_info->sn_flags = flags;
184                 vallen = sizeof(sni_info->sn_gen);
185
186                 rc = snapops->fs_get_snap_info(NULL, inode, SNAP_GENERATION,
187                                                strlen(SNAP_GENERATION),
188                                                &sni_info->sn_gen, &vallen);               
189         } 
190         RETURN(rc);                                              
191          
192 }
193 /* latest snap: returns 
194    -  the index of the latest snapshot before NOW
195    -  hence it returns 0 in case all the volume snapshots lie in the future
196    -  this is the index where a COW will land (will be created) 
197 */
198 void snap_last(struct super_block *sb, struct snap *snap)
199 {
200         struct snap_info *snap_info = S2SNAPI(sb);
201         struct snap_table *table = snap_info->sntbl;
202         time_t now = CURRENT_TIME;
203         int i ;
204
205         ENTRY;
206         /* start at the highest index in the superblock snaptime array */ 
207         if (table->sntbl_count == 0) {
208                memset(snap, 0, sizeof(struct snap)); 
209         } else {
210                 i = table->sntbl_count - 1;
211                 snap->sn_index = table->sntbl_items[i].sn_index;
212                 snap->sn_time = table->sntbl_items[i].sn_time;
213                 snap->sn_gen = table->sntbl_items[i].sn_gen;
214         }
215         CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
216                snap->sn_index, snap->sn_time, now);
217         EXIT;
218         return;
219 }
220
221 static int inline get_index_of_item(struct snap_table *table, char *name)
222 {
223         int count = table->sntbl_count;
224         int i, j;
225         ENTRY;
226         
227         for (i = 0; i < table->sntbl_max_count; i++) { 
228                 if (!strcmp(name, table->sntbl_items[i].sn_name)) {
229                         CERROR("Duplicate name %s in snaptable\n", name); 
230                         RETURN(-EINVAL);
231                 }       
232         }
233
234         for (i = 0; i < table->sntbl_max_count; i++) {
235                 int found = 0;
236                 for (j = 0; j < (count + 1); j++) {
237                         if (table->sntbl_items[j].sn_index == i) {
238                                 found = 1;
239                                 break;  
240                         }
241                 }
242                 if (!found)
243                         RETURN(i);
244         }
245         CERROR("snaptable Full\n");
246         RETURN(-ENOSPC);
247 }
248
249 int smfs_add_snap_item(struct super_block *sb, char *name)
250 {
251         struct snap_info *snap_info = S2SNAPI(sb);
252         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
253         struct snap_table *snap_table = snap_info->sntbl;
254         struct snap      *snap_item;
255         int    table_size, count = 0, index = 0, rc = 0;
256
257         count = snap_table->sntbl_count; 
258         /* XXX Is down this sema necessary*/
259         down_interruptible(&snap_info->sntbl_sema);
260         snap_item = &snap_table->sntbl_items[count];
261
262         /*add item in snap_table set generation*/
263         snap_item->sn_time = CURRENT_TIME;
264         /* find table index */
265         index = get_index_of_item(snap_table, name);
266         if (index < 0) 
267                 GOTO(exit, rc = index);
268         
269         snap_item->sn_index = index;
270         snap_item->sn_flags = 0;
271         snap_item->sn_gen = snap_table->sntbl_generation + 1; 
272         memcpy(snap_item->sn_name, name, SNAP_MAX_NAMELEN);
273         /* Wrote the whole snap_table to disk */
274         table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); 
275         
276         rc = snapops->fs_set_snap_info(sb, NULL, SNAPTABLE_INFO, 
277                                        strlen(SNAPTABLE_INFO),
278                                        snap_table, &table_size);
279         if (rc) {
280                 CERROR("Set snaptable error rc=%d\n", rc);
281                 GOTO(exit, rc);
282         }
283         snap_table->sntbl_count++;
284         snap_table->sntbl_generation++;
285 exit:
286         up(&snap_info->sntbl_sema);
287         RETURN(rc);
288 }
289 EXPORT_SYMBOL(smfs_add_snap_item);
290 /*
291  * Note: this function should be differnet with snap_do_cow.
292  * In smfs_do_cow, we check the EA for whether do cow for that inode.
293  * In smfs_needs_cow, we check whether we do need to do cow. 
294  */
295 int smfs_needs_cow(struct inode *inode)
296 {
297         struct smfs_inode_info  *smi_info = I2SMI(inode); 
298         struct snap_inode_info *snap_info = NULL;
299         struct snap snap;
300         int index = -1;
301         ENTRY;
302
303         snap_info = &(smi_info->sm_sninfo);
304         
305         snap_last(inode->i_sb, &snap);
306         /* decision .... if the snapshot is more recent than the object,
307          * then any change to the object should cause a COW.
308          */
309         if (snap_info->sn_gen < snap.sn_gen ) 
310                 index = snap.sn_index;
311
312         CDEBUG(D_INFO, "snap_needs_cow, ino %lu , get index %d\n",
313                inode->i_ino, index);
314
315         RETURN(index);
316 } /* snap_needs_cow */
317
318 /*
319  * Make a copy of the data and plug a redirector in between if there
320  * is no redirector yet.
321  */
322 int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
323 {
324         struct snap_info *snap_info = S2SNAPI(inode->i_sb);     
325         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
326         struct snap snap;
327         struct inode *ind = NULL;
328
329         ENTRY;
330
331         if (!snapops || !snapops->fs_create_indirect) 
332                 RETURN(-EINVAL);
333
334         snap_last(inode->i_sb, &snap);
335         ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen, 
336                                           dparent->d_inode, del);
337         if(!ind)
338                 RETURN(-EINVAL);
339
340         I2SMI(ind)->sm_sninfo.sn_flags = 0;
341         I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen;
342         
343         iput(ind);
344         RETURN(0);
345 }
346
347 int smfs_cow_create(struct inode *dir, struct dentry *dentry)
348 {
349         int rc = 0;
350         ENTRY;
351
352         if (smfs_needs_cow(dir) != -1) {
353                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
354                 if ((snap_do_cow(dir, dentry->d_parent, 0))) {
355                         CERROR("Do cow error\n");
356                         RETURN(-EINVAL);
357                 }
358         }
359         RETURN(rc);
360 }
361
362 int smfs_cow_setattr(struct inode *dir, struct dentry *dentry)
363 {
364         int rc = 0;
365         ENTRY;
366         
367         RETURN(rc);
368 }
369
370 int smfs_cow_link(struct inode *dir, struct dentry *dentry)
371 {
372         int rc = 0;
373         ENTRY;
374         
375         RETURN(rc);
376 }
377
378 int smfs_cow_unlink(struct inode *dir, struct dentry *dentry)
379 {
380         int rc = 0;
381         ENTRY;
382         
383         RETURN(rc);
384 }
385
386 int smfs_cow_rename(struct inode *dir, struct dentry *dentry)
387 {
388         int rc = 0;
389         ENTRY;
390         
391         RETURN(rc);
392 }
393
394 int smfs_cow_write(struct inode *dir, struct dentry *dentry)
395 {
396         int rc = 0;
397         ENTRY;
398         
399         RETURN(rc);
400 }
401
402 typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry);
403
404 static cow_funcs smfs_cow_funcs[REINT_MAX + 1] = {
405         [REINT_SETATTR] smfs_cow_setattr,
406         [REINT_CREATE]  smfs_cow_create,
407         [REINT_LINK]    smfs_cow_link,
408         [REINT_UNLINK]  smfs_cow_unlink,
409         [REINT_RENAME]  smfs_cow_rename,
410         [REINT_WRITE]   smfs_cow_write,
411 };
412
413 int smfs_cow(struct inode *dir, struct dentry *dentry, int op)
414 {
415         return smfs_cow_funcs[op](dir, dentry);
416 }
417