#define PORTALS_DEV_PATH "/dev/portals"
#define OBD_DEV_ID 1
#define OBD_DEV_PATH "/dev/obd"
+#define SMFS_DEV_ID 2
+#define SMFS_DEV_PATH "/dev/snapdev"
int ptl_name2nal(char *str);
int ptl_parse_ipaddr (__u32 *ipaddrp, char *str);
#define PORTALS_DEV_PATH "/dev/portals"
#define OBD_DEV_ID 1
#define OBD_DEV_PATH "/dev/obd"
+#define SMFS_DEV_ID 2
+#define SMFS_DEV_PATH "/dev/snapdev"
int ptl_name2nal(char *str);
int ptl_parse_ipaddr (__u32 *ipaddrp, char *str);
#define OBD_IOC_COBD_COFF _IOWR('f', 221, long)
#define OBD_IOC_COBD_CFLUSH _IOWR('f', 222, long)
-#define OBD_IOC_SNAP_ADD _IOWR('f', 230, long)
+#define OBD_IOC_SMFS_SNAP_ADD _IOWR('f', 230, long)
/* XXX _IOWR('f', 250, long) has been defined in
* portals/include/linux/kp30.h for debug, don't use it
int sn_flags; /*the flags indicated inode type */
int sn_gen; /*the inode generation*/
int sn_index; /*the inode snap_index*/
+ ino_t sn_root_ino; /*the root ino of this snap*/
};
struct smfs_inode_info {
struct inode *smi_inode;
char *smsi_cache_ftype; /* cache file system type */
char *smsi_ftype; /* file system type */
struct obd_export *smsi_exp; /* file system obd exp */
- struct snap_info *smsi_snap_info; /* snap table cow */
+ struct snap_super_info *smsi_snap_info; /* snap table cow */
smfs_pack_rec_func smsi_pack_rec[PACK_MAX]; /* sm_pack_rec type ops */
__u32 smsi_flags; /* flags */
__u32 smsi_ops_check;
struct list_head smsi_hook_list;
+ kmem_cache_t * smsi_inode_cachep; /*inode_cachep*/
};
__u32 e_num; /* number of blocks covered by extent */
};
-#define I2SMI(inode) ((struct smfs_inode_info *) (&(inode->u.generic_ip)))
+#define I2SMI(inode) ((struct smfs_inode_info *) ((inode->u.generic_ip)))
+
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#define S2SMI(sb) ((struct smfs_super_info *) (&(sb->u.generic_sbp)))
-#define S2CSB(sb) (((struct smfs_super_info *) (&(sb->u.generic_sbp)))->smsi_sb)
+#define S2SMI(sb) ((struct smfs_super_info *) ((sb->u.generic_sbp)))
+#define S2CSB(sb) (((struct smfs_super_info *)((sb->u.generic_sbp)))->smsi_sb)
#else
#define S2SMI(sb) ((struct smfs_super_info *) (sb->s_fs_info))
#define S2CSB(sb) (((struct smfs_super_info *) (sb->s_fs_info))->smsi_sb)
#endif
-#define I2CI(inode) (((struct smfs_inode_info*) (&(inode->u.generic_ip)))->smi_inode)
+#define I2CI(inode) (((struct smfs_inode_info*) ((inode->u.generic_ip)))->smi_inode)
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#define I2CSB(inode) ((struct smfs_super_info *) (&(inode->i_sb->u.generic_sbp)))
+#define I2CSB(inode) ((struct smfs_super_info *) ((inode->i_sb->u.generic_sbp)))
#else
#define I2CSB(inode) ((struct smfs_super_info *) (inode->i_sb->s_fs_info))
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#define I2FOPS(inode) (((struct smfs_super_info *) \
- (&(inode->i_sb->u.generic_sbp)))->sm_cache_fsfilt)
+ ((inode->i_sb->u.generic_sbp)))->sm_cache_fsfilt)
#else
#define I2FOPS(inode) (((struct smfs_super_info *) \
(inode->i_sb->s_fs_info))->sm_cache_fsfilt)
INIT_LIST_HEAD(&dentry->d_hash);
#else
hlist_del_init(&dentry->d_hash);
+ dentry->d_flags |= DCACHE_UNHASHED;
#endif
dput(dentry); /* this will free the dentry memory */
}
#define SNAP_MAX_TABLES 32
#define SNAP_MAX_NAMELEN 64
-#define MAX_SNAPTABLE_COUNT "MAXSnapCount"
-#define SNAPTABLE_MAGIC 0x19760218
-#define SNAPTABLE_INFO "snaptable"
-#define SNAP_GENERATION "snap_generation"
-
+#define MAX_SNAPTABLE_COUNT "MAXSnapCount"
+#define SNAPTABLE_MAGIC 0x19760218
+#define SNAPTABLE_INFO "snaptable"
+#define SNAP_GENERATION "snap_generation"
+#define SNAP_COUNT "snapcount"
+#define SNAP_ROOT_INO "snap_root_ino"
#define SNAP_LOOKUP (REINT_MAX + 1)
};
struct snap_info {
+ struct list_head sni_list;
+ ino_t sni_root_ino;
+ struct semaphore sni_sema;
+ spinlock_t sni_lock;
+ struct snap_table *sni_table;
+ struct dentry *sni_cowed_dentry;
+ struct snap_dot_info *sni_dot_info;
+};
+
+struct snap_super_info {
struct fsfilt_operations *snap_fsfilt;
struct fsfilt_operations *snap_cache_fsfilt;
- struct dentry *snap_root;
- struct semaphore sntbl_sema;
- spinlock_t sntbl_lock;
- struct snap_table *sntbl;
- struct dentry *sn_cowed_dentry;
- struct snap_dot_info *sn_dot_info;
+ struct list_head snap_list;
+ int snap_table_size;
};
-extern int smfs_add_snap_item(struct super_block *sb, char *name);
+extern int smfs_add_snap_item(struct super_block *sb, char *path_name,
+ char *name);
extern int smfs_start_cow(struct super_block *sb);
extern int smfs_stop_cow(struct super_block *sb);
return 1;
return 0;
}
-
-
+#define SNAP_MINOR 242
+#define SNAP_MAJOR 10
#endif /*_LUSTRE_SNAP_H*/
#include <linux/lustre_mds.h>
#include <linux/lustre_lite.h>
#include <linux/lustre_dlm.h>
-#include <linux/lustre_smfs.h>
-#include <linux/lustre_snap.h>
#include "llite_internal.h"
typedef struct ext2_dir_entry_2 ext2_dirent;
d_type = types[de->file_type];
offset = (char *)de - kaddr;
-#ifdef CONFIG_SNAPFS
- /*FIXME-WANGDI will get dot info from MDS*/
- if ((n << PAGE_CACHE_SHIFT | offset) == 0) {
- int off =n << PAGE_CACHE_SHIFT | offset;
- over = filldir(dirent, DOT_SNAP_NAME,
- strlen(DOT_SNAP_NAME),
- off, -1, 0);
- if (over) {
- ext2_put_page(page);
- GOTO(done, rc);
- }
- }
- offset+=EXT2_DIR_REC_LEN(strlen(DOT_SNAP_NAME));
-#endif
over = filldir(dirent, de->name, de->name_len,
(n<<PAGE_CACHE_SHIFT) | offset,
le32_to_cpu(de->inode), d_type);
int ll_gns_state;
struct timer_list ll_gns_timer;
struct list_head ll_gns_sbi_head;
- void *ll_dot_snap_info;
};
#define LL_GNS_STATE_IDLE 1100
#include <linux/lustre_ha.h>
#include <linux/lustre_dlm.h>
#include <linux/lprocfs_status.h>
-#include <linux/lustre_smfs.h>
-#include <linux/lustre_snap.h>
#include "llite_internal.h"
kmem_cache_t *ll_file_data_slab;
rc = snapops->fs_read_dotsnap_dir_page(sfi->c_file, buf, count,
cache_ppos);
-
} else {
if (cache_fsfilt->fs_readpage)
rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count,
smfs_post_setup(sb, mnt);
if (SMFS_DO_REC(S2SMI(sb)))
rc = smfs_start_rec(sb, mnt);
-#if CONFIG_SNAPFS
- if (SMFS_DO_COW(S2SMI(sb))) {
- S2SNAPI(sb)->snap_root = root_dentry;
- rc = smfs_start_cow(sb);
- }
-#endif
if (rc)
GOTO(exit, rc);
if (obd)
sb = mnt->mnt_sb;
if (SMFS_DO_REC(S2SMI(sb)))
rc = smfs_stop_rec(sb);
-#if CONFIG_SNAPFS
- if (SMFS_DO_COW(S2SMI(sb)))
- rc = smfs_stop_cow(sb);
-#endif
smfs_post_cleanup(sb);
}
RETURN(rc);
ENTRY;
#if CONFIG_SNAPFS
- rc = smfs_add_snap_item(sb, name);
+#warning "still not implement for add snap item -wangdi"
#endif
RETURN(rc);
}
#define EXT3_SNAP_ATTR "@snap"
#define EXT3_SNAP_GENERATION "@snap_generation"
-#define EXT3_MAX_SNAPS 20
+#define EXT3_MAX_SNAPS 10
#define EXT3_MAX_SNAP_DATA (sizeof(struct snap_ea))
#define EXT3_SNAP_INDEX EXT3_XATTR_INDEX_LUSTRE
+#define EXT3_SNAP_COUNT "@snapcount"
+
-#define SB_SNAPTABLE_INO(sb) (EXT3_SB(sb)->s_es->s_snaptable_ino)
#define SB_FEATURE_COMPAT(sb) (EXT3_SB(sb)->s_es->s_feature_compat)
#define SNAP_HAS_COMPAT_FEATURE(sb,mask) \
journal_t *journal; \
journal = EXT3_SB(sb)->s_journal; \
lock_kernel(); \
- handle = journal_start(journal, 1); \
+ handle = journal_start(journal, blocks); \
unlock_kernel(); \
if(IS_ERR(handle)) { \
CERROR("can't start transaction\n"); \
} else if (keylen >= strlen(SNAP_GENERATION)
&& strcmp(key, SNAP_GENERATION) == 0) {
- rc = ext3_xattr_get(inode, EXT3_SNAP_INDEX,EXT3_SNAP_GENERATION,
- (char *)val, *vallen);
+ rc = ext3_xattr_get(inode, EXT3_SNAP_INDEX,
+ EXT3_SNAP_GENERATION, (char *)val, *vallen);
+ if (rc == -ENODATA) {
+ *((__u32 *)val) = 0;
+ *vallen = sizeof(int);
+ rc = 0;
+ }
+ RETURN(rc);
+ } else if (keylen >= strlen(SNAP_COUNT) &&
+ strcmp(key, SNAP_COUNT) == 0) {
+ rc = ext3_xattr_get(inode, EXT3_SNAP_INDEX,
+ EXT3_SNAP_COUNT, val, *vallen);
if (rc == -ENODATA) {
*((__u32 *)val) = 0;
*vallen = sizeof(int);
rc = 0;
}
RETURN(rc);
- }
+ }
+
RETURN(-EINVAL);
}
if (keylen >= strlen(SNAPTABLE_INFO)
&& strcmp(key, SNAPTABLE_INFO) == 0) {
handle_t *handle;
- EXT3_JOURNAL_START(inode->i_sb, handle,
- EXT3_XATTR_TRANS_BLOCKS, rc);
+ EXT3_JOURNAL_START(inode->i_sb, handle, EXT3_XATTR_TRANS_BLOCKS,
+ rc);
if(rc)
RETURN(rc);
rc = ext3_xattr_set_handle(handle, inode, EXT3_SNAP_INDEX,
rc = ext3_set_generation(inode, *(int*)val);
RETURN(rc);
- }
+ } else if (keylen >= strlen(SNAP_COUNT) &&
+ (strcmp(key, SNAP_COUNT) == 0)) {
+ handle_t *handle;
+ EXT3_JOURNAL_START(inode->i_sb, handle,
+ EXT3_XATTR_TRANS_BLOCKS, rc);
+ if(rc)
+ RETURN(rc);
+ rc = ext3_xattr_set_handle(handle, inode, EXT3_SNAP_INDEX,
+ EXT3_SNAP_COUNT, val, *vallen, 0);
+ journal_stop(handle);
+
+ RETURN(rc);
+ } else if (keylen >= strlen(SNAP_ROOT_INO) &&
+ (strcmp(key, SNAP_ROOT_INO) == 0)) {
+
+
+
+
+ }
+
RETURN(-EINVAL);
}
static int fsfilt_ext3_dir_ent_size(char *name)
index, gen, cache_parent, del);
post_smfs_inode(inode, cache_inode);
post_smfs_inode(inode, cache_parent);
-
+ #if 0
if (cache_ind_inode && !IS_ERR(cache_ind_inode)){
/*FIXME: get indirect inode set_cow flags*/
ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino,
inode, 0);
- }
+ }
+ #endif
RETURN(ind_inode);
}
cache_ind_inode = snap_fsfilt->fs_get_indirect(cache_inode,
table, slot);
post_smfs_inode(inode, cache_inode);
-
+#if 0
if (cache_ind_inode && !IS_ERR(cache_ind_inode)){
/*FIXME: get indirect inode set_cow flags*/
ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino,
inode, slot);
}
+#endif
RETURN(ind_inode);
}
{
struct inode *inode = file->f_dentry->d_inode;
struct fsfilt_operations *snap_cops = I2SNAPCOPS(inode);
- struct snap_table *stbl = S2SNAPI(inode->i_sb)->sntbl;
int i = 0, size = 0, off_count = 0, buf_off = 0, rc = 0;
ENTRY;
-
+#if 0
/*Get the offset of dir ent*/
+ //struct snap_table *stbl = S2SNAPI(inode->i_sb)->sni_table;
while (size < *off && off_count < stbl->sntbl_count) {
char *name = stbl->sntbl_items[i].sn_name;
size +=snap_cops->fs_dir_ent_size(name);
}
if (rc > 0)
rc = 0;
-
+#else
+#warning "still not implement read .snap dir page for fsfilt Wangdi"
+#endif
RETURN(rc);
}
OBD_FREE(cfg_buf, data->ioc_plen1);
RETURN(rc);
}
- case OBD_IOC_SNAP_ADD: {
- char *name = data->ioc_inlbuf1;
- if (name) {
- rc = fsfilt_set_snap_item(obd, mds->mds_sb, name);
- }
- RETURN(rc);
- }
case OBD_IOC_PARSE: {
struct llog_ctxt *ctxt =
llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
RETURN(rc);
}
-
case OBD_IOC_DUMP_LOG: {
struct llog_ctxt *ctxt =
llog_get_context(&obd->obd_llogs, LLOG_CONFIG_ORIG_CTXT);
RETURN(rc);
}
-
case OBD_IOC_SET_READONLY: {
void *handle;
struct inode *inode = obd->u.mds.mds_sb->s_root->d_inode;
static int filter_destroy(struct obd_export *exp, struct obdo *oa,
struct lov_stripe_md *ea, struct obd_trans_info *);
-static struct obd_llogs *filter_grab_llog_for_group(struct obd_device *,
- int, struct obd_export *);
+struct obd_llogs *filter_grab_llog_for_group(struct obd_device *,
+ int, struct obd_export *);
static void filter_commit_cb(struct obd_device *obd, __u64 transno,
void *cb_data, int error)
rc = llog_catalog_list(obd, 1, data);
RETURN(rc);
}
-
- case OBD_IOC_SNAP_ADD: {
- char *name = data->ioc_inlbuf1;
- if (name) {
- rc = fsfilt_set_snap_item(obd, obd->u.filter.fo_sb, name);
- }
- RETURN(rc);
- }
case OBD_IOC_LLOG_CANCEL:
case OBD_IOC_LLOG_REMOVE:
case OBD_IOC_LLOG_INFO:
#define PORTALS_DEV_PATH "/dev/portals"
#define OBD_DEV_ID 1
#define OBD_DEV_PATH "/dev/obd"
+#define SMFS_DEV_ID 2
+#define SMFS_DEV_PATH "/dev/snapdev"
int ptl_name2nal(char *str);
int ptl_parse_ipaddr (__u32 *ipaddrp, char *str);
int cache_space_hook_init(struct super_block *sb)
{
- struct smfs_super_info *smfs_info = S2SMI(sb);
+ struct smfs_super_info *smfs_info = S2SMI(sb);
struct smfs_hook_ops *cache_hops;
int rc = 0;
ENTRY;
if (!cache_hops) {
RETURN(-ENOMEM);
}
- rc = smfs_register_hook_ops(sb, cache_hops);
+ rc = smfs_register_hook_ops(smfs_info, cache_hops);
if (rc) {
smfs_free_hook_ops(cache_hops);
RETURN(rc);
RETURN(0);
}
-int cache_space_hook_exit(struct super_block *sb)
+int cache_space_hook_exit(struct smfs_super_info *smfs_info)
{
- struct smfs_super_info *smfs_info = S2SMI(sb);
struct smfs_hook_ops *cache_hops;
- cache_hops = smfs_unregister_hook_ops(sb, CACHE_HOOK);
+ cache_hops = smfs_unregister_hook_ops(smfs_info, CACHE_HOOK);
smfs_free_hook_ops(cache_hops);
SMFS_CLEAN_CACHE_HOOK(smfs_info);
if (rc)
GOTO(exit, rc);
- inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
- if (!inode)
- GOTO(exit, rc = -ENOMEM);
+ SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode,
+ rc, exit);
d_instantiate(dentry, inode);
- sm_set_inode_ops(cache_dentry->d_inode, inode);
post_smfs_inode(dir, cache_dir);
+
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, POST_HOOK, rc,
exit);
exit:
dentry->d_inode = cache_inode;
GOTO(exit, rc = NULL);
}
- inode = smfs_get_inode(dir->i_sb, cache_inode->i_ino, dir, index);
+ SMFS_GET_INODE(dir->i_sb, cache_inode, dir, index, inode, rc2,
+ exit);
} else {
d_add(dentry, NULL);
GOTO(exit, rc);
SMFS_HOOK(dir, old_dentry, dentry, NULL, HOOK_LINK, handle, POST_HOOK,
rc, exit);
-
exit:
unlock_kernel();
post_smfs_dentry(cache_dentry);
if (cache_dir->i_op->symlink)
rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
-
- inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
post_smfs_inode(dir, cache_dir);
+
+ SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode,
+ rc, exit);
if (inode)
d_instantiate(dentry, inode);
else
if (rc)
GOTO(exit, rc);
- inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
-
- if (!inode)
- GOTO(exit, rc = -ENOENT);
-
+ SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode,
+ rc, exit);
d_instantiate(dentry, inode);
post_smfs_inode(dir, cache_dir);
mode, rdev)))
GOTO(exit, rc);
- inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
+ SMFS_GET_INODE(dir->i_sb, cache_dentry->d_inode, dir, 0, inode,
+ rc, exit);
d_instantiate(dentry, inode);
if (cache_inode->i_fop->read)
rc = cache_inode->i_fop->read(sfi->c_file, buf, size,
cache_ppos);
-
*ppos = *cache_ppos;
duplicate_file(filp, sfi->c_file);
RETURN(rc);
#include <linux/lustre_fsfilt.h>
#include <linux/lustre_smfs.h>
#include "smfs_internal.h"
-static void smfs_init_cache_inode (struct inode *inode, void *opaque)
+
+static void smfs_init_inode_info (struct inode *inode, void *opaque)
{
- struct smfs_inode_info *sm_info = (struct smfs_inode_info *)opaque;
+ struct smfs_iget_args *sargs = (struct smfs_iget_args*)opaque;
struct inode *cache_inode = NULL;
-
- cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino);
-
- if (sm_info)
- memcpy(I2SMI(inode), sm_info, sizeof(struct smfs_inode_info));
+ if (sargs)
+ cache_inode = iget(S2CSB(inode->i_sb), sargs->s_ino);
+ else
+ cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino);
+
+ OBD_ALLOC(I2SMI(inode), sizeof(struct smfs_inode_info));
+ LASSERT(I2SMI(inode));
I2CI(inode) = cache_inode;
+ CDEBUG(D_INODE, "cache_inode i_count ino %lu i_count %d\n",
+ cache_inode->i_ino, atomic_read(&cache_inode->i_count));
post_smfs_inode(inode, cache_inode);
sm_set_inode_ops(cache_inode, inode);
+
+ if (sargs) {
+ struct inode *dir = sargs->s_inode;
+
+ if (dir)
+ I2SMI(inode)->smi_flags = I2SMI(dir)->smi_flags;
#if CONFIG_SNAPFS
- if (sm_info) {
- smfs_init_snap_inode_info(inode, &sm_info->sm_sninfo);
- }
+ if (SMFS_DO_COW(S2SMI(inode->i_sb))) {
+ smfs_init_snap_inode_info(inode, sargs);
+ }
#endif
+ }
+}
+
+static void smfs_clear_inode_info(struct inode *inode)
+{
+ struct inode *cache_inode = I2CI(inode);
+
+ LASSERTF(atomic_read(&cache_inode->i_count) == 1,
+ "cache inode %lu i_count %d not 0\n", cache_inode->i_ino,
+ atomic_read(&cache_inode->i_count));
+ iput(cache_inode);
+ OBD_FREE(I2SMI(inode), sizeof(struct smfs_inode_info));
}
static void smfs_read_inode2(struct inode *inode, void *opaque)
{
ENTRY;
+
if (!inode)
return;
-
+
CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
- smfs_init_cache_inode(inode, opaque);
+ smfs_init_inode_info(inode, opaque);
CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
inode->i_ino, atomic_read(&inode->i_count));
EXIT;
static int smfs_test_inode(struct inode *inode, void *opaque)
#endif
{
- struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo;
- struct snap_inode_info *test_info = (struct snap_inode_info *)opaque;
-
- if (!sn_info || !test_info)
- return 0;
- if (sn_info->sn_index != test_info->sn_index)
- return 0;
- if (sn_info->sn_gen != test_info->sn_gen)
- return 0;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
- smfs_init_cache_inode(inode, opaque);
-#endif
+ if (!opaque)
+ return 1;
+#ifdef CONFIG_SNAPFS
+ if (SMFS_DO_COW(S2SMI(inode->i_sb)) &&
+ !smfs_snap_test_inode(inode, opaque))
+ return 0;
+#endif
return 1;
}
}
struct inode *smfs_iget(struct super_block *sb, ino_t hash,
- struct smfs_inode_info *si_info)
+ struct smfs_iget_args *sargs)
{
struct inode *inode;
LASSERT(hash != 0);
- inode = iget5_locked(sb, hash, smfs_test_inode, smfs_set_inode,
- si_info);
+ inode = iget5_locked(sb, hash, smfs_test_inode, smfs_set_inode, sargs);
if (inode) {
if (inode->i_state & I_NEW)
unlock_new_inode(inode);
CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
inode->i_generation, inode);
+
+ inode->i_ino = hash;
}
return inode;
}
#else
struct inode *smfs_iget(struct super_block *sb, ino_t hash,
- struct smfs_inode_info *si_info)
+ struct smfs_iget_args *sargs)
{
struct inode *inode;
LASSERT(hash != 0);
- inode = iget4(sb, hash, smfs_test_inode, si_info);
+ inode = iget4(sb, hash, smfs_test_inode, sargs);
if (inode)
CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
struct inode *smfs_get_inode (struct super_block *sb, ino_t hash,
struct inode *dir, int index)
{
- struct smfs_inode_info sm_info;
- struct inode *inode = NULL;
+ struct inode *inode = NULL;
+ struct smfs_iget_args sargs;
ENTRY;
+
+ sargs.s_index = index;
+ sargs.s_inode = inode;
+ sargs.s_ino = hash;
+ inode = smfs_iget(sb, hash, &sargs);
- sm_info.smi_flags = I2SMI(dir)->smi_flags;
- sm_info.sm_sninfo.sn_flags = I2SMI(dir)->sm_sninfo.sn_flags;
- sm_info.sm_sninfo.sn_index = index;
- sm_info.sm_sninfo.sn_gen = I2SMI(dir)->sm_sninfo.sn_gen;
- inode = smfs_iget(sb, hash, &sm_info);
-
RETURN(inode);
-}
-EXPORT_SYMBOL(smfs_get_inode);
+}
+
static void smfs_delete_inode(struct inode *inode)
{
struct inode *cache_inode;
#else
hlist_del_init(&cache_inode->i_hash);
#endif
-
list_del(&cache_inode->i_list);
INIT_LIST_HEAD(&cache_inode->i_list);
return;
}
+ CDEBUG(D_INFO, "cache_inode i_count ino %lu i_count %d\n",
+ inode->i_ino, atomic_read(&inode->i_count));
if (atomic_read(&cache_inode->i_count) > 1 &&
- cache_inode != cache_inode->i_sb->s_root->d_inode)
+ cache_inode != cache_inode->i_sb->s_root->d_inode) {
+ CDEBUG(D_INFO, "cache_inode i_count ino %lu i_count %d\n",
+ cache_inode->i_ino,
+ atomic_read(&cache_inode->i_count) - 1);
iput(cache_inode);
+ }
if (S2CSB(inode->i_sb)->s_op->put_inode)
S2CSB(inode->i_sb)->s_op->put_inode(cache_inode);
static void smfs_clear_inode(struct inode *inode)
{
struct inode *cache_inode;
-
+
ENTRY;
if (!inode) return;
-
+
cache_inode = I2CI(inode);
- if (cache_inode != cache_inode->i_sb->s_root->d_inode) {
- iput(cache_inode);
- SMFS_CLEAN_INODE_REC(inode);
- I2CI(inode) = NULL;
- }
+ if (cache_inode != cache_inode->i_sb->s_root->d_inode)
+ smfs_clear_inode_info(inode);
EXIT;
return;
}
#include <linux/lustre_mds.h>
#include <linux/lustre_debug.h>
#include <linux/lustre_smfs.h>
+#include <linux/lustre_snap.h>
#include "smfs_internal.h"
+static struct super_block *smfs_get_sb_by_path(char *path, int len)
+{
+ struct super_block *sb;
+ struct nameidata nd;
+ int error = 0;
+
+ ENTRY;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (path_init(path, LOOKUP_FOLLOW, &nd)) {
+ error = path_walk(path, &nd);
+ if (error) {
+ path_release(&nd);
+ RETURN(NULL);
+ }
+ } else {
+ RETURN(NULL);
+ }
+#else
+ if (path_lookup(path, LOOKUP_FOLLOW, &nd))
+ RETURN(NULL);
+
+#endif
+ /* FIXME-WANGDI: add some check code here. */
+ sb = nd.dentry->d_sb;
+ path_release(&nd);
+ RETURN(sb);
+}
struct smfs_control_device smfs_dev;
{
struct obd_ioctl_data *data = NULL;
struct super_block *sb = NULL;
- char *buf = NULL, *dir = NULL;
- int err = 0, len = 0, count = 0, do_kml = 0;
+ char *buf = NULL;
+ int err = 0, len = 0;
if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
CERROR("OBD ioctl: data error\n");
data = (struct obd_ioctl_data *)buf;
switch (cmd) {
- case IOC_SMFS_START:
- case IOC_SMFS_STOP:
- case IOC_SMFS_REINT:
- case IOC_SMFS_UNDO:{
- char *name;
+ case OBD_IOC_SMFS_SNAP_ADD:{
+ char *name, *snapshot_name;
if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
CERROR("No mountpoint passed!\n");
GOTO(out, err = -EINVAL);
}
+ if (!data->ioc_inllen2 || !data->ioc_inlbuf2) {
+ CERROR("No snapshotname passed!\n");
+ GOTO(out, err = -EINVAL);
+ }
name = (char*) data->ioc_inlbuf1;
sb = smfs_get_sb_by_path(name, data->ioc_inllen1);
if (!sb) {
CERROR("can not find superblock at %s\n", buf);
GOTO(out, err = -EINVAL);
}
- /*get cmd count*/
- if (data->ioc_inllen2 && data->ioc_inlbuf2) {
- dir = (char *)data->ioc_inlbuf2;
- }
- if (data->ioc_plen1)
- count = *((int*)data->ioc_pbuf1);
- if (data->ioc_plen2)
- do_kml = *((int*)data->ioc_pbuf2);
+ snapshot_name = (char *)data->ioc_inlbuf2;
+#ifdef CONFIG_SNAPFS
+ err = smfs_add_snap_item(sb, name, snapshot_name);
+#endif
break;
}
default: {
GOTO(out, err = -EINVAL);
}
}
-
- switch (cmd) {
- case IOC_SMFS_START:
- err = smfs_start_rec(sb, NULL);
- break;
- case IOC_SMFS_STOP:
- err = smfs_stop_rec(sb);
- break;
- case IOC_SMFS_REINT:
- case IOC_SMFS_UNDO: {
- int flags = 0;
- if (cmd == IOC_SMFS_REINT)
- SET_REC_OP_FLAGS(flags, SMFS_REINT_REC);
- else
- SET_REC_OP_FLAGS(flags, SMFS_UNDO_REC);
- if (count == 0)
- SET_REC_COUNT_FLAGS(flags, SMFS_REC_ALL);
- if (do_kml)
- SET_REC_WRITE_KML_FLAGS(flags, SMFS_WRITE_KML);
- err = smfs_process_rec(sb, count, dir, flags);
- break;
- }
- }
out:
if (buf)
obd_ioctl_freedata(buf, len);
RETURN(err);
}
-
+#define SMFS_MINOR 250
static int smfs_psdev_ioctl(struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long arg)
{
if (!inode)
RETURN(-EINVAL);
dev = MINOR(inode->i_rdev);
- if (dev != SMFS_PSDEV_MINOR)
+ if (dev != SMFS_MINOR)
RETURN(-ENODEV);
RETURN(0);
if (!inode)
RETURN(-EINVAL);
dev = MINOR(inode->i_rdev);
- if (dev != SMFS_PSDEV_MINOR)
+ if (dev != SMFS_MINOR)
RETURN(-ENODEV);
RETURN(0);
/* declare character device */
static struct file_operations smfscontrol_fops = {
- ioctl: smfs_psdev_ioctl, /* ioctl */
- open: smfs_psdev_open, /* open */
- release: smfs_psdev_release, /* release */
+ .owner = THIS_MODULE,
+ .ioctl = smfs_psdev_ioctl, /* ioctl */
+ .open = smfs_psdev_open, /* open */
+ .release = smfs_psdev_release, /* release */
};
-
-#define SMFS_MINOR 250
static struct miscdevice smfscontrol_dev = {
minor: SMFS_MINOR,
name: "smfscontrol",
#include <linux/lustre_snap.h>
#include "smfs_internal.h"
-#define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + size * sizeof(struct snap))
-static int smfs_init_snaptabe(struct super_block *sb)
+
+#define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + \
+ size * sizeof(struct snap))
+static int smfs_init_snap_super_info(struct smfs_super_info *smfs_info)
{
- struct snap_info *snap_info = S2SNAPI(sb);
- struct snap_table *snap_table = NULL;
- struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
- struct dentry *d_root = snap_info->snap_root;
- int rc = 0, size, table_size, vallen, i;
-
- ENTRY;
+ struct snap_super_info *snap_sinfo;
+ int rc = 0;
- init_MUTEX(&snap_info->sntbl_sema);
- /*Initialized table */
- /*get the maxsize of snaptable*/
- vallen = sizeof(int);
- rc = snapops->fs_get_snap_info(d_root->d_inode, MAX_SNAPTABLE_COUNT,
- strlen(MAX_SNAPTABLE_COUNT), &size,
- &vallen);
- if (size == 0) {
- CERROR("the Max snaptable count should not be zero\n");
- RETURN(-EINVAL);
- }
+ ENTRY;
- table_size = SNAPTABLE_SIZE(size);
+ OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_super_info));
+ if (!smfs_info->smsi_snap_info)
+ GOTO(exit, rc = -ENOMEM);
- OBD_ALLOC(snap_info->sntbl, table_size);
+ snap_sinfo = smfs_info->smsi_snap_info;
- if (!snap_info->sntbl) {
- CERROR("No MEM\n");
- RETURN(-ENOMEM);
- }
- snap_table = snap_info->sntbl;
-
- snap_table->sntbl_magic = cpu_to_le32((__u32)SNAPTABLE_MAGIC);
- snap_table->sntbl_max_count = size;
- for (i = 0; i < snap_table->sntbl_max_count; i++) {
- /*init sn_index to -1*/
- snap_table->sntbl_items[i].sn_index = -1;
+ /*init snap fsfilt operations*/
+ if (!snap_sinfo->snap_cache_fsfilt) {
+ char *snap_cache_ftype = NULL;
+ int tmp = strlen(smfs_info->smsi_cache_ftype) + strlen("_snap");
+
+ OBD_ALLOC(snap_cache_ftype, tmp + 1);
+ sprintf(snap_cache_ftype, "%s_snap", smfs_info->smsi_cache_ftype);
+ snap_sinfo->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
+ OBD_FREE(snap_cache_ftype, tmp + 1);
+ if (!snap_sinfo->snap_cache_fsfilt) {
+ CERROR("Can not get %s fsfilt ops needed by snap\n",
+ snap_cache_ftype);
+ GOTO(exit, rc = -EINVAL);
+ }
}
- /*get snaptable info*/
- rc = snapops->fs_get_snap_info(d_root->d_inode, SNAPTABLE_INFO,
- strlen(SNAPTABLE_INFO),
- snap_table, &table_size);
- if (rc < 0) {
- if (rc == -ENODATA) {
- snap_table->sntbl_count = 0;
- CDEBUG(D_INFO, "No snaptable here\n");
- RETURN(0);
- } else {
- CERROR("Can not retrive the snaptable from this filesystem\n");
- OBD_FREE(snap_table, table_size);
- RETURN(rc);
+ if (!snap_sinfo->snap_fsfilt) {
+ char *snap_ftype = NULL;
+ int tmp = strlen(smfs_info->smsi_ftype) + strlen("_snap");
+
+ OBD_ALLOC(snap_ftype, tmp + 1);
+ sprintf(snap_ftype, "%s_snap", smfs_info->smsi_ftype);
+ snap_sinfo->snap_fsfilt = fsfilt_get_ops(snap_ftype);
+ OBD_FREE(snap_ftype, tmp + 1);
+ if (!snap_sinfo->snap_fsfilt) {
+ CERROR("Can not get %s fsfilt ops needed by snap\n",
+ snap_ftype);
+ GOTO(exit, rc = -EINVAL);
}
- }
- if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) {
- CERROR("On disk snaptable is not right \n");
- OBD_FREE(snap_table, table_size);
- RETURN(-EIO);
}
+ INIT_LIST_HEAD(&snap_sinfo->snap_list);
+exit:
+ if (rc && smfs_info->smsi_snap_info)
+ OBD_FREE(snap_sinfo, sizeof(struct snap_super_info));
RETURN(rc);
}
+/*FIXME-wangdi Should remove it when integrated it with lustre*/
+static struct dentry *smfs_simple_mkdir(struct dentry *dir, char *name,
+ int mode, int fix)
+{
+ struct dentry *dchild;
+ int err = 0;
+
+ dchild = ll_lookup_one_len(name, dir, strlen(name));
+ if (IS_ERR(dchild))
+ GOTO(out_up, dchild);
+
+ if (dchild->d_inode) {
+ int old_mode = dchild->d_inode->i_mode;
+ if (!S_ISDIR(old_mode))
+ GOTO(out_err, err = -ENOTDIR);
+
+ /* Fixup directory permissions if necessary */
+ if (fix && (old_mode & S_IALLUGO) != (mode & S_IALLUGO)) {
+ CWARN("fixing permissions on %s from %o to %o\n",
+ name, old_mode, mode);
+ dchild->d_inode->i_mode = (mode & S_IALLUGO) |
+ (old_mode & ~S_IALLUGO);
+ mark_inode_dirty(dchild->d_inode);
+ }
+ GOTO(out_up, dchild);
+ }
+ err = vfs_mkdir(dir->d_inode, dchild, mode);
+ if (err)
+ GOTO(out_err, err);
+ RETURN(dchild);
+out_err:
+ dput(dchild);
+ dchild = ERR_PTR(err);
+out_up:
+ return dchild;
+
+}
#define COWED_NAME_LEN (7 + 8 + 1)
-static int smfs_init_cowed_dir(struct super_block *sb, struct dentry* cowed_dir)
+static int smfs_init_cowed_dir(struct snap_info *snap_info, struct dentry* dir)
{
- struct snap_info *snap_info = S2SNAPI(sb);
struct dentry *dentry = NULL;
- struct lvfs_run_ctxt saved;
char name[COWED_NAME_LEN];
int rc = 0;
ENTRY;
- sprintf(name, ".cowed_%08x", (__u32)cowed_dir->d_inode->i_ino);
- push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
- dentry = simple_mkdir(cowed_dir, name, 0777, 1);
- pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
+ sprintf(name, ".cowed_%08x", (__u32)dir->d_inode->i_ino);
+ /*FIXME-WANGDI: will use simple_mkdir, when integrating snap to lustre*/
+ dentry = smfs_simple_mkdir(dir, name, 0777, 1);
if (IS_ERR(dentry)) {
rc = PTR_ERR(dentry);
CERROR("create cowed directory: rc = %d\n", rc);
RETURN(rc);
}
- snap_info->sn_cowed_dentry = dentry;
+ snap_info->sni_cowed_dentry = dentry;
RETURN(rc);
}
-static int smfs_init_dotinfo(struct super_block *sb)
+
+static int smfs_init_dotinfo(struct snap_info *snap_info)
{
- struct snap_info *snap_info = S2SNAPI(sb);
struct snap_dot_info *dot_info = NULL;
int rc = 0;
ENTRY;
- if (snap_info->sn_dot_info)
+ if (snap_info->sni_dot_info)
RETURN(-EEXIST);
- OBD_ALLOC(snap_info->sn_dot_info, sizeof(struct snap_dot_info));
+ OBD_ALLOC(snap_info->sni_dot_info, sizeof(struct snap_dot_info));
- if (!snap_info->sn_dot_info)
+ if (!snap_info->sni_dot_info)
RETURN(-ENOMEM);
- dot_info = snap_info->sn_dot_info;
+ dot_info = snap_info->sni_dot_info;
OBD_ALLOC(dot_info->dot_name, strlen(DOT_SNAP_NAME) + 1);
if (!dot_info->dot_name) {
- OBD_FREE(snap_info->sn_dot_info, sizeof(struct snap_dot_info));
+ OBD_FREE(snap_info->sni_dot_info, sizeof(struct snap_dot_info));
RETURN(-ENOMEM);
}
memcpy(dot_info->dot_name, DOT_SNAP_NAME, strlen(DOT_SNAP_NAME));
RETURN(rc);
}
-static int smfs_cleanup_dotinfo(struct super_block *sb)
-{
- struct snap_info *snap_info = S2SNAPI(sb);
- struct snap_dot_info *dot_info = NULL;
- int rc = 0;
+static int smfs_init_snap_info(struct smfs_super_info *smb,
+ struct snap_info *snap_info, struct dentry *de)
+{
+ struct snap_table *snap_table = NULL;
+ struct fsfilt_operations *snapcops;
+ int rc = 0, size, table_size, vallen, i;
+ struct inode *root_inode = NULL;
+
ENTRY;
- if (!snap_info->sn_dot_info)
- RETURN(rc);
-
- dot_info = snap_info->sn_dot_info;
-
- if (dot_info->dot_name) {
- OBD_FREE(dot_info->dot_name, dot_info->dot_name_len + 1);
+ root_inode = iget(smb->smsi_sb, de->d_inode->i_ino);
+ if (!root_inode || is_bad_inode(root_inode))
+ RETURN(-EIO);
+ snapcops = smb->smsi_snap_info->snap_cache_fsfilt;
+ /*Initialized table */
+ /*get the maxsize of snaptable*/
+ vallen = sizeof(int);
+ rc = snapcops->fs_get_snap_info(root_inode, MAX_SNAPTABLE_COUNT,
+ strlen(MAX_SNAPTABLE_COUNT), &size,
+ &vallen);
+ if (size == 0) {
+ CERROR("the Max snaptable count should not be zero\n");
+ GOTO(exit, rc);
}
-
- OBD_FREE(dot_info, sizeof(struct snap_dot_info));
-
- RETURN(rc);
-}
+ table_size = SNAPTABLE_SIZE(size);
-int smfs_start_cow(struct super_block *sb)
-{
- int rc = 0;
+ OBD_ALLOC(snap_info->sni_table, table_size);
- ENTRY;
-
- /*init snap fsfilt operations*/
- if (!S2SNAPI(sb)->snap_cache_fsfilt) {
- char *snap_cache_ftype = NULL;
- int tmp = strlen(S2SMI(sb)->smsi_cache_ftype) + strlen("_snap");
-
- OBD_ALLOC(snap_cache_ftype, tmp + 1);
- sprintf(snap_cache_ftype, "%s_snap", S2SMI(sb)->smsi_cache_ftype);
- S2SNAPI(sb)->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
- OBD_FREE(snap_cache_ftype, tmp + 1);
- if (!S2SNAPI(sb)->snap_cache_fsfilt) {
- CERROR("Can not get %s fsfilt ops needed by snap\n",
- snap_cache_ftype);
- RETURN(-EINVAL);
- }
+ if (!snap_info->sni_table) {
+ CERROR("No MEM\n");
+ RETURN(-ENOMEM);
}
- if (!S2SNAPI(sb)->snap_fsfilt) {
- char *snap_ftype = NULL;
- int tmp = strlen(S2SMI(sb)->smsi_ftype) + strlen("_snap");
-
- OBD_ALLOC(snap_ftype, tmp + 1);
- sprintf(snap_ftype, "%s_snap", S2SMI(sb)->smsi_ftype);
- S2SNAPI(sb)->snap_fsfilt = fsfilt_get_ops(snap_ftype);
- OBD_FREE(snap_ftype, tmp + 1);
- if (!S2SNAPI(sb)->snap_fsfilt) {
- CERROR("Can not get %s fsfilt ops needed by snap\n",
- snap_ftype);
- RETURN(-EINVAL);
+ snap_table = snap_info->sni_table;
+
+ snap_table->sntbl_magic = cpu_to_le32((__u32)SNAPTABLE_MAGIC);
+ snap_table->sntbl_max_count = size;
+ /*init sn_index to -1*/
+ for (i = 0; i < snap_table->sntbl_max_count; i++)
+ snap_table->sntbl_items[i].sn_index = -1;
+ /*get snaptable info*/
+ rc = snapcops->fs_get_snap_info(root_inode, SNAPTABLE_INFO,
+ strlen(SNAPTABLE_INFO),
+ snap_table, &table_size);
+ if (rc < 0) {
+ if (rc == -ENODATA) {
+ snap_table->sntbl_count = 0;
+ } else {
+ CERROR("Can not retrive the snaptable from this filesystem\n");
+ GOTO(exit, rc);
+ }
+ } else {
+ if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) {
+ CERROR("On disk snaptable is not right \n");
+ GOTO(exit, rc = -EIO);
}
}
- rc = smfs_init_snaptabe(sb);
- if (rc) {
- CERROR("can not init snaptable rc=%d\n", rc);
- RETURN(rc);
- }
- /*init dot snap info*/
- rc = smfs_init_dotinfo(sb);
+ init_MUTEX(&snap_info->sni_sema);
+ snap_info->sni_root_ino = de->d_inode->i_ino;
+ rc = smfs_init_cowed_dir(snap_info, de);
if (rc) {
- CERROR("can not init dot snap info rc=%d\n", rc);
- RETURN(rc);
+ CERROR("Init cowed dir error rc=%d\n", rc);
+ GOTO(exit, rc);
}
- /*init cowed dir to put the primary cowed inode
- *FIXME-WANGDI, later the s_root may not be the
- *snap dir, we can indicate any dir to be cowed*/
- rc = smfs_init_cowed_dir(sb, sb->s_root);
+ rc = smfs_init_dotinfo(snap_info);
+exit:
+ if (root_inode)
+ iput(root_inode);
+ if (rc && snap_table)
+ OBD_FREE(snap_table, table_size);
RETURN(rc);
}
-EXPORT_SYMBOL(smfs_start_cow);
-int smfs_stop_cow(struct super_block *sb)
+
+static struct snap_info *smfs_create_snap_info(struct smfs_super_info *sinfo,
+ struct dentry *dentry)
{
- struct snap_info *snap_info = S2SNAPI(sb);
- struct snap_table *snap_table = snap_info->sntbl;
- int rc = 0, table_size;
+ struct snap_info *snap_info = NULL;
+ int rc = 0;
ENTRY;
-
- l_dput(snap_info->sn_cowed_dentry);
-
- if (snap_info->snap_fsfilt)
- fsfilt_put_ops(snap_info->snap_fsfilt);
- if (snap_info->snap_cache_fsfilt)
- fsfilt_put_ops(snap_info->snap_cache_fsfilt);
-
- if (snap_table) {
- table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count);
- OBD_FREE(snap_info->sntbl, table_size);
- }
- smfs_cleanup_dotinfo(sb);
-
- RETURN(rc);
+
+ OBD_ALLOC(snap_info, sizeof(struct snap_info));
+ if (!snap_info)
+ RETURN(ERR_PTR(-ENOMEM));
+ rc = smfs_init_snap_info(sinfo, snap_info, dentry);
+ if (rc)
+ GOTO(exit, snap_info = ERR_PTR(rc));
+
+ /*set cow flags for the snap root inode*/
+ I2SMI(dentry->d_inode)->smi_flags |= SM_DO_COW;
+exit:
+ if (rc)
+ OBD_FREE(snap_info, sizeof(struct snap_info));
+ RETURN(snap_info);
}
-EXPORT_SYMBOL(smfs_stop_cow);
#define COW_HOOK "cow_hook"
static int smfs_cow_pre_hook(struct inode *inode, struct dentry *dentry,
{
struct smfs_super_info *smfs_info = S2SMI(sb);
struct smfs_hook_ops *cow_hops = NULL;
- int rc = 0;
+ struct fsfilt_operations *sops;
+ struct inode *root_inode = smfs_info->smsi_sb->s_root->d_inode;
+ int snap_count = 0, rc = 0, vallen;
ENTRY;
RETURN(-ENOMEM);
}
- rc = smfs_register_hook_ops(sb, cow_hops);
-
+ rc = smfs_register_hook_ops(smfs_info, cow_hops);
if (rc) {
smfs_free_hook_ops(cow_hops);
RETURN(rc);
}
-
- OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
- if (!smfs_info->smsi_snap_info)
- GOTO(exit, rc = -ENOMEM);
-exit:
+ rc = smfs_init_snap_super_info(smfs_info);
if (rc && cow_hops) {
- smfs_unregister_hook_ops(sb, cow_hops->smh_name);
+ smfs_unregister_hook_ops(smfs_info, cow_hops->smh_name);
smfs_free_hook_ops(cow_hops);
- }
+ RETURN(rc);
+ }
+ sops = smfs_info->smsi_snap_info->snap_cache_fsfilt;
+
+ vallen = sizeof(int);
+ rc = sops->fs_get_snap_info(root_inode, SNAP_COUNT, strlen(SNAP_COUNT),
+ &snap_count, &vallen);
+ if (rc)
+ GOTO(exit, rc);
+
+ if (snap_count > 0) {
+ int snap_root_size = snap_count * sizeof(ino_t);
+ ino_t *snap_root;
+ int i;
+
+ OBD_ALLOC(snap_root, snap_root_size);
+
+ if (!snap_root)
+ GOTO(exit, rc = -ENOMEM);
+
+ rc = sops->fs_get_snap_info(root_inode, SNAP_ROOT_INO,
+ strlen(SNAP_ROOT_INO), snap_root,
+ &snap_root_size);
+ if (rc) {
+ OBD_FREE(snap_root, sizeof(int) * snap_count);
+ GOTO(exit, rc);
+ }
+ for (i = 0; i < snap_count; i++) {
+ ino_t root_ino = le32_to_cpu(snap_root[i]);
+ struct dentry *tmp = smfs_info->smsi_sb->s_root;
+ struct snap_info *snap_info;
+ struct dentry *dentry;
+
+ root_inode = smfs_get_inode(sb, root_ino, NULL, 0);
+ dentry = pre_smfs_dentry(NULL, root_inode, tmp,
+ NULL);
+ snap_info = smfs_create_snap_info(S2SMI(sb), dentry);
+ post_smfs_dentry(dentry);
+ if (IS_ERR(snap_info)) {
+ OBD_FREE(snap_root, sizeof(int) * snap_count);
+ GOTO(exit, rc = PTR_ERR(snap_info));
+ }
+ list_add(&snap_info->sni_list, &(S2SNAPI(sb)->snap_list));
+ }
+ }
+exit:
+ if (rc)
+ smfs_cow_cleanup(smfs_info);
+
RETURN(rc);
}
-int smfs_cow_cleanup(struct super_block *sb)
-{
+static int smfs_cleanup_dotinfo(struct snap_info *snap_info)
+{
+ struct snap_dot_info *dot_info = NULL;
+ int rc = 0;
+ ENTRY;
+
+ if (!snap_info->sni_dot_info)
+ RETURN(rc);
+
+ dot_info = snap_info->sni_dot_info;
+
+ if (dot_info->dot_name) {
+ OBD_FREE(dot_info->dot_name, dot_info->dot_name_len + 1);
+ }
- struct snap_info *snap_info = S2SNAPI(sb);
- struct smfs_hook_ops *cow_hops;
+ OBD_FREE(dot_info, sizeof(struct snap_dot_info));
+
+ RETURN(rc);
+}
+
+int smfs_cleanup_snap_info(struct snap_info *snap_info)
+{
+ struct snap_table *snap_table = snap_info->sni_table;
+ int rc = 0, table_size;
ENTRY;
- cow_hops = smfs_unregister_hook_ops(sb, COW_HOOK);
+ l_dput(snap_info->sni_cowed_dentry);
+ if (snap_table) {
+ table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count);
+ OBD_FREE(snap_info->sni_table, table_size);
+ }
+ smfs_cleanup_dotinfo(snap_info);
+ RETURN(rc);
+}
+
+int smfs_cow_cleanup(struct smfs_super_info *smb)
+{
+ struct snap_super_info *snap_sinfo = smb->smsi_snap_info;
+ struct list_head *snap_list = &snap_sinfo->snap_list;
+ struct smfs_hook_ops *cow_hops;
+ int rc = 0;
+ ENTRY;
+
+ while (!list_empty(snap_list)) {
+ struct snap_info *snap_info;
+
+ snap_info = list_entry(snap_list->next, struct snap_info,
+ sni_list);
+ rc = smfs_cleanup_snap_info(snap_info);
+ if (rc)
+ CERROR("cleanup snap_info error rc=%d\n", rc);
+ list_del(&snap_info->sni_list);
+ OBD_FREE(snap_info, sizeof(struct snap_info));
+ }
+
+ if (snap_sinfo->snap_fsfilt)
+ fsfilt_put_ops(snap_sinfo->snap_fsfilt);
+ if (snap_sinfo->snap_cache_fsfilt)
+ fsfilt_put_ops(snap_sinfo->snap_cache_fsfilt);
+
+ cow_hops = smfs_unregister_hook_ops(smb, COW_HOOK);
smfs_free_hook_ops(cow_hops);
- SMFS_CLEAN_COW(S2SMI(sb));
- if (snap_info)
- OBD_FREE(snap_info, sizeof(*snap_info));
- RETURN(0);
+ SMFS_CLEAN_COW(smb);
+ if (snap_sinfo)
+ OBD_FREE(snap_sinfo, sizeof(struct snap_super_info));
+ RETURN(rc);
}
+static struct snap_info *smfs_find_snap_info(struct inode *inode)
+{
+ struct snap_inode_info *snap_iinfo = I2SNAPI(inode);
+ struct snap_super_info *snap_sinfo = S2SNAPI(inode->i_sb);
+ struct snap_info *snap_info = NULL, *tmp;
+
+ ENTRY;
+ list_for_each_entry_safe(snap_info, tmp, &snap_sinfo->snap_list,
+ sni_list) {
+ if (snap_info->sni_root_ino == snap_iinfo->sn_root_ino)
+ RETURN(snap_info);
+ }
+ RETURN(NULL);
+}
static int smfs_dotsnap_dir_size(struct inode *inode)
{
- struct snap_info *snap_info = S2SNAPI(inode->i_sb);
- struct fsfilt_operations *snapops = snap_info->snap_cache_fsfilt;
- struct snap_table *stbl = snap_info->sntbl;
- int size = 0, dir_size = 0, blocks;
- int i = 0;
+ struct snap_super_info *snap_sinfo = S2SNAPI(inode->i_sb);
+ struct fsfilt_operations *snapops = snap_sinfo->snap_cache_fsfilt;
+ int size = 0, dir_size = 0, blocks, i = 0;
+ struct snap_table *snap_table = NULL;
+ struct snap_info *snap_info = NULL;
ENTRY;
-
- for (i = 0; i < stbl->sntbl_count; i++) {
- size += snapops->fs_dir_ent_size(stbl->sntbl_items[i].sn_name);
+
+ snap_info = smfs_find_snap_info(inode);
+
+ if (!snap_info) {
+ CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+ RETURN(0);
+ }
+ snap_table = snap_info->sni_table;
+ for (i = 0; i < snap_table->sntbl_count; i++) {
+ char *name = snap_table->sntbl_items[i].sn_name;
+ size += snapops->fs_dir_ent_size(name);
}
/*FIXME this is only for ext3 dir format, may need fix for other FS*/
blocks = (size + inode->i_sb->s_blocksize - 1) >>
RETURN(dir_size);
}
+int smfs_snap_test_inode(struct inode *inode, void *args)
+{
+ struct smfs_iget_args *sargs = (struct smfs_iget_args*)args;
+ struct inode *dir;
+
+ LASSERT(sargs);
+
+ dir = sargs->s_inode;
+
+ if (dir){
+ if (I2SNAPI(inode)->sn_index != I2SNAPI(dir)->sn_index)
+ return 0;
+ } else {
+ if (I2SNAPI(inode)->sn_index != sargs->s_index)
+ return 0;
+ }
+ return 1;
+}
+
/*FIXME Note indirect and primary inode
* should be recorgnized here*/
-int smfs_init_snap_inode_info(struct inode *inode,
- struct snap_inode_info *sn_info)
+int smfs_init_snap_inode_info(struct inode *inode, struct smfs_iget_args *args)
{
- struct smfs_inode_info *smi = I2SMI(inode);
+ struct inode *dir;
int vallen, rc = 0;
ENTRY;
- LASSERT(sn_info && smi);
- smi->sm_sninfo.sn_flags = sn_info->sn_flags;
- smi->sm_sninfo.sn_gen = sn_info->sn_gen;
- smi->sm_sninfo.sn_index = sn_info->sn_index;
+ LASSERT(args);
+ I2SNAPI(inode)->sn_index = args->s_index;
+
+ dir = args->s_inode;
+ if (dir) {
+ I2SNAPI(inode)->sn_flags = I2SNAPI(dir)->sn_flags;
+ I2SNAPI(inode)->sn_gen = I2SNAPI(dir)->sn_gen;
+ } else {
+ I2SNAPI(inode)->sn_flags = 0;
+ I2SNAPI(inode)->sn_gen = 0;
+ }
+
if (smfs_dotsnap_inode(inode)) {
- struct snap_table *stbl= S2SNAPI(inode->i_sb)->sntbl;
- int size = 0;
+ struct snap_info *snap_info;
+
+ snap_info = smfs_find_snap_info(inode);
+ if (!snap_info) {
+ RETURN(-EIO);
+ }
/*init dot_snap inode info*/
- size = smfs_dotsnap_dir_size(inode);
- inode->i_size = (loff_t)size;
- inode->i_nlink = stbl->sntbl_count + 2;
+ inode->i_size = (loff_t)smfs_dotsnap_dir_size(inode);
+ inode->i_nlink = snap_info->sni_table->sntbl_count + 2;
inode->i_uid = 0;
inode->i_gid = 0;
} else if (SMFS_DO_COW(S2SMI(inode->i_sb)) &&
- (smi->smi_flags & SM_DO_COW) &&
+ (I2SMI(inode)->smi_flags & SM_DO_COW) &&
smfs_primary_inode(inode)) {
struct snap_inode_info *sni_info = I2SNAPI(inode);
- struct fsfilt_operations *snapops = I2SNAPOPS(inode);
+ struct fsfilt_operations *sops = I2SNAPCOPS(inode);
vallen = sizeof(sni_info->sn_gen);
- rc = snapops->fs_get_snap_info(inode, SNAP_GENERATION,
- strlen(SNAP_GENERATION),
- &sni_info->sn_gen, &vallen);
+ rc = sops->fs_get_snap_info(I2CI(inode), SNAP_GENERATION,
+ strlen(SNAP_GENERATION),
+ &sni_info->sn_gen, &vallen);
}
RETURN(rc);
}
- hence it returns 0 in case all the volume snapshots lie in the future
- this is the index where a COW will land (will be created)
*/
-void snap_last(struct super_block *sb, struct snap *snap)
+void snap_last(struct inode *inode, struct snap *snap)
{
- struct snap_info *snap_info = S2SNAPI(sb);
- struct snap_table *table = snap_info->sntbl;
time_t now = LTIME_S(CURRENT_TIME);
+ struct snap_table *snap_table;
+ struct snap_info *snap_info;
int i ;
ENTRY;
+
+ snap_info = smfs_find_snap_info(inode);
+ if (!snap_info) {
+ CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+ EXIT;
+ return;
+ }
+ snap_table = snap_info->sni_table;
/* start at the highest index in the superblock snaptime array */
- if (table->sntbl_count == 0) {
+ if (snap_table->sntbl_count == 0) {
memset(snap, 0, sizeof(struct snap));
} else {
- i = table->sntbl_count - 1;
- snap->sn_index = table->sntbl_items[i].sn_index;
- snap->sn_time = table->sntbl_items[i].sn_time;
- snap->sn_gen = table->sntbl_items[i].sn_gen;
+ i = snap_table->sntbl_count - 1;
+ snap->sn_index = snap_table->sntbl_items[i].sn_index;
+ snap->sn_time = snap_table->sntbl_items[i].sn_time;
+ snap->sn_gen = snap_table->sntbl_items[i].sn_gen;
}
CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
snap->sn_index, snap->sn_time, now);
return;
}
-static int inline get_index_of_item(struct snap_table *table, char *name)
+static inline int get_index_of_item(struct snap_table *table, char *name)
{
int count = table->sntbl_count;
int i, j;
RETURN(-ENOSPC);
}
-int smfs_add_snap_item(struct super_block *sb, char *name)
+static struct dentry *smfs_find_snap_root(struct super_block *sb,
+ char *path_name)
{
- struct snap_info *snap_info = S2SNAPI(sb);
- struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
- struct snap_table *snap_table = snap_info->sntbl;
- struct dentry *d_root = snap_info->snap_root;
- struct snap *snap_item;
- int table_size, count = 0, index = 0, rc = 0;
+ struct dentry *dentry = NULL;
+ struct nameidata nd;
+ ENTRY;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (path_init(path_name, LOOKUP_FOLLOW, &nd)) {
+ error = path_walk(path_name, &nd);
+ if (error) {
+ path_release(&nd);
+ RETURN(NULL);
+ }
+ } else {
+ RETURN(NULL);
+ }
+#else
+ if (path_lookup(path_name, LOOKUP_FOLLOW, &nd))
+ RETURN(NULL);
+
+#endif
+ dentry = dget(nd.dentry);
+ path_release(&nd);
+ RETURN(dentry);
+}
+static int snap_add_item(struct smfs_super_info *smb,
+ struct snap_info *snap_info,
+ char *name)
+{
+ struct fsfilt_operations *snapops;
+ struct snap_table *snap_table = snap_info->sni_table;
+ struct inode *root_inode = NULL;
+ int table_size, count = 0, index = 0, rc = 0;
+ struct snap *snap_item;
+ ENTRY;
count = snap_table->sntbl_count;
+ root_inode = iget(smb->smsi_sb, snap_info->sni_root_ino);
+ if (!root_inode || is_bad_inode(root_inode))
+ RETURN(-EIO);
/* XXX Is down this sema necessary*/
- down_interruptible(&snap_info->sntbl_sema);
+ down_interruptible(&snap_info->sni_sema);
snap_item = &snap_table->sntbl_items[count];
-
+ snapops = smb->smsi_snap_info->snap_cache_fsfilt;
/*add item in snap_table set generation*/
snap_item->sn_time = LTIME_S(CURRENT_TIME);
/* find table index */
memcpy(snap_item->sn_name, name, SNAP_MAX_NAMELEN);
/* Wrote the whole snap_table to disk */
table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count);
-
- rc = snapops->fs_set_snap_info(d_root->d_inode, SNAPTABLE_INFO,
+
+ rc = snapops->fs_set_snap_info(root_inode, SNAPTABLE_INFO,
strlen(SNAPTABLE_INFO),
snap_table, &table_size);
if (rc) {
snap_table->sntbl_count++;
snap_table->sntbl_generation++;
exit:
- up(&snap_info->sntbl_sema);
+ up(&snap_info->sni_sema);
+ if (root_inode)
+ iput(root_inode);
RETURN(rc);
}
-EXPORT_SYMBOL(smfs_add_snap_item);
+
+static struct snap_info * smfs_find_create_snap_info(struct super_block *sb,
+ struct dentry *dentry)
+{
+ struct snap_super_info *snap_sinfo = S2SNAPI(sb);
+ struct snap_info *snap_info, *tmp;
+ ENTRY;
+
+ list_for_each_entry_safe(snap_info, tmp, &snap_sinfo->snap_list,
+ sni_list) {
+ if (snap_info->sni_root_ino == dentry->d_inode->i_ino) {
+ RETURN(snap_info);
+ }
+ }
+
+ CDEBUG(D_INFO, "create a new snap info root ino %lu\n",
+ dentry->d_inode->i_ino);
+
+ snap_info = smfs_create_snap_info(S2SMI(sb), dentry);
+
+ if (IS_ERR(snap_info))
+ RETURN(snap_info);
+
+ list_add(&snap_info->sni_list, &snap_sinfo->snap_list);
+ RETURN(snap_info);
+}
+
+int smfs_add_snap_item(struct super_block *sb, char *path_name, char *name)
+{
+ struct dentry *dentry = NULL;
+ struct snap_info *snap_info;
+ int rc = 0;
+ ENTRY;
+
+ if (!SMFS_DO_COW(S2SMI(sb))) {
+ RETURN(0);
+ }
+
+ if (!path_name || !name) {
+ CERROR("patch_name and snapshot_name is NULL");
+ RETURN(-EINVAL);
+ }
+ dentry = smfs_find_snap_root(sb, path_name);
+ if (IS_ERR(dentry)) {
+ CERROR("can not find snap_shot root by %s\n", path_name);
+ RETURN(PTR_ERR(dentry));
+ }
+ snap_info = smfs_find_create_snap_info(sb, dentry);
+ if (IS_ERR(snap_info)) {
+ CERROR("can not find snap_info by %s rc=%lu\n", path_name,
+ PTR_ERR(snap_info));
+ GOTO(exit, rc = PTR_ERR(snap_info));
+ }
+
+ rc = snap_add_item(S2SMI(sb), snap_info, name);
+exit:
+ dput(dentry);
+ RETURN(rc);
+}
+//EXPORT_SYMBOL(smfs_add_snap_item);
/*
* Note: this function should be differnet with snap_do_cow.
* In smfs_do_cow, we check the EA for whether do cow for that inode.
snap_info = &(smi_info->sm_sninfo);
- snap_last(inode->i_sb, &snap);
+ snap_last(inode, &snap);
/* decision .... if the snapshot is more recent than the object,
* then any change to the object should cause a COW.
*/
static int link_cowed_inode(struct inode *inode)
{
- struct snap_info *snap_info = S2SNAPI(inode->i_sb);
struct dentry *cowed_dir = NULL;
char fidname[LL_FID_NAMELEN];
+ struct snap_info *snap_info;
int fidlen = 0, rc = 0;
struct dentry *dchild = NULL;
struct dentry *tmp = NULL;
unsigned mode;
- cowed_dir = snap_info->sn_cowed_dentry;
+ snap_info = smfs_find_snap_info(inode);
+ if (!snap_info) {
+ CERROR("can not find snap info for inode %p\n", inode);
+ RETURN(-EINVAL);
+ }
+
+ cowed_dir = snap_info->sni_cowed_dentry;
fidlen = ll_fid2str(fidname, inode->i_ino, inode->i_generation);
*/
int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
{
- struct snap_info *snap_info = S2SNAPI(inode->i_sb);
- struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
+ struct fsfilt_operations *snapops = I2SNAPCOPS(inode);
struct snap snap;
- struct inode *ind = NULL;
-
- ENTRY;
+ struct inode *ind = NULL, *cache_ind = NULL;
+ ino_t ind_ino;
+ ENTRY;
if (!snapops || !snapops->fs_create_indirect)
RETURN(-EINVAL);
- snap_last(inode->i_sb, &snap);
- ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen,
- dparent->d_inode, del);
- if(ind && IS_ERR(ind)) {
+ snap_last(inode, &snap);
+ cache_ind = snapops->fs_create_indirect(I2CI(inode), snap.sn_index,
+ snap.sn_gen, I2CI(dparent->d_inode),
+ del);
+ if(cache_ind && IS_ERR(cache_ind)) {
CERROR("Create ind inode %lu index %d gen %d del %d rc%lu\n",
inode->i_ino, snap.sn_index, snap.sn_gen, del,
- PTR_ERR(ind));
+ PTR_ERR(cache_ind));
RETURN(PTR_ERR(ind));
}
+ ind_ino = cache_ind->i_ino;
+ iput(cache_ind);
+ /*FIXME: get indirect inode set_cow flags*/
+ ind = smfs_get_inode(inode->i_sb, ind_ino, inode, 0);
if (ind) {
if (!SMFS_DO_INODE_COWED(inode)) {
/*insert the inode to cowed inode*/
int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1,
void *data2)
{
- struct snap_info *snap_info = S2SNAPI(inode->i_sb);
- struct snap_table *table = snap_info->sntbl;
+ struct snap_info *snap_info = NULL;
+ struct snap_table *table;
long blocks[2]={-1,-1};
int index = 0, i, rc = 0;
size_t count;
ENTRY;
+ snap_info = smfs_find_snap_info(inode);
+ if (!snap_info) {
+ CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+ RETURN(0);
+ }
+ table = snap_info->sni_table;
+
LASSERT(data1);
LASSERT(data2);
continue;
/*Find the nearest page in snaptable and copy back it*/
for (slot = table->sntbl_count - 1; slot >= 0; slot--) {
- struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
- struct inode *cache_inode = NULL;
+ struct fsfilt_operations *sops = I2SNAPCOPS(inode);
+ struct inode *cind = NULL;
int result = 0;
index = table->sntbl_items[slot].sn_index;
- cache_inode = snapops->fs_get_indirect(inode, NULL, index);
-
- if (!cache_inode) continue;
+ cind = sops->fs_get_indirect(I2CI(inode), NULL, index);
+ if (!cind) continue;
- CDEBUG(D_INFO, "find cache_ino %lu\n", cache_inode->i_ino);
+ CDEBUG(D_INFO, "find cache_ino %lu\n", cind->i_ino);
- result = snapops->fs_copy_block(inode, cache_inode, blocks[i]);
+ result = sops->fs_copy_block(I2CI(inode), cind,
+ blocks[i]);
if (result == 1) {
- iput(cache_inode);
+ iput(cind);
result = 0;
break;
}
if (result < 0) {
- iput(cache_inode);
+ iput(cind);
up(&inode->i_sem);
GOTO(exit, rc = result);
}
- iput(cache_inode);
+ iput(cind);
}
}
exit:
}
EXPORT_SYMBOL(smfs_cow_write);
/*lookup inode in dotsnap inode */
-static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry)
+static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry,
+ struct snap_info *snap_info)
{
if (dentry->d_name.len == 1 &&
!strcmp(dentry->d_name.name, ".")) {
}
} else {
/*find the name from the snaptable*/
- struct fsfilt_operations *snapops = I2SNAPOPS(dir);
- struct snap_table *table = S2SNAPI(dir->i_sb)->sntbl;
+ struct fsfilt_operations *sops = I2SNAPCOPS(dir);
+ struct snap_table *table;
struct inode *inode;
+ ino_t cino;
int i = 0, index = -1;
+
+ table = snap_info->sni_table;
+
for (i = 0; i < table->sntbl_count; i++) {
char *name = table->sntbl_items[i].sn_name;
if ((dentry->d_name.len == strlen(name)) &&
dentry->d_name.name);
RETURN(-ENOENT);
}
- inode = snapops->fs_get_indirect(dir, NULL, index);
+ cino = sops->fs_get_indirect_ino(S2CSB(dir->i_sb), dir->i_ino,
+ index);
+ inode = smfs_get_inode(dir->i_sb, cino, dir, index);
+ if (!inode || is_bad_inode(inode)) {
+ CERROR("Can not find cino %lu inode\n", cino);
+ RETURN(-ENOENT);
+ }
d_add(dentry, inode);
}
RETURN(0);
int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1,
void *data2)
{
- struct snap_info *snap_info = S2SNAPI(inode->i_sb);
- struct snap_dot_info *dot_info = snap_info->sn_dot_info;
+ struct snap_info *snap_info;
+ struct snap_dot_info *dot_info;
int rc = 0, index = 0;
ENTRY;
+ snap_info = smfs_find_snap_info(inode);
+ if (!snap_info) {
+ CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+ RETURN(0);
+ }
+
+ dot_info = snap_info->sni_dot_info;
+
LASSERT(dot_info != NULL);
LASSERT(data1 != NULL);
RETURN(rc);
}
if (smfs_dotsnap_inode(inode)) {
- rc = smfs_dotsnap_lookup(inode, dentry);
+ rc = smfs_dotsnap_lookup(inode, dentry, snap_info);
if (rc == 0)
rc = 1;
RETURN(rc);
struct inode *smfs_cow_get_ind(struct inode *inode, int index)
{
- struct snap_info *snap_info = S2SNAPI(inode->i_sb);
- struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
- struct snap_table *table = snap_info->sntbl;
long block=(index << PAGE_CACHE_SHIFT) >> inode->i_sb->s_blocksize_bits;
+ struct fsfilt_operations *sops = I2SNAPCOPS(inode);
+ struct snap_info *snap_info = NULL;
+ struct snap_table *table = NULL;
int slot;
- ENTRY;
+ ENTRY;
+
+ snap_info = smfs_find_snap_info(inode);
+ if (!snap_info) {
+ CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
+ RETURN(NULL);
+ }
+
+ table = snap_info->sni_table;
+
for (slot = table->sntbl_count - 1; slot >= 0; slot--) {
struct address_space_operations *aops = inode->i_mapping->a_ops;
struct inode *cache_inode = NULL;
int index = 0;
index = table->sntbl_items[slot].sn_index;
- cache_inode = snapops->fs_get_indirect(inode, NULL, index);
+ cache_inode = sops->fs_get_indirect(I2CI(inode), NULL, index);
if (!cache_inode ) continue;
-
+
if (aops->bmap(cache_inode->i_mapping, block))
RETURN(cache_inode);
iput(cache_inode);
smfs_hook_func post_hook);
void smfs_free_hook_ops(struct smfs_hook_ops *hops);
-int smfs_register_hook_ops(struct super_block *sb,
+int smfs_register_hook_ops(struct smfs_super_info *smb,
struct smfs_hook_ops *smh_ops);
-struct smfs_hook_ops *smfs_unregister_hook_ops(struct super_block *sb,
+struct smfs_hook_ops *smfs_unregister_hook_ops(struct smfs_super_info *smb,
char *name);
/*smfs_lib.c*/
void smfs_put_super(struct super_block *sb);
-extern struct super_block *smfs_get_sb_by_path(char *path, int len);
int smfs_fill_super(struct super_block *sb, void *data, int silent);
/*sysctl.c*/
extern int sm_debug_level;
extern struct super_operations smfs_super_ops;
+struct smfs_iget_args {
+ struct inode *s_inode;
+ int s_index;
+ int s_ino;
+};
/*symlink.c*/
extern struct inode_operations smfs_sym_iops;
extern struct file_operations smfs_sym_fops;
extern int smfs_post_rec_create(struct inode *dir, struct dentry *dentry,
void *data1, void *data2);
/*kml.c*/
-extern int smfs_kml_init(struct super_block *sb);
-extern int smfs_do_rec(struct inode *inode);
-extern int smfs_rec_cleanup(struct super_block *sb);
-extern int smfs_rec_init(struct super_block *sb);
+int smfs_do_rec(struct inode *inode);
+int smfs_rec_cleanup(struct smfs_super_info *smfs_info);
+int smfs_rec_init(struct super_block *sb);
+
extern int smfs_rec_unpack(struct smfs_proc_args *args, char *record,
char **pbuf, int *opcode);
extern int smfs_process_rec(struct super_block *sb, int count,
char *dir, int flags);
extern smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb);
-extern int ost_rec_pack_init(struct super_block *sb);
+
+/*mds_kml.c*/
+int mds_rec_pack_init(struct smfs_super_info *smsi);
/*ost_kml.c*/
-extern int mds_rec_pack_init(struct super_block *sb);
+int ost_rec_pack_init(struct smfs_super_info *smsi);
/*smfs_llog.c*/
extern int smfs_llog_setup(struct super_block *sb, struct vfsmount *mnt);
struct dentry *old_dentry, struct inode *new_dir,
struct dentry *new_dentry);
-extern int cache_space_hook_setup(struct super_block *);
-extern int cache_space_hook_cleanup(void);
-extern int cache_space_hook_init(struct super_block *);
-extern int cache_space_hook_exit(struct super_block *);
+int cache_space_hook_setup(struct super_block *);
+int cache_space_hook_cleanup(void);
+int cache_space_hook_init(struct super_block *sb);
+int cache_space_hook_exit(struct smfs_super_info *smfs_info);
#define XATTR_SMFS_HOARD_MARK "hoard"
#define XATTR_SMFS_CACHE_LOGCOOKIE "cache"
GOTO(label, rc); \
} while(0) \
+#define SMFS_GET_INODE(sb, cache_inode, dir, index, inode, rc, label) \
+do { \
+ LASSERT(cache_inode); \
+ inode = smfs_get_inode(sb, cache_inode->i_ino, dir, index); \
+ iput(cache_inode); \
+ if (!inode) \
+ GOTO(label, rc = -ENOENT); \
+} while(0)
+
+
#if CONFIG_SNAPFS
-extern int smfs_cow_init(struct super_block *sb);
-extern int smfs_cow_cleanup(struct super_block *sb);
-extern int smfs_init_snap_inode_info(struct inode *inode,
- struct snap_inode_info *sn_info);
+int smfs_cow_init(struct super_block *sb);
+int smfs_cow_cleanup(struct smfs_super_info *smb);
+int smfs_init_snap_inode_info(struct inode *inode, struct smfs_iget_args *args);
+int smfs_snap_test_inode(struct inode *inode, void *args);
#else
#define SMFS_PRE_COW(dir, dentry, new_dir, new_dentry, op, name, rc, label)
#endif
#include <linux/lustre_fsfilt.h>
#include <linux/lustre_smfs.h>
#include "smfs_internal.h"
-static char *smfs_options(char *data, char **devstr, char **namestr,
- int *kml, int *cache, char **opts, int *iopen_nopriv,
- int *cow)
+
+static char *smfs_options(char *data, char **devstr, char **namestr,
+ char *opts, int *flags)
{
- char *pos;
struct option *opt_value = NULL;
+ char *pos;
+ int opt_len = 0;
+
+ LASSERT(opts && flags);
while (!(get_opt(&opt_value, &pos))) {
if (!strcmp(opt_value->opt, "dev")) {
if (namestr != NULL)
*namestr = opt_value->value;
} else if (!strcmp(opt_value->opt, "kml")) {
- if (kml)
- *kml = 1;
+ *flags |= SM_DO_REC;
} else if (!strcmp(opt_value->opt, "cache")) {
- if (cache)
- *cache = 1;
- } else if (!strcmp(opt_value->opt, "options")) {
- if (opts != NULL)
- *opts = opt_value->value;
- } else if (!strcmp(opt_value->opt, "iopen_nopriv")) {
- if (iopen_nopriv != NULL)
- *iopen_nopriv = 1;
+ *flags |= SM_CACHE_HOOK;
} else if (!strcmp(opt_value->opt, "snap")) {
- *cow = 1;
+ *flags |= SM_DO_COW;
+ } else if (!strcmp(opt_value->opt, "options")) {
+ if (strlen(opts) == 0)
+ sprintf((char *)opts + strlen(opts), "%s",
+ opt_value->value);
+ else
+ sprintf((char *)opts + strlen(opts), ",%s",
+ opt_value->value);
} else {
- break;
+ /*FIXME:WANGDI How about the opt_value->value*/
+ if (strlen(opts) == 0)
+ sprintf((char *)opts + strlen(opts), "%s",
+ opt_value->opt);
+ else
+ sprintf((char *)opts + strlen(opts), ",%s",
+ opt_value->opt);
}
}
return pos;
}
-
-struct super_block *smfs_get_sb_by_path(char *path, int len)
+static struct smfs_super_info *smfs_init_smb(struct super_block *sb)
{
- struct super_block *sb;
- struct nameidata nd;
- int error = 0;
-
+ struct smfs_super_info *smb;
ENTRY;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- if (path_init(path, LOOKUP_FOLLOW, &nd)) {
-#else
- if (path_lookup(path, LOOKUP_FOLLOW, &nd)) {
-#endif
- error = path_walk(path, &nd);
- if (error) {
- path_release(&nd);
- RETURN(NULL);
- }
- } else {
- RETURN(NULL);
- }
-
- /* FIXME-WANGDI: add some check code here. */
- sb = nd.dentry->d_sb;
- path_release(&nd);
- RETURN(sb);
+ OBD_ALLOC(smb, sizeof(*smb));
+ if (!smb)
+ RETURN(NULL);
+
+ S2SMI(sb) = smb;
+ RETURN(smb);
}
-
-static int smfs_init_fsfilt_ops(struct super_block *sb)
+static int smfs_init_fsfilt_ops(struct smfs_super_info *smb)
{
ENTRY;
- if (!S2SMI(sb)->sm_cache_fsfilt) {
- S2SMI(sb)->sm_cache_fsfilt =
- fsfilt_get_ops(S2SMI(sb)->smsi_cache_ftype);
- if (!S2SMI(sb)->sm_cache_fsfilt) {
+ if (!smb->sm_cache_fsfilt) {
+ smb->sm_cache_fsfilt = fsfilt_get_ops(smb->smsi_cache_ftype);
+ if (!smb->sm_cache_fsfilt) {
CERROR("Can not get %s fsfilt ops needed by kml\n",
- S2SMI(sb)->smsi_cache_ftype);
+ smb->smsi_cache_ftype);
RETURN(-EINVAL);
}
}
- if (!S2SMI(sb)->sm_fsfilt) {
- S2SMI(sb)->sm_fsfilt =
- fsfilt_get_ops(S2SMI(sb)->smsi_ftype);
- if (!S2SMI(sb)->sm_fsfilt) {
+ if (!smb->sm_fsfilt) {
+ smb->sm_fsfilt = fsfilt_get_ops(smb->smsi_ftype);
+ if (!smb->sm_fsfilt) {
CERROR("Can not get %s fsfilt ops needed by kml\n",
- S2SMI(sb)->smsi_ftype);
+ smb->smsi_ftype);
RETURN(-EINVAL);
}
}
RETURN(0);
}
-void smfs_cleanup_fsfilt_ops(struct super_block *sb)
+void smfs_cleanup_fsfilt_ops(struct smfs_super_info *smb)
{
- if (S2SMI(sb)->sm_cache_fsfilt)
- fsfilt_put_ops(S2SMI(sb)->sm_cache_fsfilt);
- if (S2SMI(sb)->sm_fsfilt)
- fsfilt_put_ops(S2SMI(sb)->sm_fsfilt);
+ if (smb->sm_cache_fsfilt)
+ fsfilt_put_ops(smb->sm_cache_fsfilt);
+ if (smb->sm_fsfilt)
+ fsfilt_put_ops(smb->sm_fsfilt);
}
-static int sm_mount_cache(struct super_block *sb, char *devstr,
- char *typestr, char *opts, int iopen_nopriv)
+static int smfs_mount_cache(struct smfs_super_info *smb, char *devstr,
+ char *typestr, char *opts)
{
- struct smfs_super_info *smb = S2SMI(sb);
int err = 0, typelen;
struct vfsmount *mnt;
- unsigned long page;
ENTRY;
typelen = strlen(typestr);
- page = __get_free_page(GFP_KERNEL);
- if (!page)
- GOTO(err_out, err = -ENOMEM);
-
- memset((void *)page, 0, PAGE_SIZE);
-
- if (iopen_nopriv)
- sprintf((char *)page, "iopen_nopriv");
-
- if (opts && strlen(opts)) {
- int n = strlen((char *)page);
- sprintf((char *)page + n, ",%s", opts);
- }
-
printk("smfs: mounting %s at %s\n", typestr, devstr);
- mnt = do_kern_mount(typestr, 0, devstr, (void *)page);
- free_page(page);
+ mnt = do_kern_mount(typestr, 0, devstr, (void *)opts);
if (IS_ERR(mnt)) {
CERROR("do_kern_mount failed: rc = %ld\n", PTR_ERR(mnt));
OBD_ALLOC(smb->smsi_ftype, strlen(SMFS_TYPE) + 1);
memcpy(smb->smsi_ftype, SMFS_TYPE, strlen(SMFS_TYPE));
-
- duplicate_sb(sb, mnt->mnt_sb);
- sm_set_sb_ops(mnt->mnt_sb, sb);
-
- err = smfs_init_fsfilt_ops(sb);
+
+ err = smfs_init_fsfilt_ops(smb);
err_out:
- return err;
+ RETURN(err);
}
-static int sm_umount_cache(struct super_block *sb)
+static int smfs_umount_cache(struct smfs_super_info *smb)
{
- struct smfs_super_info *smb = S2SMI(sb);
-
- iput(S2CSB(sb)->s_root->d_inode);
- dput(S2CSB(sb)->s_root);
+ iput(smb->smsi_sb->s_root->d_inode);
+ dput(smb->smsi_sb->s_root);
mntput(smb->smsi_mnt);
smfs_cleanup_sm_ops(smb);
- smfs_cleanup_fsfilt_ops(sb);
+ smfs_cleanup_fsfilt_ops(smb);
if (smb->smsi_cache_ftype)
OBD_FREE(smb->smsi_cache_ftype,
return 0;
}
-static int smfs_init_hook_ops(struct super_block *sb)
+static int smfs_init_hook_ops(struct smfs_super_info *smb)
{
- struct smfs_super_info *smb = S2SMI(sb);
ENTRY;
INIT_LIST_HEAD(&smb->smsi_hook_list);
RETURN(0);
}
-static void smfs_cleanup_hook_ops(struct super_block *sb)
+static void smfs_cleanup_hook_ops(struct smfs_super_info *smb)
{
- struct smfs_super_info *smb = S2SMI(sb);
struct list_head *hlist = &smb->smsi_hook_list;
ENTRY;
smh_list);
CERROR("Unregister %s hook ops\n", smfs_hops->smh_name);
- smfs_unregister_hook_ops(sb, smfs_hops->smh_name);
+ smfs_unregister_hook_ops(smb, smfs_hops->smh_name);
smfs_free_hook_ops(smfs_hops);
}
EXIT;
return;
}
-void smfs_put_super(struct super_block *sb)
+static void smfs_cleanup_smb(struct super_block *sb)
{
- if (SMFS_CACHE_HOOK(S2SMI(sb)))
- cache_space_hook_exit(sb);
- if (SMFS_DO_REC(S2SMI(sb)))
- smfs_rec_cleanup(sb);
+ struct smfs_super_info *smb;
+ ENTRY;
+
+ smb = S2SMI(sb);
+ if (smb)
+ OBD_FREE(smb, sizeof(*smb));
+ EXIT;
+ return;
+}
+static void smfs_cleanup_hooks(struct smfs_super_info *smb)
+{
+
+ if (SMFS_CACHE_HOOK(smb))
+ cache_space_hook_exit(smb);
+ if (SMFS_DO_REC(smb))
+ smfs_rec_cleanup(smb);
#if CONFIG_SNAPFS
- if (SMFS_DO_COW(S2SMI(sb)))
- smfs_cow_cleanup(sb);
+ if (SMFS_DO_COW(smb))
+ smfs_cow_cleanup(smb);
#endif
- smfs_cleanup_hook_ops(sb);
-
+}
+
+void smfs_put_super(struct super_block *sb)
+{
+ struct smfs_super_info *smfs_info = S2SMI(sb);
+
+ smfs_cleanup_hooks(smfs_info);
+
+ smfs_cleanup_hook_ops(smfs_info);
if (sb)
- sm_umount_cache(sb);
+ smfs_umount_cache(smfs_info);
+ smfs_cleanup_smb(sb);
return;
}
+
+static int smfs_init_hooks(struct super_block *sb)
+{
+ ENTRY;
+
+ if (SMFS_DO_REC(S2SMI(sb)))
+ smfs_rec_init(sb);
+ if (SMFS_CACHE_HOOK(S2SMI(sb)))
+ cache_space_hook_init(sb);
+#if CONFIG_SNAPFS
+ if (SMFS_DO_COW(S2SMI(sb)))
+ smfs_cow_init(sb);
+#endif
+ RETURN(0);
+}
+
int smfs_fill_super(struct super_block *sb, void *data, int silent)
{
- ino_t root_ino;
- char *cache_data;
-
- int iopen_nopriv = 0;
struct inode *root_inode = NULL;
- int err = 0, do_rec = 0, cache_hook = 0, do_cow = 0;
- char *devstr = NULL, *typestr = NULL, *opts = NULL;
+ struct smfs_super_info *smb = NULL;
+ char *devstr = NULL, *typestr = NULL;
+ char *opts = NULL, *cache_data = NULL;
+ unsigned long page;
+ int err = 0;
+ ino_t root_ino;
ENTRY;
- CDEBUG(D_SUPER, "mount opts: %s\n", data ?
- (char *)data : "(none)");
-
- init_option(data);
+ CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
- /* read and validate passed options. */
- cache_data = smfs_options(data, &devstr, &typestr,
- &do_rec, &cache_hook, &opts,
- &iopen_nopriv, &do_cow);
+ smb = smfs_init_smb(sb);
+ if (!smb)
+ RETURN(-ENOMEM);
+
+ page = __get_free_page(GFP_KERNEL);
+ if (!page)
+ GOTO(out_err, err = -ENOMEM);
+
+ memset((void *)page, 0, PAGE_SIZE);
+ opts = (char *)page;
+ init_option(data);
+ cache_data = smfs_options(data, &devstr, &typestr, opts,
+ &smb->smsi_flags);
if (*cache_data)
CWARN("smfs_fill_super(): options parsing stoped at "
"option %s\n", cache_data);
if (!typestr || !devstr) {
CERROR("mount options name and dev mandatory\n");
+ free_page(page);
GOTO(out_err, err = -EINVAL);
}
- err = sm_mount_cache(sb, devstr, typestr, opts, iopen_nopriv);
+ err = smfs_mount_cache(smb, devstr, typestr, opts);
+
+ free_page(page);
+
if (err) {
CERROR("Can not mount %s as %s\n", devstr, typestr);
GOTO(out_err, 0);
}
-
- err = smfs_init_hook_ops(sb);
+
+ duplicate_sb(sb, smb->smsi_sb);
+ sm_set_sb_ops(smb->smsi_sb, sb);
+
+ err = smfs_init_hook_ops(smb);
if (err) {
CERROR("Can not init super hook ops err %d\n", err);
GOTO(out_err, 0);
}
-
- if (do_rec) smfs_rec_init(sb);
- if (cache_hook) cache_space_hook_init(sb);
-
+ /*init the root_inode of smfs*/
dget(S2CSB(sb)->s_root);
root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
- root_inode = iget(sb, root_ino);
+ root_inode = smfs_get_inode(sb, root_ino, NULL, 0);
CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
sb->s_op->read_inode, root_ino, root_inode);
sb->s_root = d_alloc_root(root_inode);
if (!sb->s_root) {
- sm_umount_cache(sb);
+ smfs_umount_cache(smb);
GOTO(out_err, err=-EINVAL);
}
-#if CONFIG_SNAPFS
- if (do_cow) smfs_cow_init(sb);
-#endif
-
+
+ err = smfs_init_hooks(sb);
+ if (err) {
+ smfs_umount_cache(smb);
+ GOTO(out_err, err=-EINVAL);
+ }
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
(ulong)sb, (ulong)&sb->u.generic_sbp);
CDEBUG(D_SUPER, "sb %lx, &sb->s_fs_info: %lx\n",
(ulong)sb, (ulong)&sb->s_fs_info);
#endif
-
out_err:
cleanup_option();
+ if (err)
+ smfs_cleanup_smb(sb);
return err;
}
struct smfs_hook_ops *smfs_alloc_hook_ops(char *name, smfs_hook_func pre_hook,
- smfs_hook_func post_hook)
+ smfs_hook_func post_hook)
{
struct smfs_hook_ops *smfs_hops = NULL;
}
}
-int smfs_register_hook_ops(struct super_block *sb,
+int smfs_register_hook_ops(struct smfs_super_info *smb,
struct smfs_hook_ops *smh_ops)
{
- struct smfs_super_info *smb = S2SMI(sb);
struct list_head *hlist = &smb->smsi_hook_list;
struct list_head *p;
ENTRY;
list_add(&smh_ops->smh_list, hlist);
RETURN(0);
}
-struct smfs_hook_ops *smfs_unregister_hook_ops(struct super_block *sb,
- char *name)
+struct smfs_hook_ops *smfs_unregister_hook_ops(struct smfs_super_info *smb,
+ char *name)
{
- struct smfs_super_info *smb = S2SMI(sb);
struct list_head *hlist = &smb->smsi_hook_list;
struct list_head *p;
ENTRY;
};
#endif
-static int init_smfs(void)
-{
- int err;
-
- err = register_filesystem(&smfs_type);
- if (err)
- CERROR("register_filesystem() failed, rc = %d\n", err);
- return err;
-}
-
static int cleanup_smfs(void)
{
int err = 0;
CERROR("unregister_filesystem() failed, rc = %d\n", err);
return 0;
}
-
+static int init_smfs(void)
+{
+ int err;
+
+ err = register_filesystem(&smfs_type);
+ if (err)
+ CERROR("register_filesystem() failed, rc = %d\n", err);
+ return err;
+}
static int __init smfs_init(void)
{
int err;
{"cache_off", jt_obd_cache_off, 0,
"usage: lsync\n"},
/*snap operations*/
- {"snap_add", jt_obd_snap_add, 0, "usage: snap_add <snap_name>\n"},
+ {"snap_add", jt_obd_snap_add, 0,
+ "usage: snap_add <dev_name> <snap_name>\n"},
/* Llog operations */
{"llog_catlist", jt_llog_catlist, 0,
"list all catalog logs on current device.\n"
struct obd_ioctl_data data;
int rc = 0;
- if (argc != 2)
- return CMD_HELP;
+ if (argc != 3)
+ return CMD_HELP;
+
+ SHMEM_SETUP();
+ register_ioc_dev(SMFS_DEV_ID, SMFS_DEV_PATH);
+
IOC_INIT(data);
data.ioc_inllen1 = strlen(argv[1]) + 1;
data.ioc_inlbuf1 = argv[1];
+ data.ioc_inllen2 = strlen(argv[2]) + 2;
+ data.ioc_inlbuf2 = argv[2];
IOC_PACK(argv[0], data);
- rc = l_ioctl(OBD_DEV_ID, OBD_IOC_SNAP_ADD, buf);
+ rc = l_ioctl(SMFS_DEV_ID, OBD_IOC_SMFS_SNAP_ADD, buf);
+ unregister_ioc_dev(SMFS_DEV_ID);
+
if (rc)
fprintf(stderr, "OBD_IOC_SNAP_ADD failed: rc=%d\n", rc);
return rc;