From ff5a3e46380fdcb9eced220b1d82d0291e347340 Mon Sep 17 00:00:00 2001 From: wangdi <wangdi> Date: Sun, 4 Jan 2004 07:28:26 +0000 Subject: [PATCH] add snapfs_internal.h snapfs_support.h Makefile.am --- lustre/snapfs/Makefile.am | 19 ++ lustre/snapfs/snapfs_internal.h | 410 ++++++++++++++++++++++++++++++++ lustre/snapfs/snapfs_support.h | 156 ++++++++++++ 3 files changed, 585 insertions(+) create mode 100644 lustre/snapfs/Makefile.am create mode 100644 lustre/snapfs/snapfs_internal.h create mode 100644 lustre/snapfs/snapfs_support.h diff --git a/lustre/snapfs/Makefile.am b/lustre/snapfs/Makefile.am new file mode 100644 index 0000000000..15d50ab37b --- /dev/null +++ b/lustre/snapfs/Makefile.am @@ -0,0 +1,19 @@ +# Copyright (C) 2001 Cluster File Systems, Inc. +# +# This code is issued under the GNU General Public License. +# See the file COPYING in this distribution + + +DEFS= +SUBDIRS = . utils + +MODULE = snapfs +modulefs_DATA = snapfs.o +EXTRA_PROGRAMS = snapfs + +snapfs_SOURCES = cache.c clonefs.c dcache.c dir.c dotsnap.c file.c +snapfs_SOURCES += filter.c inode.c journal_ext3.c psdev.c +snapfs_SOURCES += snap.c snaptable.c super.c symlink.c sysctl.c + + +include $(top_srcdir)/Rules diff --git a/lustre/snapfs/snapfs_internal.h b/lustre/snapfs/snapfs_internal.h new file mode 100644 index 0000000000..ce43dbfbc0 --- /dev/null +++ b/lustre/snapfs/snapfs_internal.h @@ -0,0 +1,410 @@ +#ifndef __LINUX_SNAPFS_H +#define __LINUX_SNAPFS_H +/* maximum number of snapshot tables we maintain in the kernel */ +#define SNAP_MAX_TABLES 32 +#define SNAP_MAX_NAMELEN 64 + +/* ioctls for manipulating snapshots 40 - 60 */ +#define IOC_SNAP_TYPE 'f' +#define IOC_SNAP_MIN_NR 41 + +#define IOC_SNAP_SETTABLE _IOWR('f', 41, long) +#define IOC_SNAP_PRINTTABLE _IOWR('f', 42, long) +#define IOC_SNAP_GETINDEXFROMNAME _IOWR('f', 43, long) +#define IOC_SNAP_GET_NEXT_INO _IOWR('f', 44, long) +#define IOC_SNAP_GET_INO_INFO _IOWR('f', 45, long) + +#define IOC_SNAP_ADD _IOWR('f', 46, long) +#define IOC_SNAP_DELETE _IOWR('f', 47, long) +#define IOC_SNAP_RESTORE _IOWR('f', 48, long) +#define IOC_SNAP_DEBUG _IOWR('f', 49, long) +#define IOC_SNAP_DEVFAIL _IOWR('f', 50, long) +#define IOC_SNAP_SHOW_DOTSNAP _IOWR('f', 51, long) + +#define IOC_SNAP_MAX_NR 51 + + +struct snap { + time_t time; + unsigned int index; + unsigned int gen; + unsigned int flags; + char name[SNAP_MAX_NAMELEN]; +}; + +/* snap ioctl data for table fiddling */ +struct snap_table_data { + int tblcmd_no; /* which table */ + unsigned long dev; + unsigned int tblcmd_count; /* how many snaps */ + struct snap tblcmd_snaps[0]; /* sorted times! */ +}; + +/* we have just a single snapshot control device + it contains a list of all the snap_current info's +*/ +#define SNAPDEV_NAME "/dev/snapconf" +#define SNAP_PSDEV_MINOR 240 +#define SNAP_PSDEV_MAJOR 10 + +#ifdef __KERNEL__ + +#if 0 +#include <linux/lustre_lib.h> +#else +#include "snapfs_support.h" +#endif +/* What we use to point to IDs in the obdmd data for snapshots. If we use + * obd_id (8 bytes) instead of ino_t (4 bytes), we halve the number of + * available snapshot slots (14 in 56 bytes vs. 7 in 56 bytes until we + * increase the size of OBD_OBDMDSZ). + */ +typedef ino_t snap_id; + + +/* maximum number of snapshots per device + must fit in "o_obdmd" area of struct obdo */ +//#define OBD_OBDMDSZ 54 +//#define SNAP_MAX ((OBD_OBDMDSZ - sizeof(uint32_t))/sizeof(snap_id)) + +#define SNAP_MAX 50 + + +/* if time is 0 this designates the "current" snapshot, i.e. + the head of the tree +*/ + +/* sysctl.c */ +extern int init_snapfs_proc_sys(void); +extern void cleanup_spapfs_proc_sys(void); +extern int snap_print_entry; +extern int snap_debug_level; +extern int snap_inodes; +extern long snap_kmemory; +extern int snap_stack; + +/* snap cache information: this morally equals the superblock of a + snap_current_fs. However, that superblock is the one of the "cache" + device holding the inodes, hence we store this info in the hash of + mountpoints hanging of our control device. +*/ +struct snap_cache { + struct list_head cache_chain; + + kdev_t cache_dev; + struct super_block *cache_sb; /* the _real_ device */ + + struct list_head cache_clone_list; + int cache_snap_tableno; + + struct filter_fs *cache_filter; + + char cache_type; + char cache_show_dotsnap; +}; + +/* this is the snap_clone_info for the sb of snap_clone_fs */ +struct snap_clone_info { + struct snap_cache *clone_cache; + struct list_head clone_list_entry; + int clone_index; +}; + +/* + * it is important that things like inode, super and file operations + * for intermezzo are not defined statically. If methods are NULL + * the VFS takes special action based on that. Given that different + * cache types have NULL ops at different slots, we must install opeation + * talbes for InterMezzo with NULL's in the same spot + */ + +struct filter_ops { + /* operations on the file store */ + struct super_operations filter_sops; + + struct inode_operations filter_dir_iops; + struct inode_operations filter_file_iops; + struct inode_operations filter_sym_iops; + + struct file_operations filter_dir_fops; + struct file_operations filter_file_fops; + struct file_operations filter_sym_fops; + + struct address_space_operations filter_file_aops; + struct dentry_operations filter_dentry_ops; +}; + + +struct cache_ops { + /* operations on the file store */ + struct super_operations *cache_sops; + + struct inode_operations *cache_dir_iops; + struct inode_operations *cache_file_iops; + struct inode_operations *cache_sym_iops; + + struct file_operations *cache_dir_fops; + struct file_operations *cache_file_fops; + struct file_operations *cache_sym_fops; + + struct address_space_operations *cache_file_aops; + struct dentry_operations *cache_dentry_ops; +}; + + +#define SNAP_OP_NOOP 0 +#define SNAP_OP_CREATE 1 +#define SNAP_OP_MKDIR 2 +#define SNAP_OP_UNLINK 3 +#define SNAP_OP_RMDIR 4 +#define SNAP_OP_CLOSE 5 +#define SNAP_OP_SYMLINK 6 +#define SNAP_OP_RENAME 7 +#define SNAP_OP_SETATTR 8 +#define SNAP_OP_LINK 9 +#define SNAP_OP_OPEN 10 +#define SNAP_OP_MKNOD 11 +#define SNAP_OP_WRITE 12 +#define SNAP_OP_RELEASE 13 + +struct journal_ops { + void *(*trans_start)(struct inode *, int op); + void (*trans_commit)(void *handle); +}; + +struct snap_control_device { + struct list_head snap_dev_list; +}; + +#define D_MAXLEN 1024 + +#define SNAPSHOT_UNUSED_FLAG (1 << 0) +#define SNAPSHOT_GOOD_FLAG (1 << 1) +#define SNAPSHOT_DELETING_FLAG (1 << 2) +#define SNAPSHOT_BAD_FLAG (1 << 3) + +struct snap_disk { + __u64 time; + __u32 gen; + __u32 index; + __u32 flags; + char name[SNAP_MAX_NAMELEN]; +}; +/* snap ioctl data for attach: current always in first slot of this array */ +struct snap_obd_data { + int snap_dev; /* which device contains the data */ + unsigned int snap_index;/* which snapshot is ours */ + unsigned int snap_table;/* which table do we use */ +}; + +struct snap_table { + struct semaphore tbl_sema; + spinlock_t tbl_lock; + unsigned int tbl_count; /* how many snapshots exist in this table*/ + unsigned int generation; + struct snap snap_items[SNAP_MAX]; +}; +#define DISK_SNAPTABLE_ATTR "Snaptable" +#define DISK_SNAP_TABLE_MAGIC 0x1976 +struct snap_disk_table { + unsigned int magic; + unsigned int count; + unsigned int generation; + struct snap_disk snap_items[SNAP_MAX]; +}; + +struct snap_iterdata { + kdev_t dev; /* snap current device number */ + int index; + int tableno; + time_t time; +}; + +struct snap_ioc_data { + kdev_t dev; + char name[SNAP_MAX_NAMELEN]; +}; + +struct snap_ino_list_data{ + kdev_t dev; + ino_t ino; +}; +struct filter_inode_info { + int flags; /* the flags indicated inode type */ + int generation; /*the inode generation*/ +}; +/* dotsnap.c */ +extern int currentfs_is_under_dotsnap(struct dentry *de); + +/* cache.c */ +inline void snap_free_cache(struct snap_cache *cache); +struct snap_cache *snap_find_cache(kdev_t dev); + +/* snaptable.c */ +extern struct snap_table snap_tables[SNAP_MAX_TABLES]; +void snap_last(struct snap_cache *info, struct snap *snap); +int snap_index2slot(struct snap_table *snap_table, int snap_index); +int snap_needs_cow(struct inode *); +int snapfs_read_snaptable(struct snap_cache *cache, int tableno); +/* snap.c */ +int snap_is_redirector(struct inode *inode); +struct inode *snap_redirect(struct inode *inode, struct super_block *clone_sb); +int snap_do_cow(struct inode *inode, ino_t parent_ino, int del); + +int snap_iterate(struct super_block *sb, + int (*repeat)(struct inode *inode, void *priv), + struct inode **start, void *priv, int flag); + +struct inode *snap_get_indirect(struct inode *pri, int *table, int slot); +int snap_destroy_indirect(struct inode *pri, int index, struct inode *next_ind); +int snap_restore_indirect(struct inode *pri, int index ); +int snap_migrate_data(struct inode *dst, struct inode *src); +int snap_set_indirect(struct inode *pri, ino_t ind_ino, + int index, ino_t parent_ino); + +/* inode.c */ +extern struct super_operations currentfs_super_ops; +void cleanup_filter_info_cache(void); +int init_filter_info_cache(void); +void init_filter_data(struct inode *inode, struct snapshot_operations *snapops, + int flag); + +/* dir.c */ +extern struct inode_operations currentfs_dir_iops; +extern struct file_operations currentfs_dir_fops; +extern struct address_space_operations currentfs_file_aops; + +/* file.c */ +extern struct inode_operations currentfs_file_iops; +extern struct file_operations currentfs_file_fops; + +/* symlink.c */ +extern struct inode_operations currentfs_sym_iops; +extern struct file_operations currentfs_sym_fops; + +extern struct dentry_operations currentfs_dentry_ops; + + + +#define FILTER_DID_SUPER_OPS 0x1 +#define FILTER_DID_INODE_OPS 0x2 +#define FILTER_DID_FILE_OPS 0x4 +#define FILTER_DID_DENTRY_OPS 0x8 +#define FILTER_DID_DEV_OPS 0x10 +#define FILTER_DID_SYMLINK_OPS 0x20 +#define FILTER_DID_DIR_OPS 0x40 +#define FILTER_DID_SNAPSHOT_OPS 0x80 +#define FILTER_DID_JOURNAL_OPS 0x100 + +struct filter_fs { + int o_flags; + struct filter_ops o_fops; + struct cache_ops o_caops; + struct journal_ops *o_trops; + struct snapshot_operations *o_snapops; +}; + +#define FILTER_FS_TYPES 3 +#define FILTER_FS_EXT2 0 +#define FILTER_FS_EXT3 1 +#define FILTER_FS_REISER 2 +extern struct filter_fs filter_oppar[FILTER_FS_TYPES]; + +struct filter_fs *filter_get_filter_fs(const char *cache_type); +inline struct super_operations *filter_c2usops(struct filter_fs *cache); +inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache); +inline struct inode_operations *filter_c2udiops(struct filter_fs *cache); +inline struct inode_operations *filter_c2usiops(struct filter_fs *cache); +inline struct super_operations *filter_c2csops(struct filter_fs *cache); +inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache); +inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache); +inline struct inode_operations *filter_c2csiops(struct filter_fs *cache); +inline struct file_operations *filter_c2cffops(struct filter_fs *cache); +inline struct file_operations *filter_c2cdfops(struct filter_fs *cache); +inline struct file_operations *filter_c2csfops(struct filter_fs *cache); +inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache); +inline struct dentry_operations *filter_c2udops(struct filter_fs *cache); +inline struct address_space_operations *filter_c2cfaops(struct filter_fs *cache); +/* for snapfs */ +inline struct snapshot_operations *filter_c2csnapops(struct filter_fs *cache); + +void filter_setup_file_ops(struct filter_fs *cache, + struct inode *inode, + struct inode_operations *filter_iops, + struct file_operations *filter_fops, + struct address_space_operations *filter_aops); + +void filter_setup_dir_ops(struct filter_fs *cache, + struct inode *inode, + struct inode_operations *filter_iops, + struct file_operations *filter_fops); + +void filter_setup_symlink_ops(struct filter_fs *cache, + struct inode *inode, + struct inode_operations *filter_iops, + struct file_operations *filter_fops); + +void filter_setup_dentry_ops(struct filter_fs *cache, + struct dentry_operations *cache_dop, + struct dentry_operations *filter_dop); +void filter_setup_super_ops(struct filter_fs *cache, + struct super_operations *cache_sops, + struct super_operations *filter_sops); +/* for snapfs */ +void filter_setup_snapshot_ops(struct filter_fs *cache, + struct snapshot_operations *cache_snapops); +void filter_setup_journal_ops(struct filter_fs *cache, + struct journal_ops *cache_journal_ops); + +static inline void* snap_trans_start(struct snap_cache *cache, + struct inode *inode, int op) +{ + if( cache->cache_filter->o_trops ) + return cache->cache_filter->o_trops->trans_start(inode, op); + return NULL; +}; +static inline void snap_trans_commit(struct snap_cache *cache, void *handle) +{ + if( cache->cache_filter->o_trops ) + cache->cache_filter->o_trops->trans_commit(handle); +}; + +static inline void snapfs_cpy_attrs(struct inode *dst, struct inode *src) +{ + dst->i_mtime = src->i_mtime; + dst->i_ctime = src->i_ctime; + dst->i_atime = src->i_atime; + dst->i_size = src->i_size; + dst->i_blksize = src->i_blksize; + dst->i_blocks = src->i_blocks; + dst->i_generation = src->i_generation; + dst->i_uid = src->i_uid; + dst->i_gid = src->i_gid; + dst->i_mode = src->i_mode; +} +#ifdef SNAP_DEBUG +extern unsigned int snap_debug_failcode; +#ifdef CONFIG_LOOP_DISCARD +#define BLKDEV_FAIL(dev,fail) loop_discard_io(dev,fail) +#else +#define BLKDEV_FAIL(dev,fail) set_device_ro(dev, 1) +#endif + +static inline void snap_debug_device_fail(dev_t dev, unsigned short opcode, unsigned short pos) +{ + unsigned int failcode = (opcode<<16) | pos; + + if( failcode == snap_debug_failcode && !is_read_only(dev)){ + printk(KERN_EMERG "set block device %s into fail mode\n", bdevname(dev)); + BLKDEV_FAIL(dev, 1); + } +} +#else +#define snap_debug_device_fail(args...) do{}while(0) +#endif + +extern int snap_debug_level; +extern int snap_print_entry; + +#endif /*_KERNEL_*/ +#endif /* __LINUX_SNAPFS_H */ diff --git a/lustre/snapfs/snapfs_support.h b/lustre/snapfs/snapfs_support.h new file mode 100644 index 0000000000..7da4746f7f --- /dev/null +++ b/lustre/snapfs/snapfs_support.h @@ -0,0 +1,156 @@ +/*Got these defination from lustre*/ +#define S_SNAP (1 << 0) + +#define D_TRACE (1 << 0) /* ENTRY/EXIT markers */ +#define D_INODE (1 << 1) +#define D_SUPER (1 << 2) +#define D_EXT2 (1 << 3) /* anything from ext2_debug */ +#define D_MALLOC (1 << 4) /* print malloc, free information */ +#define D_CACHE (1 << 5) /* cache-related items */ +#define D_INFO (1 << 6) /* general information */ +#define D_IOCTL (1 << 7) /* ioctl related information */ +#define D_BLOCKS (1 << 8) /* ext2 block allocation */ +#define D_NET (1 << 9) /* network communications */ +#define D_WARNING (1 << 10) /* CWARN(...) == CDEBUG (D_WARNING, ...) */ +#define D_BUFFS (1 << 11) +#define D_OTHER (1 << 12) +#define D_DENTRY (1 << 13) +#define D_PAGE (1 << 15) /* bulk page handling */ +#define D_DLMTRACE (1 << 16) +#define D_ERROR (1 << 17) /* CERROR(...) == CDEBUG (D_ERROR, ...) */ +#define D_EMERG (1 << 18) /* CEMERG(...) == CDEBUG (D_EMERG, ...) */ +#define D_HA (1 << 19) /* recovery and failover */ +#define D_RPCTRACE (1 << 20) /* for distributed debugging */ +#define D_VFSTRACE (1 << 21) +#define D_SNAP (1 << 22) + +#ifdef __KERNEL__ +# include <linux/sched.h> /* THREAD_SIZE */ +#else +# ifndef THREAD_SIZE /* x86_64 has THREAD_SIZE in userspace */ +# define THREAD_SIZE 8192 +# endif +#endif + +# include <linux/vmalloc.h> +# define snap_debug_msg(mask, file, fn, line, stack, format, a...) \ + printk("%02x (@%lu %s:%s,l. %d %d %lu): " format, \ + (mask), (long)time(0), file, fn, line, \ + getpid() , stack, ## a); + +#define LUSTRE_TRACE_SIZE (THREAD_SIZE >> 5) + +#ifdef __KERNEL__ +# ifdef __ia64__ +# define CDEBUG_STACK (THREAD_SIZE - \ + ((unsigned long)__builtin_dwarf_cfa() & \ + (THREAD_SIZE - 1))) +# else +# define CDEBUG_STACK (THREAD_SIZE - \ + ((unsigned long)__builtin_frame_address(0) & \ + (THREAD_SIZE - 1))) +# endif + +#define CHECK_STACK(stack) \ + do { \ + if ((stack) > 3*THREAD_SIZE/4 && (stack) > snap_stack) { \ + printk( "maximum lustre stack %u\n", \ + snap_stack = (stack)); \ + } \ + } while (0) +#else /* __KERNEL__ */ +#define CHECK_STACK(stack) do { } while(0) +#define CDEBUG_STACK (0L) +#endif /* __KERNEL__ */ + +#if 1 +#define CDEBUG(mask, format, a...) \ +do { \ + CHECK_STACK(CDEBUG_STACK); \ + if (!(mask) || ((mask) & (D_ERROR | D_EMERG | D_WARNING)) || \ + (snap_debug_level & (mask))) \ + printk(format, ## a); \ +} while (0) + +#define CWARN(format, a...) CDEBUG(D_WARNING, format, ## a) +#define CERROR(format, a...) CDEBUG(D_ERROR, format, ## a) +#define CEMERG(format, a...) CDEBUG(D_EMERG, format, ## a) + +#define GOTO(label, rc) \ +do { \ + long GOTO__ret = (long)(rc); \ + CDEBUG(D_TRACE,"Process leaving via %s (rc=%lu : %ld : %lx)\n", \ + #label, (unsigned long)GOTO__ret, (signed long)GOTO__ret,\ + (signed long)GOTO__ret); \ + goto label; \ +} while (0) + +#define RETURN(rc) \ +do { \ + typeof(rc) RETURN__ret = (rc); \ + CDEBUG(D_TRACE, "Process %d leaving %s (rc=%lu : %ld : %lx)\n", \ + current->pid, __FUNCTION__, (long)RETURN__ret, \ + (long)RETURN__ret, (long)RETURN__ret); \ + return RETURN__ret; \ +} while (0) + +#define ENTRY \ +do { \ + CDEBUG(D_TRACE, "Process %d enter %s\n", \ + current->pid, __FUNCTION__); \ +} while (0) + +#define EXIT \ +do { \ + CDEBUG(D_TRACE, "Process %d leaving %s \n", \ + current->pid, __FUNCTION__); \ +} while(0) +#else +#define CDEBUG(mask, format, a...) do { } while (0) +#define CWARN(format, a...) do { } while (0) +#define CERROR(format, a...) printk("<3>" format, ## a) +#define CEMERG(format, a...) printk("<0>" format, ## a) +#define GOTO(label, rc) do { (void)(rc); goto label; } while (0) +#define RETURN(rc) return (rc) +#define ENTRY do { } while (0) +#define EXIT do { } while (0) +#endif + +#define SNAP_ALLOC(ptr, size) \ +do { \ + if (size <= 4096) { \ + ptr = kmalloc((unsigned long) size, GFP_KERNEL); \ + CDEBUG(D_MALLOC, "Proc %d %s:%d kmalloced: %d at %x.\n",\ + current->pid, __FUNCTION__, __LINE__, \ + (int) size, (int) ptr); \ + } else { \ + ptr = vmalloc((unsigned long) size); \ + CDEBUG(D_MALLOC, "Proc %d %s:%d vmalloced: %d at %x.\n",\ + current->pid, __FUNCTION__, __LINE__, \ + (int) size, (int) ptr); \ + } \ + if (ptr == 0) { \ + printk("kernel malloc returns 0 at %s:%d\n", \ + __FILE__, __LINE__); \ + } else { \ + memset(ptr, 0, size); \ + snap_kmemory += size; \ + } \ +} while (0) + +#define SNAP_FREE(ptr,size) \ +do { \ + snap_kmemory -= size; \ + if (size <= 4096) { \ + CDEBUG(D_MALLOC, "Proc %d %s:%d kfreed: %d at %x.\n", \ + current->pid, __FUNCTION__, __LINE__, \ + (int) size, (int) ptr); \ + kfree((ptr)); \ + } else { \ + CDEBUG(D_MALLOC, "Proc %d %s:%d vfreed: %d at %x.\n", \ + current->pid, __FUNCTION__, __LINE__, \ + (int) size, (int) ptr); \ + vfree((ptr)); \ + } \ +} while (0) + -- GitLab