Whamcloud - gitweb
add snapfs to cvs
[fs/lustre-release.git] / lustre / snapfs / dotsnap.c
1 /*
2  * dotsnap.c - support for .snap directories
3  */
4
5 #define EXPORT_SYMTAB
6
7
8 #define __NO_VERSION__
9 #include <linux/module.h>
10 #include <asm/uaccess.h>
11 #include <linux/sched.h>
12 #include <linux/stat.h>
13 #include <linux/string.h>
14 #include <linux/locks.h>
15 #include <linux/quotaops.h>
16 #include <linux/list.h>
17 #include <linux/file.h>
18 #include <asm/bitops.h>
19 #include <asm/byteorder.h>
20
21 #include <linux/filter.h>
22 #include <linux/snapfs.h>
23 #include <linux/snapsupport.h>
24
25 struct inode_operations dotsnap_inode_operations;
26 struct file_operations dotsnap_file_operations;
27
28 int currentfs_is_under_dotsnap(struct dentry *de) 
29 {
30         int index = 0;
31
32         while(de && de->d_parent != de) {
33                 if ( de->d_inode && de->d_inode->i_ino & 0xF0000000 ) {
34                         EXIT;
35                         return index;
36                 }
37                 index = (int)de->d_fsdata;
38                 de = de->d_parent;
39         }
40
41         EXIT;
42         return 0;
43 }
44
45 void currentfs_dotsnap_read_inode(struct snap_cache *cache, 
46                                   struct inode *inode)
47 {
48         int tableno = cache->cache_snap_tableno; 
49         struct snap_table *table; 
50         ENTRY;
51
52         table = &snap_tables[tableno];
53
54         inode->i_mode = S_IFDIR | 0755 ;
55         inode->i_op = &dotsnap_inode_operations;
56         inode->i_size = table->tbl_count - 1; 
57         /* all except current form a subdirectory and . and .. */
58         inode->i_nlink = table->tbl_count -1 + 2;
59         inode->i_uid = 0;
60         inode->i_gid = 0;
61         EXIT;
62 }
63
64 struct dentry *dotsnap_lookup(struct inode *dir,  struct dentry *dentry)
65 {
66         struct snap_table       *table;
67         struct snap_cache       *cache;
68         int i;
69         int index;
70         int tableno; 
71         ino_t ino;
72         struct inode *inode;
73         struct snapshot_operations *snapops;
74
75         ENTRY;
76
77         cache = snap_find_cache(dir->i_dev);
78         if ( !cache ) {
79                 printk("dotsnap_readdir: cannot find cache\n");
80                 make_bad_inode(dir);
81                 EXIT;
82                 return ERR_PTR(-EINVAL);
83         }
84
85         snapops = filter_c2csnapops(cache->cache_filter);
86         if (!snapops || !snapops->get_indirect_ino) {
87                 EXIT;
88                 return ERR_PTR(-EINVAL);
89         }
90
91         tableno = cache->cache_snap_tableno; 
92         table = &snap_tables[tableno];
93
94         if( table->tbl_count <= 1 )
95                 return NULL;
96         
97         index = table->tbl_index[0]; 
98         for ( i = 1 ; i < table->tbl_count ; i++ ) {
99                 if ( (dentry->d_name.len == strlen(table->tbl_name[i])) &&
100                      (memcmp(dentry->d_name.name, table->tbl_name[i], 
101                              dentry->d_name.len) == 0) ) {
102                         index = table->tbl_index[i]; 
103                         break;
104                 }
105         }
106         
107         if( i >= table->tbl_count )
108                 return ERR_PTR(-ENOENT);
109
110         inode = iget(dir->i_sb, dir->i_ino & (~0xF0000000));
111
112         if ( !inode ) 
113                 return ERR_PTR(-EINVAL);
114
115         ino =  snapops->get_indirect_ino(inode, index);
116         iput(inode); 
117
118         if ( ino == -ENOATTR || ino == 0 ) {
119                 ino = dir->i_ino & (~0xF0000000);
120         }
121
122         if ( ino == -EINVAL ) {
123                 return ERR_PTR(-EINVAL);
124         }
125 CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino);
126
127         inode = iget(dir->i_sb, ino);
128         d_add(dentry, inode); 
129         dentry->d_fsdata = (void*)index;
130         inode->i_op = dentry->d_parent->d_parent->d_inode->i_op;
131         return NULL;
132 }
133
134
135 static int dotsnap_readdir(struct file * filp,
136                            void * dirent, filldir_t filldir)
137 {
138         unsigned int i;
139         int tableno;
140         struct snap_cache *cache;
141         struct snap_table *table; 
142         struct snapshot_operations *snapops;
143
144         ENTRY; 
145
146         cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
147         if ( !cache ) {
148                 printk("dotsnap_readdir: cannot find cache\n");
149                 make_bad_inode(filp->f_dentry->d_inode);
150                 EXIT;
151                 return -EINVAL;
152         }
153
154         snapops = filter_c2csnapops(cache->cache_filter);
155         if (!snapops || !snapops->get_indirect_ino) {
156                 EXIT;
157                 return -EINVAL;
158         }
159
160         tableno = cache->cache_snap_tableno; 
161         table = &snap_tables[tableno];
162         CDEBUG(D_INODE, "\n");  
163         for (i = filp->f_pos ; i < table->tbl_count -1 ; i++) {
164                 int index;
165                 struct inode *inode;
166                 ino_t ino;
167
168                 CDEBUG(D_INODE, "%d\n",i);      
169
170                 inode = filp->f_dentry->d_inode;
171                 index = table->tbl_index[i+1];
172                 ino =  snapops->get_indirect_ino 
173                         (filp->f_dentry->d_inode, index);
174
175                 CDEBUG(D_INODE, "\n");  
176
177                 if ( ino == -ENOATTR || ino == 0 ) {
178                         ino = filp->f_dentry->d_parent->d_inode->i_ino;
179                 }
180
181                 CDEBUG(D_INODE, "\n");  
182                 if ( ino == -EINVAL ) {
183                         return -EINVAL;
184                 }
185
186                 CDEBUG(D_INODE, "Listing %s\n", table->tbl_name[i+1]);  
187                 if (filldir(dirent, table->tbl_name[i+1],
188                             strlen(table->tbl_name[i+1]),
189                             filp->f_pos, ino) < 0){
190                         CDEBUG(D_INODE, "\n");
191                         break;
192                 }
193                 filp->f_pos++;
194         }
195         EXIT;
196         return 0;
197 }
198
199
200 struct file_operations dotsnap_file_operations = {
201         readdir: dotsnap_readdir,        /* readdir */
202 };
203
204 struct inode_operations dotsnap_inode_operations =
205 {
206         default_file_ops: &dotsnap_file_operations,
207         lookup: dotsnap_lookup
208 };