diff --git a/lustre/cobd/cache_obd.c b/lustre/cobd/cache_obd.c index fdebff1c8873522d33b56d51b247294fe5504c3a..a32643012d5e0b87e518fec51638a6a6af2c184a 100644 --- a/lustre/cobd/cache_obd.c +++ b/lustre/cobd/cache_obd.c @@ -66,7 +66,8 @@ static int cobd_setup(struct obd_device *obd, obd_count len, void *buf) { struct lustre_cfg *lcfg = (struct lustre_cfg *)buf; struct cache_obd *cobd = &obd->u.cobd; - struct lustre_handle real_conn = {0,}, cache_conn = {0,}; +// struct lustre_handle real_conn = {0,}, cache_conn = {0,}; + struct lustre_handle cache_conn = {0,}; struct obd_device *real; struct obd_device *cache; int rc; @@ -109,13 +110,14 @@ static int cobd_setup(struct obd_device *obd, obd_count len, void *buf) memcpy(cobd->cobd_cache_name, lcfg->lcfg_inlbuf2, strlen(lcfg->lcfg_inlbuf2)); +#if 0 /* don't bother checking attached/setup; * obd_connect() should, and it can change underneath us */ rc = connect_to_obd(cobd->cobd_real_name, &real_conn); if (rc != 0) GOTO(exit, rc); cobd->cobd_real_exp = class_conn2export(&real_conn); - +#endif rc = connect_to_obd(cobd->cobd_cache_name, &cache_conn); if (rc != 0) { obd_disconnect(cobd->cobd_cache_exp, 0); @@ -123,6 +125,7 @@ static int cobd_setup(struct obd_device *obd, obd_count len, void *buf) } cobd->cobd_cache_exp = class_conn2export(&cache_conn); + cobd->cache_on = 1; if (!strcmp(real->obd_type->typ_name, LUSTRE_MDC_NAME)) { /* set mds_num for lustre */ int mds_num; @@ -143,7 +146,6 @@ exit: OBD_FREE(cobd->cobd_real_name, strlen(cobd->cobd_real_name) + 1); } - cobd->cache_on = 1; RETURN(rc); } @@ -155,9 +157,12 @@ static int cobd_cleanup(struct obd_device *obd, int flags) if (!list_empty(&obd->obd_exports)) return (-EBUSY); - OBD_FREE(cobd->cobd_cache_name, strlen(cobd->cobd_cache_name) + 1); - OBD_FREE(cobd->cobd_real_name, strlen(cobd->cobd_real_name) + 1); - + if (cobd->cobd_cache_name) + OBD_FREE(cobd->cobd_cache_name, + strlen(cobd->cobd_cache_name) + 1); + if (cobd->cobd_real_name) + OBD_FREE(cobd->cobd_real_name, + strlen(cobd->cobd_real_name) + 1); if (cobd->cache_on) { rc = obd_disconnect(cobd->cobd_cache_exp, flags); if (rc != 0) @@ -680,8 +685,7 @@ static int cobd_iocontrol(unsigned int cmd, struct obd_export *exp, int len, { struct obd_device *obd = class_exp2obd(exp); struct cache_obd *cobd = &obd->u.cobd; - struct obd_device *real_dev = class_exp2obd(cobd->cobd_real_exp); - struct obd_device *cache_dev = class_exp2obd(cobd->cobd_cache_exp); + struct obd_device *real_dev = NULL; struct obd_export *cobd_exp; int rc = 0; @@ -690,29 +694,40 @@ static int cobd_iocontrol(unsigned int cmd, struct obd_export *exp, int len, if (!cobd->cache_on) { struct lustre_handle cache_conn = {0,}; + rc = obd_disconnect(cobd->cobd_real_exp, 0); + if (rc != 0) + CERROR("error %d disconnecting real\n", rc); rc = connect_to_obd(cobd->cobd_cache_name, &cache_conn); if (rc != 0) RETURN(rc); cobd->cobd_cache_exp = class_conn2export(&cache_conn); + cobd->cache_on = 1; } break; case OBD_IOC_COBD_COFF: if (cobd->cache_on) { - /*Here disconnect for cancel unused ldlm resources, - *then do flush, otherwise, there will be some problems - *in flush cache - *is is right? FIXME later*/ + struct lustre_handle real_conn = {0,}; + struct obd_device *cache_dev = NULL; + int m_easize, m_cooksize; + + cache_dev = class_exp2obd(cobd->cobd_cache_exp); + m_easize = cache_dev->u.cli.cl_max_mds_easize; + m_cooksize = cache_dev->u.cli.cl_max_mds_cookiesize; rc = obd_disconnect(cobd->cobd_cache_exp, 0); if (rc != 0) CERROR("error %d disconnecting real\n", rc); - cobd->cache_on = 0; /*FIXME, should read from real_dev*/ - real_dev->u.cli.cl_max_mds_easize = - cache_dev->u.cli.cl_max_mds_easize; - real_dev->u.cli.cl_max_mds_cookiesize = - cache_dev->u.cli.cl_max_mds_cookiesize; + + rc = connect_to_obd(cobd->cobd_real_name, &real_conn); + if (rc != 0) + RETURN(rc); + cobd->cobd_real_exp = class_conn2export(&real_conn); + real_dev = class_exp2obd(cobd->cobd_real_exp); + real_dev->u.cli.cl_max_mds_easize = m_easize; + real_dev->u.cli.cl_max_mds_cookiesize = m_cooksize; + cobd->cache_on = 0; } break; case OBD_IOC_COBD_CFLUSH: diff --git a/lustre/include/linux/lustre_cfg.h b/lustre/include/linux/lustre_cfg.h index fcc9a564d9b2b3ba48d9d7260fa76476c8c89fc8..eb17e8dd2f5f4211ed3b04fd4dc5d6b7fffa5b62 100644 --- a/lustre/include/linux/lustre_cfg.h +++ b/lustre/include/linux/lustre_cfg.h @@ -277,6 +277,7 @@ struct lustre_mount_data { uint32_t lmd_nal; uint32_t lmd_server_ipaddr; uint32_t lmd_port; + uint32_t lmd_clone_index; char lmd_mds[64]; char lmd_profile[64]; }; diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index 588882627f19b03edfac090f6a17182b10a47af5..14cdee107177f08c6a18323d5d74f56135106a2f 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -870,6 +870,11 @@ struct ptlbd_rsp { extern void lustre_swab_ptlbd_rsp (struct ptlbd_rsp *r); +struct clonefs_info { + int clone_index; + int clone_flags; +}; +extern void lustre_swab_clonefs_info(struct clonefs_info *clone); /* * Opcodes for management/monitoring node. */ diff --git a/lustre/include/linux/lustre_snap.h b/lustre/include/linux/lustre_snap.h index cd8e9c64f445c07c1d070cce1017cbea5a22d5b5..77fd3693def42788045b25380d2d106d5706c231 100644 --- a/lustre/include/linux/lustre_snap.h +++ b/lustre/include/linux/lustre_snap.h @@ -146,6 +146,9 @@ struct snap_ea{ #define SNAPTABLE_INFO "snaptable" #define SNAP_GENERATION "snap_generation" + +#define SNAP_LOOKUP (REINT_MAX + 1) + struct snap { time_t sn_time; unsigned int sn_index; @@ -170,6 +173,13 @@ struct snap_info { 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) + + extern int smfs_add_snap_item(struct super_block *sb, char *name); extern int smfs_start_cow(struct super_block *sb); extern int smfs_stop_cow(struct super_block *sb); @@ -182,4 +192,5 @@ int smfs_cow(struct inode *dir, struct dentry *dentry, void *data1, void *data2, int op); int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1, void *data2); +struct inode* smfs_cow_get_ind(struct inode *inode, int index); #endif /*_LUSTRE_SNAP_H*/ diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index 3f1bd99843c8dbff78c7dbb5301d0948369cb8f3..e74997322eb5b8e1beda5b62885b683cbb644c67 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -280,7 +280,8 @@ struct client_obd { struct mdc_rpc_lock *cl_rpc_lock; struct mdc_rpc_lock *cl_setattr_lock; - struct osc_creator cl_oscc; + struct osc_creator cl_oscc; + void *cl_clone_info; }; /* Like a client, with some hangers-on. Keep mc_client_obd first so that we diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 2cca168841262d0d5206a943762a80885f26d999..03a413554e0e2510e5052935890c3bd598400136 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -198,7 +198,8 @@ extern struct super_operations lustre_super_operations; char *ll_read_opt(const char *opt, char *data); int ll_set_opt(const char *opt, char *data, int fl); -void ll_options(char *options, char **ost, char **mds, int *flags); +void ll_options(char *options, char **ost, char **mds, int *flags, + char **clone_ops); void ll_lli_init(struct ll_inode_info *lli); int ll_fill_super(struct super_block *sb, void *data, int silent); int lustre_fill_super(struct super_block *sb, void *data, int silent); diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 5aae834f46a55780351613215282ea01730fa854..170d3fde4013e34152fb88b6d8def5832ace8e08 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -32,6 +32,7 @@ #include <linux/lustre_ha.h> #include <linux/lustre_dlm.h> #include <linux/lprocfs_status.h> +#include <linux/lustre_snap.h> #include "llite_internal.h" kmem_cache_t *ll_file_data_slab; @@ -111,6 +112,70 @@ int lustre_init_ea_size(struct ll_sb_info *sbi) } 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_import *climp = class_exp2cliimp(sbi->ll_mdc_exp); + struct client_obd *cl_obd = &climp->imp_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); + } + + if (sbi->ll_osc_exp) { + struct obd_import *climp = class_exp2cliimp(sbi->ll_osc_exp); + struct client_obd *cl_obd = &climp->imp_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); + } + 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_import *climp = class_exp2cliimp(sbi->ll_mdc_exp); + struct client_obd *cl_obd = &climp->imp_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_import *climp = class_exp2cliimp(sbi->ll_osc_exp); + struct client_obd *cl_obd = &climp->imp_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) { @@ -330,7 +395,8 @@ int ll_set_opt(const char *opt, char *data, int fl) RETURN(fl); } -void ll_options(char *options, char **ost, char **mdc, int *flags) +void ll_options(char *options, char **ost, char **mdc, int *flags, + char **clone_opts) { char *this_char; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) @@ -355,12 +421,16 @@ void ll_options(char *options, char **ost, char **mdc, int *flags) continue; if (!*mdc && (*mdc = ll_read_opt("mdc", this_char))) continue; + if (!*clone_opts && (*clone_opts = ll_read_opt("clone", + this_char))) + continue; if (!(*flags & LL_SBI_NOLCK) && ((*flags) = (*flags) | ll_set_opt("nolock", this_char, LL_SBI_NOLCK))) continue; } + EXIT; } @@ -378,6 +448,7 @@ int ll_fill_super(struct super_block *sb, void *data, int silent) struct ll_sb_info *sbi; char *osc = NULL; char *mdc = NULL; + char *clone_opts = NULL; int err; ENTRY; @@ -388,7 +459,7 @@ int ll_fill_super(struct super_block *sb, void *data, int silent) RETURN(-ENOMEM); sbi->ll_flags |= LL_SBI_READAHEAD; - ll_options(data, &osc, &mdc, &sbi->ll_flags); + ll_options(data, &osc, &mdc, &sbi->ll_flags, &clone_opts); if (!osc) { CERROR("no osc\n"); @@ -401,6 +472,16 @@ int ll_fill_super(struct super_block *sb, void *data, int silent) } 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); @@ -409,6 +490,8 @@ out: OBD_FREE(mdc, strlen(mdc) + 1); if (osc) OBD_FREE(osc, strlen(osc) + 1); + if (clone_opts) + OBD_FREE(clone_opts, strlen(clone_opts) + 1); RETURN(err); } /* ll_read_super */ @@ -631,6 +714,15 @@ int lustre_fill_super(struct super_block *sb, void *data, int silent) 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(mdc, strlen(mdc) + 1); @@ -663,6 +755,9 @@ out_free: } 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; @@ -710,8 +805,11 @@ void lustre_put_super(struct super_block *sb) force_umount = obd->obd_no_recov; obd = NULL; - lustre_common_put_super(sb); +#if CONFIG_SNAPFS + lustre_cleanup_clone_info(sb); +#endif + lustre_common_put_super(sb); if (sbi->ll_lmd != NULL) { char * cln_prof; int len = strlen(sbi->ll_lmd->lmd_profile) + sizeof("-clean")+1; diff --git a/lustre/mdc/mdc_locks.c b/lustre/mdc/mdc_locks.c index f36f7f47becb6ff1d5ac2666596355bdeaa9fb56..c3bafd10facd25b66a8e50aecc84f8c4eee7d5d0 100644 --- a/lustre/mdc/mdc_locks.c +++ b/lustre/mdc/mdc_locks.c @@ -36,6 +36,7 @@ #include <linux/obd_class.h> #include <linux/lustre_mds.h> #include <linux/lustre_dlm.h> +#include <linux/lustre_snap.h> #include <linux/lprocfs_status.h> #include "mdc_internal.h" @@ -173,7 +174,20 @@ int mdc_change_cbdata(struct obd_export *exp, struct ll_fid *fid, return 0; } - +#if CONFIG_SNAPFS +int mdc_set_clone_info(struct obd_import *climp, struct lustre_msg *msg, + int offset) +{ + struct client_obd *cli_obd = &climp->imp_obd->u.cli; + struct clonefs_info *cl_info; + ENTRY; + + cl_info = (struct clonefs_info *)lustre_msg_buf(msg, offset, + sizeof (*cl_info)); + memcpy(cl_info, cli_obd->cl_clone_info, sizeof(*cl_info)); + RETURN(0); +} +#endif /* We always reserve enough space in the reply packet for a stripe MD, because * we don't know in advance the file type. */ @@ -244,9 +258,15 @@ int mdc_enqueue(struct obd_export *exp, if (it->it_op & IT_GETATTR) policy.l_inodebits.bits = MDS_INODELOCK_UPDATE; - +#if CONFIG_SNAPFS + size[4] = sizeof(struct clonefs_info); + req = ptlrpc_prep_req(class_exp2cliimp(exp), LDLM_ENQUEUE, 5, + size, NULL); +#else req = ptlrpc_prep_req(class_exp2cliimp(exp), LDLM_ENQUEUE, 4, size, NULL); + +#endif if (!req) RETURN(-ENOMEM); @@ -256,16 +276,28 @@ int mdc_enqueue(struct obd_export *exp, /* pack the intended request */ mdc_getattr_pack(req->rq_reqmsg, valid, 2, it->it_flags, data); +#if CONFIG_SNAPFS + mdc_set_clone_info(class_exp2cliimp(exp), req->rq_reqmsg, 4); +#endif /* get ready for the reply */ reply_buffers = 3; req->rq_replen = lustre_msg_size(3, repsize); } else if (it->it_op == IT_READDIR) { policy.l_inodebits.bits = MDS_INODELOCK_UPDATE; +#if CONFIG_SNAPFS + size[1] = sizeof(struct clonefs_info); + req = ptlrpc_prep_req(class_exp2cliimp(exp), LDLM_ENQUEUE, 2, + size, NULL); +#else req = ptlrpc_prep_req(class_exp2cliimp(exp), LDLM_ENQUEUE, 1, size, NULL); + +#endif if (!req) RETURN(-ENOMEM); - +#if CONFIG_SNAPFS + mdc_set_clone_info(class_exp2cliimp(exp), req->rq_reqmsg, 1); +#endif /* get ready for the reply */ reply_buffers = 1; req->rq_replen = lustre_msg_size(1, repsize); diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 45916168dac0a8baa5e249309667e155b1bd86e3..8e80be468709394f34a10b92e6d36a1433c9f7ac 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -51,6 +51,7 @@ #include <linux/obd_lov.h> #include <linux/lustre_mds.h> #include <linux/lustre_fsfilt.h> +#include <linux/lustre_snap.h> #include <linux/lprocfs_status.h> #include <linux/lustre_commit_confd.h> @@ -850,6 +851,7 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req, struct lustre_handle parent_lockh[2]; int namesize, update_mode; int rc = 0, cleanup_phase = 0, resent_req = 0; + struct clonefs_info *clone_info = NULL; char *name; ENTRY; @@ -870,6 +872,14 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req, CERROR("Can't unpack name\n"); GOTO(cleanup, rc = -EFAULT); } +#if CONFIG_SNAPFS + clone_info = lustre_swab_reqbuf(req, offset + 2, sizeof(*clone_info), + lustre_swab_clonefs_info); + if (clone_info) { + CDEBUG(D_INFO,"getattr name %s clone_info index %d \n", name, + clone_info->clone_index); + } +#endif namesize = req->rq_reqmsg->buflens[offset + 1]; LASSERT (offset == 0 || offset == 2); @@ -954,7 +964,7 @@ static int mds_getattr_name(int offset, struct ptlrpc_request *req, LCK_PR, MDS_INODELOCK_LOOKUP, &update_mode, name, namesize, child_lockh, &dchild, LCK_PR, - child_part); + child_part, clone_info); if (rc) GOTO(cleanup, rc); } else { diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index 27e7f537afd82a5c7039729142f5db0bd1dbd144..0f3a091267072020c6be9bfb410d7b2eda1bd4a7 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -50,7 +50,7 @@ int mds_get_parent_child_locked(struct obd_device *obd, struct mds_obd *mds, char *name, int namelen, struct lustre_handle *child_lockh, struct dentry **dchildp, int child_mode, - __u64 child_lockpart); + __u64 child_lockpart, void* clone_info); int mds_lock_new_child(struct obd_device *obd, struct inode *inode, struct lustre_handle *child_lockh); diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 80fe242bcc824238b17344e2c21a31c0d85a748a..3689a109e54410d483ae1095abc3b7d4ed7a6256 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -1227,7 +1227,7 @@ int mds_get_parent_child_locked(struct obd_device *obd, struct mds_obd *mds, char *name, int namelen, struct lustre_handle *child_lockh, struct dentry **dchildp, int child_mode, - __u64 child_lockpart) + __u64 child_lockpart, void *clone_info) { struct ldlm_res_id child_res_id = { .name = {0} }; struct ldlm_res_id parent_res_id = { .name = {0} }; @@ -1281,6 +1281,13 @@ int mds_get_parent_child_locked(struct obd_device *obd, struct mds_obd *mds, #endif cleanup_phase = 1; /* parent dentry */ +#ifdef CONFIG_SNAPFS + if (clone_info) { + /*FIXME is there any other FUNC will use d_fsdata, + *excepet creating inode according inum*/ + (*dparentp)->d_fsdata = clone_info; + } +#endif /* Step 2: Lookup child (without DLM lock, to get resource name) */ *dchildp = ll_lookup_one_len(name, *dparentp, namelen - 1); @@ -1659,7 +1666,7 @@ static int mds_reint_unlink(struct mds_update_record *rec, int offset, rec->ur_namelen, &child_lockh, &dchild, LCK_EX, MDS_INODELOCK_LOOKUP | - MDS_INODELOCK_UPDATE); + MDS_INODELOCK_UPDATE, NULL); } if (rc) GOTO(cleanup, rc); @@ -2514,7 +2521,7 @@ static int mds_reint_rename_create_name(struct mds_update_record *rec, &de_srcdir,LCK_PW,MDS_INODELOCK_UPDATE, &update_mode, rec->ur_tgt, rec->ur_tgtlen, &child_lockh, &de_new, LCK_EX, - MDS_INODELOCK_LOOKUP); + MDS_INODELOCK_LOOKUP, NULL); if (rc) GOTO(cleanup, rc); @@ -2609,7 +2616,7 @@ static int mds_reint_rename_to_remote(struct mds_update_record *rec, int offset, &de_srcdir,LCK_PW,MDS_INODELOCK_UPDATE, &update_mode, rec->ur_name, rec->ur_namelen, &child_lockh, &de_old, - LCK_EX, MDS_INODELOCK_LOOKUP); + LCK_EX, MDS_INODELOCK_LOOKUP, NULL); LASSERT(rc == 0); LASSERT(de_srcdir); LASSERT(de_srcdir->d_inode); diff --git a/lustre/ptlrpc/pack_generic.c b/lustre/ptlrpc/pack_generic.c index 56fb946c2243f26ed11869b1c0d61566867ebcef..1f6fc590f19921ab6a32432817d35f9605c9c7cd 100644 --- a/lustre/ptlrpc/pack_generic.c +++ b/lustre/ptlrpc/pack_generic.c @@ -33,6 +33,7 @@ #include <linux/obd_support.h> #include <linux/obd_class.h> #include <linux/lustre_net.h> +#include <linux/lustre_snap.h> #include <linux/fcntl.h> @@ -640,7 +641,11 @@ void lustre_swab_mds_body (struct mds_body *b) __swab32s (&b->suppgid); __swab32s (&b->eadatasize); } - +void lustre_swab_clonefs_info (struct clonefs_info *clone) +{ + __swab32s(&clone->clone_index); + __swab32s(&clone->clone_flags); +} void lustre_swab_mds_rec_setattr (struct mds_rec_setattr *sa) { __swab32s (&sa->sa_opcode); diff --git a/lustre/ptlrpc/ptlrpc_module.c b/lustre/ptlrpc/ptlrpc_module.c index 109737951669ee4e774da89e32d1cf3db5b8fbc4..d00dde8ca315270058cd7a3686cc6989e22c2fd2 100644 --- a/lustre/ptlrpc/ptlrpc_module.c +++ b/lustre/ptlrpc/ptlrpc_module.c @@ -182,6 +182,7 @@ EXPORT_SYMBOL(lustre_swab_ldlm_reply); EXPORT_SYMBOL(lustre_swab_ptlbd_op); EXPORT_SYMBOL(lustre_swab_ptlbd_niob); EXPORT_SYMBOL(lustre_swab_ptlbd_rsp); +EXPORT_SYMBOL(lustre_swab_clonefs_info); EXPORT_SYMBOL(mdc_create_pack); EXPORT_SYMBOL(mdc_setattr_pack); EXPORT_SYMBOL(mdc_unlink_pack); diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index 7fc58f36c72e75d0bd55fbe63102c0ae3d2cd9bf..1420009c4e2692692557bf95f062df9306084403 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -150,6 +150,8 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, if (!cache_dir && cache_dir->i_op->lookup) GOTO(exit, rc = ERR_PTR(-ENOENT)); + SMFS_PRE_COW(dir, dentry, NULL, NULL, SNAP_LOOKUP, "lookup", rc, 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); diff --git a/lustre/smfs/smfs_cow.c b/lustre/smfs/smfs_cow.c index 3c68a244a7dd27184945080b3dc8c537b495f720..d179915f821ddd27c32f798bd85ccfbac75ee711 100644 --- a/lustre/smfs/smfs_cow.c +++ b/lustre/smfs/smfs_cow.c @@ -646,6 +646,60 @@ exit: } EXPORT_SYMBOL(smfs_cow_write); +int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1, + void *data2) +{ + struct snap_info *snap_info = S2SNAPI(inode->i_sb); + struct fsfilt_operations *snapops = snap_info->snap_fsfilt; + struct dentry *dparent = dentry->d_parent; + struct clonefs_info *clone_info=(struct clonefs_info*)dparent->d_fsdata; + int rc = 0; + + if (clone_info && clone_info->clone_flags && SM_CLONE_FS) { + struct inode *ind_inode = NULL; + struct inode *cache_ind = NULL; + struct dentry *cache_dentry = NULL; + struct dentry *cache_parent = NULL; + struct inode *cache_inode; + struct dentry *tmp; + rc = 1; + + ind_inode = snapops->fs_get_indirect(inode, NULL, clone_info->clone_index); + if (!ind_inode) + RETURN(-ENOENT); + + if (!(cache_ind = I2CI(ind_inode))) + GOTO(exit, rc = -ENOENT); + + cache_parent=pre_smfs_dentry(NULL, cache_ind, dentry->d_parent); + cache_dentry=pre_smfs_dentry(cache_parent, NULL, dentry); + + tmp = cache_ind->i_op->lookup(cache_ind, cache_dentry); + + if (IS_ERR(tmp)) + GOTO(exit, rc = -ENOENT); + + if ((cache_inode = tmp ? tmp->d_inode : cache_dentry->d_inode)) { + if (IS_ERR(cache_inode)) { + dentry->d_inode = cache_inode; + GOTO(exit, rc = -ENOENT); + } + inode = iget4(inode->i_sb, cache_inode->i_ino, NULL, + &I2SMI(inode)->smi_flags); + } else { + d_add(dentry, NULL); + GOTO(exit, rc = -ENOENT); + } + d_add(dentry, inode); +exit: + iput(ind_inode); + post_smfs_dentry(cache_dentry); + post_smfs_dentry(cache_parent); + RETURN(rc); + } + RETURN(rc); +} + struct inode *smfs_cow_get_ind(struct inode *inode, int index) { struct snap_info *snap_info = S2SNAPI(inode->i_sb); @@ -673,16 +727,19 @@ struct inode *smfs_cow_get_ind(struct inode *inode, int index) RETURN(NULL); } EXPORT_SYMBOL(smfs_cow_get_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 + 1] = { + +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, }; int smfs_cow(struct inode *dir, struct dentry *dentry, void *new_dir, diff --git a/lustre/smfs/smfs_internal.h b/lustre/smfs/smfs_internal.h index cb5862a816634962cf30cbd5a6d0bad8ed9b13e4..c3ef77ec10f23107a7fa63c61a16a4978497a8c1 100644 --- a/lustre/smfs/smfs_internal.h +++ b/lustre/smfs/smfs_internal.h @@ -321,7 +321,9 @@ do { \ 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 (rc) \ + if (op == SNAP_LOOKUP && rc == 1) \ + GOTO(label, rc = 0); \ + else if (rc) \ GOTO(label, rc); \ } \ } while(0) diff --git a/lustre/utils/lconf b/lustre/utils/lconf index 858450b70d03d7332ad8aae6e0dec499290f3468..99ffab2d47c85e7df7326a8d937035c28813b61b 100755 --- a/lustre/utils/lconf +++ b/lustre/utils/lconf @@ -2432,6 +2432,7 @@ class Mountpoint(Module): def __init__(self,db): Module.__init__(self, 'MTPT', db) self.path = self.db.get_val('path') + self.clientoptions = self.db.get_val('clientoptions', '') self.fs_uuid = self.db.get_first_ref('filesystem') fs = self.db.lookup(self.fs_uuid) self.mds_uuid = fs.get_first_ref('lmv') @@ -2477,8 +2478,23 @@ class Mountpoint(Module): if config.record or config.lctl_dump: lctl.mount_option(local_node_name, self.vosc.get_name(), vmdc_name) return - cmd = "mount -t lustre_lite -o osc=%s,mdc=%s %s %s" % \ - (self.vosc.get_name(), vmdc_name, config.config, self.path) + + if config.clientoptions: + if self.clientoptions: + self.clientoptions = self.clientoptions + ',' + \ + config.clientoptions + else: + self.clientoptions = config.clientoptions + if self.clientoptions: + self.clientoptions = ',' + self.clientoptions + # Linux kernel will deal with async and not pass it to ll_fill_super, + # so replace it with Lustre async + self.clientoptions = string.replace(self.clientoptions, "async", + "lasync") + + cmd = "mount -t lustre_lite -o osc=%s,mdc=%s%s %s %s" % \ + (self.vosc.get_name(), vmdc_name, self.clientoptions, + config.config, self.path) run("mkdir", self.path) ret, val = run(cmd) if ret: @@ -3271,6 +3287,7 @@ lconf_options = [ ('reformat', "Reformat all devices (without question)"), ('mkfsoptions', "Additional options for the mk*fs command line", PARAM), ('mountfsoptions', "Additional options for mount fs command line", PARAM), + ('clientoptions', "Additional options for Lustre", PARAM), ('dump', "Dump the kernel debug log to file before portals is unloaded", PARAM), ('write_conf', "Save all the client config information on mds."), diff --git a/lustre/utils/llmount.c b/lustre/utils/llmount.c index 8e75f5cb0543610d6366f39eb9ef25dab3f4730f..198e30e5b9f032be5eb31d8885b1d614e42126ee 100644 --- a/lustre/utils/llmount.c +++ b/lustre/utils/llmount.c @@ -246,6 +246,9 @@ int parse_options(char * options, struct lustre_mount_data *lmd) } else if (!strcmp(opt, "port")) { lmd->lmd_port = val; } + else if (!strcmp(opt, "clone")) { + lmd->lmd_clone_index = val; + } } else { val = 1; if (!strncmp(opt, "no", 2)) { diff --git a/lustre/utils/lmc b/lustre/utils/lmc index 476477cde4fa5a91138daac5bd6830cb94545b58..849afb499dcef7fdcac98843ed2bd7833dba4720 100755 --- a/lustre/utils/lmc +++ b/lustre/utils/lmc @@ -137,6 +137,7 @@ Object creation command summary: --mds mds_name --lmv lmv_name --ost ost_name OR --lov lov_name + --clientoptions options --add route --node nodename @@ -236,6 +237,7 @@ lmc_options = [ ('echo_client', "", PARAM), ('path', "Specify the mountpoint for Lustre.", PARAM), ('filesystem', "Lustre filesystem name", PARAM,""), + ('clientoptions', "Specify the options for Lustre, such as async.", PARAM, ""), # lov ('lov', "Specify LOV name.", PARAM,""), @@ -558,10 +560,12 @@ class GenConfig: mgmt.appendChild(self.ref("active", mgmt_uuid)) return mgmt - def mountpoint(self, name, uuid, fs_uuid, path): + def mountpoint(self, name, uuid, fs_uuid, path, clientoptions): mtpt = self.newService("mountpoint", name, uuid) mtpt.appendChild(self.ref("filesystem", fs_uuid)) self.addElement(mtpt, "path", path) + if clientoptions: + self.addElement(mtpt, "clientoptions", clientoptions) return mtpt def filesystem(self, name, uuid, mds_uuid, obd_uuid, mgmt_uuid): @@ -1366,6 +1370,7 @@ def add_mtpt(gen, lustre, options): node_name = get_option(options, 'node') path = get_option(options, 'path') + clientoptions = get_option(options, "clientoptions") fs_name = get_option(options, 'filesystem') lov_name = get_option(options, 'lov') @@ -1402,7 +1407,7 @@ def add_mtpt(gen, lustre, options): error("MOUNTPOINT: ", name, " already exists.") uuid = new_uuid(name) - mtpt = gen.mountpoint(name, uuid, fs_uuid, path) + mtpt = gen.mountpoint(name, uuid, fs_uuid, path, clientoptions) node = findByName(lustre, node_name, "node") if not node: error('node:', node_name, "not found.")