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 /* instantiate a file handle to the cache file */
20 static void currentfs_prepare_snapfile(struct inode *inode,
21 struct file *clone_file,
22 struct inode *cache_inode,
23 struct file *cache_file,
24 struct dentry *cache_dentry)
26 cache_file->f_pos = clone_file->f_pos;
27 cache_file->f_mode = clone_file->f_mode;
28 cache_file->f_flags = clone_file->f_flags;
29 cache_file->f_count = clone_file->f_count;
30 cache_file->f_owner = clone_file->f_owner;
31 cache_file->f_dentry = cache_dentry;
32 cache_file->f_dentry->d_inode = cache_inode;
35 /* update the currentfs file struct after IO in cache file */
36 static void currentfs_restore_snapfile(struct inode *cache_inode,
37 struct file *cache_file,
38 struct inode *clone_inode,
39 struct file *clone_file)
41 cache_file->f_pos = clone_file->f_pos;
45 static ssize_t currentfs_write (struct file *filp, const char *buf,
46 size_t count, loff_t *ppos)
48 struct snap_cache *cache;
49 struct inode *inode = filp->f_dentry->d_inode;
51 struct file_operations *fops;
53 long block[2]={-1,-1}, mask, i;
54 struct snap_table *table;
57 struct address_space_operations *aops;
58 struct inode *cache_inode = NULL;
59 struct snapshot_operations *snapops;
63 if (currentfs_is_under_dotsnap(filp->f_dentry))
66 cache = snap_find_cache(inode->i_dev);
70 if ( snap_needs_cow(inode) != -1 ) {
71 CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
72 snap_do_cow(inode, filp->f_dentry->d_parent->d_inode->i_ino, 0);
75 fops = filter_c2cffops(cache->cache_filter);
76 if (!fops || !fops->write)
79 if (filp->f_flags & O_APPEND)
88 * we only need to copy back the first and last blocks
90 mask = inode->i_sb->s_blocksize-1;
92 block[0] = pos >> inode->i_sb->s_blocksize_bits;
95 block[1] = pos >> inode->i_sb->s_blocksize_bits;
96 if( block[0] == block[1] )
99 aops = filter_c2cfaops(cache->cache_filter);
100 snapops = filter_c2csnapops(cache->cache_filter);
102 for( i=0; i<2; i++ ){
103 if(block[i]!=-1 && aops->bmap(inode->i_mapping, block[i])) {
104 table = &snap_tables[cache->cache_snap_tableno];
105 for (slot = table->tbl_count - 1; slot >= 1; slot--) {
106 struct address_space_operations *c_aops =
107 cache_inode->i_mapping->a_ops;
109 index = table->snap_items[slot].index;
110 cache_inode = snap_get_indirect(inode, NULL, index);
112 if ( !cache_inode ) continue;
114 if (c_aops->bmap(cache_inode->i_mapping, block[i])) {
115 CDEBUG(D_SNAP, "find cache_ino %lu\n",
117 if( snapops && snapops->copy_block) {
118 snapops->copy_block(inode,
119 cache_inode, block[i]);
128 rc = fops->write(filp, buf, count, ppos);
132 static int currentfs_readpage(struct file *file, struct page *page)
135 struct inode *inode = file->f_dentry->d_inode;
136 unsigned long ind_ino = inode->i_ino;
137 struct inode *pri_inode = NULL;
138 struct inode *cache_inode = NULL;
139 struct file open_file;
140 struct dentry open_dentry ;
141 struct address_space_operations *c_aops;
142 struct snap_cache *cache;
144 struct snap_table *table;
147 int search_older = 0;
151 cache = snap_find_cache(inode->i_dev);
156 c_aops = filter_c2cfaops(cache->cache_filter);
158 block = page->index >> inode->i_sb->s_blocksize_bits;
160 /* if there is a block in the cache, return the cache readpage */
161 if( inode->i_blocks && c_aops->bmap(inode->i_mapping, block) ) {
162 CDEBUG(D_SNAP, "block %lu in cache, ino %lu\n",
163 block, inode->i_ino);
164 result = c_aops->readpage(file, page);
169 * clonefs_readpage will fill this with primary ino number
170 * we need it to follow the cloned chain of primary inode
172 if( file->f_dentry->d_fsdata ){
173 pri_inode = iget(inode->i_sb, (unsigned long)file->f_dentry->d_fsdata);
180 table = &snap_tables[cache->cache_snap_tableno];
182 for (slot = table->tbl_count - 1; slot >= 1; slot--)
184 struct address_space_operations *c_aops =
185 cache_inode->i_mapping->a_ops;
187 index = table->snap_items[slot].index;
188 cache_inode = snap_get_indirect(inode, NULL, index);
190 if (!cache_inode ) continue;
192 /* we only want slots between cache_inode to the oldest one */
193 if(search_older && cache_inode->i_ino == ind_ino )
196 if (!search_older && c_aops->bmap(cache_inode->i_mapping, block))
206 currentfs_prepare_snapfile(inode, file, cache_inode, &open_file,
209 down(&cache_inode->i_sem);
211 if( c_aops->readpage ) {
212 CDEBUG(D_SNAP, "block %lu NOT in cache, use redirected ino %lu\n",
213 block, cache_inode->i_ino );
214 result = c_aops->readpage(&open_file, page);
216 CDEBUG(D_SNAP, "cache ino %lu, readpage is NULL\n",
219 up(&cache_inode->i_sem);
220 currentfs_restore_snapfile(inode, file, cache_inode, &open_file);
224 struct address_space_operations currentfs_file_aops = {
225 readpage: currentfs_readpage,
228 struct file_operations currentfs_file_fops = {
229 write: currentfs_write,
232 struct inode_operations currentfs_file_iops = {