Whamcloud - gitweb
LU-2783 ofd: Implement OBD_IOC_GET_OBJ_VERSION
[fs/lustre-release.git] / lustre / ofd / ofd_obd.c
index b4dd026..dbb7fc9 100644 (file)
@@ -51,7 +51,7 @@ static int ofd_export_stats_init(struct ofd_device *ofd,
 {
        struct obd_device       *obd = ofd_obd(ofd);
        struct nid_stat         *stats;
-       int                      num_stats, i;
+       int                      num_stats;
        int                      rc, newnid = 0;
 
        ENTRY;
@@ -75,18 +75,6 @@ static int ofd_export_stats_init(struct ofd_device *ofd,
        stats = exp->exp_nid_stats;
        LASSERT(stats != NULL);
 
-       OBD_ALLOC(stats->nid_brw_stats, sizeof(struct brw_stats));
-       if (stats->nid_brw_stats == NULL)
-               GOTO(clean, rc = -ENOMEM);
-
-       for (i = 0; i < BRW_LAST; i++)
-               spin_lock_init(&stats->nid_brw_stats->hist[i].oh_lock);
-
-       rc = lprocfs_seq_create(stats->nid_proc, "brw_stats", 0644,
-                               &ofd_per_nid_stats_fops, stats);
-       if (rc)
-               CWARN("Error adding the brw_stats file\n");
-
        num_stats = (sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
                     LPROC_OFD_LAST - 1;
 
@@ -128,10 +116,11 @@ static int ofd_parse_connect_data(const struct lu_env *env,
                RETURN(0);
 
        CDEBUG(D_RPCTRACE, "%s: cli %s/%p ocd_connect_flags: "LPX64
-              " ocd_version: %x ocd_grant: %d ocd_index: %u\n",
+              " ocd_version: %x ocd_grant: %d ocd_index: %u"
+              " ocd_group %u\n",
               exp->exp_obd->obd_name, exp->exp_client_uuid.uuid, exp,
               data->ocd_connect_flags, data->ocd_version,
-              data->ocd_grant, data->ocd_index);
+              data->ocd_grant, data->ocd_index, data->ocd_group);
 
        if (fed->fed_group != 0 && fed->fed_group != data->ocd_group) {
                CWARN("!!! This export (nid %s) used object group %d "
@@ -145,7 +134,7 @@ static int ofd_parse_connect_data(const struct lu_env *env,
        fed->fed_group = data->ocd_group;
 
        data->ocd_connect_flags &= OST_CONNECT_SUPPORTED;
-       exp->exp_connect_flags = data->ocd_connect_flags;
+       exp->exp_connect_data = *data;
        data->ocd_version = LUSTRE_VERSION_CODE;
 
        /* Kindly make sure the SKIP_ORPHAN flag is from MDS. */
@@ -164,7 +153,7 @@ static int ofd_parse_connect_data(const struct lu_env *env,
                data->ocd_grant_extent = ofd->ofd_dt_conf.ddp_grant_frag >> 10;
        }
 
-       if (exp->exp_connect_flags & OBD_CONNECT_GRANT)
+       if (exp_connect_flags(exp) & OBD_CONNECT_GRANT)
                data->ocd_grant = ofd_grant_connect(env, exp, data->ocd_grant);
 
        if (data->ocd_connect_flags & OBD_CONNECT_INDEX) {
@@ -192,7 +181,7 @@ static int ofd_parse_connect_data(const struct lu_env *env,
                data->ocd_brw_size = 65536;
        } else if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) {
                data->ocd_brw_size = min(data->ocd_brw_size,
-                             (__u32)(PTLRPC_MAX_BRW_PAGES << CFS_PAGE_SHIFT));
+                                        (__u32)DT_MAX_BRW_SIZE);
                if (data->ocd_brw_size == 0) {
                        CERROR("%s: cli %s/%p ocd_connect_flags: "LPX64
                               " ocd_version: %x ocd_grant: %d ocd_index: %u "
@@ -236,14 +225,24 @@ static int ofd_parse_connect_data(const struct lu_env *env,
        if (data->ocd_connect_flags & OBD_CONNECT_MAXBYTES)
                data->ocd_maxbytes = ofd->ofd_dt_conf.ddp_maxbytes;
 
-        RETURN(0);
+       if (data->ocd_connect_flags & OBD_CONNECT_PINGLESS) {
+               if (suppress_pings) {
+                       spin_lock(&exp->exp_obd->obd_dev_lock);
+                       list_del_init(&exp->exp_obd_chain_timed);
+                       spin_unlock(&exp->exp_obd->obd_dev_lock);
+               } else {
+                       data->ocd_connect_flags &= ~OBD_CONNECT_PINGLESS;
+               }
+       }
+
+       RETURN(0);
 }
 
 static int ofd_obd_reconnect(const struct lu_env *env, struct obd_export *exp,
                             struct obd_device *obd, struct obd_uuid *cluuid,
                             struct obd_connect_data *data, void *localdata)
 {
-       struct ofd_device       *ofd = ofd_dev(obd->obd_lu_dev);
+       struct ofd_device       *ofd;
        int                      rc;
 
        ENTRY;
@@ -251,6 +250,8 @@ static int ofd_obd_reconnect(const struct lu_env *env, struct obd_export *exp,
        if (exp == NULL || obd == NULL || cluuid == NULL)
                RETURN(-EINVAL);
 
+       ofd = ofd_dev(obd->obd_lu_dev);
+
        rc = lu_env_refill((struct lu_env *)env);
        if (rc != 0) {
                CERROR("Failure to refill session: '%d'\n", rc);
@@ -406,7 +407,7 @@ static int ofd_destroy_export(struct obd_export *exp)
        ofd_grant_discard(exp);
        ofd_fmd_cleanup(exp);
 
-       if (exp->exp_connect_flags & OBD_CONNECT_GRANT_SHRINK) {
+       if (exp_connect_flags(exp) & OBD_CONNECT_GRANT_SHRINK) {
                if (ofd->ofd_tot_granted_clients > 0)
                        ofd->ofd_tot_granted_clients --;
        }
@@ -485,7 +486,7 @@ static int ofd_set_info_async(const struct lu_env *env, struct obd_export *exp,
                              __u32 keylen, void *key, __u32 vallen, void *val,
                              struct ptlrpc_request_set *set)
 {
-       struct ofd_device       *ofd = ofd_exp(exp);
+       struct ofd_device       *ofd;
        int                      rc = 0;
 
        ENTRY;
@@ -495,6 +496,8 @@ static int ofd_set_info_async(const struct lu_env *env, struct obd_export *exp,
                RETURN(-EINVAL);
        }
 
+       ofd = ofd_exp(exp);
+
        if (KEY_IS(KEY_CAPA_KEY)) {
                rc = ofd_update_capa_key(ofd, val);
                if (rc)
@@ -523,7 +526,7 @@ static int ofd_get_info(const struct lu_env *env, struct obd_export *exp,
                        __u32 keylen, void *key, __u32 *vallen, void *val,
                        struct lov_stripe_md *lsm)
 {
-       struct ofd_device       *ofd = ofd_exp(exp);
+       struct ofd_device       *ofd;
        int                      rc = 0;
 
        ENTRY;
@@ -533,6 +536,8 @@ static int ofd_get_info(const struct lu_env *env, struct obd_export *exp,
                RETURN(-EINVAL);
        }
 
+       ofd = ofd_exp(exp);
+
        if (KEY_IS(KEY_BLOCKSIZE)) {
                __u32 *blocksize = val;
                if (blocksize) {
@@ -560,7 +565,7 @@ static int ofd_get_info(const struct lu_env *env, struct obd_export *exp,
                ofd_info_init(env, exp);
                oseq = ofd_seq_load(env, ofd,
                                    (obd_seq)exp->exp_filter_data.fed_group);
-               LASSERT(oseq != NULL);
+               LASSERT(!IS_ERR(oseq));
                if (last_id) {
                        if (*vallen < sizeof(*last_id)) {
                                ofd_seq_put(env, oseq);
@@ -612,6 +617,41 @@ static int ofd_get_info(const struct lu_env *env, struct obd_export *exp,
        } else if (KEY_IS(KEY_SYNC_LOCK_CANCEL)) {
                *((__u32 *) val) = ofd->ofd_sync_lock_cancel;
                *vallen = sizeof(__u32);
+       } else if (KEY_IS(KEY_LAST_FID)) {
+               struct lu_env           env;
+               struct ofd_device       *ofd = ofd_exp(exp);
+               struct ofd_seq          *oseq;
+               struct ost_id           *oid = val;
+               int                     rc;
+
+               if (oid == NULL) {
+                       *vallen = sizeof(struct ost_id);
+                       RETURN(0);
+               }
+
+               if (*vallen < sizeof(*oid))
+                       RETURN(-EOVERFLOW);
+
+               rc = lu_env_init(&env, LCT_DT_THREAD);
+               if (rc != 0)
+                       RETURN(rc);
+               ofd_info_init(&env, exp);
+
+               ostid_le_to_cpu(oid, oid);
+               CDEBUG(D_HA, "Get LAST FID for seq "LPX64"\n", oid->oi_seq);
+
+               oseq = ofd_seq_load(&env, ofd, oid->oi_seq);
+               if (IS_ERR(oseq))
+                       GOTO(out_fini, rc = PTR_ERR(oseq));
+
+               CDEBUG(D_HA, "LAST FID is "POSTID"\n", oseq->os_last_oid,
+                      oseq->os_seq);
+
+               *oid = oseq->os_oi;
+               *vallen = sizeof(*oid);
+               ofd_seq_put(&env, oseq);
+out_fini:
+               lu_env_fini(&env);
        } else {
                CERROR("Not supported key %s\n", (char*)key);
                rc = -EOPNOTSUPP;
@@ -730,7 +770,7 @@ static int ofd_statfs(const struct lu_env *env,  struct obd_export *exp,
 
        /* The QoS code on the MDS does not care about space reserved for
         * precreate, so take it out. */
-       if (exp->exp_connect_flags & OBD_CONNECT_MDS) {
+       if (exp_connect_flags(exp) & OBD_CONNECT_MDS) {
                struct filter_export_data *fed;
 
                fed = &obd->obd_self_export->exp_filter_data;
@@ -1076,7 +1116,7 @@ static int ofd_orphans_destroy(const struct lu_env *env,
        }
 
        LASSERT(exp != NULL);
-       skip_orphan = !!(exp->exp_connect_flags & OBD_CONNECT_SKIP_ORPHAN);
+       skip_orphan = !!(exp_connect_flags(exp) & OBD_CONNECT_SKIP_ORPHAN);
 
        last = ofd_seq_last_oid(oseq);
        LCONSOLE_INFO("%s: deleting orphan objects from "LPX64":"LPU64
@@ -1119,7 +1159,8 @@ int ofd_create(const struct lu_env *env, struct obd_export *exp,
        struct ofd_thread_info  *info;
        obd_seq                 seq = oa->o_seq;
        struct ofd_seq          *oseq;
-       int                      rc = 0, diff;
+       int                     rc = 0, diff;
+       int                     sync_trans = 0;
 
        ENTRY;
 
@@ -1133,8 +1174,9 @@ int ofd_create(const struct lu_env *env, struct obd_export *exp,
               seq, oa->o_id);
 
        oseq = ofd_seq_load(env, ofd, seq);
-       if (oseq == NULL) {
-               CERROR("%s: Can't find oseq "LPX64"\n", ofd_name(ofd), seq);
+       if (IS_ERR(oseq)) {
+               CERROR("%s: Can't find FID Sequence "LPX64": rc = %ld\n",
+                      ofd_name(ofd), seq, PTR_ERR(oseq));
                RETURN(-EINVAL);
        }
 
@@ -1194,6 +1236,20 @@ int ofd_create(const struct lu_env *env, struct obd_export *exp,
                        diff = 1; /* shouldn't we create this right now? */
                } else {
                        diff = oa->o_id - ofd_seq_last_oid(oseq);
+                       /* Do sync create if the seq is about to used up */
+                       if (fid_seq_is_idif(oa->o_seq) ||
+                           fid_seq_is_mdt0(oa->o_seq)) {
+                               if (unlikely(oa->o_id >= IDIF_MAX_OID - 1))
+                                       sync_trans = 1;
+                       } else if (fid_seq_is_norm(oa->o_seq)) {
+                               if (unlikely(oa->o_id >=
+                                            LUSTRE_DATA_SEQ_MAX_WIDTH - 1))
+                                       sync_trans = 1;
+                       } else {
+                               CERROR("%s : invalid o_seq "LPX64": rc = %d\n",
+                                      ofd_name(ofd), oa->o_seq, -EINVAL);
+                               GOTO(out, rc = -EINVAL);
+                       }
                }
        }
        if (diff > 0) {
@@ -1209,9 +1265,9 @@ int ofd_create(const struct lu_env *env, struct obd_export *exp,
                                              ofd_obd(ofd)->obd_self_export,
                                              &diff);
                        if (rc) {
-                               CDEBUG(D_HA, "%s: failed to acquire grant space"
-                                      "for precreate (%d)\n",
-                                      ofd_name(ofd), diff);
+                               CDEBUG(D_HA, "%s: failed to acquire grant "
+                                      "space for precreate (%d): rc = %d\n",
+                                      ofd_name(ofd), diff, rc);
                                diff = 0;
                        }
                }
@@ -1234,7 +1290,7 @@ int ofd_create(const struct lu_env *env, struct obd_export *exp,
                        }
 
                        rc = ofd_precreate_objects(env, ofd, next_id,
-                                                  oseq, count);
+                                                  oseq, count, sync_trans);
                        if (rc > 0) {
                                created += rc;
                                diff -= rc;
@@ -1247,7 +1303,8 @@ int ofd_create(const struct lu_env *env, struct obd_export *exp,
                         * them, even if last creation failed */
                        rc = 0;
                else
-                       CERROR("unable to precreate: %d\n", rc);
+                       CERROR("%s: unable to precreate: rc = %d\n",
+                              ofd_name(ofd), rc);
 
                oa->o_id = ofd_seq_last_oid(oseq);
                oa->o_valid |= OBD_MD_FLID | OBD_MD_FLGROUP;
@@ -1366,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)
 {
@@ -1377,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);
 
@@ -1395,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;