Whamcloud - gitweb
add snapfs_internal.h snapfs_support.h Makefile.am
authorwangdi <wangdi>
Sun, 4 Jan 2004 07:28:26 +0000 (07:28 +0000)
committerwangdi <wangdi>
Sun, 4 Jan 2004 07:28:26 +0000 (07:28 +0000)
lustre/snapfs/Makefile.am [new file with mode: 0644]
lustre/snapfs/snapfs_internal.h [new file with mode: 0644]
lustre/snapfs/snapfs_support.h [new file with mode: 0644]

diff --git a/lustre/snapfs/Makefile.am b/lustre/snapfs/Makefile.am
new file mode 100644 (file)
index 0000000..15d50ab
--- /dev/null
@@ -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 (file)
index 0000000..ce43dbf
--- /dev/null
@@ -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 (file)
index 0000000..7da4746
--- /dev/null
@@ -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)
+