int mpi_size[4];
int mpi_total_size;
};
-
+typedef int (*smfs_hook_func)(struct inode *inode, struct dentry *dentry,
+ void *data1, void *data2, int op, void *handle);
+struct smfs_hook_ops {
+ struct list_head smh_list;
+ char * smh_name;
+ smfs_hook_func smh_post_op;
+ smfs_hook_func smh_pre_op;
+};
struct smfs_super_info {
struct super_block *smsi_sb;
struct vfsmount *smsi_mnt; /* mount the cache kern */
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_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_flags; /* flags */
__u32 smsi_ops_check;
+ struct list_head smsi_hook_list;
};
-#define SMFS_FILE_TYPE "smfs"
+
+#define SMFS_FILE_TYPE "smfs"
#define SMFS_FILE_MAGIC 0x19760218
struct smfs_file_info {
struct snap sntbl_items[0];
};
+struct snap_dot_info {
+ char *dot_name;
+ int dot_name_len;
+ int dot_snap_enable;
+};
+
struct snap_info {
struct fsfilt_operations *snap_fsfilt;
struct fsfilt_operations *snap_cache_fsfilt;
spinlock_t sntbl_lock;
struct snap_table *sntbl;
struct dentry *sn_cowed_dentry;
-};
-#define SM_CLONE_FS 0x01
-#define SET_CLONE_INDEX(clone_info, index) \
- (((struct clonefs_info *)clone_info)->clone_index = index)
-#define SET_CLONE_FLAGS(clone_info, flags) \
- (((struct clonefs_info *)clone_info)->clone_flags = flags)
+ struct snap_dot_info *sn_dot_info;
+};
extern int smfs_add_snap_item(struct super_block *sb, char *name);
extern int smfs_start_cow(struct super_block *sb);
RETURN(rc);
}
-#if CONFIG_SNAPFS
-int lustre_set_clone_info(struct super_block *sb, int clone_index)
-{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
-
- ENTRY;
-
- CDEBUG(D_INFO, "set clone index %d\n", clone_index);
- if (!clone_index)
- RETURN(0);
-
- if (sbi->ll_mdc_exp) {
- struct obd_device *obd = class_exp2obd(sbi->ll_mdc_exp);
- struct client_obd *cl_obd = &obd->u.cli;
-
- OBD_ALLOC(cl_obd->cl_clone_info, sizeof(struct clonefs_info));
- if (!cl_obd->cl_clone_info)
- RETURN(-ENOMEM);
- SET_CLONE_INDEX(cl_obd->cl_clone_info, clone_index);
- SET_CLONE_FLAGS(cl_obd->cl_clone_info, SM_CLONE_FS);
- cl_obd->cl_clone_info->cl_clone_info->clone_magic =
- cpu_to_le32(CLONE_INFO_MAGI);
- }
-
- if (sbi->ll_osc_exp) {
- struct obd_device *obd = class_exp2obd(sbi->ll_osc_exp);
- struct client_obd *cl_obd = &obd->u.cli;
-
- OBD_ALLOC(cl_obd->cl_clone_info, sizeof(struct clonefs_info));
- if (!cl_obd->cl_clone_info)
- RETURN(-ENOMEM);
- SET_CLONE_INDEX(cl_obd->cl_clone_info, clone_index);
- SET_CLONE_FLAGS(cl_obd->cl_clone_info, SM_CLONE_FS);
- cl_obd->cl_clone_info->cl_clone_info->clone_magic =
- cpu_to_le32(CLONE_INFO_MAGI);
- }
- RETURN(0);
-}
-
-int lustre_cleanup_clone_info(struct super_block *sb)
-{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
-
- ENTRY;
-
- if (sbi->ll_mdc_exp) {
- struct obd_device *obd = class_exp2obd(sbi->ll_mdc_exp);
- struct client_obd *cl_obd = &obd->u.cli;
-
- if (!cl_obd->cl_clone_info)
- RETURN(0);
- CDEBUG(D_INFO, "clean clone info %p\n", cl_obd->cl_clone_info);
- OBD_FREE(cl_obd->cl_clone_info, sizeof(struct clonefs_info));
- }
-
- if (sbi->ll_osc_exp) {
- struct obd_device *obd = class_exp2obd(sbi->ll_osc_exp);
- struct client_obd *cl_obd = &obd->u.cli;
-
- if (!cl_obd->cl_clone_info)
- RETURN(0);
- CDEBUG(D_INFO, "clean clone info %p\n", cl_obd->cl_clone_info);
- OBD_FREE(cl_obd->cl_clone_info, sizeof(struct clonefs_info));
- }
- RETURN(0);
-}
-#endif
-
int lustre_common_fill_super(struct super_block *sb, char *mdc, char *osc)
{
}
err = lustre_common_fill_super(sb, mdc, osc);
-#if CONFIG_SNAPFS
- if (clone_opts) {
- int clone_index = 0;
- char *endp;
-
- /*set clone info to the super block*/
- clone_index = simple_strtoul(clone_opts, &endp, 0);
- err = lustre_set_clone_info(sb, clone_index);
- }
-#endif
out:
if (err)
lustre_free_sbi(sb);
if (err)
GOTO(out_free, err);
-
-#if CONFIG_SNAPFS
- if (lmd->lmd_clone_index) {
- err = lustre_set_clone_info(sb, lmd->lmd_clone_index);
- }
-
- if (err)
- GOTO(out_free, err);
-#endif
out_dev:
if (mdc)
}
OBD_FREE(sbi->ll_lmd, sizeof(*sbi->ll_lmd));
}
-#if CONFIG_SNAPFS
- lustre_cleanup_clone_info(sb);
-#endif
lustre_free_sbi(sb);
goto out_dev;
force_umount = obd->obd_no_recov;
obd = NULL;
-#if CONFIG_SNAPFS
- lustre_cleanup_clone_info(sb);
-#endif
-
lustre_common_put_super(sb);
if (sbi->ll_lmd != NULL) {
char * cln_prof;
sb->s_op = cache_sops(smb);
return;
}
+struct smfs_hook_ops *smfs_alloc_hook_ops(char *name, smfs_hook_func pre_hook,
+ smfs_hook_func post_hook)
+{
+ struct smfs_hook_ops *smfs_hops = NULL;
+
+ ENTRY;
+ OBD_ALLOC(smfs_hops, sizeof(struct smfs_hook_ops));
+
+ if (!smfs_hops)
+ RETURN(NULL);
+
+ OBD_ALLOC(smfs_hops->smh_name, strlen(name) + 1);
+
+ if (!smfs_hops->smh_name) {
+ OBD_FREE(smfs_hops, sizeof(struct smfs_hook_ops));
+ RETURN(NULL);
+ }
+
+ memcpy(smfs_hops->smh_name, name, strlen(name));
+
+ smfs_hops->smh_post_op = post_hook;
+ smfs_hops->smh_pre_op = pre_hook;
+
+ RETURN(smfs_hops);
+}
+
+void smfs_free_hook_ops(struct smfs_hook_ops *hops)
+{
+ if (hops) {
+ if (hops->smh_name){
+ OBD_FREE(hops->smh_name, strlen(hops->smh_name) + 1);
+ }
+ OBD_FREE(hops, sizeof(struct smfs_hook_ops));
+ }
+}
+
+int smfs_register_hook_ops(struct super_block *sb,
+ 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_for_each(p, hlist) {
+ struct smfs_hook_ops *found;
+ found = list_entry(p, struct smfs_hook_ops, smh_list);
+ if (!strcmp(found->smh_name, smh_ops->smh_name)) {
+ CWARN("hook ops %s list reregister\n", smh_ops->smh_name);
+ RETURN(0);
+ }
+ }
+ 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_super_info *smb = S2SMI(sb);
+ struct list_head *hlist = &smb->smsi_hook_list;
+ struct list_head *p;
+ ENTRY;
+
+ list_for_each(p, hlist) {
+ struct smfs_hook_ops *found;
+
+ found = list_entry(p, typeof(*found), smh_list);
+ if (!memcmp(found->smh_name, name, strlen(name))) {
+ list_del(p);
+ RETURN(found);
+ }
+ }
+ RETURN(NULL);
+}
+
static struct cache_purge_queue smfs_cpq;
static struct cache_purge_queue *cpq = &smfs_cpq;
+#define CACHE_HOOK "cache_hook"
+int cache_space_pre_hook(struct inode *inode, struct dentry *dentry,
+ void *data1, void *data2, int op, void *handle)
+{
+ int rc = 0;
+ ENTRY;
+
+ if (smfs_cache_hook(inode)) {
+ if (!handle) {
+ handle = smfs_trans_start(inode, KML_CACHE_NOOP, NULL);
+ if (IS_ERR(handle)) {
+ RETURN(PTR_ERR(handle));
+ }
+ }
+ cache_space_pre(inode, op);
+ }
+ RETURN(rc);
+}
+
+int cache_space_post_hook(struct inode *inode, struct dentry *dentry,
+ void *data1, void *data2, int op, void *handle)
+{
+ int rc = 0;
+ ENTRY;
+ if (smfs_cache_hook(inode)) {
+ struct inode *new_inode = (struct inode*)data1;
+ struct dentry *new_dentry = (struct dentry*)data2;
+ LASSERT(handle != NULL);
+ rc = cache_space_post(op, handle, inode, dentry, new_inode,
+ new_dentry);
+ }
+ RETURN(rc);
+}
+
int cache_space_hook_init(struct super_block *sb)
{
struct smfs_super_info *smfs_info = S2SMI(sb);
+ struct smfs_hook_ops *cache_hops;
+ int rc = 0;
+ ENTRY;
+ cache_hops = smfs_alloc_hook_ops(CACHE_HOOK, cache_space_pre_hook,
+ cache_space_post_hook);
+ if (!cache_hops) {
+ RETURN(-ENOMEM);
+ }
+ rc = smfs_register_hook_ops(sb, cache_hops);
+ if (rc) {
+ smfs_free_hook_ops(cache_hops);
+ RETURN(rc);
+ }
SMFS_SET_CACHE_HOOK(smfs_info);
- return 0;
+
+ RETURN(0);
}
+
int cache_space_hook_exit(struct super_block *sb)
{
struct smfs_super_info *smfs_info = S2SMI(sb);
+ struct smfs_hook_ops *cache_hops;
+
+ cache_hops = smfs_unregister_hook_ops(sb, CACHE_HOOK);
+ smfs_free_hook_ops(cache_hops);
SMFS_CLEAN_CACHE_HOOK(smfs_info);
return 0;
typedef int (*cache_hook_op)(void *handle, struct inode *old_dir,
struct dentry *old_dentry, struct inode *new_dir,
struct dentry *new_dentry);
-static cache_hook_op cache_space_hook_ops[CACHE_HOOK_MAX + 1] = {
- [CACHE_HOOK_CREATE] cache_space_hook_create,
- [CACHE_HOOK_LOOKUP] cache_space_hook_lookup,
- [CACHE_HOOK_LINK] cache_space_hook_link,
- [CACHE_HOOK_UNLINK] cache_space_hook_unlink,
- [CACHE_HOOK_SYMLINK] cache_space_hook_create,
- [CACHE_HOOK_MKDIR] cache_space_hook_mkdir,
- [CACHE_HOOK_RMDIR] cache_space_hook_rmdir,
- [CACHE_HOOK_MKNOD] cache_space_hook_create,
- [CACHE_HOOK_RENAME] cache_space_hook_rename,
+
+static cache_hook_op cache_space_hook_ops[HOOK_MAX + 1] = {
+ [HOOK_CREATE] cache_space_hook_create,
+ [HOOK_LOOKUP] cache_space_hook_lookup,
+ [HOOK_LINK] cache_space_hook_link,
+ [HOOK_UNLINK] cache_space_hook_unlink,
+ [HOOK_SYMLINK] cache_space_hook_create,
+ [HOOK_MKDIR] cache_space_hook_mkdir,
+ [HOOK_RMDIR] cache_space_hook_rmdir,
+ [HOOK_MKNOD] cache_space_hook_create,
+ [HOOK_RENAME] cache_space_hook_rename,
+ [HOOK_SETATTR] NULL,
+ [HOOK_WRITE] NULL,
};
int cache_space_post(int op, void *handle, struct inode *old_dir,
struct dentry *old_dentry, struct inode *new_dir,
struct dentry *new_dentry)
{
- int rc;
+ int rc = 0;
ENTRY;
- LASSERT(op <= CACHE_HOOK_MAX && cache_space_hook_ops[op] != NULL);
+ LASSERT(op <= HOOK_MAX + 1);
- rc = cache_space_hook_ops[op](handle, old_dir, old_dentry,
- new_dir, new_dentry);
+ if (cache_space_hook_ops[op])
+ rc = cache_space_hook_ops[op](handle, old_dir, old_dentry,
+ new_dir, new_dentry);
RETURN(rc);
}
handle = smfs_trans_start(dir, FSFILT_OP_CREATE, NULL);
if (IS_ERR(handle))
RETURN(-ENOSPC);
-
- SMFS_CACHE_HOOK_PRE(CACHE_HOOK_CREATE, handle, dir, rc);
-
+
+ lock_kernel();
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, PRE_HOOK, rc,
+ exit);
cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
- lock_kernel();
if (!cache_dentry || !cache_parent)
GOTO(exit, rc = -ENOMEM);
-
-
- SMFS_PRE_COW(dir, dentry, NULL, NULL, REINT_CREATE, "create", rc, exit);
-
+
pre_smfs_inode(dir, cache_dir);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
if (cache_dir && cache_dir->i_op->create)
d_instantiate(dentry, inode);
sm_set_inode_ops(cache_dentry->d_inode, inode);
post_smfs_inode(dir, cache_dir);
-
- /*Do KML post hook*/
-
- SMFS_KML_POST(dir, dentry, NULL, NULL, REINT_CREATE,
- "create", rc, exit);
- SMFS_CACHE_HOOK_POST(CACHE_HOOK_CREATE, handle, dir, dentry,
- NULL, NULL, rc, exit);
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, POST_HOOK, rc,
+ exit);
exit:
unlock_kernel();
post_smfs_dentry(cache_dentry);
if (!(cache_dir = I2CI(dir)))
RETURN(ERR_PTR(-ENOENT));
- SMFS_CACHE_HOOK_PRE(CACHE_HOOK_LOOKUP, handle, dir, rc2);
-
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, PRE_HOOK, rc2,
+ exit);
if (rc2)
RETURN(ERR_PTR(rc2));
if (!cache_dir && cache_dir->i_op->lookup)
GOTO(exit, rc = ERR_PTR(-ENOENT));
- SMFS_PRE_COW(dir, dentry, NULL, NULL, SNAP_LOOKUP, "lookup", rc2, exit);
-
/* perform lookup in backing fs. */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
rc = cache_dir->i_op->lookup(cache_dir, cache_dentry);
d_add(dentry, inode);
rc = NULL;
- SMFS_CACHE_HOOK_POST(CACHE_HOOK_LOOKUP, handle, dir, dentry,
- NULL, NULL, rc2, exit);
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, POST_HOOK, rc2,
+ exit);
exit:
if (rc2)
rc = ERR_PTR(rc2);
handle = smfs_trans_start(dir, FSFILT_OP_LINK, NULL);
if (IS_ERR(handle))
RETURN(-ENOSPC);
-
- SMFS_CACHE_HOOK_PRE(CACHE_HOOK_LINK, handle, dir, rc);
lock_kernel();
-
- SMFS_PRE_COW(dir, old_dentry, NULL, NULL, REINT_LINK, "link", rc, exit);
+ SMFS_HOOK(dir, old_dentry, NULL, NULL, HOOK_LINK, handle, PRE_HOOK, rc,
+ exit);
cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
d_instantiate(dentry, inode);
post_smfs_inode(dir, cache_dir);
- SMFS_KML_POST(dir, old_dentry, dentry, NULL,
- REINT_LINK, "link", rc, exit);
-
- SMFS_CACHE_HOOK_POST(CACHE_HOOK_LINK, handle,
- dir, old_dentry, NULL, NULL, rc, exit);
+ SMFS_HOOK(dir, old_dentry, dentry, NULL, HOOK_LINK, handle, POST_HOOK,
+ rc, exit);
+
exit:
unlock_kernel();
post_smfs_dentry(cache_dentry);
if (IS_ERR(handle))
RETURN(-ENOSPC);
- SMFS_CACHE_HOOK_PRE(CACHE_HOOK_UNLINK, handle, dir, rc);
-
- SMFS_PRE_COW(dir, dentry, NULL, NULL, REINT_UNLINK, "unlink", rc, exit);
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_UNLINK, handle, PRE_HOOK, rc,
+ exit);
cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
post_smfs_inode(dir, cache_dir);
unlock_kernel();
- SMFS_KML_POST(dir, dentry, &mode, NULL, REINT_UNLINK,
- "unlink", rc, exit);
-
- SMFS_CACHE_HOOK_POST(CACHE_HOOK_UNLINK, handle, dir, dentry,
- NULL, NULL, rc, exit);
+
+ SMFS_HOOK(dir, dentry, &mode, NULL, HOOK_UNLINK, handle, POST_HOOK,
+ rc, exit);
exit:
post_smfs_dentry(cache_dentry);
post_smfs_dentry(cache_parent);
if (!cache_dir)
RETURN(-ENOENT);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
-
- if (!cache_parent || !cache_dentry)
- GOTO(exit, rc = -ENOMEM);
-
handle = smfs_trans_start(dir, FSFILT_OP_SYMLINK, NULL);
if (IS_ERR(handle))
RETURN(-ENOSPC);
+
+ lock_kernel();
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_SYMLINK, handle, PRE_HOOK, rc,
+ exit);
- SMFS_CACHE_HOOK_PRE(CACHE_HOOK_SYMLINK, handle, dir, rc);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
- SMFS_PRE_COW(dir, dentry, NULL, NULL, REINT_CREATE, "symlink", rc,
- exit);
-
+ if (!cache_parent || !cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
pre_smfs_inode(dir, cache_dir);
- lock_kernel();
if (cache_dir->i_op->symlink)
rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
rc = -ENOENT;
tgt_len = strlen(symname) + 1;
- SMFS_KML_POST(dir, dentry, (char*)symname, &tgt_len, REINT_CREATE,
- "symlink", rc, exit);
-
- SMFS_CACHE_HOOK_POST(CACHE_HOOK_SYMLINK, handle, dir, dentry,
- NULL, NULL, rc, exit);
+
+ SMFS_HOOK(dir, dentry, (char *)symname, &tgt_len, HOOK_SYMLINK, handle,
+ POST_HOOK, rc, exit);
exit:
unlock_kernel();
post_smfs_dentry(cache_dentry);
if (IS_ERR(handle))
RETURN(-ENOSPC);
- SMFS_CACHE_HOOK_PRE(CACHE_HOOK_MKDIR, handle, dir, rc);
-
- SMFS_PRE_COW(dir, dentry, NULL, NULL, REINT_CREATE, "mkdir", rc,
- exit);
+ lock_kernel();
+
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, PRE_HOOK, rc,
+ exit);
+
cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
- lock_kernel();
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
d_instantiate(dentry, inode);
post_smfs_inode(dir, cache_dir);
- SMFS_KML_POST(dir, dentry, NULL, NULL,
- REINT_CREATE, "mkdir", rc, exit);
-
- SMFS_CACHE_HOOK_POST(CACHE_HOOK_MKDIR, handle,
- dir, dentry, NULL, NULL, rc, exit);
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, POST_HOOK, rc,
+ exit);
exit:
unlock_kernel();
post_smfs_dentry(cache_dentry);
RETURN(-ENOSPC);
}
- SMFS_CACHE_HOOK_PRE(CACHE_HOOK_RMDIR, handle, dir, rc);
+ lock_kernel();
- SMFS_PRE_COW(dir, dentry, NULL, NULL, REINT_UNLINK, "rmdir", rc, exit);
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_RMDIR, handle, PRE_HOOK, rc,
+ exit);
cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
- lock_kernel();
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
unlock_kernel();
- SMFS_KML_POST(dir, dentry, &mode, NULL,
- REINT_UNLINK, "rmdir", rc, exit);
-
- SMFS_CACHE_HOOK_POST(CACHE_HOOK_RMDIR, handle, dir, dentry,
- NULL, NULL, rc, exit);
+ SMFS_HOOK(dir, dentry, &mode, NULL, HOOK_RMDIR, handle, POST_HOOK,
+ rc, exit);
exit:
post_smfs_dentry(cache_dentry);
post_smfs_dentry(cache_parent);
CERROR("smfs_do_mkdir: no space for transaction\n");
RETURN(-ENOSPC);
}
- SMFS_CACHE_HOOK_PRE(CACHE_HOOK_MKNOD, handle, dir, rc);
- SMFS_PRE_COW(dir, dentry, NULL, NULL, REINT_CREATE, "mknod", rc, exit);
+ lock_kernel();
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, PRE_HOOK, rc,
+ exit);
+
cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
- lock_kernel();
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
pre_smfs_inode(dir, cache_dir);
pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
- SMFS_KML_POST(dir, dentry, NULL, NULL,
- REINT_CREATE, "mknod", rc, exit);
-
- SMFS_CACHE_HOOK_POST(CACHE_HOOK_MKNOD, handle, dir,
- dentry, NULL, NULL, rc, exit);
+ SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, POST_HOOK, rc,
+ exit);
+
exit:
unlock_kernel();
post_smfs_dentry(cache_dentry);
}
lock_kernel();
- SMFS_PRE_COW(old_dir, old_dentry, new_dir, new_dentry, REINT_RENAME,
- "rename", rc, exit);
- SMFS_CACHE_HOOK_PRE(CACHE_HOOK_RENAME, handle, old_dir, rc);
-
+
+ SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle,
+ PRE_HOOK, rc, exit);
+
cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry);
cache_old_dentry = pre_smfs_dentry(cache_old_parent, cache_old_inode,
old_dentry);
post_smfs_inode(old_dir, cache_old_dir);
post_smfs_inode(new_dir, cache_new_dir);
- SMFS_KML_POST(old_dir, old_dentry, new_dir,
- new_dentry, REINT_RENAME, "rename", rc, exit);
+ SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle,
+ POST_HOOK, rc, exit);
+
if (new_dentry->d_inode)
post_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode);
-
- SMFS_CACHE_HOOK_POST(CACHE_HOOK_RENAME, handle, old_dir, old_dentry,
- new_dir, new_dentry, rc, exit);
exit:
unlock_kernel();
post_smfs_dentry(cache_old_dentry);
else {
tmp_ppos = *ppos;
}
-
- SMFS_PRE_COW(filp->f_dentry->d_inode, filp->f_dentry, &count, &tmp_ppos,
- REINT_WRITE, "write", rc, exit);
+ SMFS_HOOK(filp->f_dentry->d_inode, filp->f_dentry, &count, &tmp_ppos,
+ HOOK_WRITE, NULL, PRE_HOOK, rc, exit);
if (ppos != &(filp->f_pos)) {
cache_ppos = &tmp_ppos;
count, cache_ppos);
}
- SMFS_KML_POST(filp->f_dentry->d_inode, filp->f_dentry,
- ppos, &count, REINT_WRITE, "write", rc, exit);
+ SMFS_HOOK(filp->f_dentry->d_inode, filp->f_dentry, ppos, &count,
+ HOOK_WRITE, NULL, POST_HOOK, rc, exit);
exit:
post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
*ppos = *cache_ppos;
if (cache_inode->i_op->setattr)
rc = cache_inode->i_op->setattr(cache_dentry, attr);
- SMFS_KML_POST(dentry->d_inode, dentry, attr, NULL,
- REINT_SETATTR, "setattr", rc, exit);
+ SMFS_HOOK(dentry->d_inode, dentry, attr, NULL, HOOK_SETATTR, NULL,
+ POST_HOOK, rc, exit);
+
exit:
post_smfs_inode(dentry->d_inode, cache_inode);
post_smfs_dentry(cache_dentry);
}
typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2);
-
-static post_kml_rec smfs_kml_post[REINT_MAX + 1] = {
- [REINT_SETATTR] smfs_post_rec_setattr,
- [REINT_CREATE] smfs_post_rec_create,
- [REINT_LINK] smfs_post_rec_link,
- [REINT_UNLINK] smfs_post_rec_unlink,
- [REINT_RENAME] smfs_post_rec_rename,
- [REINT_WRITE] smfs_post_rec_write,
+ void *data1, void *data2);
+
+static post_kml_rec smfs_kml_post[HOOK_MAX + 1] = {
+ [HOOK_CREATE] smfs_post_rec_create,
+ [HOOK_LOOKUP] NULL,
+ [HOOK_LINK] smfs_post_rec_link,
+ [HOOK_UNLINK] smfs_post_rec_unlink,
+ [HOOK_SYMLINK] smfs_post_rec_create,
+ [HOOK_MKDIR] smfs_post_rec_create,
+ [HOOK_RMDIR] smfs_post_rec_unlink,
+ [HOOK_MKNOD] smfs_post_rec_create,
+ [HOOK_RENAME] smfs_post_rec_rename,
+ [HOOK_SETATTR] smfs_post_rec_setattr,
+ [HOOK_WRITE] smfs_post_rec_write,
};
int smfs_post_kml_rec(struct inode *dir, struct dentry *dst_dentry,
void *data1, void *data2, int op)
{
- return smfs_kml_post[op](dir, dst_dentry, data1, data2);
+ if (smfs_kml_post[op]) {
+ return smfs_kml_post[op](dir, dst_dentry, data1, data2);
+ }
+ return 0;
}
return smsi->smsi_pack_rec[index];
}
+static int smfs_rec_post_hook(struct inode *inode, struct dentry *dentry,
+ void *data1, void *data2, int op, void *handle)
+{
+ int rc = 0;
+ ENTRY;
+
+ if (smfs_do_rec(inode))
+ rc = smfs_post_kml_rec(inode, dentry, data1, data2, op);
+
+ RETURN(rc);
+}
+#define KML_HOOK "kml_hook"
int smfs_rec_init(struct super_block *sb)
{
struct smfs_super_info *smfs_info = S2SMI(sb);
+ struct smfs_hook_ops *rec_hops = NULL;
int rc = 0;
SMFS_SET_REC(smfs_info);
ost_rec_pack_init(sb);
mds_rec_pack_init(sb);
+ rec_hops = smfs_alloc_hook_ops(KML_HOOK, NULL, smfs_rec_post_hook);
+ if (!rec_hops) {
+ RETURN(-ENOMEM);
+ }
+
+ rc = smfs_register_hook_ops(sb, rec_hops);
+
+ if (rc && rec_hops) {
+ smfs_unregister_hook_ops(sb, rec_hops->smh_name);
+ smfs_free_hook_ops(rec_hops);
+ }
RETURN(rc);
}
int smfs_rec_cleanup(struct super_block *sb)
{
+ struct smfs_hook_ops *rec_hops;
int rc = 0;
+ rec_hops = smfs_unregister_hook_ops(sb, KML_HOOK);
+ smfs_free_hook_ops(rec_hops);
SMFS_CLEAN_REC(S2SMI(sb));
+
RETURN(rc);
}
snap_info->sn_cowed_dentry = dentry;
RETURN(rc);
}
+#define DOT_SNAP_NAME ".snap"
+static int smfs_init_dotinfo(struct super_block *sb)
+{
+ struct snap_info *snap_info = S2SNAPI(sb);
+ struct snap_dot_info *dot_info = NULL;
+ int rc = 0;
+ ENTRY;
+
+ if (snap_info->sn_dot_info)
+ RETURN(-EEXIST);
+
+ OBD_ALLOC(snap_info->sn_dot_info, sizeof(struct snap_dot_info));
+
+ if (!snap_info->sn_dot_info)
+ RETURN(-ENOMEM);
+
+ dot_info = snap_info->sn_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));
+ RETURN(-ENOMEM);
+ }
+ memcpy(dot_info->dot_name, DOT_SNAP_NAME, strlen(DOT_SNAP_NAME));
+
+ dot_info->dot_name_len = strlen(DOT_SNAP_NAME);
+ dot_info->dot_snap_enable = 1;
+
+ 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;
+ 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);
+ }
+
+ OBD_FREE(dot_info, sizeof(struct snap_dot_info));
+
+ RETURN(rc);
+}
+
int smfs_start_cow(struct super_block *sb)
{
int rc = 0;
CERROR("can not init snaptable rc=%d\n", rc);
RETURN(rc);
}
+ /*init dot snap info*/
+ rc = smfs_init_dotinfo(sb);
+ if (rc) {
+ CERROR("can not init dot snap info rc=%d\n", rc);
+ RETURN(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*/
table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count);
OBD_FREE(snap_info->sntbl, table_size);
}
-
+ smfs_cleanup_dotinfo(sb);
+
RETURN(rc);
}
EXPORT_SYMBOL(smfs_stop_cow);
+#define COW_HOOK "cow_hook"
+static int smfs_cow_pre_hook(struct inode *inode, struct dentry *dentry,
+ void *data1, void *data2, int op, void *handle)
+{
+ int rc = 0;
+ ENTRY;
+
+ if (smfs_do_cow(inode)) {
+ rc = smfs_cow(inode, dentry, data1, data2, op);
+ }
+ RETURN(rc);
+}
int smfs_cow_init(struct super_block *sb)
{
struct smfs_super_info *smfs_info = S2SMI(sb);
+ struct smfs_hook_ops *cow_hops = NULL;
int rc = 0;
+ ENTRY;
+
SMFS_SET_COW(smfs_info);
+ cow_hops = smfs_alloc_hook_ops(COW_HOOK, smfs_cow_pre_hook, NULL);
+ if (!cow_hops) {
+ RETURN(-ENOMEM);
+ }
+
+ rc = smfs_register_hook_ops(sb, 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)
- RETURN(-ENOMEM);
-
+ GOTO(exit, rc = -ENOMEM);
+exit:
+ if (rc && cow_hops) {
+ smfs_unregister_hook_ops(sb, cow_hops->smh_name);
+ smfs_free_hook_ops(cow_hops);
+ }
RETURN(rc);
}
int smfs_cow_cleanup(struct super_block *sb)
{
- struct snap_info *snap_info = S2SNAPI(sb);
-
+ struct snap_info *snap_info = S2SNAPI(sb);
+ struct smfs_hook_ops *cow_hops;
ENTRY;
+
+ cow_hops = smfs_unregister_hook_ops(sb, COW_HOOK);
+ smfs_free_hook_ops(cow_hops);
+
SMFS_CLEAN_COW(S2SMI(sb));
if (snap_info)
OBD_FREE(snap_info, sizeof(*snap_info));
ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen,
dparent->d_inode, del);
if(ind && IS_ERR(ind)) {
- CERROR("Create ind inode %lu index %d gen %d del %d\n rc%d\n",
+ CERROR("Create ind inode %lu index %d gen %d del %d\n rc%u\n",
inode->i_ino, snap.sn_index, snap.sn_gen, del,
PTR_ERR(ind));
RETURN(PTR_ERR(ind));
typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry,
void *new_dir, void *new_dentry);
-
-static cow_funcs smfs_cow_funcs[REINT_MAX + 2] = {
- [REINT_SETATTR] smfs_cow_setattr,
- [REINT_CREATE] smfs_cow_create,
- [REINT_LINK] smfs_cow_link,
- [REINT_UNLINK] smfs_cow_unlink,
- [REINT_RENAME] smfs_cow_rename,
- [REINT_WRITE] smfs_cow_write,
- [SNAP_LOOKUP] smfs_cow_lookup,
+static cow_funcs smfs_cow_funcs[HOOK_MAX + 1] = {
+ [HOOK_CREATE] smfs_cow_create,
+ [HOOK_LOOKUP] smfs_cow_lookup,
+ [HOOK_LINK] smfs_cow_link,
+ [HOOK_UNLINK] smfs_cow_unlink,
+ [HOOK_SYMLINK] smfs_cow_create,
+ [HOOK_MKDIR] smfs_cow_create,
+ [HOOK_RMDIR] smfs_cow_unlink,
+ [HOOK_MKNOD] smfs_cow_create,
+ [HOOK_RENAME] smfs_cow_rename,
+ [HOOK_SETATTR] smfs_cow_setattr,
+ [HOOK_WRITE] smfs_cow_write,
};
int smfs_cow(struct inode *dir, struct dentry *dentry, void *new_dir,
void *new_dentry, int op)
{
- return smfs_cow_funcs[op](dir, dentry, new_dir, new_dentry);
+ if (smfs_cow_funcs[op]) {
+ return smfs_cow_funcs[op](dir, dentry, new_dir, new_dentry);
+ }
+ return 0;
}
#define MYPATHLEN(buffer, path) ((buffer) + PAGE_SIZE - (path))
-#define SMFS_KML_POST(dir, dentry, data1, data2, op, name, rc, label) \
-do { \
- if (smfs_do_rec(dir) && !rc) { \
- CDEBUG(D_INODE, "Do %s kml post for dir %lu \n", \
- name, dir->i_ino); \
- rc = smfs_post_kml_rec(dir, dentry, data1, data2, op); \
- if (rc) \
- GOTO(label, rc); \
- } \
-} while(0)
#define PACK_KML_REC_INIT(buffer, op_code) \
do{ \
buffer += sizeof(opcode); \
} while (0)
+
extern int init_smfs_proc_sys(void);
/*options.c*/
extern int get_opt(struct option **option, char **pos);
{
return &smb->sm_ops->sm_journal_ops;
}
+
+struct smfs_hook_ops *smfs_alloc_hook_ops(char *name,
+ smfs_hook_func pre_hook,
+ smfs_hook_func post_hook);
+
+void smfs_free_hook_ops(struct smfs_hook_ops *hops);
+int smfs_register_hook_ops(struct super_block *sb,
+ struct smfs_hook_ops *smh_ops);
+
+struct smfs_hook_ops *smfs_unregister_hook_ops(struct super_block *sb,
+ char *name);
/*super.c*/
extern int init_smfs(void);
extern int cleanup_smfs(void);
rc = 0;
RETURN(rc);
}
+#define HOOK_CREATE 1
+#define HOOK_LOOKUP 2
+#define HOOK_LINK 3
+#define HOOK_UNLINK 4
+#define HOOK_SYMLINK 5
+#define HOOK_MKDIR 6
+#define HOOK_RMDIR 7
+#define HOOK_MKNOD 8
+#define HOOK_RENAME 9
+#define HOOK_SETATTR 10
+#define HOOK_WRITE 11
+#define HOOK_MAX 11
-#define CACHE_HOOK_CREATE 1
-#define CACHE_HOOK_LOOKUP 2
-#define CACHE_HOOK_LINK 3
-#define CACHE_HOOK_UNLINK 4
-#define CACHE_HOOK_SYMLINK 5
-#define CACHE_HOOK_MKDIR 6
-#define CACHE_HOOK_RMDIR 7
-#define CACHE_HOOK_MKNOD 8
-#define CACHE_HOOK_RENAME 9
-
-#define CACHE_HOOK_MAX 9
-
-#define SMFS_CACHE_HOOK_PRE(op, handle, dir, rc) \
-{ \
- while (smfs_cache_hook(dir)) { \
- if (!handle) { \
- handle = smfs_trans_start(dir, KML_CACHE_NOOP, NULL); \
- if (IS_ERR(handle)) { \
- rc = -ENOSPC; \
- break; \
- } \
- } \
- CDEBUG(D_INODE, "cache hook pre: op %d, dir %lu\n", \
- op, dir->i_ino); \
- cache_space_pre(dir, op); \
- break; \
- } \
-}
-
-#define SMFS_CACHE_HOOK_POST(op, handle, old_dir, old_dentry, \
- new_dir, new_dentry, rc, label) \
-{ \
- if (!rc && smfs_cache_hook(old_dir)) { \
- LASSERT(handle != NULL); \
- CDEBUG(D_INODE, "cache hook post: op %d, dir %lu\n", \
- op, old_dir->i_ino); \
- rc = cache_space_post(op, handle, old_dir, old_dentry, \
- new_dir, new_dentry); \
- if (rc) \
- GOTO(label, rc); \
- } \
-}
-#if CONFIG_SNAPFS
-/*snap macros*/
-#define SMFS_PRE_COW(dir, dentry, new_dir, new_dentry, op, name, rc, label) \
+#define PRE_HOOK 0
+#define POST_HOOK 1
+#define SMFS_HOOK(inode, dentry, data1, data2, op, handle, flag, rc, label) \
do { \
- if (smfs_do_cow(dir) && !rc) { \
- CDEBUG(D_INODE, "Do %s snap post for dir %lu \n", \
- name, dir->i_ino); \
- rc = smfs_cow(dir, dentry, new_dir, new_dentry, op); \
- if (op == SNAP_LOOKUP && rc == 1) \
- GOTO(label, rc = 0); \
- else if (rc) \
- GOTO(label, rc); \
+ LASSERT(inode->i_sb); \
+ if (!rc) { \
+ struct smfs_super_info *smb = S2SMI(inode->i_sb); \
+ struct list_head *hlist = &smb->smsi_hook_list; \
+ struct list_head *p; \
+ \
+ list_for_each(p, hlist) { \
+ struct smfs_hook_ops *hops; \
+ \
+ hops = list_entry(p, typeof(*hops), smh_list); \
+ if (flag == PRE_HOOK && hops->smh_pre_op) \
+ rc = hops->smh_pre_op(inode, dentry, data1, \
+ data2, op, handle); \
+ else if (flag == POST_HOOK && hops->smh_post_op) \
+ rc = hops->smh_post_op(inode, dentry, data1, \
+ data2, op, handle); \
+ if (rc) \
+ break; \
+ } \
} \
-} while(0)
+ if (rc) \
+ GOTO(label, rc); \
+} 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, int flags);
#else
#define SMFS_PRE_COW(dir, dentry, new_dir, new_dentry, op, name, rc, label)
#endif
-
#endif /*__KERNEL*/
#endif /* __LINUX_SMFS_H */
return 0;
}
+static int smfs_init_hook_ops(struct super_block *sb)
+{
+ 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)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+ struct list_head *hlist = &smb->smsi_hook_list;
+ ENTRY;
+
+ while (!list_empty(hlist)) {
+ struct smfs_hook_ops *smfs_hops;
+
+ smfs_hops = list_entry(hlist->next, struct smfs_hook_ops,
+ smh_list);
+ CERROR("Unregister %s hook ops\n", smfs_hops->smh_name);
+
+ smfs_unregister_hook_ops(sb, smfs_hops->smh_name);
+ smfs_free_hook_ops(smfs_hops);
+ }
+ EXIT;
+ return;
+}
+
void smfs_put_super(struct super_block *sb)
{
if (SMFS_CACHE_HOOK(S2SMI(sb)))
#if CONFIG_SNAPFS
if (SMFS_DO_COW(S2SMI(sb)))
smfs_cow_cleanup(sb);
-#endif
+#endif
+ smfs_cleanup_hook_ops(sb);
+
if (sb)
sm_umount_cache(sb);
return;
}
-
static int smfs_fill_super(struct super_block *sb,
void *data, int silent)
{
CERROR("Can not mount %s as %s\n", devstr, typestr);
GOTO(out_err, 0);
}
-
+
+ err = smfs_init_hook_ops(sb);
+ 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);