2 * dotsnap.c - support for .snap directories
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>
21 #include <linux/filter.h>
22 #include <linux/snapfs.h>
23 #include <linux/snapsupport.h>
25 struct inode_operations dotsnap_inode_operations;
26 struct file_operations dotsnap_file_operations;
28 int currentfs_is_under_dotsnap(struct dentry *de)
32 while(de && de->d_parent != de) {
33 if ( de->d_inode && de->d_inode->i_ino & 0xF0000000 ) {
37 index = (int)de->d_fsdata;
45 void currentfs_dotsnap_read_inode(struct snap_cache *cache,
48 int tableno = cache->cache_snap_tableno;
49 struct snap_table *table;
52 table = &snap_tables[tableno];
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;
64 struct dentry *dotsnap_lookup(struct inode *dir, struct dentry *dentry)
66 struct snap_table *table;
67 struct snap_cache *cache;
73 struct snapshot_operations *snapops;
77 cache = snap_find_cache(dir->i_dev);
79 printk("dotsnap_readdir: cannot find cache\n");
82 return ERR_PTR(-EINVAL);
85 snapops = filter_c2csnapops(cache->cache_filter);
86 if (!snapops || !snapops->get_indirect_ino) {
88 return ERR_PTR(-EINVAL);
91 tableno = cache->cache_snap_tableno;
92 table = &snap_tables[tableno];
94 if( table->tbl_count <= 1 )
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];
107 if( i >= table->tbl_count )
108 return ERR_PTR(-ENOENT);
110 inode = iget(dir->i_sb, dir->i_ino & (~0xF0000000));
113 return ERR_PTR(-EINVAL);
115 ino = snapops->get_indirect_ino(inode, index);
118 if ( ino == -ENOATTR || ino == 0 ) {
119 ino = dir->i_ino & (~0xF0000000);
122 if ( ino == -EINVAL ) {
123 return ERR_PTR(-EINVAL);
125 CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino);
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;
135 static int dotsnap_readdir(struct file * filp,
136 void * dirent, filldir_t filldir)
140 struct snap_cache *cache;
141 struct snap_table *table;
142 struct snapshot_operations *snapops;
146 cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
148 printk("dotsnap_readdir: cannot find cache\n");
149 make_bad_inode(filp->f_dentry->d_inode);
154 snapops = filter_c2csnapops(cache->cache_filter);
155 if (!snapops || !snapops->get_indirect_ino) {
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++) {
168 CDEBUG(D_INODE, "%d\n",i);
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);
175 CDEBUG(D_INODE, "\n");
177 if ( ino == -ENOATTR || ino == 0 ) {
178 ino = filp->f_dentry->d_parent->d_inode->i_ino;
181 CDEBUG(D_INODE, "\n");
182 if ( ino == -EINVAL ) {
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");
200 struct file_operations dotsnap_file_operations = {
201 readdir: dotsnap_readdir, /* readdir */
204 struct inode_operations dotsnap_inode_operations =
206 default_file_ops: &dotsnap_file_operations,
207 lookup: dotsnap_lookup