nvlist_t ***, uint_t *);
extern int zpool_events_next(libzfs_handle_t *, nvlist_t **, int *, int, int);
extern int zpool_events_clear(libzfs_handle_t *, int *);
+extern int zpool_events_seek(libzfs_handle_t *, uint64_t, int);
extern void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *,
size_t len);
extern int zfs_ioctl(libzfs_handle_t *, int, struct zfs_cmd *);
#ifdef _KERNEL
-#define ZEVENT_SHUTDOWN 0x1
+#define ZEVENT_SHUTDOWN 0x1
typedef void zevent_cb_t(nvlist_t *, nvlist_t *);
extern void zfs_zevent_fd_rele(int);
extern int zfs_zevent_next(zfs_zevent_t *, nvlist_t **, uint64_t *, uint64_t *);
extern int zfs_zevent_wait(zfs_zevent_t *);
+extern int zfs_zevent_seek(zfs_zevent_t *, uint64_t);
extern void zfs_zevent_init(zfs_zevent_t **);
extern void zfs_zevent_destroy(zfs_zevent_t *);
ZFS_IOC_LINUX = ('Z' << 8) + 0x80,
ZFS_IOC_EVENTS_NEXT,
ZFS_IOC_EVENTS_CLEAR,
+ ZFS_IOC_EVENTS_SEEK,
/*
* FreeBSD - 1/64 numbers reserved.
#define ZEVENT_NONBLOCK 0x1
#define ZEVENT_SIZE 1024
+#define ZEVENT_SEEK_START 0
+#define ZEVENT_SEEK_END UINT64_MAX
+
typedef enum zinject_type {
ZINJECT_UNINITIALIZED,
ZINJECT_DATA_FAULT,
return (0);
}
+/*
+ * Seek to a specific EID, ZEVENT_SEEK_START, or ZEVENT_SEEK_END for
+ * the passed zevent_fd file handle. On success zero is returned,
+ * otherwise -1 is returned and hdl->libzfs_error is set to the errno.
+ */
+int
+zpool_events_seek(libzfs_handle_t *hdl, uint64_t eid, int zevent_fd)
+{
+ zfs_cmd_t zc = {"\0"};
+ int error = 0;
+
+ zc.zc_guid = eid;
+ zc.zc_cleanup_fd = zevent_fd;
+
+ if (zfs_ioctl(hdl, ZFS_IOC_EVENTS_SEEK, &zc) != 0) {
+ switch (errno) {
+ case ENOENT:
+ error = zfs_error_fmt(hdl, EZFS_NOENT,
+ dgettext(TEXT_DOMAIN, "cannot get event"));
+ break;
+
+ case ENOMEM:
+ error = zfs_error_fmt(hdl, EZFS_NOMEM,
+ dgettext(TEXT_DOMAIN, "cannot get event"));
+ break;
+
+ default:
+ error = zpool_standard_error_fmt(hdl, errno,
+ dgettext(TEXT_DOMAIN, "cannot get event"));
+ break;
+ }
+ }
+
+ return (error);
+}
+
void
zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
char *pathname, size_t len)
return (error);
}
+/*
+ * The caller may seek to a specific EID by passing that EID. If the EID
+ * is still available in the posted list of events the cursor is positioned
+ * there. Otherwise ENOENT is returned and the cursor is not moved.
+ *
+ * There are two reserved EIDs which may be passed and will never fail.
+ * ZEVENT_SEEK_START positions the cursor at the start of the list, and
+ * ZEVENT_SEEK_END positions the cursor at the end of the list.
+ */
+int
+zfs_zevent_seek(zfs_zevent_t *ze, uint64_t eid)
+{
+ zevent_t *ev;
+ int error = 0;
+
+ mutex_enter(&zevent_lock);
+
+ if (eid == ZEVENT_SEEK_START) {
+ if (ze->ze_zevent)
+ list_remove(&ze->ze_zevent->ev_ze_list, ze);
+
+ ze->ze_zevent = NULL;
+ goto out;
+ }
+
+ if (eid == ZEVENT_SEEK_END) {
+ if (ze->ze_zevent)
+ list_remove(&ze->ze_zevent->ev_ze_list, ze);
+
+ ev = list_head(&zevent_list);
+ if (ev) {
+ ze->ze_zevent = ev;
+ list_insert_head(&ev->ev_ze_list, ze);
+ } else {
+ ze->ze_zevent = NULL;
+ }
+
+ goto out;
+ }
+
+ for (ev = list_tail(&zevent_list); ev != NULL;
+ ev = list_prev(&zevent_list, ev)) {
+ if (ev->ev_eid == eid) {
+ if (ze->ze_zevent)
+ list_remove(&ze->ze_zevent->ev_ze_list, ze);
+
+ ze->ze_zevent = ev;
+ list_insert_head(&ev->ev_ze_list, ze);
+ break;
+ }
+ }
+
+ if (ev == NULL)
+ error = ENOENT;
+
+out:
+ mutex_exit(&zevent_lock);
+
+ return (error);
+}
+
void
zfs_zevent_init(zfs_zevent_t **zep)
{
return (0);
}
+/*
+ * inputs:
+ * zc_guid eid | ZEVENT_SEEK_START | ZEVENT_SEEK_END
+ * zc_cleanup zevent file descriptor
+ */
+static int
+zfs_ioc_events_seek(zfs_cmd_t *zc)
+{
+ zfs_zevent_t *ze;
+ minor_t minor;
+ int error;
+
+ error = zfs_zevent_fd_hold(zc->zc_cleanup_fd, &minor, &ze);
+ if (error != 0)
+ return (error);
+
+ error = zfs_zevent_seek(ze, zc->zc_guid);
+ zfs_zevent_fd_rele(zc->zc_cleanup_fd);
+
+ return (error);
+}
+
/*
* inputs:
* zc_name name of new filesystem or snapshot
zfs_secpolicy_config, NO_NAME, B_FALSE, POOL_CHECK_NONE);
zfs_ioctl_register_legacy(ZFS_IOC_EVENTS_CLEAR, zfs_ioc_events_clear,
zfs_secpolicy_config, NO_NAME, B_FALSE, POOL_CHECK_NONE);
+ zfs_ioctl_register_legacy(ZFS_IOC_EVENTS_SEEK, zfs_ioc_events_seek,
+ zfs_secpolicy_config, NO_NAME, B_FALSE, POOL_CHECK_NONE);
}
int