return rc;
}
-/****** Changelog API ********/
-
-static int changelog_ioctl(const char *mdtname, int opc, int id,
- long long recno, int flags)
-{
- struct ioc_changelog data;
- int *idx;
-
- data.icc_id = id;
- data.icc_recno = recno;
- data.icc_flags = flags;
- idx = (int *)(&data.icc_mdtindex);
-
- return root_ioctl(mdtname, opc, &data, idx, WANT_ERROR);
-}
-
-#define CHANGELOG_PRIV_MAGIC 0xCA8E1080
-struct changelog_private {
- int magic;
- enum changelog_send_flag flags;
- struct lustre_kernelcomm kuc;
-};
-
-/** Start reading from a changelog
- * @param priv Opaque private control structure
- * @param flags Start flags (e.g. CHANGELOG_FLAG_BLOCK)
- * @param device Report changes recorded on this MDT
- * @param startrec Report changes beginning with this record number
- * (just call llapi_changelog_fini when done; don't need an endrec)
- */
-int llapi_changelog_start(void **priv, enum changelog_send_flag flags,
- const char *device, long long startrec)
-{
- struct changelog_private *cp;
- static bool warned;
- int rc;
-
- /* Set up the receiver control struct */
- cp = calloc(1, sizeof(*cp));
- if (cp == NULL)
- return -ENOMEM;
-
- cp->magic = CHANGELOG_PRIV_MAGIC;
- cp->flags = flags;
-
- /* Set up the receiver */
- rc = libcfs_ukuc_start(&cp->kuc, 0 /* no group registration */, 0);
- if (rc < 0)
- goto out_free;
-
- *priv = cp;
-
- /* CHANGELOG_FLAG_JOBID will eventually become mandatory. Display a
- * warning if it's missing. */
- if (!(flags & CHANGELOG_FLAG_JOBID) && !warned) {
- llapi_err_noerrno(LLAPI_MSG_WARN, "warning: %s() called "
- "w/o CHANGELOG_FLAG_JOBID", __func__);
- warned = true;
- }
-
- /* Tell the kernel to start sending */
- rc = changelog_ioctl(device, OBD_IOC_CHANGELOG_SEND, cp->kuc.lk_wfd,
- startrec, flags);
- /* Only the kernel reference keeps the write side open */
- close(cp->kuc.lk_wfd);
- cp->kuc.lk_wfd = LK_NOFD;
- if (rc < 0) {
- /* frees and clears priv */
- llapi_changelog_fini(priv);
- return rc;
- }
-
- return 0;
-
-out_free:
- free(cp);
- return rc;
-}
-
-/** Finish reading from a changelog */
-int llapi_changelog_fini(void **priv)
-{
- struct changelog_private *cp = (struct changelog_private *)*priv;
-
- if (!cp || (cp->magic != CHANGELOG_PRIV_MAGIC))
- return -EINVAL;
-
- libcfs_ukuc_stop(&cp->kuc);
- free(cp);
- *priv = NULL;
- return 0;
-}
-
-/**
- * Convert all records to a same format according to the caller's wishes.
- * Default is CLF_VERSION | CLF_RENAME.
- * Add CLF_JOBID if explicitely requested.
- *
- * \param rec The record to remap. It is expected to be big enough to
- * properly handle the final format.
- * \return 1 if anything changed. 0 otherwise.
- */
-/** Read the next changelog entry
- * @param priv Opaque private control structure
- * @param rech Changelog record handle; record will be allocated here
- * @return 0 valid message received; rec is set
- * <0 error code
- * 1 EOF
- */
-#define DEFAULT_RECORD_FMT (CLF_VERSION | CLF_RENAME)
-int llapi_changelog_recv(void *priv, struct changelog_rec **rech)
-{
- struct changelog_private *cp = (struct changelog_private *)priv;
- struct kuc_hdr *kuch;
- enum changelog_rec_flags rec_fmt = DEFAULT_RECORD_FMT;
- int rc = 0;
-
- if (!cp || (cp->magic != CHANGELOG_PRIV_MAGIC))
- return -EINVAL;
- if (rech == NULL)
- return -EINVAL;
- kuch = malloc(KUC_CHANGELOG_MSG_MAXSIZE);
- if (kuch == NULL)
- return -ENOMEM;
-
- if (cp->flags & CHANGELOG_FLAG_JOBID)
- rec_fmt |= CLF_JOBID;
-
-repeat:
- rc = libcfs_ukuc_msg_get(&cp->kuc, (char *)kuch,
- KUC_CHANGELOG_MSG_MAXSIZE,
- KUC_TRANSPORT_CHANGELOG);
- if (rc < 0)
- goto out_free;
-
- if ((kuch->kuc_transport != KUC_TRANSPORT_CHANGELOG) ||
- ((kuch->kuc_msgtype != CL_RECORD) &&
- (kuch->kuc_msgtype != CL_EOF))) {
- llapi_err_noerrno(LLAPI_MSG_ERROR,
- "Unknown changelog message type %d:%d\n",
- kuch->kuc_transport, kuch->kuc_msgtype);
- rc = -EPROTO;
- goto out_free;
- }
-
- if (kuch->kuc_msgtype == CL_EOF) {
- if (cp->flags & CHANGELOG_FLAG_FOLLOW) {
- /* Ignore EOFs */
- goto repeat;
- } else {
- rc = 1;
- goto out_free;
- }
- }
-
- /* Our message is a changelog_rec. Use pointer math to skip
- * kuch_hdr and point directly to the message payload. */
- *rech = (struct changelog_rec *)(kuch + 1);
- changelog_remap_rec(*rech, rec_fmt);
-
- return 0;
-
-out_free:
- *rech = NULL;
- free(kuch);
- return rc;
-}
-
-/** Release the changelog record when done with it. */
-int llapi_changelog_free(struct changelog_rec **rech)
-{
- if (*rech) {
- /* We allocated memory starting at the kuc_hdr, but passed
- * the consumer a pointer to the payload.
- * Use pointer math to get back to the header.
- */
- struct kuc_hdr *kuch = (struct kuc_hdr *)*rech - 1;
- free(kuch);
- }
- *rech = NULL;
- return 0;
-}
-
-int llapi_changelog_clear(const char *mdtname, const char *idstr,
- long long endrec)
-{
- long id;
-
- if (endrec < 0) {
- llapi_err_noerrno(LLAPI_MSG_ERROR,
- "can't purge negative records\n");
- return -EINVAL;
- }
-
- id = strtol(idstr + strlen(CHANGELOG_USER_PREFIX), NULL, 10);
- if ((id == 0) || (strncmp(idstr, CHANGELOG_USER_PREFIX,
- strlen(CHANGELOG_USER_PREFIX)) != 0)) {
- llapi_err_noerrno(LLAPI_MSG_ERROR,
- "expecting id of the form '"
- CHANGELOG_USER_PREFIX
- "<num>'; got '%s'\n", idstr);
- return -EINVAL;
- }
-
- return changelog_ioctl(mdtname, OBD_IOC_CHANGELOG_CLEAR, id, endrec, 0);
-}
-
int llapi_fid2path(const char *device, const char *fidstr, char *buf,
int buflen, long long *recno, int *linkno)
{