From a87b1b04494193c39e3e4289b0d41c228d9451b1 Mon Sep 17 00:00:00 2001 From: kalpak Date: Tue, 3 Feb 2009 19:17:29 +0000 Subject: [PATCH] b=17187 i=nikita i=nathan open file using fid --- lustre/ChangeLog | 6 + lustre/fid/fid_lib.c | 13 ++ lustre/fld/fld_handler.c | 9 + lustre/include/lustre/lustre_idl.h | 1 + lustre/include/lustre_fid.h | 5 + lustre/mdd/mdd_device.c | 380 ++++++++++++++++++++++++++++++++++++- lustre/mdd/mdd_internal.h | 9 + lustre/mdd/mdd_object.c | 4 +- lustre/tests/sanity.sh | 13 ++ 9 files changed, 437 insertions(+), 3 deletions(-) diff --git a/lustre/ChangeLog b/lustre/ChangeLog index 171283c..8a7efd9 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -1948,6 +1948,12 @@ Details : While using HA for Lustre servers with Linux RAID, it is possible written. Also while reading the MMP block, we should read it from disk and not the cached one. +Severity : enhancement +Bugzilla : 17187 +Description: open file using fid +Details : A file can be opened using just its fid, like + /.lustre/fid/SEQ:OID:VER - this is needed for HSM and replication + -------------------------------------------------------------------------------- 2007-08-10 Cluster File Systems, Inc. diff --git a/lustre/fid/fid_lib.c b/lustre/fid/fid_lib.c index 76e779a..ab6422c 100644 --- a/lustre/fid/fid_lib.c +++ b/lustre/fid/fid_lib.c @@ -70,6 +70,7 @@ * * The first 0x400 sequences of normal FID are reserved for special purpose. * FID_SEQ_START + 1 is for local file id generation. + * FID_SEQ_START + 2 is for .lustre directory and its objects */ const struct lu_seq_range LUSTRE_SEQ_SPACE_RANGE = { FID_SEQ_START + 0x400ULL, @@ -89,3 +90,15 @@ const struct lu_fid LUSTRE_BFL_FID = { .f_seq = 0x0000000000000003, .f_oid = 0x0000000000000001, .f_ver = 0x0000000000000000 }; EXPORT_SYMBOL(LUSTRE_BFL_FID); + +/** Special fid for ".lustre" directory */ +const struct lu_fid LU_DOT_LUSTRE_FID = { .f_seq = LU_DOT_LUSTRE_SEQ, + .f_oid = 0x0000000000000001, + .f_ver = 0x0000000000000000 }; +EXPORT_SYMBOL(LU_DOT_LUSTRE_FID); + +/** Special fid for "fid" special object in .lustre */ +const struct lu_fid LU_OBF_FID = { .f_seq = LU_DOT_LUSTRE_SEQ, + .f_oid = 0x0000000000000002, + .f_ver = 0x0000000000000000 }; +EXPORT_SYMBOL(LU_OBF_FID); diff --git a/lustre/fld/fld_handler.c b/lustre/fld/fld_handler.c index 2b6ab12..5092ac1 100644 --- a/lustre/fld/fld_handler.c +++ b/lustre/fld/fld_handler.c @@ -67,6 +67,7 @@ #include #include #include "fld_internal.h" +#include #ifdef __KERNEL__ @@ -466,6 +467,7 @@ int fld_server_init(struct lu_server_fld *fld, struct dt_device *dt, int mds_node_id) { int cache_size, cache_threshold; + struct lu_seq_range range; int rc; ENTRY; @@ -499,6 +501,13 @@ int fld_server_init(struct lu_server_fld *fld, struct dt_device *dt, GOTO(out, rc); fld->lsf_control_exp = NULL; + + /* Insert reserved sequence number of ".lustre" into fld cache. */ + range.lsr_start = LU_DOT_LUSTRE_SEQ; + range.lsr_end = LU_DOT_LUSTRE_SEQ + 1; + range.lsr_mdt = 0; + fld_cache_insert(fld->lsf_cache, &range); + EXIT; out: if (rc) diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index 19f63d5..76327b2 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -372,6 +372,7 @@ static inline __u32 lu_igif_gen(const struct lu_fid *fid) } #define DFID "["LPX64":0x%x:0x%x]" +#define SFID "0x%llx:0x%x:0x%x" #define PFID(fid) \ fid_seq(fid), \ diff --git a/lustre/include/lustre_fid.h b/lustre/include/lustre_fid.h index 7c8085f..921b423 100644 --- a/lustre/include/lustre_fid.h +++ b/lustre/include/lustre_fid.h @@ -57,6 +57,8 @@ struct lu_context; extern const struct lu_seq_range LUSTRE_SEQ_SPACE_RANGE; extern const struct lu_seq_range LUSTRE_SEQ_ZERO_RANGE; extern const struct lu_fid LUSTRE_BFL_FID; +extern const struct lu_fid LU_OBF_FID; +extern const struct lu_fid LU_DOT_LUSTRE_FID; enum { /* @@ -82,6 +84,9 @@ enum { /** special fid seq: used for local object create. */ #define FID_SEQ_LOCAL_FILE (FID_SEQ_START + 1) +/** special fid seq: used for .lustre objects. */ +#define LU_DOT_LUSTRE_SEQ (FID_SEQ_START + 0x02ULL) + /** special OID for local objects */ enum { /** \see osd_oi_index_create */ diff --git a/lustre/mdd/mdd_device.c b/lustre/mdd/mdd_device.c index e9bfcfc..07924a0 100644 --- a/lustre/mdd/mdd_device.c +++ b/lustre/mdd/mdd_device.c @@ -60,12 +60,16 @@ #include #include /* for changelogs */ #include +#include #include "mdd_internal.h" const struct md_device_operations mdd_ops; +static struct lu_device_type mdd_device_type; static const char mdd_root_dir_name[] = "ROOT"; +static const char mdd_obf_dir_name[] = "fid"; +static const char mdd_dot_lustre_name[] = ".lustre"; static int mdd_device_init(const struct lu_env *env, struct lu_device *d, const char *name, struct lu_device *next) @@ -112,6 +116,8 @@ static void mdd_device_shutdown(const struct lu_env *env, ENTRY; mdd_changelog_fini(env, m); dt_txn_callback_del(m->mdd_child, &m->mdd_txn_cb); + mdd_object_put(env, m->mdd_dot_lustre_objs.mdd_obf); + mdd_object_put(env, m->mdd_dot_lustre); if (m->mdd_obd_dev) mdd_fini_obd(env, m, cfg); orph_index_fini(env, m); @@ -300,6 +306,369 @@ int mdd_changelog_write_header(struct mdd_device *mdd, int markerflags) RETURN(rc); } +/** + * Create ".lustre" directory. + */ +static int create_dot_lustre_dir(const struct lu_env *env, struct mdd_device *m) +{ + struct lu_fid *fid = &mdd_env_info(env)->mti_fid; + struct md_object *mdo; + int rc; + + memcpy(fid, &LU_DOT_LUSTRE_FID, sizeof(struct lu_fid)); + mdo = llo_store_create_index(env, &m->mdd_md_dev, m->mdd_child, + mdd_root_dir_name, mdd_dot_lustre_name, + fid, &dt_directory_features); + /* .lustre dir may be already present */ + if (IS_ERR(mdo) && PTR_ERR(mdo) != -EEXIST) { + rc = PTR_ERR(mdo); + CERROR("creating obj [%s] fid = "DFID" rc = %d\n", + mdd_dot_lustre_name, PFID(fid), rc); + RETURN(rc); + } + + return 0; +} + +static int dot_lustre_attr_get(const struct lu_env *env, struct md_object *obj, + struct md_attr *ma) +{ + struct mdd_object *mdd_obj = md2mdd_obj(obj); + + return mdd_attr_get_internal_locked(env, mdd_obj, ma); +} + +static int dot_lustre_attr_set(const struct lu_env *env, struct md_object *obj, + const struct md_attr *ma) +{ + return -EPERM; +} + +static int dot_lustre_xattr_get(const struct lu_env *env, + struct md_object *obj, struct lu_buf *buf, + const char *name) +{ + return 0; +} + +/** + * Direct access to the ".lustre" directory is not allowed. + */ +static int dot_lustre_mdd_open(const struct lu_env *env, struct md_object *obj, + int flags) +{ + return -EPERM; +} + +static int dot_lustre_path(const struct lu_env *env, struct md_object *obj, + char *path, int pathlen, __u64 recno, int *linkno) +{ + return -ENOSYS; +} + +static struct md_object_operations mdd_dot_lustre_obj_ops = { + .moo_attr_get = dot_lustre_attr_get, + .moo_attr_set = dot_lustre_attr_set, + .moo_xattr_get = dot_lustre_xattr_get, + .moo_open = dot_lustre_mdd_open, + .moo_path = dot_lustre_path +}; + +static int dot_lustre_lookup(const struct lu_env *env, struct md_object *p, + const struct lu_name *lname, struct lu_fid *f, + struct md_op_spec *spec) +{ + if (strcmp(lname->ln_name, mdd_obf_dir_name) == 0) + *f = LU_OBF_FID; + else + return -ENOENT; + + return 0; +} + +static int dot_lustre_create(const struct lu_env *env, struct md_object *pobj, + const struct lu_name *lname, + struct md_object *child, struct md_op_spec *spec, + struct md_attr* ma) +{ + return -EPERM; +} + +static int dot_lustre_rename(const struct lu_env *env, + struct md_object *src_pobj, + struct md_object *tgt_pobj, + const struct lu_fid *lf, + const struct lu_name *lsname, + struct md_object *tobj, + const struct lu_name *ltname, struct md_attr *ma) +{ + return -EPERM; +} + +static int dot_lustre_link(const struct lu_env *env, struct md_object *tgt_obj, + struct md_object *src_obj, + const struct lu_name *lname, struct md_attr *ma) +{ + return -EPERM; +} + +static int dot_lustre_unlink(const struct lu_env *env, struct md_object *pobj, + struct md_object *cobj, const struct lu_name *lname, + struct md_attr *ma) +{ + return -EPERM; +} + +static struct md_dir_operations mdd_dot_lustre_dir_ops = { + .mdo_lookup = dot_lustre_lookup, + .mdo_create = dot_lustre_create, + .mdo_rename = dot_lustre_rename, + .mdo_link = dot_lustre_link, + .mdo_unlink = dot_lustre_unlink, +}; + +static int obf_attr_get(const struct lu_env *env, struct md_object *obj, + struct md_attr *ma) +{ + int rc = 0; + + if (ma->ma_need & MA_INODE) { + struct mdd_device *mdd = mdo2mdd(obj); + + /* "fid" is a virtual object and hence does not have any "real" + * attributes. So we reuse attributes of .lustre for "fid" dir */ + ma->ma_need |= MA_INODE; + rc = dot_lustre_attr_get(env, &mdd->mdd_dot_lustre->mod_obj, ma); + if (rc) + return rc; + ma->ma_valid |= MA_INODE; + } + + /* "fid" directory does not have any striping information. */ + if (ma->ma_need & MA_LOV) { + struct mdd_object *mdd_obj = md2mdd_obj(obj); + + if (ma->ma_valid & MA_LOV) + return 0; + + if (!(S_ISREG(mdd_object_type(mdd_obj)) || + S_ISDIR(mdd_object_type(mdd_obj)))) + return 0; + + if (ma->ma_need & MA_LOV_DEF) { + rc = mdd_get_default_md(mdd_obj, ma->ma_lmm, + &ma->ma_lmm_size); + if (rc > 0) { + ma->ma_valid |= MA_LOV; + rc = 0; + } + } + } + + return rc; +} + +static int obf_attr_set(const struct lu_env *env, struct md_object *obj, + const struct md_attr *ma) +{ + return -EPERM; +} + +static int obf_xattr_get(const struct lu_env *env, + struct md_object *obj, struct lu_buf *buf, + const char *name) +{ + return 0; +} + +static int obf_mdd_open(const struct lu_env *env, struct md_object *obj, + int flags) +{ + struct mdd_object *mdd_obj = md2mdd_obj(obj); + + mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD); + mdd_obj->mod_count++; + mdd_write_unlock(env, mdd_obj); + + return 0; +} + +static int obf_mdd_close(const struct lu_env *env, struct md_object *obj, + struct md_attr *ma) +{ + struct mdd_object *mdd_obj = md2mdd_obj(obj); + + mdd_write_lock(env, mdd_obj, MOR_TGT_CHILD); + mdd_obj->mod_count--; + mdd_write_unlock(env, mdd_obj); + + return 0; +} + +/** Nothing to list in "fid" directory */ +static int obf_mdd_readpage(const struct lu_env *env, struct md_object *obj, + const struct lu_rdpg *rdpg) +{ + return -EPERM; +} + +static int obf_path(const struct lu_env *env, struct md_object *obj, + char *path, int pathlen, __u64 recno, int *linkno) +{ + return -ENOSYS; +} + +static struct md_object_operations mdd_obf_obj_ops = { + .moo_attr_get = obf_attr_get, + .moo_attr_set = obf_attr_set, + .moo_xattr_get = obf_xattr_get, + .moo_open = obf_mdd_open, + .moo_close = obf_mdd_close, + .moo_readpage = obf_mdd_readpage, + .moo_path = obf_path +}; + +/** + * Lookup method for "fid" object. Only filenames with correct SEQ:OID format + * are valid. We also check if object with passed fid exists or not. + */ +static int obf_lookup(const struct lu_env *env, struct md_object *p, + const struct lu_name *lname, struct lu_fid *f, + struct md_op_spec *spec) +{ + char *name = (char *)lname->ln_name; + struct mdd_device *mdd = mdo2mdd(p); + struct mdd_object *child; + int rc = 0; + + while (*name == '[') + name++; + + sscanf(name, SFID, &(f->f_seq), &(f->f_oid), + &(f->f_ver)); + if (!fid_is_sane(f)) { + CWARN("bad FID format [%s], should be "DFID"\n", lname->ln_name, + (__u64)1, 2, 0); + GOTO(out, rc = -EINVAL); + } + + /* Check if object with this fid exists */ + child = mdd_object_find(env, mdd, f); + if (child == NULL) + GOTO(out, rc = 0); + if (IS_ERR(child)) + GOTO(out, rc = PTR_ERR(child)); + + if (mdd_object_exists(child) == 0) + rc = -ENOENT; + + mdd_object_put(env, child); + +out: + return rc; +} + +static int obf_create(const struct lu_env *env, struct md_object *pobj, + const struct lu_name *lname, struct md_object *child, + struct md_op_spec *spec, struct md_attr* ma) +{ + return -EPERM; +} + +static int obf_rename(const struct lu_env *env, + struct md_object *src_pobj, struct md_object *tgt_pobj, + const struct lu_fid *lf, const struct lu_name *lsname, + struct md_object *tobj, const struct lu_name *ltname, + struct md_attr *ma) +{ + return -EPERM; +} + +static int obf_link(const struct lu_env *env, struct md_object *tgt_obj, + struct md_object *src_obj, const struct lu_name *lname, + struct md_attr *ma) +{ + return -EPERM; +} + +static int obf_unlink(const struct lu_env *env, struct md_object *pobj, + struct md_object *cobj, const struct lu_name *lname, + struct md_attr *ma) +{ + return -EPERM; +} + +static struct md_dir_operations mdd_obf_dir_ops = { + .mdo_lookup = obf_lookup, + .mdo_create = obf_create, + .mdo_rename = obf_rename, + .mdo_link = obf_link, + .mdo_unlink = obf_unlink +}; + +/** + * Create special in-memory "fid" object for open-by-fid. + */ +static int mdd_obf_setup(const struct lu_env *env, struct mdd_device *m) +{ + struct mdd_object *mdd_obf; + struct lu_object *obf_lu_obj; + int rc = 0; + + m->mdd_dot_lustre_objs.mdd_obf = mdd_object_find(env, m, + &LU_OBF_FID); + if (m->mdd_dot_lustre_objs.mdd_obf == NULL || + IS_ERR(m->mdd_dot_lustre_objs.mdd_obf)) + GOTO(out, rc = -ENOENT); + + mdd_obf = m->mdd_dot_lustre_objs.mdd_obf; + mdd_obf->mod_obj.mo_dir_ops = &mdd_obf_dir_ops; + mdd_obf->mod_obj.mo_ops = &mdd_obf_obj_ops; + /* Don't allow objects to be created in "fid" dir */ + mdd_obf->mod_flags |= IMMUTE_OBJ; + + obf_lu_obj = mdd2lu_obj(mdd_obf); + obf_lu_obj->lo_header->loh_attr |= (LOHA_EXISTS | S_IFDIR); + +out: + return rc; +} + +/** Setup ".lustre" directory object */ +static int mdd_dot_lustre_setup(const struct lu_env *env, struct mdd_device *m) +{ + struct dt_object *dt_dot_lustre; + struct lu_fid *fid = &mdd_env_info(env)->mti_fid; + int rc; + + rc = create_dot_lustre_dir(env, m); + if (rc) + return rc; + + dt_dot_lustre = dt_store_open(env, m->mdd_child, mdd_root_dir_name, + mdd_dot_lustre_name, fid); + if (IS_ERR(dt_dot_lustre)) { + rc = PTR_ERR(dt_dot_lustre); + GOTO(out, rc); + } + + /* references are released in mdd_device_shutdown() */ + m->mdd_dot_lustre = lu2mdd_obj(lu_object_locate(dt_dot_lustre->do_lu.lo_header, + &mdd_device_type)); + + lu_object_put(env, &dt_dot_lustre->do_lu); + + m->mdd_dot_lustre->mod_obj.mo_dir_ops = &mdd_dot_lustre_dir_ops; + m->mdd_dot_lustre->mod_obj.mo_ops = &mdd_dot_lustre_obj_ops; + + rc = mdd_obf_setup(env, m); + if (rc) + CERROR("Error initializing \"fid\" object - %d.\n", rc); + +out: + RETURN(rc); +} + static int mdd_process_config(const struct lu_env *env, struct lu_device *d, struct lustre_cfg *cfg) { @@ -435,8 +804,17 @@ static int mdd_prepare(const struct lu_env *env, LASSERT(root != NULL); lu_object_put(env, &root->do_lu); rc = orph_index_init(env, mdd); - } else + } else { rc = PTR_ERR(root); + } + if (rc) + GOTO(out, rc); + + rc = mdd_dot_lustre_setup(env, mdd); + if (rc) { + CERROR("Error(%d) initializing .lustre objects\n", rc); + GOTO(out, rc); + } out: RETURN(rc); diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index c855f80..0d66a68d 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -110,6 +110,11 @@ struct mdd_changelog { __u64 mc_starttime; }; +/** Objects in .lustre dir */ +struct mdd_dot_lustre_objs { + struct mdd_object *mdd_obf; +}; + struct mdd_device { struct md_device mdd_md_dev; struct dt_device *mdd_child; @@ -123,6 +128,8 @@ struct mdd_device { struct mdd_txn_op_descr mdd_tod[MDD_TXN_LAST_OP]; struct mdd_changelog mdd_cl; unsigned long mdd_atime_diff; + struct mdd_object *mdd_dot_lustre; + struct mdd_dot_lustre_objs mdd_dot_lustre_objs; }; enum mod_flags { @@ -362,6 +369,8 @@ extern const struct lu_device_operations mdd_lu_ops; struct mdd_object *mdd_object_find(const struct lu_env *env, struct mdd_device *d, const struct lu_fid *f); +int mdd_get_default_md(struct mdd_object *mdd_obj, struct lov_mds_md *lmm, + int *size); /* mdd_quota.c*/ #ifdef HAVE_QUOTA_SUPPORT diff --git a/lustre/mdd/mdd_object.c b/lustre/mdd/mdd_object.c index 0cf918a..9d0dbc1 100644 --- a/lustre/mdd/mdd_object.c +++ b/lustre/mdd/mdd_object.c @@ -582,8 +582,8 @@ int mdd_iattr_get(const struct lu_env *env, struct mdd_object *mdd_obj, RETURN(rc); } -static int mdd_get_default_md(struct mdd_object *mdd_obj, - struct lov_mds_md *lmm, int *size) +int mdd_get_default_md(struct mdd_object *mdd_obj, struct lov_mds_md *lmm, + int *size) { struct lov_desc *ldesc; struct mdd_device *mdd = mdo2mdd(&mdd_obj->mod_obj); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 348fe13..568620d 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -5948,6 +5948,19 @@ err17935 () { fi } +test_154() { + cp /etc/hosts $DIR/$tfile + + fid=`$LFS path2fid $DIR/$tfile` + rc=$? + [ $rc -ne 0 ] && error "error: could not get fid for $DIR/$tfile." + + diff $DIR/$tfile $DIR/.lustre/fid/$fid || error "open by fid failed: did not find expected data in file." + + echo "Opening a file by FID succeeded" +} +run_test 154 "Opening a file by FID" + #Changelogs test_160() { remote_mds && skip "remote MDS" && return -- 1.8.3.1