From 6d33530cc018602a665fc5e724f9f64dcba421c9 Mon Sep 17 00:00:00 2001 From: Li Wei Date: Tue, 19 Feb 2013 10:13:02 +0800 Subject: [PATCH] LU-2783 ofd: Implement OBD_IOC_GET_OBJ_VERSION This patch implements OBD_IOC_GET_OBJ_VERSION for ofd, so that tests can use "lctl getobjversion" on OST objects. jt_get_obj_version() now takes ID and group pairs, as well as FIDs, for OST objects. Although the code are for testing purposes only, dereferencing an ioc_inlbuf without checking its size is still unacceptable. Hence, mdt_ioc_version_get() is changed to check sizes first. Signed-off-by: Li Wei Change-Id: If259aeca281dcb3f4ee4dc719719f722cf72cad4 Reviewed-on: http://review.whamcloud.com/5467 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Mike Pershin Reviewed-by: Emoly Liu Reviewed-by: Oleg Drokin --- lustre/mdt/mdt_handler.c | 27 +++++++++++++-------- lustre/ofd/ofd_obd.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++- lustre/utils/lctl.c | 3 ++- lustre/utils/obd.c | 63 +++++++++++++++++++++++++++++++----------------- 4 files changed, 121 insertions(+), 34 deletions(-) diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 7d16db7..3576847 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -5816,17 +5816,24 @@ static int mdt_ioc_child(struct lu_env *env, struct mdt_device *mdt, static int mdt_ioc_version_get(struct mdt_thread_info *mti, void *karg) { - struct obd_ioctl_data *data = karg; - struct lu_fid *fid = (struct lu_fid *)data->ioc_inlbuf1; - __u64 version; - struct mdt_object *obj; - struct mdt_lock_handle *lh; - int rc; - ENTRY; + struct obd_ioctl_data *data = karg; + struct lu_fid *fid; + __u64 version; + struct mdt_object *obj; + struct mdt_lock_handle *lh; + int rc; + ENTRY; - CDEBUG(D_IOCTL, "getting version for "DFID"\n", PFID(fid)); - if (!fid_is_sane(fid)) - RETURN(-EINVAL); + if (data->ioc_inlbuf1 == NULL || data->ioc_inllen1 != sizeof(*fid) || + data->ioc_inlbuf2 == NULL || data->ioc_inllen2 != sizeof(version)) + RETURN(-EINVAL); + + fid = (struct lu_fid *)data->ioc_inlbuf1; + + if (!fid_is_sane(fid)) + RETURN(-EINVAL); + + CDEBUG(D_IOCTL, "getting version for "DFID"\n", PFID(fid)); lh = &mti->mti_lh[MDT_LH_PARENT]; mdt_lock_reg_init(lh, LCK_CR); diff --git a/lustre/ofd/ofd_obd.c b/lustre/ofd/ofd_obd.c index 35f73d6..dbb7fc9 100644 --- a/lustre/ofd/ofd_obd.c +++ b/lustre/ofd/ofd_obd.c @@ -1423,6 +1423,63 @@ out: return rc; } +static int ofd_ioc_get_obj_version(const struct lu_env *env, + struct ofd_device *ofd, void *karg) +{ + struct obd_ioctl_data *data = karg; + struct lu_fid fid; + struct ofd_object *fo; + dt_obj_version_t version; + int rc = 0; + + ENTRY; + + if (data->ioc_inlbuf2 == NULL || data->ioc_inllen2 != sizeof(version)) + GOTO(out, rc = -EINVAL); + + if (data->ioc_inlbuf1 != NULL && data->ioc_inllen1 == sizeof(fid)) { + fid = *(struct lu_fid *)data->ioc_inlbuf1; + } else if (data->ioc_inlbuf3 != NULL && + data->ioc_inllen3 == sizeof(__u64) && + data->ioc_inlbuf4 != NULL && + data->ioc_inllen4 == sizeof(__u64)) { + struct ost_id ostid; + + ostid.oi_id = *(__u64 *)data->ioc_inlbuf3; + ostid.oi_seq = *(__u64 *)data->ioc_inlbuf4; + rc = fid_ostid_unpack(&fid, &ostid, 0); + if (rc != 0) + GOTO(out, rc); + } else { + GOTO(out, rc = -EINVAL); + } + + if (!fid_is_sane(&fid)) + GOTO(out, rc = -EINVAL); + + fo = ofd_object_find(env, ofd, &fid); + if (IS_ERR(fo)) + GOTO(out, rc = PTR_ERR(fo)); + + if (!ofd_object_exists(fo)) + GOTO(out_fo, rc = -ENOENT); + + if (lu_object_remote(&fo->ofo_obj.do_lu)) + GOTO(out_fo, rc = -EREMOTE); + + version = dt_version_get(env, ofd_object_child(fo)); + if (version == 0) + GOTO(out_fo, rc = -EIO); + + *(dt_obj_version_t *)data->ioc_inlbuf2 = version; + + EXIT; +out_fo: + ofd_object_put(env, fo); +out: + return rc; +} + int ofd_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void *uarg) { @@ -1434,7 +1491,7 @@ int ofd_iocontrol(unsigned int cmd, struct obd_export *exp, int len, ENTRY; CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd); - rc = lu_env_init(&env, LCT_LOCAL); + rc = lu_env_init(&env, LCT_DT_THREAD); if (rc) RETURN(rc); @@ -1452,6 +1509,9 @@ int ofd_iocontrol(unsigned int cmd, struct obd_export *exp, int len, if (rc == 0) rc = dt_ro(&env, ofd->ofd_osd); break; + case OBD_IOC_GET_OBJ_VERSION: + rc = ofd_ioc_get_obj_version(&env, ofd, karg); + break; default: CERROR("%s: not supported cmd = %d\n", obd->obd_name, cmd); rc = -ENOTTY; diff --git a/lustre/utils/lctl.c b/lustre/utils/lctl.c index f7a1a29..1c8772b 100644 --- a/lustre/utils/lctl.c +++ b/lustre/utils/lctl.c @@ -345,7 +345,8 @@ command_t cmdlist[] = { "usage: memhog []"}, {"getobjversion", jt_get_obj_version, 0, "get the version of an object on servers\n" - "usage: getobjversion "}, + "usage: getobjversion \n" + " getobjversion -i -g "}, /* LFSCK commands */ {"==== LFSCK ====", jt_noop, 0, "LFSCK"}, diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index e6b9f11..53f2fc5 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -3584,31 +3584,50 @@ out: int jt_get_obj_version(int argc, char **argv) { - struct lu_fid fid; - struct obd_ioctl_data data; - __u64 version; - char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf, *fidstr; - int rc; + struct lu_fid fid; + struct obd_ioctl_data data; + __u64 version, id = ULLONG_MAX, group = ULLONG_MAX; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf, *fidstr; + int rc, c; + + while ((c = getopt(argc, argv, "i:g:")) != -1) { + switch (c) { + case 'i': + id = strtoull(optarg, NULL, 0); + break; + case 'g': + group = strtoull(optarg, NULL, 0); + break; + default: + return CMD_HELP; + } + } - if (argc != 2) - return CMD_HELP; + argc -= optind; + argv += optind; - fidstr = argv[1]; - while (*fidstr == '[') - fidstr++; - sscanf(fidstr, SFID, RFID(&fid)); - if (!fid_is_sane(&fid)) { - fprintf(stderr, "bad FID format [%s], should be "DFID"\n", - fidstr, (__u64)1, 2, 0); - return -EINVAL; - } + if (!(id != ULLONG_MAX && group != ULLONG_MAX && argc == 0) && + !(id == ULLONG_MAX && group == ULLONG_MAX && argc == 1)) + return CMD_HELP; - memset(&data, 0, sizeof data); - data.ioc_dev = cur_device; - data.ioc_inlbuf1 = (char *) &fid; - data.ioc_inllen1 = sizeof fid; - data.ioc_inlbuf2 = (char *) &version; - data.ioc_inllen2 = sizeof version; + memset(&data, 0, sizeof data); + data.ioc_dev = cur_device; + if (argc == 1) { + fidstr = *argv; + while (*fidstr == '[') + fidstr++; + sscanf(fidstr, SFID, RFID(&fid)); + + data.ioc_inlbuf1 = (char *) &fid; + data.ioc_inllen1 = sizeof fid; + } else { + data.ioc_inlbuf3 = (char *) &id; + data.ioc_inllen3 = sizeof id; + data.ioc_inlbuf4 = (char *) &group; + data.ioc_inllen4 = sizeof group; + } + data.ioc_inlbuf2 = (char *) &version; + data.ioc_inllen2 = sizeof version; memset(buf, 0, sizeof *buf); rc = obd_ioctl_pack(&data, &buf, sizeof rawbuf); -- 1.8.3.1