From: niu Date: Tue, 27 Jan 2004 01:49:59 +0000 (+0000) Subject: * update b_localprc from HEAD X-Git-Tag: v1_7_100~1^248~50 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=099851831442770ee864a6ac5ceb56e524f67526;p=fs%2Flustre-release.git * update b_localprc from HEAD --- diff --git a/lustre/kernel_patches/patches/snapfs_core-2.4.20.patch b/lustre/kernel_patches/patches/snapfs_core-2.4.20.patch index 4f1067d..60b27d0 100644 --- a/lustre/kernel_patches/patches/snapfs_core-2.4.20.patch +++ b/lustre/kernel_patches/patches/snapfs_core-2.4.20.patch @@ -2,8 +2,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c =================================================================== --- linux-2.4.20-8.orig/fs/ext3/snap.c 2003-01-30 18:24:37.000000000 +0800 -+++ linux-2.4.20-8/fs/ext3/snap.c 2004-01-18 01:48:54.000000000 +0800 -@@ -0,0 +1,2588 @@ ++++ linux-2.4.20-8/fs/ext3/snap.c 2004-01-27 00:07:10.000000000 +0800 +@@ -0,0 +1,2577 @@ +/* fs/ext3/snap.c + * + * Copyright (c) 2002 Cluster File Systems, Inc. @@ -46,6 +46,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c +#define EXT3_MAX_SNAP_DATA (sizeof(struct snap_ea)) +#define EXT3_SNAP_INDEX EXT3_XATTR_INDEX_LUSTRE + ++#define EXT3_SNAP_DEBUG +#ifdef EXT3_SNAP_DEBUG + #define snap_debug(f, a...) \ + do { \ @@ -227,9 +228,10 @@ Index: linux-2.4.20-8/fs/ext3/snap.c +/*SET FLAGS*/ +extern int ext3_bmap(struct address_space *mapping, long block); +extern int ext3_load_inode_bitmap (struct super_block * sb, unsigned int block_group); ++extern int ext3_block_truncate_page(handle_t *handle, struct address_space *mapping, ++ loff_t from); +/* helper functions to manipulate field 'parent' in snap_ea */ -+//static inline int -+static int ++static inline int +set_parent_ino(struct snap_ea *pea, int size, int index, ino_t val) +{ + char * p = (char*) pea; @@ -241,26 +243,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + + return 0; +} -+static inline ino_t -+get_parent_ino(struct snap_ea *pea, int size, int index) -+{ -+ char * p = (char*)pea; -+ int offset; -+ -+ offset = sizeof(ino_t)*2 + (size - sizeof(ino_t)*2)/2; -+ offset += sizeof(ino_t) * index; -+ return *(ino_t*)(p+offset); -+} -+static inline void snap_double_lock(struct inode *i1, struct inode *i2) -+{ -+ double_down(&i1->i_sem, &i2->i_sem); -+} -+ -+static inline void snap_double_unlock(struct inode *i1, struct inode *i2) -+{ -+ double_up(&i1->i_sem, &i2->i_sem); -+} -+ +/* ext3_iterate_cowed_inode: + * iterate all the cowed inode with the same index and + * run the associate function @repeat @@ -424,7 +406,7 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + lock_super(pri->i_sb); + ext3_journal_get_write_access(handle, sbi->s_sbh); + sbi->s_es->s_first_cowed_pri_ino = cpu_to_le32(pri->i_ino); -+ SB_LAST_COWED_INO(pri->i_sb) = cpu_to_le32(pri->i_ino); ++ SB_FIRST_COWED_INO(pri->i_sb) = cpu_to_le32(pri->i_ino); + pri->i_sb->s_dirt = 1; + ext3_journal_dirty_metadata(handle, sbi->s_sbh); + unlock_super(pri->i_sb); @@ -515,7 +497,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + if (inode->i_ino == le32_to_cpu(SB_FIRST_COWED_INO(inode->i_sb))) { + SB_FIRST_COWED_INO(inode->i_sb) = cpu_to_le32(next_ino); + EXT3_I(inode)->i_flags &= ~EXT3_SNAP_PRI_FLAG; -+ ++ if (next_ino == 0) ++ SB_LAST_COWED_INO(inode->i_sb) = 0; + } else { + if (!prev_ino) + goto err_exit; @@ -673,7 +656,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + * Is it right in snapfs EXT3, check it later? + */ + inlist = 0; -+ // ea_size = SNAP_EA_SIZE_FROM_INDEX(index); + } else if (err < 0 || err > EXT3_MAX_SNAP_DATA) { + goto out_unlock; + } @@ -804,8 +786,20 @@ Index: linux-2.4.20-8/fs/ext3/snap.c +{ + return (EXT3_I(inode)->i_file_acl != 0); +} ++/* XXX This function has a very bad effect to ++ * the performance of filesystem, ++ * will find another way to fix it ++ */ ++static void fs_flushinval_pages(handle_t *handle, struct inode* inode) ++{ ++ if (inode->i_blocks > 0 && inode->i_mapping) { ++ fsync_inode_data_buffers(inode); ++ // ext3_block_truncate_page(handle, inode->i_mapping, inode->i_size); ++ truncate_inode_pages(inode->i_mapping, 0); ++ } ++} + -+/* ext3_migrate_data: ++/* ext3_migrate_data2: + * MOVE all the data blocks from inode src to inode dst as well as + * COPY all attributes(meta data) from inode src to inode dst. + * For extended attributes(EA), we COPY all the EAs but skip the Snap EA from src to dst. @@ -826,6 +820,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + if (dst->i_ino == src->i_ino) + return 0; + ++ fs_flushinval_pages(handle, src); ++ + ext3_copy_meta(handle, dst, src); + + snap_debug("migrating data blocks from %lu to %lu\n", src->i_ino, dst->i_ino); @@ -857,7 +853,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + ext3_mark_inode_dirty(handle, src); + ext3_mark_inode_dirty(handle, dst); + -+ truncate_inode_pages(src->i_mapping, 0); + + return SNAP_ERROR(err); +} @@ -1261,9 +1256,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + ext3_journal_stop(handle, pri); +} + -+ -+ -+ +static handle_t * ext3_copy_data(handle_t *handle, struct inode *dst, + struct inode *src, int *has_orphan) +{ @@ -1287,7 +1279,9 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + snap_debug("create_indirect:fail to extend " + "journal, restart trans\n"); + loopfail( 3 ); -+ if( !*has_orphan ){ ++ if(!*has_orphan) { ++ snap_debug("add orphan ino %lu nlink %d to orphan list \n", ++ dst->i_ino, dst->i_nlink); +#ifdef EXT3_ENABLE_SNAP_ORPHAN + add_snap_orphan(handle, dst, src); +#else @@ -1487,9 +1481,11 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + * or ext3_rmdir will report errors "bad dir, no data blocks" + */ + if( S_ISDIR(pri->i_mode)) { -+ handle = ext3_copy_data( handle, pri, ind, &has_orphan ); -+ if( !handle ) ++ handle = ext3_copy_data(handle, pri, ind, &has_orphan); ++ if(!handle) { ++ err = -EINVAL; + goto exit_unlock; ++ } + } + + pri->u.ext3_i.i_flags |= EXT3_DEL_FL; @@ -1526,17 +1522,15 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + * it has been cowed and has ea ) + */ + if( S_ISLNK(ind->i_mode) && -+ (( ind->i_blocks == 0) || (ext3_has_ea(ind) && ind->i_blocks == bpib )) ){ -+ snap_debug("ino %lu is fast symlink\n", -+ pri->i_ino); -+ memcpy(EXT3_I(pri)->i_data, -+ EXT3_I(ind)->i_data, -+ sizeof(EXT3_I(ind)->i_data)); ++ ((ind->i_blocks == 0) || (ext3_has_ea(ind) && ind->i_blocks == bpib))) { ++ snap_debug("ino %lu is fast symlink\n", pri->i_ino); ++ memcpy(EXT3_I(pri)->i_data, EXT3_I(ind)->i_data, ++ sizeof(EXT3_I(ind)->i_data)); + pri->i_size = ind->i_size; + } + else { + handle = ext3_copy_data(handle, pri, ind, &has_orphan); -+ if( !handle ) ++ if (!handle) + goto exit_unlock; + } + } @@ -1564,7 +1558,9 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + pri->i_sb->s_dirt = 1; + unlock_super(pri->i_sb); + } -+ if(has_orphan) { ++ if (has_orphan) { ++ snap_debug("del %lu nlink %d from orphan list\n", ++ ind->i_ino, ind->i_nlink); +#ifdef EXT3_ENABLE_SNAP_ORPHAN + remove_snap_orphan(handle, ind); +#else @@ -1581,9 +1577,19 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + up(&ind->i_sem); + ind->i_nlink = 0; +exit: ++ if (has_orphan) { ++ snap_debug("del %lu nlink %d from orphan list\n", ++ ind->i_ino, ind->i_nlink); ++#ifdef EXT3_ENABLE_SNAP_ORPHAN ++ remove_snap_orphan(handle, ind); ++#else ++ ext3_orphan_del(handle, ind); ++#endif ++ } + iput(ind); + ext3_journal_stop(handle, pri); -+ snap_debug("exiting with error %d\n", err); ++ if (err) ++ snap_err("exiting with error %d\n", err); + return NULL; +} + @@ -1898,59 +1904,58 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + return 0; + + if( pri == pri->i_sb->u.ext3_sb.s_journal_inode ){ -+ printk( KERN_EMERG "TRY TO DESTROY JOURNAL'S IND\n"); ++ snap_err("TRY TO DESTROY JOURNAL'S IND\n"); + return -EINVAL; + } + -+ handle = ext3_journal_start(pri, SNAP_DESTROY_TRANS_BLOCKS); -+ if( !handle ) -+ return -EINVAL; -+ + err = ext3_xattr_get(pri, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR, -+ buf, EXT3_MAX_SNAP_DATA); ++ buf, EXT3_MAX_SNAP_DATA); + if (err < 0) { -+ if (err == -ENODATA) -+ snap_err("inode %lu is not a redirector\n", pri->i_ino); -+ else -+ snap_err(EXT3_SNAP_ATTR " attribute read error\n"); -+ goto err_stop; ++ snap_err("inode %lu attribute read error\n", pri->i_ino); ++ return err; + } + + snaps = (struct snap_ea *)buf; + if ( !snaps->ino[index] ) { + snap_err("for pri ino %lu, index %d, redirect ino is 0\n", + pri->i_ino, index); -+ err = -EINVAL; -+ goto err_stop; ++ return -EINVAL; + } + + snap_debug("for pri ino %lu, reading inode %lu at index %d\n", + pri->i_ino, (ulong)le32_to_cpu(snaps->ino[index]), index); + + ind = iget(pri->i_sb, le32_to_cpu (snaps->ino[index]) ); ++ ++ if ( !ind || IS_ERR(ind) || is_bad_inode(ind)) ++ return -EINVAL; ++ + snap_debug("iget ind %lu, ref count = %d\n", + ind->i_ino, atomic_read(&ind->i_count)); + -+ if ( !ind || IS_ERR(ind) || is_bad_inode(ind) ) { -+ err = -EINVAL; -+ goto err_stop; ++ handle = ext3_journal_start(pri, SNAP_DESTROY_TRANS_BLOCKS); ++ if (!handle) { ++ iput(ind); ++ return -EINVAL; + } -+ + /* if it's block level cow, first copy the blocks back */ + if (EXT3_HAS_COMPAT_FEATURE(pri->i_sb, EXT3_FEATURE_COMPAT_BLOCKCOW) && -+ S_ISREG(pri->i_mode)) { ++ S_ISREG(pri->i_mode)) { + + int blocks; -+ if( !next_ind ) next_ind = pri; ++ if (!next_ind) { ++ next_ind = pri; ++ down(&ind->i_sem); ++ } else { ++ double_down(&next_ind->i_sem, &ind->i_sem); ++ } + blocks = (next_ind->i_size + next_ind->i_sb->s_blocksize-1) + >> next_ind->i_sb->s_blocksize_bits; -+ +#define FAST_MIGRATE_BLOCK +#ifdef FAST_MIGRATE_BLOCK + snap_debug("migrate block back from ino %lu to %lu\n", + ind->i_ino, next_ind->i_ino); + -+ snap_double_lock(next_ind, ind); + for(i = 0; i < blocks; i++) { + if( ext3_bmap(next_ind->i_mapping, i) ) + continue; @@ -1963,36 +1968,22 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + next_ind->i_blocks = calculate_i_blocks( next_ind, blocks); + ext3_mark_inode_dirty(handle, next_ind); + -+ snap_double_unlock(next_ind, ind); -+ -+#if 0 -+ snap_double_lock(pri, ind); -+ -+ for(i = 0; i < blocks; i++) { -+ if( ext3_bmap(pri, i) ) continue; -+ if( !ext3_bmap(ind, i) ) continue; -+ ext3_migrate_block( pri, ind, i) ; -+ } -+ /* Now re-compute the i_blocks */ -+ /* XXX shall we take care of ind here? probably not */ -+ pri->i_blocks = calculate_i_blocks( pri, blocks); -+ mark_inode_dirty(pri); -+ -+ double_unlock(pri, ind); -+#endif +#else -+ snap_double_lock(next_ind, ind); + for (i = 0; i < blocks; i++) { -+ if (ext3_bmap (next_ind->i_mapping, i) ) ++ if (ext3_bmap(next_ind->i_mapping, i)) + continue; -+ if (ext3_copy_block (next_ind, ind, i ) < 0) break; ++ if (ext3_copy_block(next_ind, ind, i ) < 0) ++ break; + } + ext3_mark_inode_dirty(handle, next_ind); -+ double_unlock(next_ind, ind); -+ +#endif -+ } ++ if (next_ind == pri) ++ up(&ind->i_sem); ++ else ++ double_up(&next_ind->i_sem, &ind->i_sem); + ++ } ++ + snap_debug("delete indirect ino %lu\n", ind->i_ino); + snap_debug("iput ind %lu, ref count = %d\n", + ind->i_ino, atomic_read(&ind->i_count)); @@ -2062,7 +2053,6 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + pri->i_ctime = ctime; + ext3_mark_inode_dirty(handle, pri); + } -+err_stop: + ext3_journal_stop(handle, pri); + return err; +} @@ -2098,23 +2088,22 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + /* XXX: check this, ext3_new_inode, the first arg should be "dir" */ + tmp = ext3_new_inode(handle, pri, (int)pri->i_mode, 0); + if(tmp) { -+ snap_double_lock(pri, tmp); ++ double_down(&pri->i_sem, &tmp->i_sem); + ext3_migrate_data(handle, tmp, pri); -+ snap_double_unlock(pri, tmp); ++ double_up(&pri->i_sem, &tmp->i_sem); + + tmp->i_nlink = 0; + iput(tmp); + } + else + snap_err("restore_indirect, new_inode err\n"); -+ -+ snap_double_lock(pri, ind); ++ ++ double_down(&pri->i_sem, &ind->i_sem); + ext3_migrate_data(handle, pri, ind); + /* clear the cow flag for pri because ind has it */ + pri->u.ext3_i.i_flags &= ~EXT3_COW_FL; + ext3_mark_inode_dirty(handle, pri); -+ snap_double_unlock(pri, ind); -+ ++ double_up(&pri->i_sem, &ind->i_sem); + iput(ind); + +// ext3_destroy_indirect(pri, index); @@ -2594,8 +2583,8 @@ Index: linux-2.4.20-8/fs/ext3/snap.c + Index: linux-2.4.20-8/fs/ext3/Makefile =================================================================== ---- linux-2.4.20-8.orig/fs/ext3/Makefile 2004-01-05 10:54:03.000000000 +0800 -+++ linux-2.4.20-8/fs/ext3/Makefile 2004-01-13 00:10:14.000000000 +0800 +--- linux-2.4.20-8.orig/fs/ext3/Makefile 2004-01-19 22:06:25.000000000 +0800 ++++ linux-2.4.20-8/fs/ext3/Makefile 2004-01-19 22:06:25.000000000 +0800 @@ -13,7 +13,7 @@ obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ @@ -2607,8 +2596,8 @@ Index: linux-2.4.20-8/fs/ext3/Makefile export-objs += xattr.o Index: linux-2.4.20-8/fs/ext3/inode.c =================================================================== ---- linux-2.4.20-8.orig/fs/ext3/inode.c 2004-01-05 10:54:03.000000000 +0800 -+++ linux-2.4.20-8/fs/ext3/inode.c 2004-01-18 01:48:19.000000000 +0800 +--- linux-2.4.20-8.orig/fs/ext3/inode.c 2004-01-19 22:06:24.000000000 +0800 ++++ linux-2.4.20-8/fs/ext3/inode.c 2004-01-26 01:12:48.000000000 +0800 @@ -1191,7 +1191,7 @@ * So, if we see any bmap calls here on a modified, data-journaled file, * take extra steps to flush any blocks which might be in the cache. @@ -2618,10 +2607,19 @@ Index: linux-2.4.20-8/fs/ext3/inode.c { struct inode *inode = mapping->host; journal_t *journal; +@@ -1403,7 +1403,7 @@ + * This required during truncate. We need to physically zero the tail end + * of that block so it doesn't yield old data if the file is later grown. + */ +-static int ext3_block_truncate_page(handle_t *handle, ++int ext3_block_truncate_page(handle_t *handle, + struct address_space *mapping, loff_t from) + { + unsigned long index = from >> PAGE_CACHE_SHIFT; Index: linux-2.4.20-8/fs/ext3/ialloc.c =================================================================== ---- linux-2.4.20-8.orig/fs/ext3/ialloc.c 2004-01-05 10:54:03.000000000 +0800 -+++ linux-2.4.20-8/fs/ext3/ialloc.c 2004-01-16 20:48:29.000000000 +0800 +--- linux-2.4.20-8.orig/fs/ext3/ialloc.c 2004-01-19 22:06:24.000000000 +0800 ++++ linux-2.4.20-8/fs/ext3/ialloc.c 2004-01-19 22:06:25.000000000 +0800 @@ -160,6 +160,13 @@ return retval; } @@ -2638,8 +2636,8 @@ Index: linux-2.4.20-8/fs/ext3/ialloc.c * that have access to it, and as such there are no Index: linux-2.4.20-8/fs/ext3/super.c =================================================================== ---- linux-2.4.20-8.orig/fs/ext3/super.c 2004-01-05 10:54:03.000000000 +0800 -+++ linux-2.4.20-8/fs/ext3/super.c 2004-01-18 01:40:10.000000000 +0800 +--- linux-2.4.20-8.orig/fs/ext3/super.c 2004-01-19 22:06:24.000000000 +0800 ++++ linux-2.4.20-8/fs/ext3/super.c 2004-01-19 22:06:25.000000000 +0800 @@ -1324,6 +1324,13 @@ sbi->s_mount_state = le16_to_cpu(es->s_state); sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb)); @@ -2654,10 +2652,24 @@ Index: linux-2.4.20-8/fs/ext3/super.c for (i=0; i < 4; i++) sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); sbi->s_def_hash_version = es->s_def_hash_version; +Index: linux-2.4.20-8/fs/ext3/ext3-exports.c +=================================================================== +--- linux-2.4.20-8.orig/fs/ext3/ext3-exports.c 2004-01-19 22:06:19.000000000 +0800 ++++ linux-2.4.20-8/fs/ext3/ext3-exports.c 2004-01-26 01:13:53.000000000 +0800 +@@ -21,6 +21,9 @@ + EXPORT_SYMBOL(ext3_xattr_set); + EXPORT_SYMBOL(ext3_prep_san_write); + EXPORT_SYMBOL(ext3_map_inode_page); ++EXPORT_SYMBOL(ext3_orphan_add); ++EXPORT_SYMBOL(ext3_orphan_del); ++EXPORT_SYMBOL(ext3_block_truncate_page) + + EXPORT_SYMBOL(ext3_abort); + EXPORT_SYMBOL(ext3_decode_error); Index: linux-2.4.20-8/include/linux/snap.h =================================================================== --- linux-2.4.20-8.orig/include/linux/snap.h 2003-01-30 18:24:37.000000000 +0800 -+++ linux-2.4.20-8/include/linux/snap.h 2004-01-13 00:10:14.000000000 +0800 ++++ linux-2.4.20-8/include/linux/snap.h 2004-01-19 22:11:26.000000000 +0800 @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2002 Cluster File Systems, Inc. @@ -2927,8 +2939,8 @@ Index: linux-2.4.20-8/include/linux/snap.h +#endif Index: linux-2.4.20-8/include/linux/ext3_fs.h =================================================================== ---- linux-2.4.20-8.orig/include/linux/ext3_fs.h 2004-01-05 10:54:03.000000000 +0800 -+++ linux-2.4.20-8/include/linux/ext3_fs.h 2004-01-16 20:45:09.000000000 +0800 +--- linux-2.4.20-8.orig/include/linux/ext3_fs.h 2004-01-19 22:06:24.000000000 +0800 ++++ linux-2.4.20-8/include/linux/ext3_fs.h 2004-01-19 22:11:15.000000000 +0800 @@ -183,7 +183,13 @@ #define EXT3_INDEX_FL 0x00001000 /* hash-indexed directory */ #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */ @@ -3000,8 +3012,8 @@ Index: linux-2.4.20-8/include/linux/ext3_fs.h EXT3_FEATURE_INCOMPAT_RECOVER) Index: linux-2.4.20-8/include/linux/ext3_fs_sb.h =================================================================== ---- linux-2.4.20-8.orig/include/linux/ext3_fs_sb.h 2004-01-05 10:54:00.000000000 +0800 -+++ linux-2.4.20-8/include/linux/ext3_fs_sb.h 2004-01-13 00:10:14.000000000 +0800 +--- linux-2.4.20-8.orig/include/linux/ext3_fs_sb.h 2004-01-19 22:06:18.000000000 +0800 ++++ linux-2.4.20-8/include/linux/ext3_fs_sb.h 2004-01-19 22:10:06.000000000 +0800 @@ -86,6 +86,13 @@ wait_queue_head_t s_delete_thread_queue; wait_queue_head_t s_delete_waiter_queue; @@ -3018,8 +3030,8 @@ Index: linux-2.4.20-8/include/linux/ext3_fs_sb.h #endif /* _LINUX_EXT3_FS_SB */ Index: linux-2.4.20-8/include/linux/ext3_jbd.h =================================================================== ---- linux-2.4.20-8.orig/include/linux/ext3_jbd.h 2004-01-05 10:53:59.000000000 +0800 -+++ linux-2.4.20-8/include/linux/ext3_jbd.h 2004-01-13 00:10:14.000000000 +0800 +--- linux-2.4.20-8.orig/include/linux/ext3_jbd.h 2004-01-19 22:06:15.000000000 +0800 ++++ linux-2.4.20-8/include/linux/ext3_jbd.h 2004-01-19 22:11:15.000000000 +0800 @@ -71,6 +71,33 @@ #define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8 @@ -3057,13 +3069,14 @@ Index: linux-2.4.20-8/include/linux/ext3_jbd.h %diffstat fs/ext3/Makefile | 2 + fs/ext3/ext3-exports.c | 3 fs/ext3/ialloc.c | 7 - fs/ext3/inode.c | 2 - fs/ext3/snap.c | 2588 +++++++++++++++++++++++++++++++++++++++++++++ + fs/ext3/inode.c | 4 + fs/ext3/snap.c | 2577 +++++++++++++++++++++++++++++++++++++++++++++ fs/ext3/super.c | 7 include/linux/ext3_fs.h | 38 include/linux/ext3_fs_sb.h | 7 include/linux/ext3_jbd.h | 27 include/linux/snap.h | 266 ++++ - 9 files changed, 2939 insertions(+), 5 deletions(-) + 10 files changed, 2932 insertions(+), 6 deletions(-) diff --git a/lustre/snapfs/clonefs.c b/lustre/snapfs/clonefs.c index b4f136c..2292c49 100644 --- a/lustre/snapfs/clonefs.c +++ b/lustre/snapfs/clonefs.c @@ -422,19 +422,17 @@ struct address_space_operations clonefs_file_address_ops = { static int clonefs_readlink(struct dentry *dentry, char *buf, int len) { - int res; struct inode * cache_inode; struct inode * old_inode; + int rc = -ENOENT; ENTRY; cache_inode = clonefs_get_inode(dentry->d_inode); - res = -ENOENT; - - if ( ! cache_inode ) { + if (!cache_inode) { CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); - RETURN(res); + RETURN(rc); } /* XXX: shall we allocate a new dentry ? @@ -446,8 +444,8 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len) /* set dentry inode to cache inode */ dentry->d_inode = cache_inode; - if ( cache_inode->i_op->readlink ) { - res = cache_inode->i_op->readlink(dentry, buf, len); + if (cache_inode->i_op->readlink) { + rc = cache_inode->i_op->readlink(dentry, buf, len); }else { CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino); } @@ -457,21 +455,21 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len) iput(cache_inode); - RETURN(res); + RETURN(rc); } static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd) { struct inode * cache_inode; struct inode * old_inode; - int res; + int rc = -ENOENT; ENTRY; cache_inode = clonefs_get_inode(dentry->d_inode); - if ( ! cache_inode ) { + if (!cache_inode) { CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); - RETURN(-ENOENT); + RETURN(rc); } /* XXX: shall we allocate a new dentry ? @@ -483,8 +481,8 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd) /* set dentry inode to cache inode */ dentry->d_inode = cache_inode; - if ( cache_inode->i_op->follow_link ) { - res = cache_inode->i_op->follow_link(dentry, nd); + if (cache_inode->i_op->follow_link) { + rc = cache_inode->i_op->follow_link(dentry, nd); } /* restore the old inode */ @@ -492,16 +490,103 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd) iput(cache_inode); - RETURN(res); + RETURN(rc); } +static ssize_t +clonefs_getxattr(struct dentry *dentry, const char *name, + void *buffer, size_t size) +{ + struct inode * cache_inode; + struct inode * old_inode; + int rc = -ENOENT; + + ENTRY; + + cache_inode = clonefs_get_inode(dentry->d_inode); + if (!cache_inode) { + CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); + RETURN(rc); + } + + /* XXX: shall we allocate a new dentry ? + The following is safe for ext2, etc. because ext2_follow_link + only use the inode info */ + /* save the old dentry inode */ + old_inode = dentry->d_inode; + /* set dentry inode to cache inode */ + dentry->d_inode = cache_inode; + + if (cache_inode->i_op->getxattr) { + rc = cache_inode->i_op->getxattr(dentry, name, buffer, size); + } + + /* restore the old inode */ + dentry->d_inode = old_inode; + + iput(cache_inode); + + RETURN(rc); +} +static ssize_t +clonefs_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + struct inode * cache_inode; + struct inode * old_inode; + int rc = -ENOENT; + + ENTRY; + + cache_inode = clonefs_get_inode(dentry->d_inode); + if (!cache_inode) { + CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n"); + RETURN(rc); + } + + /* XXX: shall we allocate a new dentry ? + The following is safe for ext2, etc. because ext2_follow_link + only use the inode info */ + + /* save the old dentry inode */ + old_inode = dentry->d_inode; + /* set dentry inode to cache inode */ + dentry->d_inode = cache_inode; + + if (cache_inode->i_op->listxattr) { + rc = cache_inode->i_op->listxattr(dentry, buffer, size); + } + + /* restore the old inode */ + dentry->d_inode = old_inode; + + iput(cache_inode); + + RETURN(rc); + +} struct inode_operations clonefs_symlink_inode_ops = { /*FIXME later getxattr, listxattr, * other method need to be replaced too * */ - readlink: clonefs_readlink, /* readlink */ - follow_link: clonefs_follow_link,/* follow_link */ + readlink: clonefs_readlink, /* readlink */ + follow_link: clonefs_follow_link, /* follow_link */ + getxattr: clonefs_getxattr, /* get xattr */ + listxattr: clonefs_listxattr, /* list xattr */ }; +int clonefs_mounted(struct snap_cache *cache, int index) +{ + struct snap_clone_info *clone_sb; + struct list_head *list, *end; + + end = list = &cache->cache_clone_list; + + list_for_each_entry(clone_sb, list, clone_list_entry) { + if (clone_sb->clone_index == index) + return 1; + } + return 0; +} + diff --git a/lustre/snapfs/dir.c b/lustre/snapfs/dir.c index 4db0908..d139d20 100644 --- a/lustre/snapfs/dir.c +++ b/lustre/snapfs/dir.c @@ -37,10 +37,13 @@ static ino_t get_parent_ino(struct inode * inode) static void d_unadd_iput(struct dentry *dentry) { + spin_lock(&dcache_lock); list_del(&dentry->d_alias); INIT_LIST_HEAD(&dentry->d_alias); list_del(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_hash); + spin_unlock(&dcache_lock); + iput(dentry->d_inode); dentry->d_inode = NULL; } @@ -76,7 +79,8 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry) ino = 0xF0000000 | dir->i_ino; snap = iget(dir->i_sb, ino); - CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n", snap->i_ino, snap->i_mode); + CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n", + snap->i_ino, snap->i_mode); d_add(dentry, snap); RETURN(NULL); } @@ -87,10 +91,14 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry) } rc = iops->lookup(dir, dentry); - if ( rc || !dentry->d_inode) { + if (rc || !dentry->d_inode || + is_bad_inode(dentry->d_inode) || + IS_ERR(dentry->d_inode)) { RETURN(NULL); } - + + CDEBUG(D_INODE, "cache inode ino %lu, mode %o\n", + dentry->d_inode->i_ino, dentry->d_inode->i_mode); /* * If we are under dotsnap, we need save extra data into * dentry->d_fsdata: For dir, we only need _this_ snapshot's index; @@ -160,13 +168,13 @@ static int currentfs_create(struct inode *dir, struct dentry *dentry, int mode) } cache = snap_find_cache(dir->i_dev); - if ( !cache ) { + if (!cache) { RETURN(-EINVAL); } handle = snap_trans_start(cache, dir, SNAP_OP_CREATE); - if ( snap_needs_cow(dir) != -1 ) { + if (snap_needs_cow(dir) != -1) { CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino); snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 1); if ((snap_do_cow(dir, get_parent_ino(dir), 0))) { @@ -242,7 +250,12 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) CERROR("Error in currentfs_mkdir, dentry->d_inode is NULL\n"); } - snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 3); + set_filter_ops(cache, dentry->d_inode); + init_filter_data(dentry->d_inode, 0); + + CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op); + snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 3); + exit: snap_trans_commit(cache, handle); @@ -320,8 +333,11 @@ static int currentfs_symlink(struct inode *dir, struct dentry *dentry, snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 2); rc = iops->symlink(dir, dentry, symname); - snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3); + set_filter_ops(cache, dentry->d_inode); + init_filter_data(dentry->d_inode, 0); + + snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3); exit: snap_trans_commit(cache, handle); RETURN(rc); @@ -360,6 +376,9 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode, snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 2); rc = iops->mknod(dir, dentry, mode, rdev); + + set_filter_ops(cache, dentry->d_inode); + init_filter_data(dentry->d_inode, 0); snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 3); /* XXX do we need to set the correct snap_{*}_iops */ @@ -380,7 +399,6 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry) off_t i_size = 0; ino_t ino = 0; int keep_inode = 0; -// struct dentry_operations *save_dop = NULL; void *handle = NULL; ENTRY; @@ -416,23 +434,10 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry) if (snap_needs_cow(dentry->d_inode) != -1 || snap_is_redirector(dentry->d_inode)) { snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 2); - snap_do_cow (dir, get_parent_ino(dir), SNAP_CREATE_IND_DEL_PRI); + snap_do_cow (dentry->d_inode, get_parent_ino(dentry->d_inode), + SNAP_CREATE_IND_DEL_PRI); keep_inode = 1; } -#if 0 - if ( keep_inode ) { - printk("set up dentry ops, before %p\n",dentry->d_op); - save_dop = dentry->d_op; - - filter_setup_dentry_ops(cache->cache_filter, - dentry->d_op, ¤tfs_dentry_ops); - dentry->d_op = filter_c2udops(cache->cache_filter); - - printk("set up dentry ops, after %p\n",dentry->d_op); - - } - -#endif if( keep_inode && dentry->d_inode ) { ino = dentry->d_inode->i_ino; @@ -445,31 +450,20 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry) rc = iops->rmdir(dir, dentry); snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 5); - /* XXX : check this */ -#if 0 - if ( keep_inode ) { - dentry->d_op = save_dop; - printk("restore dentry ops, now at %p\n",dentry->d_op); - } - -#endif - if( keep_inode && ino) { - inode = iget ( dir->i_sb, ino); + inode = iget (dir->i_sb, ino); if( inode) { // inode->i_ctime = i_ctime; inode->i_nlink = i_nlink; inode->i_size = i_size; mark_inode_dirty(inode); iput( inode); -#ifdef CONFIG_SNAPFS_EXT3 /* * In Ext3, rmdir() will put this inode into * orphan list, we must remove it out. It's ugly!! */ if( cache->cache_type == FILTER_FS_EXT3 ) ext3_orphan_del(handle, inode); -#endif snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 6); } } @@ -698,5 +692,8 @@ struct inode_operations currentfs_dir_iops = { rmdir: currentfs_rmdir, unlink: currentfs_unlink, rename: currentfs_rename, - lookup: currentfs_lookup + lookup: currentfs_lookup, + removexattr: currentfs_removexattr, + setattr: currentfs_setattr, + setxattr: currentfs_setxattr, }; diff --git a/lustre/snapfs/file.c b/lustre/snapfs/file.c index f819aa1..a8a8860 100644 --- a/lustre/snapfs/file.c +++ b/lustre/snapfs/file.c @@ -43,16 +43,16 @@ static int copy_back_page(struct inode *dst, char *kaddr_src, *kaddr_dst; struct snap_cache *cache; struct address_space_operations *c_aops; - struct page *src_page, *dst_page; + struct page *src_page = NULL, *dst_page = NULL; unsigned long index, offset, bytes; int err = 0; ENTRY; - index = start >> PAGE_CACHE_SHIFT; + offset = (start & (PAGE_CACHE_SIZE -1)); /* Within page */ bytes = end - start; - offset = start & PAGE_CACHE_MASK; + index = start >> PAGE_CACHE_SHIFT; - if (!has_pages(src, index)) + if (!has_pages(src, index) || bytes > 4096) RETURN(0); cache = snap_find_cache(src->i_dev); @@ -89,13 +89,15 @@ static int copy_back_page(struct inode *dst, } kaddr_dst = kmap(dst_page); - err = c_aops->prepare_write(NULL, dst_page, offset, bytes); + err = c_aops->prepare_write(NULL, dst_page, offset, offset + bytes); 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, offset, bytes); + err = c_aops->commit_write(NULL, dst_page, offset, offset + bytes); + CDEBUG(D_SNAP, "copy back pages %p index %lu src %lu dst %lu \n", + dst_page, dst_page->index, src->i_ino, dst->i_ino); if (err) goto unlock_dst_page; err = 1; @@ -132,28 +134,36 @@ static ssize_t currentfs_write (struct file *filp, const char *buf, if ( !cache ) RETURN(-EINVAL); + down(&inode->i_sem); + if ( snap_needs_cow(inode) != -1 ) { CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino); snap_do_cow(inode, filp->f_dentry->d_parent->d_inode->i_ino, 0); } fops = filter_c2cffops(cache->cache_filter); - if (!fops || !fops->write) - RETURN(-EINVAL); - + if (!fops || !fops->write) { + up(&inode->i_sem); + RETURN(-EINVAL); + } if (filp->f_flags & O_APPEND) pos = inode->i_size; else { pos = *ppos; - if (pos != *ppos) + if (pos != *ppos){ + up(&inode->i_sem); RETURN(-EINVAL); + } } - if (pos & PAGE_CACHE_MASK) { + + CDEBUG(D_SNAP, "write offset %lld count %u \n", pos, count); + + if (pos & (PAGE_CACHE_SIZE - 1)) { start[0] = pos & PAGE_CACHE_MASK; end[0] = pos; } pos += count - 1; - if ((pos+1) & PAGE_CACHE_MASK) { + if ((pos+1) & (PAGE_CACHE_SIZE - 1)) { start[1] = pos; end[1] = PAGE_CACHE_ALIGN(pos); } @@ -161,7 +171,9 @@ static ssize_t currentfs_write (struct file *filp, const char *buf, if (((start[0] >> PAGE_CACHE_SHIFT) == (start[1] >> PAGE_CACHE_SHIFT)) || pos > inode->i_size) start[1] = -1; - + + CDEBUG(D_SNAP, "copy back start[0] %ld end[0] %ld start[1] %ld end[1] %ld \n", + start[0], end[0], start[1], end[1]); for (i = 0; i < 2; i++) { if (start[i] == -1) continue; @@ -189,11 +201,14 @@ static ssize_t currentfs_write (struct file *filp, const char *buf, if (result < 0) { iput(cache_inode); rc = result; + up(&inode->i_sem); goto exit; } iput(cache_inode); } } + + up(&inode->i_sem); rc = fops->write(filp, buf, count, ppos); exit: RETURN(rc); @@ -221,7 +236,7 @@ static int currentfs_readpage(struct file *file, struct page *page) c_aops = filter_c2cfaops(cache->cache_filter); - block = page->index >> inode->i_sb->s_blocksize_bits; + block = (page->index << PAGE_CACHE_SHIFT) >> inode->i_sb->s_blocksize_bits; /* if there is a block in the cache, return the cache readpage */ if(c_aops->bmap(inode->i_mapping, block) ) { @@ -246,7 +261,6 @@ static int currentfs_readpage(struct file *file, struct page *page) table = &snap_tables[cache->cache_snap_tableno]; 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); @@ -259,12 +273,19 @@ static int currentfs_readpage(struct file *file, struct page *page) if (!search_older && c_aops->bmap(cache_inode->i_mapping, block)) break; iput(cache_inode); + cache_inode = NULL; } if (pri_inode) iput(pri_inode); - if (!cache_inode ) - RETURN(-EINVAL); - + if (!cache_inode) { + CDEBUG(D_SNAP, "block %lu is a hole of inode %lu \n", + block, inode->i_ino); + memset(kmap(page), 0, PAGE_CACHE_SIZE); + flush_dcache_page(page); + GOTO(exit, rc = 0); + } + CDEBUG(D_INODE, "readpage ino %lu icount %d \n", cache_inode->i_ino, + atomic_read(&cache_inode->i_count)); down(&cache_inode->i_sem); /*Here we have changed a file to read, @@ -284,13 +305,14 @@ static int currentfs_readpage(struct file *file, struct page *page) GOTO(exit_release, rc = -EIO); memcpy(kmap(page), kmap(cache_page), PAGE_CACHE_SIZE); + flush_dcache_page(page); kunmap(cache_page); page_cache_release(cache_page); up(&cache_inode->i_sem); iput(cache_inode); - +exit: kunmap(page); SetPageUptodate(page); UnlockPage(page); @@ -315,6 +337,8 @@ struct file_operations currentfs_file_fops = { }; struct inode_operations currentfs_file_iops = { - revalidate: NULL, + setattr: currentfs_setattr, + setxattr: currentfs_setxattr, + removexattr: currentfs_removexattr, }; diff --git a/lustre/snapfs/inode.c b/lustre/snapfs/inode.c index 25619a8..97bfd46 100644 --- a/lustre/snapfs/inode.c +++ b/lustre/snapfs/inode.c @@ -64,6 +64,8 @@ void init_filter_data(struct inode *inode, return; } snapops = filter_c2csnapops(cache->cache_filter); + + if (inode->i_filterdata) return; inode->i_filterdata = (struct filter_inode_info *) \ kmem_cache_alloc(filter_info_cache, SLAB_KERNEL); @@ -104,7 +106,95 @@ void set_filter_ops(struct snap_cache *cache, struct inode *inode) inode->i_ino, inode->i_op); } } +int currentfs_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +{ + struct snap_cache *cache; + struct inode *inode = dentry->d_inode; + struct inode_operations *iops; + int rc; + + ENTRY; + + cache = snap_find_cache(inode->i_dev); + if (!cache) { + CERROR("currentfs_setxattr: cannot find cache\n"); + RETURN(-EINVAL); + } + + iops = filter_c2cfiops(cache->cache_filter); + + if (!iops || !iops->setxattr) { + RETURN(-EINVAL); + } + if ( snap_needs_cow(inode) != -1 ) { + CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino); + snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0); + } + + rc = iops->setxattr(dentry, name, value, size, flags); + + RETURN(rc); +} +int currentfs_removexattr(struct dentry *dentry, const char *name) +{ + struct snap_cache *cache; + struct inode *inode = dentry->d_inode; + struct inode_operations *iops; + int rc; + + ENTRY; + + cache = snap_find_cache(inode->i_dev); + if (!cache) { + CERROR("currentfs_setxattr: cannot find cache\n"); + RETURN(-EINVAL); + } + + iops = filter_c2cfiops(cache->cache_filter); + + if (!iops || !iops->removexattr) { + RETURN(-EINVAL); + } + + if (snap_needs_cow(inode) != -1) { + CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino); + snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0); + } + rc = iops->removexattr(dentry, name); + + RETURN(rc); +} + +int currentfs_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct snap_cache *cache; + struct inode *inode = dentry->d_inode; + struct inode_operations *iops; + int rc; + + ENTRY; + + cache = snap_find_cache(inode->i_dev); + if (!cache) { + CERROR("currentfs_setxattr: cannot find cache\n"); + RETURN(-EINVAL); + } + iops = filter_c2cfiops(cache->cache_filter); + + if (!iops || !iops->setattr) { + RETURN(-EINVAL); + } + if ( snap_needs_cow(inode) != -1 ) { + CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino); + snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0); + } + + rc = iops->setattr(dentry, attr); + + RETURN(rc); +} /* Superblock operations. */ static void currentfs_read_inode(struct inode *inode) { @@ -113,7 +203,6 @@ static void currentfs_read_inode(struct inode *inode) if( !inode ) return; - CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino); cache = snap_find_cache(inode->i_dev); @@ -131,10 +220,14 @@ static void currentfs_read_inode(struct inode *inode) if(filter_c2csops(cache->cache_filter)) filter_c2csops(cache->cache_filter)->read_inode(inode); + CDEBUG(D_INODE, "read_inode ino %lu icount %d \n", + inode->i_ino, atomic_read(&inode->i_count)); set_filter_ops(cache, inode); /*init filter_data struct * FIXME flag should be set future*/ init_filter_data(inode, 0); + CDEBUG(D_INODE, "read_inode ino %lu icount %d \n", + inode->i_ino, atomic_read(&inode->i_count)); return; } @@ -217,3 +310,8 @@ struct super_operations currentfs_super_ops = { put_super: currentfs_put_super, clear_inode: currentfs_clear_inode, }; + + + + + diff --git a/lustre/snapfs/utils/snapconf.c b/lustre/snapfs/utils/snapconf.c index 4aad130..1b22b8d 100644 --- a/lustre/snapfs/utils/snapconf.c +++ b/lustre/snapfs/utils/snapconf.c @@ -41,6 +41,8 @@ command_t cmdlist[] = { "dev open available snap device\n"}, {"add", snap_snap_add, 0, "add [table_no] add snapshot to the device\n"}, + {"del", snap_snap_del, 0, + "del [table_no] del snapshot to the device\n"}, {"snap_list", snap_snap_list, 0, "snap_list [table_no] list all the snapshots on the device\n"}, diff --git a/lustre/snapfs/utils/snapctl.h b/lustre/snapfs/utils/snapctl.h index fe9eb5d..6640b4a 100644 --- a/lustre/snapfs/utils/snapctl.h +++ b/lustre/snapfs/utils/snapctl.h @@ -19,4 +19,5 @@ extern void init_snap_list(void); extern int snap_dev_open(int argc, char **argv); extern int snap_dev_list(int argc, char **argv); extern int snap_snap_add(int argc, char **argv); +extern int snap_snap_del(int argc, char **argv); extern int snap_snap_list(int argc, char **argv);