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-05 10:54:25.000000000 +0800
-@@ -0,0 +1,2650 @@
++++ linux-2.4.20-8/fs/ext3/snap.c 2004-01-13 00:11:40.000000000 +0800
+@@ -0,0 +1,2645 @@
+/* fs/ext3/snap.c
+ *
+ * Copyright (c) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
+ }
+ err = ext3_xattr_get(last_inode, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR,
+ buf, EXT3_MAX_SNAP_DATA);
-+ if (err == -ENOENT) {
++ if (err == -ENODATA) {
+ snap_debug("no existing attributes - zeroing\n");
+ memset(buf, 0, EXT3_MAX_SNAP_DATA);
+ } else if (err < 0 || err > EXT3_MAX_SNAP_DATA) {
+ /* read ea at first */
+ err = ext3_xattr_get(pri, EXT3_SNAP_INDEX ,EXT3_SNAP_ATTR,
+ buf, EXT3_MAX_SNAP_DATA);
-+ if (err == -ENOENT || err == -ENOATTR) {
++ if (err == -ENODATA || err == -ENOATTR) {
+ snap_debug("no extended attributes - zeroing\n");
+ memset(buf, 0, EXT3_MAX_SNAP_DATA);
+ /* XXX
+ * Copy inode metadata from one inode to another, excluding blocks and size.
+ * FIXME do we copy EA data - ACLs and such (excluding snapshot data)?
+ */
-+static void ext3_copy_meta(struct inode *dst, struct inode *src)
++static void ext3_copy_meta(handle_t *handle, struct inode *dst, struct inode *src)
+{
+ int size;
+
+ while ((namelen = strlen(name))) {
+ int attrlen;
+ char *buf;
-+ handle_t *handle = ext3_journal_current_handle();
+
+ /* don't copy snap data */
+ if (!strcmp(name, EXT3_SNAP_ATTR)) {
+ * This is for LAN free backup later.
+ */
+
-+static int ext3_migrate_data (struct inode *dst, struct inode *src)
++static int ext3_migrate_data (handle_t *handle, struct inode *dst, struct inode *src)
+{
+ unsigned long err = 0;
-+ handle_t *handle = NULL;
+ /* 512 byte disk blocks per inode block */
+ int bpib = src->i_sb->s_blocksize >> 9;
+
+
+ if (dst->i_ino == src->i_ino)
+ return 0;
-+ handle = ext3_journal_start(dst, SNAP_MIGRATEDATA_TRANS_BLOCKS);
-+ if( !handle )
-+ return -EINVAL;
-+ ext3_copy_meta(dst, src);
++
++ ext3_copy_meta(handle, dst, src);
+
+ snap_debug("migrating %ld data blocks from %lu to %lu\n",
+ blocks, src->i_ino, dst->i_ino);
+ ext3_mark_inode_dirty(handle, src);
+ ext3_mark_inode_dirty(handle, dst);
+
-+ ext3_journal_stop(handle, dst);
-+
+ return SNAP_ERROR(err);
+}
+
+
+ err = ext3_xattr_get(primary, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR,
+ buf, EXT3_MAX_SNAP_DATA);
-+ if (err == -ENOENT) {
++ if (err == -ENODATA) {
+ slot = 0;
+ } else if (err < 0) {
+ snap_debug(" attribute read error\n");
+ goto exit;
+ }
+
-+ ext3_migrate_data(tmp, pri);
++ ext3_migrate_data(handle, tmp, pri);
+ snap_debug("freeing half-copied %lu blocks\n", tmp->i_blocks );
+ tmp->i_nlink = 0;
+ iput( tmp );
+ /* third: restore ind inode to pri inode */
+ snap_debug("restore %lu blocks to primary inode %lu\n",
+ ind->i_blocks, pri->i_ino);
-+ ext3_migrate_data(pri, ind);
++ ext3_migrate_data(handle, pri, ind);
+
+ /* final: delete ind inode */
+ ind->i_nlink = 0;
+ tmp = ext3_new_inode(handle, pri, (int)pri->i_mode, 0);
+ if(tmp) {
+ down(&tmp->i_sem);
-+ ext3_migrate_data(tmp, pri);
++ ext3_migrate_data(handle, tmp, pri);
+ up(&tmp->i_sem);
+ tmp->i_nlink = 0;
+ iput(tmp);
+ loopfail( 2 );
+
+ snap_debug("got new inode %lu\n", ind->i_ino);
++ ind->i_rdev = pri->i_rdev;
+ ind->i_op = pri->i_op;
+ ext3_set_generation(ind, (unsigned long)gen);
+ /* If we are deleting the primary inode, we want to ensure that it is
+ snap_debug("deleting primary inode\n");
+
+ down(&ind->i_sem);
-+ err = ext3_migrate_data(ind, pri);
++ err = ext3_migrate_data(handle, ind, pri);
+ if (err)
+ goto exit_unlock;
+
+
+ pri->u.ext3_i.i_flags |= EXT3_DEL_FL;
+ ind->u.ext3_i.i_flags |= EXT3_COW_FL;
-+ if(S_ISREG(pri->i_mode)) pri->i_nlink = 1;
++ if(S_ISREG(pri->i_mode)) pri->i_nlink = 1;
+ pri->u.ext3_i.i_dtime = CURRENT_TIME;
+ //pri->u.ext3_i.i_generation++;
+ ext3_mark_inode_dirty(handle, pri);
+ up(&ind->i_sem);
+ } else {
+ down(&ind->i_sem);
-+ err = ext3_migrate_data(ind, pri);
++ err = ext3_migrate_data(handle, ind, pri);
+ if (err)
+ goto exit_unlock;
+
+ err = ext3_xattr_get(pri, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR,
+ buf, EXT3_MAX_SNAP_DATA);
+ if (err < 0) {
-+ if (err == -ENOENT)
++ 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");
+ continue;
+ if (ext3_copy_block (next_ind, ind, i ) < 0) break;
+ }
-+ mark_inode_dirty(next_ind);
++ ext3_mark_inode_dirty(handle, next_ind);
+ double_unlock(next_ind, ind);
+
+#endif
+ tmp = ext3_new_inode(handle, pri, (int)pri->i_mode, 0);
+ if(tmp) {
+ snap_double_lock(pri, tmp);
-+ ext3_migrate_data(tmp, pri);
++ ext3_migrate_data(handle, tmp, pri);
+ snap_double_unlock(pri, tmp);
+
+ tmp->i_nlink = 0;
+ snap_err("restore_indirect, new_inode err\n");
+
+ snap_double_lock(pri, ind);
-+ ext3_migrate_data(pri, ind);
++ 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);
+ err = ext3_xattr_get(primary, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR,
+ buf, EXT3_MAX_SNAP_DATA);
+
-+ if (err == -ENOENT) {
++ if (err == -ENODATA) {
+ memset(buf, 0, EXT3_MAX_SNAP_DATA);
+ }
+ else if (err < 0) {
Index: linux-2.4.20-8/fs/ext3/ioctl.c
===================================================================
--- linux-2.4.20-8.orig/fs/ext3/ioctl.c 2004-01-05 10:54:00.000000000 +0800
-+++ linux-2.4.20-8/fs/ext3/ioctl.c 2004-01-05 10:54:25.000000000 +0800
++++ linux-2.4.20-8/fs/ext3/ioctl.c 2004-01-13 00:10:14.000000000 +0800
@@ -13,6 +13,12 @@
#include <linux/ext3_jbd.h>
#include <linux/sched.h>
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-05 10:54:25.000000000 +0800
++++ linux-2.4.20-8/fs/ext3/Makefile 2004-01-13 00:10:14.000000000 +0800
@@ -13,7 +13,7 @@
obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.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-05 10:54:25.000000000 +0800
++++ linux-2.4.20-8/fs/ext3/inode.c 2004-01-13 00:10:14.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.
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-05 10:54:25.000000000 +0800
++++ linux-2.4.20-8/fs/ext3/ialloc.c 2004-01-13 00:10:14.000000000 +0800
@@ -78,7 +78,6 @@
sb->u.ext3_sb.s_inode_bitmap[bitmap_nr] = bh;
return retval;
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-05 10:54:25.000000000 +0800
++++ linux-2.4.20-8/include/linux/snap.h 2004-01-13 00:10:14.000000000 +0800
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
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-05 10:54:25.000000000 +0800
++++ linux-2.4.20-8/include/linux/ext3_fs.h 2004-01-13 00:10:14.000000000 +0800
@@ -183,7 +183,13 @@
#define EXT3_INDEX_FL 0x00001000 /* hash-indexed directory */
#define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */
/*
* Structure of an inode on the disk
*/
-@@ -429,7 +450,14 @@
+@@ -429,7 +450,15 @@
__u8 s_def_hash_version; /* Default hash version to use */
__u8 s_reserved_char_pad;
__u16 s_reserved_word_pad;
- __u32 s_reserved[192]; /* Padding to the end of the block */
+ /* for snapfs */
-+ __u32 s_first_meta_bg; /* First metablock group */
-+ __u32 s_mkfs_time; /* When the filesystem was created */
++ __u32 s_default_mount_opts;
++ __u32 s_first_meta_bg; /* First metablock group */
++ __u32 s_mkfs_time; /* When the filesystem was created */
+ __u32 s_first_cowed_pri_ino; /* For snapfs,the first cowed primary inode */
+ __u32 s_last_cowed_pri_ino; /* last cowed ino in memory */
+ __u32 s_snaptable_ino; /* snaptable ino in memory */
+ __u32 s_last_snap_orphan; /* SnapFS: start of cowing indirect inode */
-+ __u32 s_reserved[186]; /* Padding to the end of the block,originally 204 */
++ __u32 s_reserved[185]; /* Padding to the end of the block,originally 204 */
};
#ifdef __KERNEL__
-@@ -503,6 +531,9 @@
+@@ -503,6 +532,9 @@
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
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-05 10:54:25.000000000 +0800
++++ linux-2.4.20-8/include/linux/ext3_fs_sb.h 2004-01-13 00:10:14.000000000 +0800
@@ -86,6 +86,13 @@
wait_queue_head_t s_delete_thread_queue;
wait_queue_head_t s_delete_waiter_queue;
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-05 10:54:25.000000000 +0800
++++ linux-2.4.20-8/include/linux/ext3_jbd.h 2004-01-13 00:10:14.000000000 +0800
@@ -71,6 +71,33 @@
#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8
fs/ext3/ialloc.c | 8
fs/ext3/inode.c | 2
fs/ext3/ioctl.c | 103 +
- fs/ext3/snap.c | 2650 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/ext3_fs.h | 37
+ fs/ext3/snap.c | 2645 +++++++++++++++++++++++++++++++++++++++++++++
+ 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, 3096 insertions(+), 6 deletions(-)
+ 9 files changed, 3092 insertions(+), 6 deletions(-)
inode->i_op = &clonefs_file_inode_ops;
if (inode->i_mapping)
inode->i_mapping->a_ops = &clonefs_file_address_ops;
+ inode->i_fop = &clonefs_file_file_ops;
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &clonefs_dir_inode_ops;
+ inode->i_fop = &clonefs_dir_file_ops;
} else if (S_ISLNK(inode->i_mode)) {
inode->i_op = &clonefs_symlink_inode_ops;
} else {
dput(dentry); /* this will free the dentry memory */
}
+static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
+{
+ atomic_set(&dentry->d_count, 1);
+ dentry->d_vfs_flags = 0;
+ dentry->d_flags = 0;
+ dentry->d_inode = inode;
+ dentry->d_op = NULL;
+ dentry->d_fsdata = NULL;
+ dentry->d_mounted = 0;
+ INIT_LIST_HEAD(&dentry->d_hash);
+ INIT_LIST_HEAD(&dentry->d_lru);
+ INIT_LIST_HEAD(&dentry->d_subdirs);
+ INIT_LIST_HEAD(&dentry->d_alias);
+}
/*
* Return the underlying fs dentry with name in 'dentry' that points
* to the right inode. 'dir' is the clone fs directory to search for
*/
struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry)
{
- struct inode *cache_dir;
- struct dentry *cache_dentry;
+ struct inode *cache_dir = NULL;
+ struct dentry *cache_dentry = NULL;
struct inode *cache_inode;
struct dentry *result;
+ struct dentry tmp;
struct inode *inode;
struct snap_clone_info *clone_sb;
ENTRY;
cache_dir = clonefs_get_inode(dir);
-
- cache_dentry = d_alloc(dentry->d_parent, &dentry->d_name);
+ if (!cache_dir)
+ RETURN(ERR_PTR(-ENOENT));
+ /*FIXME later, we make parent dentry here
+ *there may some problems in lookup
+ */
+ prepare_parent_dentry(&tmp, cache_dir);
+ cache_dentry = d_alloc(&tmp, &dentry->d_name);
+
if (!cache_dentry) {
iput(cache_dir);
RETURN(ERR_PTR(-ENOENT));
struct inode *cache_inode;
struct file open_file;
struct dentry open_dentry;
- struct inode *inode=file->f_dentry->d_inode;
+ struct inode *inode = file->f_dentry->d_inode;
ENTRY;
&open_dentry);
/* tell currentfs_readpage the primary inode number */
open_dentry.d_fsdata = (void*)inode->i_ino;
-
+ page->mapping->host = cache_inode;
/* potemkin case: we are handed a directory inode */
down(&cache_inode->i_sem);
/* XXX - readpage NULL on directories... */
result = cache_inode->i_mapping->a_ops->readpage(&open_file, page);
up(&cache_inode->i_sem);
+ page->mapping->host = inode;
clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
iput(cache_inode);
RETURN(result);
void init_filter_data(struct inode *inode,
- struct snapshot_operations *snapops,
int flag)
{
struct filter_inode_info *i;
+ struct snap_cache *cache;
+ struct snapshot_operations *snapops;
- if (inode->i_filterdata){
+ if (inode->i_filterdata || inode->i_ino & 0xF0000000)
return;
- }
+ cache = snap_find_cache(inode->i_dev);
+ if (!cache) {
+ CERROR("currentfs_read_inode: cannot find cache\n");
+ make_bad_inode(inode);
+ return;
+ }
+ snapops = filter_c2csnapops(cache->cache_filter);
+
inode->i_filterdata = (struct filter_inode_info *) \
kmem_cache_alloc(filter_info_cache, SLAB_KERNEL);
i = inode->i_filterdata;
i -> generation = snapops->get_generation(inode);
i -> flags = flag;
}
+
+void set_filter_ops(struct snap_cache *cache, struct inode *inode)
+{
+ /* XXX now set the correct snap_{file,dir,sym}_iops */
+ if (S_ISDIR(inode->i_mode)) {
+ inode->i_op = filter_c2udiops(cache->cache_filter);
+ inode->i_fop = filter_c2udfops(cache->cache_filter);
+ } else if (S_ISREG(inode->i_mode)) {
+ if ( !filter_c2cfiops(cache->cache_filter) ) {
+ filter_setup_file_ops(cache->cache_filter, inode,
+ ¤tfs_file_iops,
+ ¤tfs_file_fops,
+ ¤tfs_file_aops);
+ }
+ CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
+ inode->i_ino, inode->i_op);
+ inode->i_fop = filter_c2uffops(cache->cache_filter);
+ inode->i_op = filter_c2ufiops(cache->cache_filter);
+ if (inode->i_mapping)
+ inode->i_mapping->a_ops = filter_c2ufaops(cache->cache_filter);
+
+ }
+ else if (S_ISLNK(inode->i_mode)) {
+ if ( !filter_c2csiops(cache->cache_filter) ) {
+ filter_setup_symlink_ops(cache->cache_filter, inode,
+ ¤tfs_sym_iops, ¤tfs_sym_fops);
+ }
+ inode->i_op = filter_c2usiops(cache->cache_filter);
+ inode->i_fop = filter_c2usfops(cache->cache_filter);
+ CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
+ inode->i_ino, inode->i_op);
+ }
+}
+
/* Superblock operations. */
static void currentfs_read_inode(struct inode *inode)
{
struct snap_cache *cache;
- struct snapshot_operations *snapops;
ENTRY;
if( !inode )
currentfs_dotsnap_read_inode(cache, inode);
return;
}
- snapops = filter_c2csnapops(cache->cache_filter);
-
- if (!snapops || !snapops->get_indirect)
- return;
if(filter_c2csops(cache->cache_filter))
filter_c2csops(cache->cache_filter)->read_inode(inode);
- /* XXX now set the correct snap_{file,dir,sym}_iops */
- if (S_ISDIR(inode->i_mode))
- inode->i_op = filter_c2udiops(cache->cache_filter);
- else if (S_ISREG(inode->i_mode)) {
- if ( !filter_c2cfiops(cache->cache_filter) ) {
- filter_setup_file_ops(cache->cache_filter, inode,
- ¤tfs_file_iops,
- ¤tfs_file_fops,
- ¤tfs_file_aops);
- }
- CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
- inode->i_ino, inode->i_op);
- }
- else if (S_ISLNK(inode->i_mode)) {
- if ( !filter_c2csiops(cache->cache_filter) ) {
- filter_setup_symlink_ops(cache->cache_filter, inode,
- ¤tfs_sym_iops, ¤tfs_sym_fops);
- }
- inode->i_op = filter_c2usiops(cache->cache_filter);
- CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
- inode->i_ino, inode->i_op);
- }
+ set_filter_ops(cache, inode);
/*init filter_data struct
* FIXME flag should be set future*/
- init_filter_data(inode, snapops, 0);
+ init_filter_data(inode, 0);
return;
}