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;
44 static ssize_t currentfs_write (struct file *filp, const char *buf,
45 size_t count, loff_t *ppos)
47 struct snap_cache *cache;
48 struct inode *inode = filp->f_dentry->d_inode;
49 struct file_operations *fops;
50 long block[2]={-1,-1};
51 struct snap_table *table;
52 struct inode *cache_inode = NULL;
53 struct snapshot_operations *snapops;
54 int slot = 0, index = 0, result = 0;
61 if (currentfs_is_under_dotsnap(filp->f_dentry))
64 cache = snap_find_cache(inode->i_dev);
68 if ( snap_needs_cow(inode) != -1 ) {
69 CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
70 snap_do_cow(inode, filp->f_dentry->d_parent->d_inode->i_ino, 0);
73 fops = filter_c2cffops(cache->cache_filter);
74 if (!fops || !fops->write)
77 if (filp->f_flags & O_APPEND)
86 * we only need to copy back the first and last blocks
88 mask = inode->i_sb->s_blocksize-1;
90 block[0] = pos >> inode->i_sb->s_blocksize_bits;
93 block[1] = pos >> inode->i_sb->s_blocksize_bits;
94 if( block[0] == block[1] )
97 snapops = filter_c2csnapops(cache->cache_filter);
99 for (i = 0; i < 2; i++) {
102 table = &snap_tables[cache->cache_snap_tableno];
103 /*Find the nearest block in snaptable and copy back it*/
104 for (slot = table->tbl_count - 1; slot >= 1; slot--) {
106 index = table->snap_items[slot].index;
107 cache_inode = snap_get_indirect(inode, NULL, index);
109 if (!cache_inode) continue;
111 CDEBUG(D_SNAP, "find cache_ino %lu\n", cache_inode->i_ino);
113 if (snapops && snapops->copy_block) {
114 result = snapops->copy_block(inode, cache_inode, block[i]);
116 CDEBUG(D_SNAP, "copy block %lu back from ind %lu to %lu\n",
117 block[i], cache_inode->i_ino, inode->i_ino);
131 rc = fops->write(filp, buf, count, ppos);
136 static int currentfs_readpage(struct file *file, struct page *page)
139 struct inode *inode = file->f_dentry->d_inode;
140 unsigned long ind_ino = inode->i_ino;
141 struct inode *pri_inode = NULL;
142 struct inode *cache_inode = NULL;
143 struct file open_file;
144 struct dentry open_dentry ;
145 struct address_space_operations *c_aops;
146 struct snap_cache *cache;
148 struct snap_table *table;
151 int search_older = 0;
155 cache = snap_find_cache(inode->i_dev);
160 c_aops = filter_c2cfaops(cache->cache_filter);
162 block = page->index >> inode->i_sb->s_blocksize_bits;
164 /* if there is a block in the cache, return the cache readpage */
165 if( inode->i_blocks && c_aops->bmap(inode->i_mapping, block) ) {
166 CDEBUG(D_SNAP, "block %lu in cache, ino %lu\n",
167 block, inode->i_ino);
168 result = c_aops->readpage(file, page);
173 * clonefs_readpage will fill this with primary ino number
174 * we need it to follow the cloned chain of primary inode
176 if( file->f_dentry->d_fsdata ){
177 pri_inode = iget(inode->i_sb, (unsigned long)file->f_dentry->d_fsdata);
184 table = &snap_tables[cache->cache_snap_tableno];
186 for (slot = table->tbl_count - 1; slot >= 1; slot--) {
188 index = table->snap_items[slot].index;
189 cache_inode = snap_get_indirect(inode, NULL, index);
191 if (!cache_inode ) continue;
193 /* we only want slots between cache_inode to the oldest one */
194 if(search_older && cache_inode->i_ino == ind_ino )
197 if (!search_older && c_aops->bmap(cache_inode->i_mapping, block))
207 currentfs_prepare_snapfile(inode, file, cache_inode, &open_file,
210 down(&cache_inode->i_sem);
212 if( c_aops->readpage ) {
213 CDEBUG(D_SNAP, "block %lu NOT in cache, use redirected ino %lu\n",
214 block, cache_inode->i_ino );
215 result = c_aops->readpage(&open_file, page);
217 CDEBUG(D_SNAP, "cache ino %lu, readpage is NULL\n",
220 up(&cache_inode->i_sem);
221 currentfs_restore_snapfile(inode, file, cache_inode, &open_file);
225 struct address_space_operations currentfs_file_aops = {
226 readpage: currentfs_readpage,
229 struct file_operations currentfs_file_fops = {
230 write: currentfs_write,
233 struct inode_operations currentfs_file_iops = {