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