From cdbe35c08c66deadfc7b0470871187af1f96ea74 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Fri, 15 Sep 2017 20:49:02 +0000 Subject: [PATCH] LU-9771 flr: extend DATA_VERSION API to read layout version The API is extended to fetch layout version from ost objects. Test-Parameters: testlist=sanity-flr Signed-off-by: Jinshan Xiong Change-Id: Iba852633992f0c52af8837cfed70922c1ed9ae00 Reviewed-on: https://review.whamcloud.com/29092 Reviewed-by: Bobi Jam Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Dmitry Eremin --- lustre/include/cl_object.h | 1 + lustre/include/lustre/lustreapi.h | 1 + lustre/include/uapi/linux/lustre/lustre_user.h | 12 ++++-- lustre/llite/file.c | 52 +++++++++++++++++--------- lustre/lov/lov_io.c | 8 +++- lustre/ofd/ofd_dev.c | 10 +++++ lustre/osc/osc_io.c | 11 ++++-- lustre/tests/multiop.c | 18 ++++++++- lustre/utils/liblustreapi.c | 39 ++++++++++++++----- 9 files changed, 114 insertions(+), 38 deletions(-) diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h index 61338cd..4ab1dc0 100644 --- a/lustre/include/cl_object.h +++ b/lustre/include/cl_object.h @@ -1819,6 +1819,7 @@ struct cl_io { } ci_setattr; struct cl_data_version_io { u64 dv_data_version; + u32 dv_layout_version; int dv_flags; } ci_data_version; struct cl_fault_io { diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index 1ae9361..cc50d5d 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -344,6 +344,7 @@ int llapi_get_version_string(char *version, unsigned int version_size); int llapi_get_version(char *buffer, int buffer_size, char **version) __attribute__((deprecated)); int llapi_get_data_version(int fd, __u64 *data_version, __u64 flags); +extern int llapi_get_ost_layout_version(int fd, __u32 *layout_version); int llapi_hsm_state_get_fd(int fd, struct hsm_user_state *hus); int llapi_hsm_state_get(const char *path, struct hsm_user_state *hus); int llapi_hsm_state_set_fd(int fd, __u64 setmask, __u64 clearmask, diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index c538657..a9e53af 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -1242,11 +1242,15 @@ enum changelog_message_type { /********* Misc **********/ struct ioc_data_version { - __u64 idv_version; - __u64 idv_flags; /* See LL_DV_xxx */ + __u64 idv_version; + __u32 idv_layout_version; /* FLR: layout version for OST objects */ + __u32 idv_flags; /* enum ioc_data_version_flags */ +}; + +enum ioc_data_version_flags { + LL_DV_RD_FLUSH = (1 << 0), /* Flush dirty pages from clients */ + LL_DV_WR_FLUSH = (1 << 1), /* Flush all caching pages from clients */ }; -#define LL_DV_RD_FLUSH (1 << 0) /* Flush dirty pages from clients */ -#define LL_DV_WR_FLUSH (1 << 1) /* Flush all caching pages from clients */ #ifndef offsetof #define offsetof(typ, memb) ((unsigned long)((char *)&(((typ *)0)->memb))) diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 8b516bb..96115bd 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -2105,18 +2105,8 @@ gf_free: RETURN(rc); } -/* - * Read the data_version for inode. - * - * This value is computed using stripe object version on OST. - * Version is computed using server side locking. - * - * @param flags if do sync on the OST side; - * 0: no sync - * LL_DV_RD_FLUSH: flush dirty pages, LCK_PR on OSTs - * LL_DV_WR_FLUSH: drop all caching pages, LCK_PW on OSTs - */ -int ll_data_version(struct inode *inode, __u64 *data_version, int flags) +static int +ll_ioc_data_version(struct inode *inode, struct ioc_data_version *ioc) { struct cl_object *obj = ll_i2info(inode)->lli_clob; struct lu_env *env; @@ -2126,11 +2116,12 @@ int ll_data_version(struct inode *inode, __u64 *data_version, int flags) ENTRY; + ioc->idv_version = 0; + ioc->idv_layout_version = UINT_MAX; + /* If no file object initialized, we consider its version is 0. */ - if (obj == NULL) { - *data_version = 0; + if (obj == NULL) RETURN(0); - } env = cl_env_get(&refcheck); if (IS_ERR(env)) @@ -2139,7 +2130,8 @@ int ll_data_version(struct inode *inode, __u64 *data_version, int flags) io = vvp_env_thread_io(env); io->ci_obj = obj; io->u.ci_data_version.dv_data_version = 0; - io->u.ci_data_version.dv_flags = flags; + io->u.ci_data_version.dv_layout_version = UINT_MAX; + io->u.ci_data_version.dv_flags = ioc->idv_flags; restart: if (cl_io_init(env, io, CIT_DATA_VERSION, io->ci_obj) == 0) @@ -2147,7 +2139,8 @@ restart: else result = io->ci_result; - *data_version = io->u.ci_data_version.dv_data_version; + ioc->idv_version = io->u.ci_data_version.dv_data_version; + ioc->idv_layout_version = io->u.ci_data_version.dv_layout_version; cl_io_fini(env, io); @@ -2160,6 +2153,29 @@ restart: } /* + * Read the data_version for inode. + * + * This value is computed using stripe object version on OST. + * Version is computed using server side locking. + * + * @param flags if do sync on the OST side; + * 0: no sync + * LL_DV_RD_FLUSH: flush dirty pages, LCK_PR on OSTs + * LL_DV_WR_FLUSH: drop all caching pages, LCK_PW on OSTs + */ +int ll_data_version(struct inode *inode, __u64 *data_version, int flags) +{ + struct ioc_data_version ioc = { .idv_flags = flags }; + int rc; + + rc = ll_ioc_data_version(inode, &ioc); + if (!rc) + *data_version = ioc.idv_version; + + return rc; +} + +/* * Trigger a HSM release request for the provided inode. */ int ll_hsm_release(struct inode *inode) @@ -2887,7 +2903,7 @@ out: RETURN(-EFAULT); idv.idv_flags &= LL_DV_RD_FLUSH | LL_DV_WR_FLUSH; - rc = ll_data_version(inode, &idv.idv_version, idv.idv_flags); + rc = ll_ioc_data_version(inode, &idv); if (rc == 0 && copy_to_user((char __user *)arg, &idv, sizeof(idv))) diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index 9440d4f..317fb3f 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -868,14 +868,18 @@ lov_io_data_version_end(const struct lu_env *env, const struct cl_io_slice *ios) { struct lov_io *lio = cl2lov_io(env, ios); struct cl_io *parent = lio->lis_cl.cis_io; + struct cl_data_version_io *pdv = &parent->u.ci_data_version; struct lov_io_sub *sub; ENTRY; list_for_each_entry(sub, &lio->lis_active, sub_linkage) { + struct cl_data_version_io *sdv = &sub->sub_io.u.ci_data_version; + lov_io_end_wrapper(env, &sub->sub_io); - parent->u.ci_data_version.dv_data_version += - sub->sub_io.u.ci_data_version.dv_data_version; + pdv->dv_data_version += sdv->dv_data_version; + if (pdv->dv_layout_version > sdv->dv_layout_version) + pdv->dv_layout_version = sdv->dv_layout_version; if (parent->ci_result == 0) parent->ci_result = sub->sub_io.ci_result; diff --git a/lustre/ofd/ofd_dev.c b/lustre/ofd/ofd_dev.c index 8b498c0..19f8381 100644 --- a/lustre/ofd/ofd_dev.c +++ b/lustre/ofd/ofd_dev.c @@ -1332,6 +1332,16 @@ static int ofd_getattr_hdl(struct tgt_session_info *tsi) repbody->oa.o_valid |= OBD_MD_FLDATAVERSION; repbody->oa.o_data_version = curr_version; } + + if (fo->ofo_ff.ff_layout_version > 0) { + repbody->oa.o_valid |= OBD_MD_LAYOUT_VERSION; + repbody->oa.o_layout_version = + fo->ofo_ff.ff_layout_version + fo->ofo_ff.ff_range; + + CDEBUG(D_INODE, DFID": get layout version: %u\n", + PFID(&tsi->tsi_fid), + repbody->oa.o_layout_version); + } } ofd_object_put(tsi->tsi_env, fo); diff --git a/lustre/osc/osc_io.c b/lustre/osc/osc_io.c index 5ccff72..bcfbe8b 100644 --- a/lustre/osc/osc_io.c +++ b/lustre/osc/osc_io.c @@ -715,11 +715,16 @@ static void osc_io_data_version_end(const struct lu_env *env, if (cbargs->opc_rc != 0) { slice->cis_io->ci_result = cbargs->opc_rc; - } else if (!(oio->oi_oa.o_valid & OBD_MD_FLDATAVERSION)) { - slice->cis_io->ci_result = -EOPNOTSUPP; } else { - dv->dv_data_version = oio->oi_oa.o_data_version; slice->cis_io->ci_result = 0; + if (!(oio->oi_oa.o_valid & + (OBD_MD_LAYOUT_VERSION | OBD_MD_FLDATAVERSION))) + slice->cis_io->ci_result = -ENOTSUPP; + + if (oio->oi_oa.o_valid & OBD_MD_LAYOUT_VERSION) + dv->dv_layout_version = oio->oi_oa.o_layout_version; + if (oio->oi_oa.o_valid & OBD_MD_FLDATAVERSION) + dv->dv_data_version = oio->oi_oa.o_data_version; } EXIT; diff --git a/lustre/tests/multiop.c b/lustre/tests/multiop.c index 7d284f9..f959746 100644 --- a/lustre/tests/multiop.c +++ b/lustre/tests/multiop.c @@ -219,7 +219,6 @@ int main(int argc, char **argv) lustre_fid fid; struct timespec ts; struct lov_user_md_v3 lum; - __u64 dv; if (argc < 3) { fprintf(stderr, usage, argv[0]); @@ -643,7 +642,9 @@ int main(int argc, char **argv) for (i = 0; i < mmap_len && mmap_ptr; i += 4096) mmap_ptr[i] += junk++; break; - case 'x': + case 'x': { + __u64 dv; + rc = llapi_get_data_version(fd, &dv, 0); if (rc) { fprintf(stderr, "cannot get file data version" @@ -652,6 +653,19 @@ int main(int argc, char **argv) } printf("dataversion is %ju\n", (uintmax_t)dv); break; + } + case 'X': { + __u32 layout_version; + + rc = llapi_get_ost_layout_version(fd, &layout_version); + if (rc) { + fprintf(stderr, "cannot get ost layout version" + " %d\n", rc); + exit(-rc); + } + printf("ostlayoutversion: %u\n", layout_version); + break; + } case 'y': if (fsync(fd) == -1) { save_errno = errno; diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index ccf9e8c..1fdc411 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -4750,18 +4750,39 @@ int llapi_get_connect_flags(const char *mnt, __u64 *flags) */ int llapi_get_data_version(int fd, __u64 *data_version, __u64 flags) { - int rc; - struct ioc_data_version idv; + int rc; + struct ioc_data_version idv; - idv.idv_flags = flags; + idv.idv_flags = (__u32)flags; - rc = ioctl(fd, LL_IOC_DATA_VERSION, &idv); - if (rc) - rc = -errno; - else - *data_version = idv.idv_version; + rc = ioctl(fd, LL_IOC_DATA_VERSION, &idv); + if (rc) + rc = -errno; + else + *data_version = idv.idv_version; - return rc; + return rc; +} + +/* + * Fetch layout version from OST objects. Layout version on OST objects are + * only set when the file is a mirrored file AND after the file has been + * written at least once. + * + * It actually fetches the least layout version from the objects. + */ +int llapi_get_ost_layout_version(int fd, __u32 *layout_version) +{ + int rc; + struct ioc_data_version idv = { 0 }; + + rc = ioctl(fd, LL_IOC_DATA_VERSION, &idv); + if (rc) + rc = -errno; + else + *layout_version = idv.idv_layout_version; + + return rc; } /* -- 1.8.3.1