From 9382ed8ffa3f9f6c6d55775d5b28a87f503c79e2 Mon Sep 17 00:00:00 2001 From: wangdi Date: Sat, 17 Jan 2004 13:46:45 +0000 Subject: [PATCH] put copy_block method of regular file in snapfs module not in kernel patches --- lustre/snapfs/file.c | 215 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 166 insertions(+), 49 deletions(-) diff --git a/lustre/snapfs/file.c b/lustre/snapfs/file.c index dee3eaa..32b7041 100644 --- a/lustre/snapfs/file.c +++ b/lustre/snapfs/file.c @@ -10,35 +10,94 @@ #include #include #include +#include #include #include #include #include "snapfs_internal.h" -/* instantiate a file handle to the cache file */ -static void currentfs_prepare_snapfile(struct inode *inode, - struct file *clone_file, - struct inode *cache_inode, - struct file *cache_file, - struct dentry *cache_dentry) +static int has_pages(struct inode *inode, int index) { - cache_file->f_pos = clone_file->f_pos; - cache_file->f_mode = clone_file->f_mode; - cache_file->f_flags = clone_file->f_flags; - cache_file->f_count = clone_file->f_count; - cache_file->f_owner = clone_file->f_owner; - cache_file->f_dentry = cache_dentry; - cache_file->f_dentry->d_inode = cache_inode; + unsigned long offset = index << PAGE_CACHE_SHIFT; + unsigned long blk_start = offset >> inode->i_sb->s_blocksize_bits; + unsigned long blk_end = (offset + PAGE_CACHE_SIZE) >> inode->i_sb->s_blocksize_bits; + int inside = 0; + + while (blk_start <= blk_end) { + if (inode->i_mapping && inode->i_mapping->a_ops) { + inside = inode->i_mapping->a_ops->bmap(inode->i_mapping, blk_start); + } + blk_start++; + } + return inside; } -/* update the currentfs file struct after IO in cache file */ -static void currentfs_restore_snapfile(struct inode *cache_inode, - struct file *cache_file, - struct inode *clone_inode, - struct file *clone_file) +static int copy_back_page(struct inode *dst, struct inode *src, + int index) { - cache_file->f_pos = clone_file->f_pos; + char *kaddr_src, *kaddr_dst; + struct snap_cache *cache; + struct address_space_operations *c_aops; + struct page *src_page, *dst_page; + int err = 0; + ENTRY; + + if (!has_pages(src, index)) + RETURN(0); + + cache = snap_find_cache(src->i_dev); + if (!cache) + RETURN(-EINVAL); + c_aops = filter_c2cfaops(cache->cache_filter); + + if (!c_aops) + RETURN(-EINVAL); + + src_page = grab_cache_page(src->i_mapping, index); + if (!src_page) { + CERROR("copy block %d from %lu to %lu ENOMEM \n", + index, src->i_ino, dst->i_ino); + RETURN(-ENOMEM); + } + + c_aops->readpage(NULL, src_page); + wait_on_page(src_page); + + kaddr_src = kmap(src_page); + if (!Page_Uptodate(src_page)) { + CERROR("Can not read page index %d of inode %lu\n", + index, src->i_ino); + err = -EIO; + goto unlock_src_page; + } + dst_page = grab_cache_page(dst->i_mapping, index); + if (!dst_page) { + CERROR("copy block %d from %lu to %lu ENOMEM \n", + index, src->i_ino, dst->i_ino); + err = -ENOMEM; + goto unlock_src_page; + } + kaddr_dst = kmap(dst_page); + + err = c_aops->prepare_write(NULL, dst_page, 0, PAGE_CACHE_SIZE); + if (err) + goto unlock_dst_page; + memcpy(kaddr_dst, kaddr_src, PAGE_CACHE_SIZE); + flush_dcache_page(dst_page); + + err = c_aops->commit_write(NULL, dst_page, 0, PAGE_CACHE_SIZE); + if (err) + goto unlock_dst_page; + err = 1; +unlock_dst_page: + kunmap(dst_page); + UnlockPage(dst_page); + page_cache_release(dst_page); +unlock_src_page: + kunmap(src_page); + page_cache_release(src_page); + RETURN(err); } static ssize_t currentfs_write (struct file *filp, const char *buf, @@ -47,12 +106,11 @@ static ssize_t currentfs_write (struct file *filp, const char *buf, struct snap_cache *cache; struct inode *inode = filp->f_dentry->d_inode; struct file_operations *fops; - long block[2]={-1,-1}; + long page[2]={-1,-1}; struct snap_table *table; struct inode *cache_inode = NULL; - struct snapshot_operations *snapops; int slot = 0, index = 0, result = 0; - long mask, i; + long i; ssize_t rc; loff_t pos; @@ -85,6 +143,7 @@ static ssize_t currentfs_write (struct file *filp, const char *buf, /* * we only need to copy back the first and last blocks */ +#if 0 mask = inode->i_sb->s_blocksize-1; if( pos & mask ) block[0] = pos >> inode->i_sb->s_blocksize_bits; @@ -128,27 +187,63 @@ static ssize_t currentfs_write (struct file *filp, const char *buf, iput(cache_inode); } } - rc = fops->write(filp, buf, count, ppos); +#else + if (pos & PAGE_CACHE_MASK) + page[0] = pos >> PAGE_CACHE_SHIFT; + pos += count - 1; + if ((pos+1) & PAGE_CACHE_MASK) + page[1] = pos >> PAGE_CACHE_SHIFT; + if (page[0] == page[1]) + page[1] = -1; + + for (i = 0; i < 2; i++) { + if (page[i] == -1) + continue; + table = &snap_tables[cache->cache_snap_tableno]; + /*Find the nearest page in snaptable and copy back it*/ + for (slot = table->tbl_count - 1; slot >= 1; slot--) { + cache_inode = NULL; + index = table->snap_items[slot].index; + cache_inode = snap_get_indirect(inode, NULL, index); + + if (!cache_inode) continue; + + CDEBUG(D_SNAP, "find cache_ino %lu\n", cache_inode->i_ino); + + result = copy_back_page(inode, cache_inode, page[i]); + if (result == 1) { + CDEBUG(D_SNAP, "copy page%lu back from ind %lu to %lu\n", + page[i], cache_inode->i_ino, inode->i_ino); + iput(cache_inode); + result = 0; + break; + } + if (result < 0) { + iput(cache_inode); + rc = result; + goto exit; + } + iput(cache_inode); + } + } +#endif + rc = fops->write(filp, buf, count, ppos); exit: RETURN(rc); } static int currentfs_readpage(struct file *file, struct page *page) { - int result = 0; struct inode *inode = file->f_dentry->d_inode; unsigned long ind_ino = inode->i_ino; struct inode *pri_inode = NULL; struct inode *cache_inode = NULL; - struct file open_file; - struct dentry open_dentry ; struct address_space_operations *c_aops; struct snap_cache *cache; - long block; struct snap_table *table; - int slot = 0; - int index = 0; - int search_older = 0; + struct page *cache_page = NULL; + int rc = 0, slot = 0, index = 0, search_older = 0; + long block; ENTRY; @@ -162,11 +257,11 @@ static int currentfs_readpage(struct file *file, struct page *page) block = page->index >> inode->i_sb->s_blocksize_bits; /* if there is a block in the cache, return the cache readpage */ - if( inode->i_blocks && c_aops->bmap(inode->i_mapping, block) ) { + if(c_aops->bmap(inode->i_mapping, block) ) { CDEBUG(D_SNAP, "block %lu in cache, ino %lu\n", block, inode->i_ino); - result = c_aops->readpage(file, page); - RETURN(result); + rc = c_aops->readpage(file, page); + RETURN(rc); } /* @@ -198,30 +293,52 @@ static int currentfs_readpage(struct file *file, struct page *page) break; iput(cache_inode); } - if( pri_inode ) - iput(pri_inode); + if (pri_inode) iput(pri_inode); - if ( !cache_inode ) + if (!cache_inode ) RETURN(-EINVAL); - currentfs_prepare_snapfile(inode, file, cache_inode, &open_file, - &open_dentry); - down(&cache_inode->i_sem); - if( c_aops->readpage ) { - CDEBUG(D_SNAP, "block %lu NOT in cache, use redirected ino %lu\n", - block, cache_inode->i_ino ); - result = c_aops->readpage(&open_file, page); - }else { - CDEBUG(D_SNAP, "cache ino %lu, readpage is NULL\n", - cache_inode->i_ino); - } + /*Here we have changed a file to read, + *So we should rewrite generic file read here + *FIXME later, the code is ugly + */ + + cache_page = grab_cache_page(cache_inode->i_mapping, page->index); + if (!cache_page) + GOTO(exit_release, rc = -ENOMEM); + if ((rc = c_aops->readpage(file, cache_page))) + GOTO(exit_release, 0); + + wait_on_page(cache_page); + + if (!Page_Uptodate(cache_page)) + GOTO(exit_release, rc = -EIO); + + memcpy(kmap(page), kmap(cache_page), PAGE_CACHE_SIZE); + + kunmap(cache_page); + page_cache_release(cache_page); + up(&cache_inode->i_sem); - currentfs_restore_snapfile(inode, file, cache_inode, &open_file); iput(cache_inode); - RETURN(result); + + kunmap(page); + SetPageUptodate(page); + UnlockPage(page); + + RETURN(rc); + +exit_release: + if (cache_page) + page_cache_release(cache_page); + up(&cache_inode->i_sem); + iput(cache_inode); + UnlockPage(page); + RETURN(rc); } + struct address_space_operations currentfs_file_aops = { readpage: currentfs_readpage, }; -- 1.8.3.1