/* * Copyright (c) 1997-2003 Erez Zadok * Copyright (c) 2001-2003 Stony Brook University * * For specific licensing information, see the COPYING file distributed with * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. * * This Copyright notice must be kept intact and distributed with all * fistgen sources INCLUDING sources generated by fistgen. */ /* * Copyright (C) 2004, 2005 Markus Klotzbuecher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ /* * $Id$ */ #ifndef __MINI_FO_H_ #define __MINI_FO_H_ #ifdef __KERNEL__ /* META stuff */ #define META_FILENAME "META_dAfFgHE39ktF3HD2sr" /* use xattrs? */ #define XATTR /* File attributes that when changed, result in a file beeing copied to storage */ #define COPY_FLAGS ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE /* * mini_fo filestates */ #define MODIFIED 1 #define UNMODIFIED 2 #define CREATED 3 #define DEL_REWRITTEN 4 #define DELETED 5 #define NON_EXISTANT 6 /* fist file systems superblock magic */ # define MINI_FO_SUPER_MAGIC 0xf15f /* * STRUCTURES: */ /* mini_fo inode data in memory */ struct mini_fo_inode_info { inode_t *wii_inode; inode_t *wii_inode2; /* pointer to storage inode */ /* META-data lists */ /* deleted list, ex wol */ struct list_head deleted_list; int deleted_list_size; /* renamed list */ struct list_head renamed_list; int renamed_list_size; /* add other lists here ... */ }; /* mini_fo dentry data in memory */ struct mini_fo_dentry_info { dentry_t *wdi_dentry; dentry_t *wdi_dentry2; /* pointer to storage dentry */ unsigned int state; /* state of the mini_fo dentry */ }; /* mini_fo super-block data in memory */ struct mini_fo_sb_info { super_block_t *wsi_sb, *wsi_sb2; /* mk: might point to the same sb */ struct vfsmount *hidden_mnt, *hidden_mnt2; dentry_t *base_dir_dentry; dentry_t *storage_dir_dentry; ; }; /* readdir_data, readdir helper struct */ struct readdir_data { struct list_head ndl_list; /* linked list head ptr */ int ndl_size; /* list size */ int sto_done; /* flag to show that the storage dir entries have * all been read an now follow base entries */ }; /* file private data. */ struct mini_fo_file_info { struct file *wfi_file; struct file *wfi_file2; /* pointer to storage file */ struct readdir_data rd; }; /* struct ndl_entry */ struct ndl_entry { struct list_head list; char *name; int len; }; /******************************** * META-data structures ********************************/ /* deleted entry */ struct deleted_entry { struct list_head list; char *name; int len; }; /* renamed entry */ struct renamed_entry { struct list_head list; char *old_name; /* old directory with full path */ int old_len; /* length of above string */ char *new_name; /* new directory name */ int new_len; /* length of above string */ }; /* attr_change entry */ struct attr_change_entry { struct list_head list; char *name; int len; }; /* link entry */ struct link_entry { struct list_head list; int links_moved; int inum_base; int inum_sto; char *weird_name; int weird_name_len; }; /* Some other stuff required for mini_fo_filldir64, copied from * fs/readdir.c */ #define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1)) #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) struct linux_dirent64 { u64 d_ino; s64 d_off; unsigned short d_reclen; unsigned char d_type; char d_name[0]; }; struct getdents_callback64 { struct linux_dirent64 * current_dir; struct linux_dirent64 * previous; int count; int error; }; struct linux_dirent { unsigned long d_ino; unsigned long d_off; unsigned short d_reclen; char d_name[1]; }; struct getdents_callback { struct linux_dirent * current_dir; struct linux_dirent * previous; int count; int error; }; /* * MACROS: */ /* file TO private_data */ # define ftopd(file) ((struct mini_fo_file_info *)((file)->private_data)) # define __ftopd(file) ((file)->private_data) /* file TO hidden_file */ # define ftohf(file) ((ftopd(file))->wfi_file) # define ftohf2(file) ((ftopd(file))->wfi_file2) /* inode TO private_data */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) # define itopd(ino) ((struct mini_fo_inode_info *)(ino)->i_private) # define __itopd(ino) ((ino)->i_private) #else # define itopd(ino) ((struct mini_fo_inode_info *)(ino)->u.generic_ip) # define __itopd(ino) ((ino)->u.generic_ip) #endif /* inode TO hidden_inode */ # define itohi(ino) (itopd(ino)->wii_inode) # define itohi2(ino) (itopd(ino)->wii_inode2) /* superblock TO private_data */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) # define stopd(super) ((struct mini_fo_sb_info *)(super)->s_fs_info) # define __stopd(super) ((super)->s_fs_info) #else # define stopd(super) ((struct mini_fo_sb_info *)(super)->u.generic_sbp) # define __stopd(super) ((super)->u.generic_sbp) #endif /* unused? # define vfs2priv stopd */ /* superblock TO hidden_superblock */ # define stohs(super) (stopd(super)->wsi_sb) # define stohs2(super) (stopd(super)->wsi_sb2) /* dentry TO private_data */ # define dtopd(dentry) ((struct mini_fo_dentry_info *)(dentry)->d_fsdata) # define __dtopd(dentry) ((dentry)->d_fsdata) /* dentry TO hidden_dentry */ # define dtohd(dent) (dtopd(dent)->wdi_dentry) # define dtohd2(dent) (dtopd(dent)->wdi_dentry2) /* dentry to state */ # define dtost(dent) (dtopd(dent)->state) # define sbt(sb) ((sb)->s_type->name) #define IS_WRITE_FLAG(flag) (flag & (O_RDWR | O_WRONLY | O_APPEND)) #define IS_COPY_FLAG(flag) (flag & (COPY_FLAGS)) /* macros to simplify non-SCA code */ # define MALLOC_PAGE_POINTERS(hidden_pages, num_hidden_pages) # define MALLOC_PAGEDATA_POINTERS(hidden_pages_data, num_hidden_pages) # define FREE_PAGE_POINTERS(hidden_pages, num) # define FREE_PAGEDATA_POINTERS(hidden_pages_data, num) # define FOR_EACH_PAGE # define CURRENT_HIDDEN_PAGE hidden_page # define CURRENT_HIDDEN_PAGEDATA hidden_page_data # define CURRENT_HIDDEN_PAGEINDEX page->index /* * EXTERNALS: */ extern struct file_operations mini_fo_main_fops; extern struct file_operations mini_fo_dir_fops; extern struct inode_operations mini_fo_main_iops; extern struct inode_operations mini_fo_dir_iops; extern struct inode_operations mini_fo_symlink_iops; extern struct super_operations mini_fo_sops; extern struct dentry_operations mini_fo_dops; extern struct vm_operations_struct mini_fo_shared_vmops; extern struct vm_operations_struct mini_fo_private_vmops; extern struct address_space_operations mini_fo_aops; #if 0 /* unused by mini_fo */ extern int mini_fo_interpose(dentry_t *hidden_dentry, dentry_t *this_dentry, super_block_t *sb, int flag); #if defined(FIST_FILTER_DATA) || defined(FIST_FILTER_SCA) extern page_t *mini_fo_get1page(file_t *file, int index); extern int mini_fo_fill_zeros(file_t *file, page_t *page, unsigned from); # endif /* FIST_FILTER_DATA || FIST_FILTER_SCA */ # define mini_fo_hidden_dentry(d) __mini_fo_hidden_dentry(__FILE__,__FUNCTION__,__LINE__,(d)) # define mini_fo_hidden_sto_dentry(d) __mini_fo_hidden_sto_dentry(__FILE__,__FUNCTION__,__LINE__,(d)) extern dentry_t *__mini_fo_hidden_dentry(char *file, char *func, int line, dentry_t *this_dentry); extern dentry_t *__mini_fo_hidden_sto_dentry(char *file, char *func, int line, dentry_t *this_dentry); extern int mini_fo_read_file(const char *filename, void *buf, int len); extern int mini_fo_write_file(const char *filename, void *buf, int len); extern dentry_t *fist_lookup(dentry_t *dir, const char *name, vnode_t **out, uid_t uid, gid_t gid); #endif /* unused by mini_fo */ /* state transition functions */ extern int nondir_unmod_to_mod(dentry_t *dentry, int cp_flag); extern int nondir_del_rew_to_del(dentry_t *dentry); extern int nondir_creat_to_del(dentry_t *dentry); extern int nondir_mod_to_del(dentry_t *dentry); extern int nondir_unmod_to_del(dentry_t *dentry); extern int dir_unmod_to_mod(dentry_t *dentry); /* rename specials */ extern int rename_directory(inode_t *old_dir, dentry_t *old_dentry, inode_t *new_dir, dentry_t *new_dentry); extern int rename_nondir(inode_t *old_dir, dentry_t *old_dentry, inode_t *new_dir, dentry_t *new_dentry); /* misc stuff */ extern int mini_fo_tri_interpose(dentry_t *hidden_dentry, dentry_t *hidden_sto_dentry, dentry_t *dentry, super_block_t *sb, int flag); extern int mini_fo_cp_cont(dentry_t *tgt_dentry, struct vfsmount *tgt_mnt, dentry_t *src_dentry, struct vfsmount *src_mnt); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) extern struct inode *mini_fo_iget(struct super_block *sb, unsigned long ino); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd); extern int create_sto_nod(dentry_t *dentry, int mode, dev_t dev); extern int create_sto_reg_file(dentry_t *dentry, int mode, struct nameidata *nd); #else extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode); extern int create_sto_nod(dentry_t *dentry, int mode, int dev); extern int create_sto_reg_file(dentry_t *dentry, int mode); #endif extern int create_sto_dir(dentry_t *dentry, int mode); extern int exists_in_storage(dentry_t *dentry); extern int is_mini_fo_existant(dentry_t *dentry); extern int get_neg_sto_dentry(dentry_t *dentry); extern int build_sto_structure(dentry_t *dir, dentry_t *dentry); extern int get_mini_fo_bpath(dentry_t *dentry, char **bpath, int *bpath_len); extern dentry_t *bpath_walk(super_block_t *sb, char *bpath); extern int bpath_put(dentry_t *dentry); /* check_mini_fo types functions */ extern int check_mini_fo_dentry(dentry_t *dentry); extern int check_mini_fo_file(file_t *file); extern int check_mini_fo_inode(inode_t *inode); /* General meta functions, can be called from outside of meta.c */ extern int meta_build_lists(dentry_t *dentry); extern int meta_put_lists(dentry_t *dentry); extern int __meta_put_lists(inode_t *inode); extern int meta_add_d_entry(dentry_t *dentry, const char *name, int len); extern int meta_add_r_entry(dentry_t *dentry, const char *old_name, int old_len, const char *new_name, int new_len); extern int meta_remove_r_entry(dentry_t *dentry, const char *name, int len); extern int meta_check_d_entry(dentry_t *dentry, const char *name, int len); extern int __meta_check_d_entry(inode_t *inode, const char *name, int len); extern char* meta_check_r_entry(dentry_t *dentry, const char *name, int len); extern char* __meta_check_r_entry(inode_t *inode, const char *name, int len); extern int meta_is_r_entry(dentry_t *dentry, const char *name, int len); extern int __meta_is_r_entry(inode_t *inode, const char *name, int len); /* Specific meta functions, should be called only inside meta.c */ extern int __meta_put_d_list(inode_t *inode); extern int __meta_put_r_list(inode_t *inode); extern int meta_list_add_d_entry(dentry_t *dentry, const char *name, int len); extern int meta_list_add_r_entry(dentry_t *dentry, const char *old_name, int old_len, const char *new_name, int new_len); extern int meta_list_remove_r_entry(dentry_t *dentry, const char *name, int len); extern int __meta_list_remove_r_entry(inode_t *inode, const char *name, int len); extern int meta_write_d_entry(dentry_t *dentry, const char *name, int len); extern int meta_write_r_entry(dentry_t *dentry, const char *old_name, int old_len, const char *new_name, int new_len); extern int meta_sync_lists(dentry_t *dentry); extern int meta_sync_d_list(dentry_t *dentry, int app_flag); extern int meta_sync_r_list(dentry_t *dentry, int app_flag); /* ndl stuff */ extern int ndl_add_entry(struct readdir_data *rd, const char *name, int len); extern void ndl_put_list(struct readdir_data *rd); extern int ndl_check_entry(struct readdir_data *rd, const char *name, int len); # define copy_inode_size(dst, src) \ dst->i_size = src->i_size; \ dst->i_blocks = src->i_blocks; static inline void fist_copy_attr_atime(inode_t *dest, const inode_t *src) { ASSERT(dest != NULL); ASSERT(src != NULL); dest->i_atime = src->i_atime; } static inline void fist_copy_attr_times(inode_t *dest, const inode_t *src) { ASSERT(dest != NULL); ASSERT(src != NULL); dest->i_atime = src->i_atime; dest->i_mtime = src->i_mtime; dest->i_ctime = src->i_ctime; } static inline void fist_copy_attr_timesizes(inode_t *dest, const inode_t *src) { ASSERT(dest != NULL); ASSERT(src != NULL); dest->i_atime = src->i_atime; dest->i_mtime = src->i_mtime; dest->i_ctime = src->i_ctime; copy_inode_size(dest, src); } static inline void fist_copy_attr_all(inode_t *dest, const inode_t *src) { ASSERT(dest != NULL); ASSERT(src != NULL); dest->i_mode = src->i_mode; dest->i_nlink = src->i_nlink; dest->i_uid = src->i_uid; dest->i_gid = src->i_gid; dest->i_rdev = src->i_rdev; dest->i_atime = src->i_atime; dest->i_mtime = src->i_mtime; dest->i_ctime = src->i_ctime; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) dest->i_blksize = src->i_blksize; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,12) dest->i_blkbits = src->i_blkbits; # endif /* linux 2.4.12 and newer */ copy_inode_size(dest, src); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) dest->i_attr_flags = src->i_attr_flags; #else dest->i_flags = src->i_flags; #endif } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) /* copied from linux/fs.h */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) static inline void double_lock(struct dentry *d1, struct dentry *d2) { struct mutex *m1 = &d1->d_inode->i_mutex; struct mutex *m2 = &d2->d_inode->i_mutex; if (m1 != m2) { if ((unsigned long) m1 < (unsigned long) m2) { struct mutex *tmp = m2; m2 = m1; m1 = tmp; } mutex_lock(m1); } mutex_lock(m2); } static inline void double_unlock(struct dentry *d1, struct dentry *d2) { struct mutex *m1 = &d1->d_inode->i_mutex; struct mutex *m2 = &d2->d_inode->i_mutex; mutex_unlock(m1); if (m1 != m2) mutex_unlock(m2); dput(d1); dput(d2); } #else static inline void double_down(struct semaphore *s1, struct semaphore *s2) { if (s1 != s2) { if ((unsigned long) s1 < (unsigned long) s2) { struct semaphore *tmp = s2; s2 = s1; s1 = tmp; } down(s1); } down(s2); } static inline void double_up(struct semaphore *s1, struct semaphore *s2) { up(s1); if (s1 != s2) up(s2); } static inline void double_lock(struct dentry *d1, struct dentry *d2) { double_down(&d1->d_inode->i_sem, &d2->d_inode->i_sem); } static inline void double_unlock(struct dentry *d1, struct dentry *d2) { double_up(&d1->d_inode->i_sem,&d2->d_inode->i_sem); dput(d1); dput(d2); } #endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) */ #endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */ #endif /* __KERNEL__ */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) static inline dentry_t *nd_get_dentry(struct nameidata *nd) { return (nd->path.dentry); } static inline struct vfsmount *nd_get_mnt(struct nameidata *nd) { return (nd->path.mnt); } #else static inline dentry_t *nd_get_dentry(struct nameidata *nd) { return (nd->dentry); } static inline struct vfsmount *nd_get_mnt(struct nameidata *nd) { return (nd->mnt); } #endif /* * Definitions for user and kernel code */ /* ioctls */ #endif /* not __MINI_FO_H_ */