Whamcloud - gitweb
LU-17308 mgs: move pool_cmd check to the kernel
[fs/lustre-release.git] / lustre / utils / liblustreapi_chlg.c
index d9c7af0..31b291c 100644 (file)
 #include <poll.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/ioctl.h>
 
 #include <lustre/lustreapi.h>
+#include <linux/lustre/lustre_ioctl.h>
 
 
 static int chlg_dev_path(char *path, size_t path_len, const char *device)
@@ -68,6 +70,8 @@ struct changelog_private {
        int                              clp_fd;
        /* Changelog delivery mode */
        enum changelog_send_flag         clp_send_flags;
+       /* Changelog extra flags */
+       enum changelog_send_extra_flag   clp_send_extra_flags;
        /* Available bytes in buffer */
        size_t                           clp_buf_len;
        /* Current position in buffer */
@@ -89,8 +93,8 @@ int llapi_changelog_start(void **priv, enum changelog_send_flag flags,
                          const char *device, long long startrec)
 {
        struct changelog_private *cp;
+       static bool warned_extra_flags;
        static bool warned_jobid;
-       static bool warned_follow;
        char cdev_path[PATH_MAX];
        int rc;
 
@@ -128,6 +132,17 @@ int llapi_changelog_start(void **priv, enum changelog_send_flag flags,
 
        *priv = cp;
 
+       /* CHANGELOG_FLAG_EXTRA_FLAGS will eventually become mandatory.
+        * If it wasn't specified, display a warning here.
+        * Code elsewhere will remove the corresponding extension.
+        */
+       if (!(flags & CHANGELOG_FLAG_EXTRA_FLAGS) && !warned_extra_flags) {
+               llapi_err_noerrno(LLAPI_MSG_WARN,
+                     "warning: %s() called without CHANGELOG_FLAG_EXTRA_FLAGS",
+                     __func__);
+               warned_extra_flags = true;
+       }
+
        /* CHANGELOG_FLAG_JOBID will eventually become mandatory. Display a
         * warning if it's missing. */
        if (!(flags & CHANGELOG_FLAG_JOBID) && !warned_jobid) {
@@ -136,12 +151,14 @@ int llapi_changelog_start(void **priv, enum changelog_send_flag flags,
                warned_jobid = true;
        }
 
-       /* Behavior expected by CHANGELOG_FLAG_FOLLOW is not implemented, warn
-        * the user and ignore it. */
-       if (flags & CHANGELOG_FLAG_FOLLOW && !warned_follow) {
-               llapi_err_noerrno(LLAPI_MSG_WARN, "warning: %s() called with "
-                                 "CHANGELOG_FLAG_FOLLOW (ignored)", __func__);
-               warned_follow = true;
+       if (flags & CHANGELOG_FLAG_FOLLOW) {
+               int rc;
+
+               rc = ioctl(cp->clp_fd, OBD_IOC_CHLG_SET_FLAGS,
+                          CHANGELOG_FLAG_FOLLOW);
+               if (rc < 0)
+                       llapi_err_noerrno(LLAPI_MSG_ERROR, "can't enable "
+                                         "CHANGELOG_FLAG_FOLLOW");
        }
 
        return 0;
@@ -212,6 +229,7 @@ int llapi_changelog_recv(void *priv, struct changelog_rec **rech)
 {
        struct changelog_private *cp = priv;
        enum changelog_rec_flags rec_fmt = DEFAULT_RECORD_FMT;
+       enum changelog_rec_extra_flags rec_extra_fmt = CLFE_INVALID;
        struct changelog_rec *tmp;
        int rc = 0;
 
@@ -228,12 +246,24 @@ int llapi_changelog_recv(void *priv, struct changelog_rec **rech)
        if (cp->clp_send_flags & CHANGELOG_FLAG_JOBID)
                rec_fmt |= CLF_JOBID;
 
+       if (cp->clp_send_flags & CHANGELOG_FLAG_EXTRA_FLAGS) {
+               rec_fmt |= CLF_EXTRA_FLAGS;
+               if (cp->clp_send_extra_flags & CHANGELOG_EXTRA_FLAG_UIDGID)
+                       rec_extra_fmt |= CLFE_UIDGID;
+               if (cp->clp_send_extra_flags & CHANGELOG_EXTRA_FLAG_NID)
+                       rec_extra_fmt |= CLFE_NID;
+               if (cp->clp_send_extra_flags & CHANGELOG_EXTRA_FLAG_OMODE)
+                       rec_extra_fmt |= CLFE_OPEN;
+               if (cp->clp_send_extra_flags & CHANGELOG_EXTRA_FLAG_XATTR)
+                       rec_extra_fmt |= CLFE_XATTR;
+       }
+
        if (cp->clp_buf + cp->clp_buf_len <= cp->clp_buf_pos) {
                ssize_t refresh;
 
                refresh = chlg_read_bulk(cp);
                if (refresh == 0) {
-                       /* EOF, CHANGELOG_FLAG_FOLLOW ignored for now LU-7659 */
+                       /* EOF */
                        rc = 1;
                        goto out_free;
                } else if (refresh < 0) {
@@ -249,7 +279,7 @@ int llapi_changelog_recv(void *priv, struct changelog_rec **rech)
               changelog_rec_size(tmp) + tmp->cr_namelen);
 
        cp->clp_buf_pos += changelog_rec_size(tmp) + tmp->cr_namelen;
-       changelog_remap_rec(*rech, rec_fmt);
+       changelog_remap_rec(*rech, rec_fmt, rec_extra_fmt);
 
        return 0;
 
@@ -267,12 +297,21 @@ int llapi_changelog_free(struct changelog_rec **rech)
        return 0;
 }
 
+int llapi_changelog_in_buf(void *priv)
+{
+       struct changelog_private *cp = priv;
+       if (cp->clp_buf + cp->clp_buf_len > cp->clp_buf_pos)
+               return 1;
+       return 0;
+}
+
 int llapi_changelog_clear(const char *mdtname, const char *idstr,
                          long long endrec)
 {
        char dev_path[PATH_MAX];
        char cmd[64];
        size_t cmd_len = sizeof(cmd);
+       char *dashp, *clidp = NULL;
        int fd;
        int rc;
 
@@ -284,17 +323,26 @@ int llapi_changelog_clear(const char *mdtname, const char *idstr,
 
        chlg_dev_path(dev_path, sizeof(dev_path), mdtname);
 
-       rc = snprintf(cmd, cmd_len, "clear:%s:%lld", idstr, endrec);
-       if (rc >= sizeof(cmd))
-               return -EINVAL;
+       dashp = strchr(idstr, '-');
+       if (dashp) {
+               clidp = strndup(idstr, dashp - idstr);
+               if (!clidp)
+                       return -ENOMEM;
+       }
 
+       rc = snprintf(cmd, cmd_len, "clear:%s:%lld", dashp ? clidp : idstr,
+                     endrec);
+       if (rc >= sizeof(cmd)) {
+               rc = -EINVAL;
+               goto out;
+       }
        cmd_len = rc + 1;
 
        fd = open(dev_path, O_WRONLY);
        if (fd < 0) {
                rc = -errno;
                llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", dev_path);
-               return rc;
+               goto out;
        }
 
        rc = write(fd, cmd, cmd_len);
@@ -309,5 +357,40 @@ int llapi_changelog_clear(const char *mdtname, const char *idstr,
 
 out_close:
        close(fd);
+out:
+       free(clidp);
        return rc;
 }
+
+/**
+ * Set extra flags for reading changelogs
+ *
+ * @param priv         Opaque private control structure
+ * @param extra_flags  Read extra flags (e.g. CHANGELOG_EXTRA_FLAG_UIDGID)
+ *
+ * Just call this function right after llapi_changelog_start().
+ */
+int llapi_changelog_set_xflags(void *priv,
+                              enum changelog_send_extra_flag extra_flags)
+{
+       struct changelog_private *cp = priv;
+       static bool warned_uidgid;
+
+       if (!cp || cp->clp_magic != CHANGELOG_PRIV_MAGIC)
+               return -EINVAL;
+
+       cp->clp_send_extra_flags = extra_flags;
+
+       /* CHANGELOG_EXTRA_FLAG_UIDGID will eventually become mandatory.
+        * If it wasn't specified, display a warning here.
+        * Code elsewhere will remove the corresponding extension.
+        */
+       if (!(extra_flags & CHANGELOG_EXTRA_FLAG_UIDGID) && !warned_uidgid) {
+               llapi_err_noerrno(LLAPI_MSG_WARN,
+                    "warning: %s() called without CHANGELOG_EXTRA_FLAG_UIDGID",
+                    __func__);
+               warned_uidgid = true;
+       }
+
+       return 0;
+}