Whamcloud - gitweb
1)update snapfs, add more hooks for dir ops, some fixes for snap setup.
[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 #define COWED_NAME_LEN       (7 + 8 + 1) 
100 static int smfs_init_cowed_dir(struct super_block *sb, struct dentry* cowed_dir)  
101 {
102         struct snap_info *snap_info = S2SNAPI(sb);      
103         struct dentry    *dentry = NULL;
104         struct lvfs_run_ctxt saved;
105         char   name[COWED_NAME_LEN];
106         int    rc = 0;
107         ENTRY;
108          
109         sprintf(name, ".cowed_%08x", (__u32)cowed_dir->d_inode->i_ino);
110         push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
111         dentry = simple_mkdir(cowed_dir, name, 0777, 1);
112         pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
113         if (IS_ERR(dentry)) {
114                 rc = PTR_ERR(dentry);
115                 CERROR("create cowed directory: rc = %d\n", rc);
116                 RETURN(rc);
117         }
118         snap_info->sn_cowed_dentry = dentry;
119         RETURN(rc);
120 }
121 int smfs_start_cow(struct super_block *sb)
122 {
123         struct smfs_super_info *smfs_info = S2SMI(sb);
124         int rc = 0;
125
126         ENTRY;
127         OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
128      
129         if (!smfs_info->smsi_snap_info) 
130                 RETURN(-ENOMEM);
131         
132         /*init snap fsfilt operations*/
133         if (!S2SNAPI(sb)->snap_cache_fsfilt) {
134                 char *snap_cache_ftype = NULL;
135                 int   tmp = strlen(S2SMI(sb)->smsi_cache_ftype) + strlen("_snap");
136                 
137                 OBD_ALLOC(snap_cache_ftype, tmp + 1);  
138                 sprintf(snap_cache_ftype, "%s_snap", S2SMI(sb)->smsi_cache_ftype);
139                 S2SNAPI(sb)->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
140                 OBD_FREE(snap_cache_ftype, tmp + 1);
141                 if (!S2SNAPI(sb)->snap_cache_fsfilt) {
142                         CERROR("Can not get %s fsfilt ops needed by snap\n",
143                                snap_cache_ftype);
144                         RETURN(-EINVAL);
145                 }
146         }
147         if (!S2SNAPI(sb)->snap_fsfilt) {
148                 char *snap_ftype = NULL;
149                 int   tmp = strlen(S2SMI(sb)->smsi_ftype) + strlen("_snap");
150                 
151                 OBD_ALLOC(snap_ftype, tmp + 1);  
152                 sprintf(snap_ftype, "%s_snap", S2SMI(sb)->smsi_ftype);
153                 S2SNAPI(sb)->snap_fsfilt = fsfilt_get_ops(snap_ftype);
154                 OBD_FREE(snap_ftype, tmp + 1);
155                 if (!S2SNAPI(sb)->snap_fsfilt) {
156                         CERROR("Can not get %s fsfilt ops needed by snap\n",
157                                snap_ftype);
158                         RETURN(-EINVAL);
159                 }
160         }
161         rc = smfs_init_snaptabe(sb); 
162         if (rc) {
163                 CERROR("can not init snaptable rc=%d\n", rc);
164                 RETURN(rc);
165         }
166         /*init cowed dir to put the primary cowed inode
167          *FIXME-WANGDI, later the s_root may not be the 
168          *snap dir, we can indicate any dir to be cowed*/
169         rc = smfs_init_cowed_dir(sb, sb->s_root);
170         RETURN(rc);
171 }
172 EXPORT_SYMBOL(smfs_start_cow);
173 int smfs_stop_cow(struct super_block *sb)
174 {
175         struct snap_info       *snap_info = S2SNAPI(sb);        
176         struct snap_table      *snap_table = snap_info->sntbl;  
177         int rc = 0, table_size;
178         ENTRY;
179
180         l_dput(snap_info->sn_cowed_dentry);
181          
182         if (snap_info->snap_fsfilt) 
183                 fsfilt_put_ops(snap_info->snap_fsfilt);
184         if (snap_info->snap_cache_fsfilt)
185                 fsfilt_put_ops(snap_info->snap_cache_fsfilt);
186
187         if (snap_table) {
188                 table_size =  SNAPTABLE_SIZE(snap_table->sntbl_max_count);
189                 OBD_FREE(snap_info->sntbl, table_size);
190         }
191         if (snap_info) 
192                OBD_FREE(snap_info, sizeof(*snap_info)); 
193         
194         RETURN(rc);
195 }
196 EXPORT_SYMBOL(smfs_stop_cow);
197
198 int smfs_cow_init(struct super_block *sb)
199 {
200         struct smfs_super_info *smfs_info = S2SMI(sb);
201         int rc = 0;
202
203         SMFS_SET_COW(smfs_info);
204       
205         RETURN(rc);
206 }
207
208 int smfs_cow_cleanup(struct super_block *sb)
209 {
210         ENTRY;
211         SMFS_CLEAN_COW(S2SMI(sb));
212         RETURN(0);
213 }
214
215 /*FIXME Note indirect and primary inode 
216 * should be recorgnized here*/
217 int smfs_init_snap_inode_info(struct inode *inode, int flags)
218 {
219         int vallen, rc = 0;
220         ENTRY;
221
222         if (SMFS_DO_COW(S2SMI(inode->i_sb)) &&
223             (flags & SM_DO_COW)) {
224                 struct snap_inode_info *sni_info = I2SNAPI(inode);
225                 struct fsfilt_operations *snapops = I2SNAPOPS(inode);
226                 
227                 sni_info->sn_flags = flags;
228                 vallen = sizeof(sni_info->sn_gen);
229
230                 rc = snapops->fs_get_snap_info(NULL, inode, SNAP_GENERATION,
231                                                strlen(SNAP_GENERATION),
232                                                &sni_info->sn_gen, &vallen);               
233         } 
234         RETURN(rc);                                              
235          
236 }
237 /* latest snap: returns 
238    -  the index of the latest snapshot before NOW
239    -  hence it returns 0 in case all the volume snapshots lie in the future
240    -  this is the index where a COW will land (will be created) 
241 */
242 void snap_last(struct super_block *sb, struct snap *snap)
243 {
244         struct snap_info *snap_info = S2SNAPI(sb);
245         struct snap_table *table = snap_info->sntbl;
246         time_t now = CURRENT_TIME;
247         int i ;
248
249         ENTRY;
250         /* start at the highest index in the superblock snaptime array */ 
251         if (table->sntbl_count == 0) {
252                memset(snap, 0, sizeof(struct snap)); 
253         } else {
254                 i = table->sntbl_count - 1;
255                 snap->sn_index = table->sntbl_items[i].sn_index;
256                 snap->sn_time = table->sntbl_items[i].sn_time;
257                 snap->sn_gen = table->sntbl_items[i].sn_gen;
258         }
259         CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
260                snap->sn_index, snap->sn_time, now);
261         EXIT;
262         return;
263 }
264
265 static int inline get_index_of_item(struct snap_table *table, char *name)
266 {
267         int count = table->sntbl_count;
268         int i, j;
269         ENTRY;
270         
271         for (i = 0; i < table->sntbl_max_count; i++) { 
272                 if (!strcmp(name, table->sntbl_items[i].sn_name)) {
273                         CERROR("Duplicate name %s in snaptable\n", name); 
274                         RETURN(-EINVAL);
275                 }       
276         }
277
278         for (i = 0; i < table->sntbl_max_count; i++) {
279                 int found = 0;
280                 for (j = 0; j < (count + 1); j++) {
281                         if (table->sntbl_items[j].sn_index == i) {
282                                 found = 1;
283                                 break;  
284                         }
285                 }
286                 if (!found)
287                         RETURN(i);
288         }
289         CERROR("snaptable Full\n");
290         RETURN(-ENOSPC);
291 }
292
293 int smfs_add_snap_item(struct super_block *sb, char *name)
294 {
295         struct snap_info *snap_info = S2SNAPI(sb);
296         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
297         struct snap_table *snap_table = snap_info->sntbl;
298         struct snap      *snap_item;
299         int    table_size, count = 0, index = 0, rc = 0;
300
301         count = snap_table->sntbl_count; 
302         /* XXX Is down this sema necessary*/
303         down_interruptible(&snap_info->sntbl_sema);
304         snap_item = &snap_table->sntbl_items[count];
305
306         /*add item in snap_table set generation*/
307         snap_item->sn_time = CURRENT_TIME;
308         /* find table index */
309         index = get_index_of_item(snap_table, name);
310         if (index < 0) 
311                 GOTO(exit, rc = index);
312         
313         snap_item->sn_index = index;
314         snap_item->sn_flags = 0;
315         snap_item->sn_gen = snap_table->sntbl_generation + 1; 
316         memcpy(snap_item->sn_name, name, SNAP_MAX_NAMELEN);
317         /* Wrote the whole snap_table to disk */
318         table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); 
319         
320         rc = snapops->fs_set_snap_info(sb, NULL, SNAPTABLE_INFO, 
321                                        strlen(SNAPTABLE_INFO),
322                                        snap_table, &table_size);
323         if (rc) {
324                 CERROR("Set snaptable error rc=%d\n", rc);
325                 GOTO(exit, rc);
326         }
327         snap_table->sntbl_count++;
328         snap_table->sntbl_generation++;
329 exit:
330         up(&snap_info->sntbl_sema);
331         RETURN(rc);
332 }
333 EXPORT_SYMBOL(smfs_add_snap_item);
334 /*
335  * Note: this function should be differnet with snap_do_cow.
336  * In smfs_do_cow, we check the EA for whether do cow for that inode.
337  * In smfs_needs_cow, we check whether we do need to do cow. 
338  */
339 int smfs_needs_cow(struct inode *inode)
340 {
341         struct smfs_inode_info  *smi_info = I2SMI(inode); 
342         struct snap_inode_info *snap_info = NULL;
343         struct snap snap;
344         int index = -1;
345         ENTRY;
346
347         snap_info = &(smi_info->sm_sninfo);
348         
349         snap_last(inode->i_sb, &snap);
350         /* decision .... if the snapshot is more recent than the object,
351          * then any change to the object should cause a COW.
352          */
353         if (snap_info->sn_gen < snap.sn_gen ) 
354                 index = snap.sn_index;
355
356         CDEBUG(D_INFO, "snap_needs_cow, ino %lu , get index %d\n",
357                inode->i_ino, index);
358
359         RETURN(index);
360 } /* snap_needs_cow */
361
362 static int link_cowed_inode(struct inode *inode)
363 {
364         struct snap_info *snap_info = S2SNAPI(inode->i_sb);     
365         struct dentry *cowed_dir = NULL;
366         char fidname[LL_FID_NAMELEN];
367         int fidlen = 0, rc = 0;
368         struct dentry *dchild = NULL;
369         struct dentry *tmp = NULL;
370         unsigned mode;
371
372         cowed_dir = snap_info->sn_cowed_dentry;
373         
374         fidlen = ll_fid2str(fidname, inode->i_ino, inode->i_generation);
375
376         down(&cowed_dir->d_inode->i_sem);
377         dchild = ll_lookup_one_len(fidname, cowed_dir, fidlen);
378         if (IS_ERR(dchild)) {
379                 rc = PTR_ERR(dchild);
380                 if (rc != -EPERM && rc != -EACCES)
381                         CERROR("child lookup error %d\n", rc);
382                 GOTO(out_lock, rc);
383         }
384         if (dchild->d_inode != NULL) {
385                 CERROR("re-cowed file %s?\n", dchild->d_name.name);
386                 LASSERT(dchild->d_inode == inode);
387                 GOTO(out_dput, rc = 0);
388         }
389         tmp = pre_smfs_dentry(NULL, inode, cowed_dir);
390         /* link() is semanticaly-wrong for S_IFDIR, so we set S_IFREG
391          * for linking and return real mode back then -bzzz */
392         mode = inode->i_mode;
393         inode->i_mode = S_IFREG;
394         rc = vfs_link(tmp, cowed_dir->d_inode, dchild);
395         post_smfs_dentry(tmp);
396         if (rc) {
397                 CERROR("error linking cowed inode %s to COWED: rc = %d\n",
398                         fidname, rc);
399         } 
400         inode->i_mode = mode;
401         if ((mode & S_IFMT) == S_IFDIR) {
402                 dchild->d_inode->i_nlink++;
403                 cowed_dir->d_inode->i_nlink++;
404         }
405         mark_inode_dirty(dchild->d_inode);
406 out_dput:
407         dput(dchild);
408 out_lock:       
409         up(&cowed_dir->d_inode->i_sem);
410         RETURN(rc);
411 }
412 /*
413  * Make a copy of the data and plug a redirector in between if there
414  * is no redirector yet.
415  */
416 int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
417 {
418         struct snap_info *snap_info = S2SNAPI(inode->i_sb);     
419         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
420         struct snap snap;
421         struct inode *ind = NULL;
422
423         ENTRY;
424
425         if (!snapops || !snapops->fs_create_indirect) 
426                 RETURN(-EINVAL);
427
428         snap_last(inode->i_sb, &snap);
429         ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen, 
430                                           dparent->d_inode, del);
431         if(!ind)
432                 RETURN(-EINVAL);
433         if (!SMFS_DO_INODE_COWED(inode)) {
434                 /*insert the inode to cowed inode*/
435                 SMFS_SET_INODE_COWED(inode); 
436                 link_cowed_inode(inode); 
437         }
438         
439         I2SMI(ind)->sm_sninfo.sn_flags = 0;
440         I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen;
441         
442         iput(ind);
443         RETURN(0);
444 }
445 /*Dir inode will do cow*/
446 int smfs_cow_create(struct inode *dir, struct dentry *dentry)
447 {
448         int rc = 0;
449         struct dentry *dparent;
450         ENTRY;
451
452         if (smfs_needs_cow(dir) != -1) {
453                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
454                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
455                 dparent = dentry->d_parent->d_parent;
456                 if ((snap_do_cow(dir, dparent, 0))) {
457                         CERROR("Do cow error\n");
458                         RETURN(-EINVAL);
459                 }
460         }
461         RETURN(rc);
462 }
463
464 int smfs_cow_setattr(struct inode *dir, struct dentry *dentry)
465 {
466         int rc = 0;
467         ENTRY;
468         if (smfs_needs_cow(dir) != -1) {
469                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
470                 if ((snap_do_cow(dir, dentry->d_parent, 0))) {
471                         CERROR("Do cow error\n");
472                         RETURN(-EINVAL);
473                 }
474         }
475         RETURN(rc);
476 }
477
478 int smfs_cow_link(struct inode *dir, struct dentry *dentry)
479 {
480         int rc = 0;
481         struct dentry *dparent;
482         ENTRY;
483  
484         if (smfs_needs_cow(dir) != -1) {
485                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
486                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
487                 dparent = dentry->d_parent->d_parent;
488                 if ((snap_do_cow(dir, dparent, 0))) {
489                         CERROR("Do cow error\n");
490                         RETURN(-EINVAL);
491                 }
492                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 0))) {
493                         CERROR("Do cow error\n");
494                         RETURN(-EINVAL);
495                 }
496         }
497         RETURN(rc);
498 }
499
500 int smfs_cow_unlink(struct inode *dir, struct dentry *dentry)
501 {
502         struct dentry *dparent;
503         int rc = 0;
504         ENTRY;
505
506         if (smfs_needs_cow(dir) != -1) {
507                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
508                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
509                 dparent = dentry->d_parent->d_parent;
510                 if ((snap_do_cow(dir, dparent, 0))) {
511                         CERROR("Do cow error\n");
512                         RETURN(-EINVAL);
513                 }
514                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 1))) {
515                         CERROR("Do cow error\n");
516                         RETURN(-EINVAL);
517                 }
518         
519         }
520         RETURN(rc);
521 }
522
523 int smfs_cow_rename(struct inode *dir, struct dentry *dentry)
524 {
525         int rc = 0;
526         ENTRY;
527         
528         RETURN(rc);
529 }
530
531 int smfs_cow_write(struct inode *dir, struct dentry *dentry)
532 {
533         int rc = 0;
534         ENTRY;
535         
536         RETURN(rc);
537 }
538
539 typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry);
540
541 static cow_funcs smfs_cow_funcs[REINT_MAX + 1] = {
542         [REINT_SETATTR] smfs_cow_setattr,
543         [REINT_CREATE]  smfs_cow_create,
544         [REINT_LINK]    smfs_cow_link,
545         [REINT_UNLINK]  smfs_cow_unlink,
546         [REINT_RENAME]  smfs_cow_rename,
547         [REINT_WRITE]   smfs_cow_write,
548 };
549
550 int smfs_cow(struct inode *dir, struct dentry *dentry, int op)
551 {
552         return smfs_cow_funcs[op](dir, dentry);
553 }
554