2 * dotsnap.c - support for .snap directories
5 #define DEBUG_SUBSYSTEM S_SNAP
7 #include <linux/module.h>
8 #include <linux/kernel.h>
9 #include <linux/string.h>
10 #include <linux/slab.h>
11 #include <linux/stat.h>
12 #include <linux/unistd.h>
13 #include <linux/jbd.h>
14 #include <linux/ext3_fs.h>
15 #include <linux/snap.h>
17 #include "snapfs_internal.h"
19 struct inode_operations dotsnap_inode_operations;
20 struct file_operations dotsnap_file_operations;
22 int currentfs_is_under_dotsnap(struct dentry *de)
26 while(de && de->d_parent != de) {
27 if ( de->d_inode && de->d_inode->i_ino & 0xF0000000 ) {
31 index = (int)de->d_fsdata;
38 void currentfs_dotsnap_read_inode(struct snap_cache *cache,
41 int tableno = cache->cache_snap_tableno;
42 struct snap_table *table;
45 table = &snap_tables[tableno];
47 inode->i_mode = S_IFDIR | 0755 ;
48 inode->i_op = &dotsnap_inode_operations;
49 inode->i_size = table->tbl_count - 1;
50 /* all except current form a subdirectory and . and .. */
51 inode->i_nlink = table->tbl_count -1 + 2;
57 struct dentry *dotsnap_lookup(struct inode *dir, struct dentry *dentry)
59 struct snap_table *table;
60 struct snap_cache *cache;
66 struct snapshot_operations *snapops;
70 cache = snap_find_cache(dir->i_dev);
72 CERROR("dotsnap_readdir: cannot find cache\n");
74 RETURN(ERR_PTR(-EINVAL));
77 snapops = filter_c2csnapops(cache->cache_filter);
78 if (!snapops || !snapops->get_indirect_ino) {
79 RETURN(ERR_PTR(-EINVAL));
82 tableno = cache->cache_snap_tableno;
83 table = &snap_tables[tableno];
85 if( table->tbl_count <= 1 )
88 index = table->snap_items[0].index;;
89 for ( i = 1 ; i < table->tbl_count ; i++ ) {
90 if ( (dentry->d_name.len == strlen(table->snap_items[i].name)) &&
91 (memcmp(&dentry->d_name.name[0], &table->snap_items[i].name[0],
92 dentry->d_name.len) == 0) ) {
93 index = table->snap_items[i].index;
98 if( i >= table->tbl_count )
99 RETURN(ERR_PTR(-ENOENT));
101 inode = iget(dir->i_sb, dir->i_ino & (~0xF0000000));
104 RETURN(ERR_PTR(-EINVAL));
106 ino = snapops->get_indirect_ino(inode, index);
109 if ( ino == -ENOATTR || ino == 0 ) {
110 ino = dir->i_ino & (~0xF0000000);
113 if ( ino == -EINVAL ) {
114 RETURN(ERR_PTR(-EINVAL));
116 CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino);
118 inode = iget(dir->i_sb, ino);
119 d_add(dentry, inode);
120 dentry->d_fsdata = (void*)index;
121 inode->i_op = dentry->d_parent->d_parent->d_inode->i_op;
126 static int dotsnap_readdir(struct file * filp,
127 void * dirent, filldir_t filldir)
131 struct snap_cache *cache;
132 struct snap_table *table;
133 struct snapshot_operations *snapops;
137 cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
139 CDEBUG(D_INODE, "dotsnap_readdir: cannot find cache\n");
140 make_bad_inode(filp->f_dentry->d_inode);
144 snapops = filter_c2csnapops(cache->cache_filter);
145 if (!snapops || !snapops->get_indirect_ino) {
149 tableno = cache->cache_snap_tableno;
150 table = &snap_tables[tableno];
151 for (i = filp->f_pos ; i < table->tbl_count -1 ; i++) {
157 inode = filp->f_dentry->d_inode;
158 index = table->snap_items[i+1].index;
159 ino = snapops->get_indirect_ino
160 (filp->f_dentry->d_inode, index);
162 if ( ino == -ENOATTR || ino == 0 ) {
163 ino = filp->f_dentry->d_parent->d_inode->i_ino;
166 if ( ino == -EINVAL ) {
170 CDEBUG(D_INODE, "Listing %s\n", &table->snap_items[i+1].name[0]);
171 if (filldir(dirent, &table->snap_items[i+1].name[0],
172 strlen(&table->snap_items[i+1].name[0]),
173 filp->f_pos, ino, 0) < 0){
174 CDEBUG(D_INODE, "\n");
183 struct file_operations dotsnap_file_operations = {
184 readdir: dotsnap_readdir, /* readdir */
187 struct inode_operations dotsnap_inode_operations =
189 lookup: dotsnap_lookup