Whamcloud - gitweb
b=3031
[fs/lustre-release.git] / lustre / snapfs / snaptable.c
1
2 /*
3  *  snaptable.c
4  *
5  *  Manipulate snapshot tables
6  *
7  */
8
9 #define DEBUG_SUBSYSTEM S_SNAP
10
11 #include <linux/module.h>
12 #include <linux/kmod.h>
13 #include <linux/init.h>
14 #include <linux/fs.h>
15 #include <linux/slab.h>
16 #include <linux/string.h>
17 #include <linux/snap.h>
18 #include <linux/time.h>
19 #include <asm/uaccess.h>
20 #include "snapfs_internal.h" 
21
22
23 struct snap_table snap_tables[SNAP_MAX_TABLES];
24
25 int snap_index2slot(struct snap_table *snap_table, int snap_index)
26 {
27         int slot;
28
29         for ( slot=0 ; slot < snap_table->tbl_count ; slot++ )
30                 if ( snap_table->snap_items[slot].index == snap_index )
31                         return slot;
32         return -1;
33 }
34
35
36
37 /* latest snap: returns 
38    -  the index of the latest snapshot before NOW
39    -  hence it returns 0 in case all the volume snapshots lie in the future
40    -  this is the index where a COW will land (will be created) 
41 */
42
43 void snap_last(struct snap_cache *info, struct snap *snap)
44 {
45         int i ;
46         time_t now = CURRENT_TIME;
47         struct snap_table *table;
48         int tableno = info->cache_snap_tableno;
49
50         ENTRY;
51         if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
52                 CERROR("invalid table no %d\n", tableno);
53                 snap->index = -1;
54         }
55         
56         table = &snap_tables[tableno];
57
58         /* start at the highest index in the superblock 
59            snaptime array */ 
60         i = table->tbl_count - 1;
61
62         /* NOTE: i>0 is an unnecessary check */
63         snap->index = table->snap_items[i].index;
64         snap->time = table->snap_items[i].time;
65         snap->gen = table->snap_items[i].gen;
66         CDEBUG(D_SNAP, "index: %d, time[i]: %ld, now: %ld\n",
67                snap->index, snap->time, now);
68         return;
69 }
70
71 /* return -1 if no COW is needed, otherwise the index of the 
72    clone to COW to is returned
73 */
74
75 int snap_needs_cow(struct inode *inode)
76 {
77         struct snap snap;
78         struct snap_cache *cache;
79         struct filter_inode_info   *filter_info; 
80         int index = -1;
81         ENTRY;
82
83         cache = snap_find_cache(inode->i_dev);
84         if ( !cache ) {
85                 RETURN(index);
86         }
87         filter_info = (struct filter_inode_info *) inode->i_filterdata;
88         /* here we find the time of the last snap to compare with */
89
90         snap_last(cache, &snap);
91         /* decision .... if the snapshot is more recent than the object,
92          * then any change to the object should cause a COW.
93          */
94         if (filter_info && filter_info->generation < snap.gen ) {
95                 index = snap.index;
96         }
97
98         CDEBUG(D_SNAP, "snap_needs_cow, ino %lu , get index %d\n",
99                inode->i_ino, index);
100
101         RETURN(index);
102 } /* snap_needs_cow */
103
104 int snap_print_table(struct ioc_snap_tbl_data *data, char *buf, int *buflen)
105 {
106         struct snap_table *table;
107         struct ioc_snap_tbl_data *stbl_out;
108         int tableno = data->no;
109         int i, rc = 0, nleft = (*buflen);
110
111         char *buf_ptr;
112
113         if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
114                 CERROR("invalid table number %d\n", tableno);
115                 RETURN(-EINVAL);
116         }
117         
118         table = &snap_tables[tableno];
119         stbl_out = (struct ioc_snap_tbl_data *)buf;
120         stbl_out->count = table->tbl_count - 1;
121         stbl_out->no = tableno; 
122         buf_ptr = (char*)stbl_out->snaps; 
123         nleft -= buf_ptr - buf; 
124         for (i = 1; i < table->tbl_count; i++) {
125                 memcpy(buf_ptr, &table->snap_items[i], sizeof(struct snap));
126                 
127                 nleft -= sizeof(struct snap);
128                 if(nleft < 0) { 
129                         CERROR("can not get enough space to print snaptable\n");
130                         rc = -ERANGE;
131                         goto exit; 
132                 } else {
133                         buf_ptr += sizeof(struct snap);
134                 }       
135         }
136 exit:
137         if(nleft > 0) 
138                 (*buflen) = (*buflen) - nleft;
139         return 0;
140 }
141 static int inline get_index_of_item(struct snap_table *table, char *name)
142 {
143         int count = table->tbl_count;
144         int i, j;
145         
146         for (i = 0; i < SNAP_MAX; i++) { 
147                 if (!strcmp(name, table->snap_items[i].name)) 
148                         return -EINVAL; 
149         }
150         for (i = 0; i < SNAP_MAX; i++) {
151                 int found = 0;
152                 for (j = 0; j < (count + 1); j++) {
153                         if (table->snap_items[j].index == i) {
154                                 found = 1;
155                                 break;  
156                         }
157                 }
158                 if (!found)
159                         return i;
160         }
161         return -EINVAL;
162 }
163 /* This function will write one item(a snapshot) to snaptable  
164  * and will also write to disk.
165  */
166 static int snaptable_add_item(struct ioc_snap_tbl_data *data)
167 {
168         struct snap_table               *table;
169         struct snap_disk_table          *disk_snap_table;
170         struct snapshot_operations      *snapops;
171         struct snap_cache               *cache;
172         int                             tableno , index, i, count, rc;
173         
174         if (!(cache = snap_find_cache((kdev_t)data->dev)))
175                 RETURN(-ENODEV);
176
177         snapops = filter_c2csnapops(cache->cache_filter);
178         if (!snapops || !snapops->set_meta_attr)
179                 RETURN(-EINVAL);
180
181         tableno = data->no;
182         if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
183                 CERROR("invalid table number %d\n", tableno);
184                 RETURN(-EINVAL);
185         }
186         table = &snap_tables[tableno];  
187         count = table->tbl_count;
188
189         /* XXX Is down this sema necessary*/
190         down_interruptible(&table->tbl_sema);
191
192         /*add item in snap_table set generation*/
193         table->snap_items[count].gen = table->generation + 1;
194         table->snap_items[count].time = CURRENT_TIME;
195         /* find table index */
196         index = get_index_of_item(table, data->snaps[0].name);
197         if (index < 0) {
198                 CERROR("snaptable full Or Duplicate name in snaptable\n");
199                 GOTO(exit, rc = -EINVAL);
200         }
201         
202         table->snap_items[count].index = index;
203         table->snap_items[count].flags = 0;
204         memcpy(&table->snap_items[count].name[0], 
205                data->snaps[0].name, SNAP_MAX_NAMELEN);
206         /* we will write the whole snap_table to disk */
207         SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
208         if (!disk_snap_table)
209                 GOTO(exit, rc = -ENOMEM);
210         disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC);
211         disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count);
212         disk_snap_table->generation = cpu_to_le32((__u32)table->generation + 1);
213         memset(&disk_snap_table->snap_items[0], 0, 
214                SNAP_MAX * sizeof(struct snap_disk));
215         
216         for (i = 1; i <= count; i++) {
217                 struct snap *item = &table->snap_items[i];
218                 disk_snap_table->snap_items[i-1].time = cpu_to_le64((__u64)item->time);
219                 disk_snap_table->snap_items[i-1].gen = cpu_to_le32((__u32)item->gen);
220                 disk_snap_table->snap_items[i-1].flags = cpu_to_le32((__u32)item->flags);
221                 disk_snap_table->snap_items[i-1].index = cpu_to_le32((__u32)item->index);
222                 memcpy(&disk_snap_table->snap_items[i-1].name , item->name, SNAP_MAX_NAMELEN);
223         }
224         rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
225                                     (char*)disk_snap_table, sizeof(struct snap_disk_table));
226
227         SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
228         table->tbl_count++;
229         table->generation++;
230 exit:
231         up(&table->tbl_sema);
232         RETURN(rc);
233 }
234
235 static int delete_inode(struct inode *primary, void *param)
236 {
237         struct snap_iterdata * data;
238         int tableno = 0;
239         int index = 0;
240         int rc = 0;
241
242         struct inode *redirect;
243         ino_t old_ind = 0;
244         struct snap_table *table;
245         int slot;
246         int delete_slot;
247         int this_index;
248         struct inode *next_ind = NULL;
249         int my_table[SNAP_MAX];
250
251         ENTRY;
252
253         if(!primary) RETURN(0);
254
255         data = (struct snap_iterdata*) param;
256
257         if (data) {
258                 index = data->index;
259                 tableno = data->tableno;
260         }
261
262         CDEBUG(D_SNAP, "delete_inode ino %lu, index %d\n", primary->i_ino, index);
263
264         table = &snap_tables[tableno];
265
266         redirect = snap_get_indirect(primary, NULL, index);
267
268         if (!redirect) {
269                 CDEBUG(D_SNAP, "redirect inode index %d not exist \n", index);
270                 RETURN(0); 
271         }
272         old_ind = redirect->i_ino;
273         iput(redirect);
274
275         /* In destroy indirect inode, we lock the primary inode here */
276         down(&primary->i_sem);  
277         slot = snap_index2slot(table, index) - 1;
278         if (slot > 0) {
279                 this_index = table->snap_items[slot].index;
280                 redirect = snap_get_indirect(primary, NULL, this_index);
281                 if (redirect) { 
282                         iput(redirect);
283                 } else {
284                         snap_set_indirect(primary, old_ind, this_index, 0);
285                         snap_set_indirect(primary, 0, index, 0);
286                         up(&primary->i_sem);            
287                         RETURN(0);
288                 }
289         }
290         
291         delete_slot = snap_index2slot(table, index);
292         for (slot = table->tbl_count - 1; slot > delete_slot; slot --) {
293                 my_table[slot - delete_slot] = table->snap_items[slot].index;
294         }
295         
296         this_index = table->tbl_count - delete_slot - 1;
297         next_ind = snap_get_indirect(primary, my_table, this_index);
298
299         if (next_ind && (next_ind->i_ino == primary->i_ino)) {
300                 iput(next_ind);
301                 next_ind = NULL;
302         }
303         rc = snap_destroy_indirect(primary, index, next_ind);
304
305         up(&primary->i_sem);
306         
307         if (next_ind)   iput(next_ind);
308         
309         if (rc != 0)    
310                 CERROR("snap_destroy_indirect(ino %lu,index %d),ret %d\n",
311                         primary->i_ino, index, rc);
312         RETURN(0);
313 }
314
315 static int snap_delete(struct super_block *sb, struct snap_iterdata *data)
316 {
317         CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
318                 data->dev, data->tableno, data->index, data->time );
319
320         snap_iterate(sb, &delete_inode, NULL, data, SNAP_ITERATE_COWED_INODE);
321         
322         return 0;
323 }
324
325 /* This function will delete one item(a snapshot) in the snaptable  
326  * and will also delete the item in the disk.
327  * FIXME later, this should be in a transaction.
328  */
329 int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
330 {
331         struct snap_table               *table;
332         struct snap_disk_table          *disk_snap_table;
333         struct snapshot_operations      *snapops;
334         struct snap_cache               *cache;
335         int                             tableno = data->tableno; 
336         int                             index, i, del_slot, rc;
337         
338         if (!(cache = snap_find_cache((kdev_t)data->dev)))
339                 RETURN(-ENODEV);
340
341         if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
342                 CERROR("invalid table number %d\n", tableno);
343                 RETURN(-EINVAL);
344         }
345
346         snapops = filter_c2csnapops(cache->cache_filter);
347         if (!snapops || !snapops->set_meta_attr)
348                 RETURN(-EINVAL);
349         
350         index = data->index;
351         if (clonefs_mounted(cache, index)) {
352                 CERROR("Please first umount this clonefs \n");
353                 RETURN(-EBUSY);         
354         }       
355         /*first delete the snapshot
356          * FIXME if snap delete error, how to handle this error*/
357         rc = snap_delete(sb, data);
358         if (rc) 
359                 RETURN(-EINVAL);
360         /*delete item in snaptable */
361         table = &snap_tables[tableno];
362
363         del_slot = snap_index2slot(table, index);
364         if (del_slot < 0)
365                 RETURN(-EINVAL);
366
367         down_interruptible(&table->tbl_sema);
368         
369         SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
370
371         if (!disk_snap_table) {
372                 up(&table->tbl_sema);
373                 RETURN(-ENOMEM);
374         }
375
376         /* we will delete the item  snap_table to disk */
377
378         index = del_slot;
379         /*Move the items after the delete slot forward one step*/
380         memset(&table->snap_items[index], 0, sizeof(struct snap));
381         while(index < table->tbl_count - 1) {
382                 struct snap *item = &table->snap_items[index];
383                         
384                 item->time = table->snap_items[index + 1].time;
385                 item->flags = table->snap_items[index + 1].flags;
386                 item->gen = table->snap_items[index + 1].gen;
387                 item->index = table->snap_items[index + 1].index;
388                 memcpy(&item->name[0], &table->snap_items[index + 1].name[0],
389                        SNAP_MAX_NAMELEN);
390                 index ++;
391         }
392
393         table->tbl_count --;
394                 
395         disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC);
396         disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count - 1);
397         disk_snap_table->generation = cpu_to_le32((__u32)table->generation + 1);
398         memset(&disk_snap_table->snap_items[0], 0, 
399                SNAP_MAX * sizeof(struct snap_disk));
400
401         for (i = 0; i < table->tbl_count - 1; i++) {
402                 struct snap_disk *disk_item = &disk_snap_table->snap_items[i];
403                 struct snap *item = &table->snap_items[i+1];
404                 
405                 disk_item[i].time = cpu_to_le64((__u64)item->time);
406                 disk_item[i].gen = cpu_to_le32((__u32)item->gen);
407                 disk_item[i].flags = cpu_to_le32((__u32)item->flags);
408                 disk_item[i].index = cpu_to_le32((__u32)item->index);
409                 memcpy(&disk_item[i].name , item->name, SNAP_MAX_NAMELEN);
410         }
411
412         rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
413                                     (char*)disk_snap_table, sizeof(struct snap_disk_table));
414
415         SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
416         
417         up(&table->tbl_sema);
418         RETURN(rc);
419 }
420
421 int snapfs_read_snaptable(struct snap_cache *cache, int tableno)
422 {
423         struct snap_table               *table;
424         struct snap_disk_table          *disk_snap_table;
425         struct snapshot_operations      *snapops;
426         int                             i, rc;
427         int                             size = 0;
428
429         
430         snapops = filter_c2csnapops(cache->cache_filter);
431         if (!snapops || !snapops->get_meta_attr)
432                 RETURN(-EINVAL);
433         
434         SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
435
436         size = sizeof(struct snap_disk_table);
437
438         
439         table = &snap_tables[tableno];
440
441         memset(table, 0, sizeof(struct snap_table));
442         init_MUTEX(&table->tbl_sema); 
443
444         /*Initialized table */
445         table->tbl_count = 1;
446         rc = snapops->get_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
447                                (char*)disk_snap_table, &size);
448         if (rc < 0) {
449                 SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
450                 RETURN(rc);
451         }
452         
453         if (le32_to_cpu(disk_snap_table->magic) != DISK_SNAP_TABLE_MAGIC) {
454                 CERROR("On disk snaptable is not right \n");
455                 RETURN(rc);
456         }
457         table->generation = le32_to_cpu(disk_snap_table->generation);
458         table->tbl_count += le32_to_cpu(disk_snap_table->count);
459         for ( i = 0; i < disk_snap_table->count; i++) {
460                 struct snap *item = &table->snap_items[i + 1];
461                 item->time = le64_to_cpu(disk_snap_table->snap_items[i].time);
462                 item->gen = le32_to_cpu(disk_snap_table->snap_items[i].gen);
463                 item->flags = le32_to_cpu(disk_snap_table->snap_items[i].flags);
464                 item->index = le32_to_cpu(disk_snap_table->snap_items[i].index);
465                 memcpy(&item->name[0], &disk_snap_table->snap_items[i].name[0],
466                        SNAP_MAX_NAMELEN);
467         }
468         SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
469         return 0;
470 }
471
472 static int getdata(struct ioc_data *input, void **karg)
473 {
474         void *tmp = NULL;
475
476         if (!input->ioc_inlen || !input->ioc_inbuf) 
477                 return 0;
478
479         SNAP_ALLOC(tmp, input->ioc_inlen);
480         if (!tmp)
481                 RETURN(-ENOMEM);
482
483         CDEBUG(D_SNAP, "snap_alloc:len %d, add %p\n", input->ioc_inlen, tmp);
484
485         memset(tmp, 0, input->ioc_inlen);
486         if (copy_from_user(tmp, input->ioc_inbuf, input->ioc_inlen)) {
487                 CERROR("get inbuf data error \n");
488                 SNAP_FREE(tmp, input->ioc_inlen);
489                 RETURN(-EFAULT);
490         }
491         *karg = tmp;
492
493         return 0;
494 }
495
496 static inline void freedata(void *data, struct ioc_data *input) 
497 {
498         SNAP_FREE(data, input->ioc_inlen);
499         CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", input->ioc_inlen, data);
500 }
501
502 static int get_next_inode(struct inode *pri, void *ino)
503 {
504         static ino_t prev_ino = -1 ;    
505         ino_t this_ino = pri->i_ino;
506         ino_t find_ino = *(ino_t *)ino;
507         ino_t *found = ino; 
508
509         if( find_ino == 0) {
510                 (*found) = this_ino;
511                 return -1;
512         }
513
514         if( find_ino == prev_ino ) {
515                 (*found) = this_ino;
516                 return -1;
517         }
518         else {
519                 prev_ino = this_ino; 
520         }       
521         return 0;
522 }
523
524
525 static int snap_get_next_inode(struct snap_ino_list_data *data, ino_t *found_ino, ino_t *parent_ino)
526 {
527         kdev_t dev = data->dev;
528         ino_t this_ino = data->ino; 
529
530         struct snap_cache *cache;
531
532         struct inode *inode;
533         struct dentry * dentry;
534
535         ENTRY;
536
537         cache = snap_find_cache(dev); 
538         if ( !cache ) {
539                 EXIT;
540                 return -EINVAL;
541         }
542
543         snap_iterate( cache->cache_sb, &get_next_inode, NULL, &(data->ino), 
544                         SNAP_ITERATE_COWED_INODE);
545
546         if( data->ino == this_ino ) {
547                 data->ino = 0;
548         }
549
550         *found_ino = data->ino;
551
552         if( !(*found_ino) )     return 0;
553
554         *parent_ino = 0;
555         inode = iget (cache->cache_sb, *found_ino);
556         if (list_empty(&inode->i_dentry)) {
557                 CERROR("No dentry for ino %lu, Error(XXX)! \n", inode->i_ino);
558                 iput(inode);    
559                 return 0;
560         }
561         else {
562                 dentry = dget(list_entry(inode->i_dentry.next, struct dentry, d_alias));
563         }
564         if( dentry->d_parent->d_inode)  
565                 *parent_ino = dentry->d_parent->d_inode->i_ino;
566         else    
567                 *parent_ino = 0;
568
569         dput(dentry);
570         iput(inode);
571
572         return 0;
573 }
574
575 static int print_inode(struct inode *pri,void *param)
576 {
577         CDEBUG(D_SNAP, "cowed inode list: ino %lu \n", pri->i_ino);
578         return 0;
579 }
580
581 static int snap_print(struct super_block *sb, void *data)
582 {
583         snap_iterate(sb, &print_inode, NULL, data, SNAP_ITERATE_COWED_INODE);
584         return 0;
585 }
586
587 static int delete_new_inode(struct inode *pri, void *param)
588 {
589         struct snap_iterdata * data;
590
591         int index = 1;
592         time_t restore_time = 0xFFFFFFFF;
593
594         ENTRY; 
595
596         if(!pri) 
597                 RETURN(0);
598
599         if(snap_is_redirector(pri))
600                 RETURN(0);
601         
602         data = (struct snap_iterdata*) param;
603
604         if(data) {
605                 index = data->index;
606                 restore_time = data->time;
607         }
608
609         CDEBUG(D_SNAP, "ino %lu, index=%d, time=%lu\n", 
610                         pri->i_ino, index, restore_time);
611
612
613         if( pri->i_mtime > restore_time || pri->i_ctime > restore_time ) {
614                 struct list_head *head = &pri->i_dentry, *pos;
615
616                 CDEBUG(D_SNAP, "snap_restore ino %lu is newer, delete \n",pri->i_ino);
617                 for( pos = head->next; pos != head; pos = pos->next ){
618                         d_drop( list_entry(pos, struct dentry, d_alias) );
619                 }
620                 pri->i_nlink = 0;
621         }
622         RETURN(0);
623 }
624
625 static int restore_inode(struct inode *pri, void *param)
626 {
627         struct snap_iterdata * data;
628         int tableno = 0;
629
630         int index = 1;
631         time_t restore_time = 0xFFFFFFFF;
632
633         struct inode *ind = NULL;
634         int slot;
635         int restore_slot;
636         struct snap_table *table;
637         int restore_index;
638         
639         ENTRY; 
640
641         if(!pri) RETURN(0);
642
643         data = (struct snap_iterdata*) param;
644
645         if(data) {
646                 index = data->index;
647                 tableno  = data->tableno;
648                 restore_time = data->time;
649         }
650
651         CDEBUG(D_SNAP, "ino %lu, index=%d, time=%lu, tableno %d\n", 
652                         pri->i_ino, index, restore_time, tableno);
653
654         /* XXX: should we have = here? */       
655         if(pri->i_mtime > restore_time || pri->i_ctime > restore_time) {
656                 restore_index = index;
657                 table = &snap_tables[tableno];
658                 /* first find if there are indirected at the index */
659                 ind = snap_get_indirect(pri, NULL, index);
660                 /* if not found, get the FIRST index after this and before NOW*/
661                 /* XXX fix this later, now use tbl_count, not NOW */
662                 if(!ind) {
663                         restore_slot = snap_index2slot(table, index);
664                         for(slot = restore_slot; slot <= table->tbl_count; 
665                             slot++) {
666                                 ind = snap_get_indirect (pri, NULL, 
667                                         table->snap_items[slot].index);
668                                 if(ind) {
669                                         restore_index = table->snap_items[slot].index;
670                                         break;
671                                 }
672                         }
673                 }
674
675                 if(ind) {
676                         CDEBUG(D_SNAP, "restore ino %lu with index %d\n",
677                                         pri->i_ino, restore_index);
678                         iput(ind);
679                         snap_restore_indirect(pri, restore_index);
680                         /* XXX */
681                         //delete_inode(pri, param);
682                         snap_destroy_indirect(pri, restore_index, NULL);
683                 }
684                 else {  
685                         CDEBUG(D_SNAP, "ERROR:restore ino %lu\n", pri->i_ino);  
686                 }
687         }
688         else {
689                 CDEBUG(D_SNAP, "ino %lu is older, don't restore\n", pri->i_ino);
690         }
691         RETURN(0);
692 }
693
694 //int snap_restore(struct super_block *sb, void *data)
695 static int snap_restore(struct super_block *sb, struct snap_iterdata *data)
696 {       
697         CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
698                 data->dev, data->tableno, data->index, data->time );
699
700         snap_iterate(sb, &delete_new_inode, NULL, data, SNAP_ITERATE_ALL_INODE);
701         snap_iterate(sb, &restore_inode, NULL, data, SNAP_ITERATE_COWED_INODE );
702         return 0;
703 }
704
705 /* return the index number of a name in a table */
706 int snap_get_index_from_name(int tableno, char *name)
707 {
708         struct snap_table *table;
709         int slot;
710
711         if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
712                 CERROR("invalid table number %d\n", tableno);
713                 return -EINVAL;
714         }
715
716         table = &snap_tables[tableno];
717
718         for ( slot = 0 ; slot < table->tbl_count; slot++) {
719                 if (!strcmp(&table->snap_items[slot].name[0], name)) {
720                         return table->snap_items[slot].index;
721                 }
722         }
723         return -EINVAL;
724 }
725
726 int snap_iterate_func( struct ioc_snap_tbl_data *data, unsigned int cmd)
727 {
728         struct snapshot_operations      *snapops;
729         struct snap_iterdata iterate_data;
730         struct super_block *sb;
731         struct snap_cache *cache;
732         struct snap_table *table;
733         int index, tableno, slot, rc;
734
735         ENTRY;
736         
737         if (!(cache = snap_find_cache((kdev_t)data->dev)))
738                 RETURN(-ENODEV);
739
740         snapops = filter_c2csnapops(cache->cache_filter);
741         if (!snapops || !snapops->set_meta_attr)
742                 RETURN(-EINVAL);
743
744         tableno = data->no;
745         if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
746                 CERROR("invalid table number %d\n", tableno);
747                 RETURN(-EINVAL);
748         }
749
750         sb = cache->cache_sb;
751         table = &snap_tables[tableno];
752         
753         index = snap_get_index_from_name(tableno, data->snaps[0].name);
754         if (index < 0) {
755                 CERROR("Could not find %s in snaptable\n", 
756                        data->snaps[0].name);
757                 RETURN(-EINVAL);
758         }
759         iterate_data.dev = (kdev_t)data->dev;
760         iterate_data.index = index;
761         iterate_data.tableno = tableno;
762         slot = snap_index2slot (table, index);
763         if( slot < 0 ) 
764                 RETURN(-EINVAL);
765         
766         iterate_data.time = table->snap_items[slot].time;
767         CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
768                iterate_data.dev, iterate_data.tableno, 
769                iterate_data.index, iterate_data.time);
770
771         switch (cmd) {
772                 case IOC_SNAP_DEBUG:
773                         rc = snap_print(sb, &iterate_data);     
774                         break;
775                 case IOC_SNAP_DELETE:
776                         rc = snaptable_delete_item(sb, &iterate_data);  
777                         break;
778                 case IOC_SNAP_RESTORE:
779                         rc = snap_restore(sb, &iterate_data);   
780                         break;
781                 default:
782                         CERROR("unrecognized cmd %d \n", cmd);
783                         rc = -EINVAL;
784                         break;
785         }
786         RETURN(rc);
787 }
788
789 #define BUF_SIZE 1024
790 int snap_ioctl (struct inode * inode, struct file * filp, 
791                             unsigned int cmd, unsigned long arg)
792 {
793         struct ioc_data input; 
794         void *karg = NULL;
795         int rc = 0;
796         kdev_t dev;
797
798         ENTRY;  
799
800         dev = MINOR(inode->i_rdev);
801         if (dev != SNAP_PSDEV_MINOR)
802                 RETURN(-ENODEV);
803
804         if (!inode) {
805                 CDEBUG(D_IOCTL, "invalid inode\n");
806                 RETURN(-EINVAL);
807         }
808
809         if ( _IOC_TYPE(cmd) != IOC_SNAP_TYPE || 
810              _IOC_NR(cmd) < IOC_SNAP_MIN_NR  || 
811              _IOC_NR(cmd) > IOC_SNAP_MAX_NR ) {
812                 /*FIXME: Sometimes Gettimeof the day will come here
813                  * still do not know the reason*/
814                 CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
815                                 _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
816                 RETURN(0);
817         }
818
819         /* get data structures */
820         rc = copy_from_user(&input, (void *)arg, sizeof(input));
821         if (rc) RETURN(rc);
822
823         /* get data from the input data*/
824         rc = getdata(&input, &karg);
825         if (rc) RETURN(rc);
826
827         switch (cmd) {
828         case IOC_SNAP_ADD: {
829                 rc = snaptable_add_item(karg);
830                 break;
831         }
832         case IOC_SNAP_PRINTTABLE: {
833                 struct ioc_data *output;
834                 char   *tmp;
835                 
836                 SNAP_ALLOC(tmp, BUF_SIZE);
837                 output=(struct ioc_data*)tmp;
838                 output->ioc_inbuf = output->ioc_bulk;
839                 output->ioc_inlen = BUF_SIZE - sizeof(int) - sizeof(unsigned long);
840                 snap_print_table(karg, output->ioc_inbuf, &(output->ioc_inlen));
841                 
842                 rc = copy_to_user((char *)arg, output, 
843                                   (output->ioc_inlen + sizeof(int) + sizeof(unsigned long)));
844                 SNAP_FREE(tmp, BUF_SIZE);
845
846                 break;
847         }
848         case IOC_SNAP_GETINDEXFROMNAME: {
849                 int index = 0;
850                 char name[SNAP_MAX_NAMELEN];
851                 int tableno = 0; 
852                 struct snap_cache *cache;
853                 kdev_t dev;
854                 int name_len;
855
856                 struct get_index_struct {
857                         kdev_t dev;
858                         char name[SNAP_MAX_NAMELEN];
859                 };
860
861                 struct get_index_struct *data = karg;
862         
863                 name_len = input.ioc_inlen - sizeof(kdev_t);    
864                 dev = data->dev;
865                 memset(name, 0, SNAP_MAX_NAMELEN);      
866                 if(name_len > SNAP_MAX_NAMELEN)
867                         name_len = SNAP_MAX_NAMELEN;
868                 if(name_len < 0 ) 
869                         name_len = 0;
870                 /*for(i=0 ; i< name_len; i++) {
871                         name[i] = data->name[i];
872                 }
873                 */
874                 memcpy(name, data->name, name_len);
875                 printk("dev %d , len %d, name_len %d, find name is [%s]\n", 
876                         dev, input.ioc_inlen, name_len, name);
877                 cache = snap_find_cache(dev); 
878                 if ( !cache ) {
879                         EXIT;
880                         rc = -EINVAL;
881                         break;
882                 }
883                 tableno = cache->cache_snap_tableno;
884
885                 index = snap_get_index_from_name(tableno, name);
886                 rc = copy_to_user((char *)arg, &index, sizeof(index));
887                 break;
888         }
889         case IOC_SNAP_GET_NEXT_INO: { 
890                 struct get_ino_struct{
891                         ino_t found_ino;
892                         ino_t parent_ino;
893                 }get_ino;
894                 get_ino.found_ino = 0;
895                 get_ino.parent_ino = 0;
896                 rc = snap_get_next_inode(karg,  &get_ino.found_ino, &get_ino.parent_ino);
897                 rc = copy_to_user((char *)arg, &get_ino, sizeof(get_ino));
898                 break;
899         }
900         case IOC_SNAP_GET_INO_INFO: { 
901                 struct ioc_ino_info{
902                         kdev_t dev;
903                         ino_t ino;
904                         int index;
905                 };
906                 struct snap_cache *cache;
907                 struct inode *pri;
908                 struct inode *ind;
909                 struct ioc_ino_info *data = karg;
910                 ino_t ind_ino = 0;
911         
912                 cache = snap_find_cache(data->dev); 
913                 if ( !cache ) {
914                         EXIT;
915                         rc = -EINVAL;
916                         break;
917                 }
918                 printk("get_ino_info, dev %d, ino %lu, index %d\n",
919                          data->dev, data->ino, data->index);    
920                 pri = iget(cache->cache_sb, data->ino);
921                 ind = snap_get_indirect(pri, NULL, data->index);
922                 if(ind) {
923                         ind_ino = ind->i_ino;
924                         iput(ind);
925                 }
926                 iput(pri);
927                 printk("get_ino_info, get ind %lu\n", ind_ino);
928                 rc = copy_to_user((char *)arg, &ind_ino, sizeof(ino_t));
929                 break;
930         }
931         case IOC_SNAP_DELETE: 
932         case IOC_SNAP_RESTORE:
933         case IOC_SNAP_DEBUG:
934                 rc = snap_iterate_func(karg, cmd);
935                 break;
936 #ifdef SNAP_DEBUG
937         case IOC_SNAP_DEVFAIL:
938                 snap_debug_failcode = (unsigned int)arg;
939                 break;
940 #endif
941         case IOC_SNAP_SHOW_DOTSNAP: {
942                 struct ioc_show_info{
943                         kdev_t dev;
944                         int show;
945                 };
946                 struct snap_cache *cache;
947                 struct ioc_show_info *data = karg;
948
949                 cache = snap_find_cache(data->dev);
950                 if( !cache ) {
951                         EXIT;
952                         rc = -EINVAL;
953                         break;
954                 }
955                 cache->cache_show_dotsnap = (char)data->show;
956                 CDEBUG(D_IOCTL, "Set show dotsnap: %s\n",
957                         data->show ? "Yes" : "No");
958                 
959                 break;
960         }
961         default:
962                 rc = -EINVAL;
963                 break;
964         }
965
966         freedata(karg, &input);
967         RETURN(rc);
968 }