Whamcloud - gitweb
LU-2783 ofd: Implement OBD_IOC_GET_OBJ_VERSION
authorLi Wei <wei.g.li@intel.com>
Tue, 19 Feb 2013 02:13:02 +0000 (10:13 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 28 Mar 2013 03:17:35 +0000 (23:17 -0400)
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 <wei.g.li@intel.com>
Change-Id: If259aeca281dcb3f4ee4dc719719f722cf72cad4
Reviewed-on: http://review.whamcloud.com/5467
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Mike Pershin <mike.pershin@intel.com>
Reviewed-by: Emoly Liu <emoly.liu@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/mdt/mdt_handler.c
lustre/ofd/ofd_obd.c
lustre/utils/lctl.c
lustre/utils/obd.c

index 7d16db7..3576847 100644 (file)
@@ -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)
 {
 
 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);
 
         lh = &mti->mti_lh[MDT_LH_PARENT];
         mdt_lock_reg_init(lh, LCK_CR);
index 35f73d6..dbb7fc9 100644 (file)
@@ -1423,6 +1423,63 @@ out:
        return rc;
 }
 
        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)
 {
 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);
        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);
 
        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;
                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;
        default:
                CERROR("%s: not supported cmd = %d\n", obd->obd_name, cmd);
                rc = -ENOTTY;
index f7a1a29..1c8772b 100644 (file)
@@ -345,7 +345,8 @@ command_t cmdlist[] = {
          "usage: memhog <page count> [<gfp flags>]"},
         {"getobjversion", jt_get_obj_version, 0,
          "get the version of an object on servers\n"
          "usage: memhog <page count> [<gfp flags>]"},
         {"getobjversion", jt_get_obj_version, 0,
          "get the version of an object on servers\n"
-         "usage: getobjversion <fid>"},
+        "usage: getobjversion <fid>\n"
+        "       getobjversion -i <id> -g <group>"},
 
        /* LFSCK commands */
        {"==== LFSCK ====", jt_noop, 0, "LFSCK"},
 
        /* LFSCK commands */
        {"==== LFSCK ====", jt_noop, 0, "LFSCK"},
index e6b9f11..53f2fc5 100644 (file)
@@ -3584,31 +3584,50 @@ out:
 
 int jt_get_obj_version(int argc, char **argv)
 {
 
 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);
 
         memset(buf, 0, sizeof *buf);
         rc = obd_ioctl_pack(&data, &buf, sizeof rawbuf);