+struct llog_del_ost_priv {
+ char *logname;
+ char *ostname;
+ int found;
+ int dryrun;
+};
+
+/**
+ * Callback to search and delete ostname in llog
+ *
+ * \param record[in] pointer to llog record
+ * \param data[in] pointer to ostname
+ *
+ * \retval 1 if ostname is found and entry deleted
+ * 0 if ostname is not found
+ * < 0 if error
+ */
+static int llog_del_ost_cb(const char *record, void *data)
+{
+ char ost_filter[MAX_STRING_SIZE] = {'\0'};
+ char log_idxstr[MAX_STRING_SIZE] = {'\0'};
+ long int log_idx = 0;
+ struct llog_del_ost_priv *priv = data;
+ char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
+ struct obd_ioctl_data ioc_data = { 0 };
+ int rc = 0;
+
+ if (priv->ostname && priv->ostname[0])
+ snprintf(ost_filter, sizeof(ost_filter), " %s", priv->ostname);
+
+ if (!strstr(record, ost_filter))
+ return rc;
+
+ rc = sscanf(record, "- { index: %ld", &log_idx);
+ if (rc < 0) {
+ fprintf(stderr, "error: record without index:\n%s\n",
+ record);
+ return 0;
+ }
+ snprintf(log_idxstr, sizeof(log_idxstr), "%ld", log_idx);
+
+ ioc_data.ioc_dev = cur_device;
+ ioc_data.ioc_inllen1 = strlen(priv->logname) + 1;
+ ioc_data.ioc_inlbuf1 = priv->logname;
+ ioc_data.ioc_inllen3 = strlen(log_idxstr) + 1;
+ ioc_data.ioc_inlbuf3 = log_idxstr;
+
+ rc = llapi_ioctl_pack(&ioc_data, &buf, sizeof(rawbuf));
+ if (rc) {
+ fprintf(stderr, "ioctl_pack for catalog '%s' failed: %s\n",
+ ioc_data.ioc_inlbuf1, strerror(-rc));
+ return rc;
+ }
+
+ if (priv->dryrun) {
+ fprintf(stdout, "[DRY RUN] cancel catalog '%s:%s':\"%s\"\n",
+ ioc_data.ioc_inlbuf1, ioc_data.ioc_inlbuf3, record);
+ } else {
+ rc = l_ioctl(OBD_DEV_ID, OBD_IOC_LLOG_CANCEL, buf);
+ if (rc)
+ fprintf(stderr, "cancel catalog '%s:%s' failed: %s\n",
+ ioc_data.ioc_inlbuf1, ioc_data.ioc_inlbuf3,
+ strerror(errno));
+ else {
+ fprintf(stdout, "cancel catalog %s log_idx %ld: done\n",
+ priv->logname, log_idx);
+ priv->found++;
+ }
+ }
+ return rc;
+}
+
+/**
+ * Search and delete ost in llog
+ *
+ * \param logname[in] pointer to config log name
+ * \param last_index[in] the index of the last llog record
+ * \param ostname[in] pointer to ost name
+ * \param dryrun[in] dry run?
+ *
+ * \retval 1 if ostname is found and deleted
+ * 0 if ostname is not found
+ */
+static int llog_del_ost(char *logname, long last_index, char *ostname,
+ int dryrun)
+{
+ long start, end, inc = MAX_IOC_BUFLEN / 128;
+ int rc = 0;
+ struct llog_del_ost_priv priv = { logname, ostname, false, dryrun };
+
+ for (end = last_index; end > 1; end -= inc) {
+ start = end - inc > 0 ? end - inc : 1;
+ rc = jt_llog_print_iter(logname, start, end, llog_del_ost_cb,
+ &priv, true, false);
+ if (rc)
+ break;
+ }
+
+ if (priv.found)
+ fprintf(stdout, "del_ost: cancelled %d catalog entries\n",
+ priv.found);
+ else
+ fprintf(stdout, "del_ost: no catalog entry deleted\n");
+
+ return rc;
+}
+