int zfs_snapshot_list_next(void *ptr, char *snapname, uint64_t *idp, uint64_t *cookiep, boolean_t *case_conflictp) { zfsvfs_t *zfsvfs = NULL; int err; ASSERT(ptr); zfsvfs = (zfsvfs_t *) ptr; err = dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN, snapname, idp, cookiep, case_conflictp); return err; }
static zfs_handle_t *libzfs_zfs_snapshot_next(libzfs_handle_t *p_libzfshd, const char *psz_zfs, char *psz_buffer, size_t i_buffer, uint64_t *p_cookie, const char **ppsz_error) { objset_t *p_os; size_t i_zfs_len = strlen(psz_zfs); int i_error; /* Check the size of the zfs name */ if(i_zfs_len >= i_buffer) { *ppsz_error = "ZFS name too long to handle snapshots"; return NULL; } if(*p_cookie == 0) dmu_objset_find(psz_zfs, dmu_objset_prefetch, NULL, DS_FIND_SNAPSHOTS); top: if((i_error = dmu_objset_hold(psz_zfs, FTAG, &p_os))) { *ppsz_error = "Unable to hold the zfs filesystem"; return NULL; } snprintf(psz_buffer, i_buffer, "%s@", psz_zfs); if((i_error = dmu_snapshot_list_next(p_os, i_buffer - i_zfs_len - 1, psz_buffer + i_zfs_len + 1, NULL, p_cookie, NULL))) *ppsz_error = "Unable to get the next snapshot"; dmu_objset_rele(p_os, FTAG); zfs_handle_t *p_zfs_snap = NULL; if(i_error == 0) { i_error = dmu_objset_hold(psz_buffer, FTAG, &p_os); if(i_error == ENOENT) goto top; if(!(p_zfs_snap = libzfs_make_dataset_handle(p_libzfshd, psz_buffer))) *ppsz_error = "Unable to create a zfs handle for the snapshot"; dmu_objset_rele(p_os, FTAG); } return p_zfs_snap; }
/* ARGSUSED */ static int zfsctl_snapdir_readdir_cb(vnode_t *vp, void *dp, int *eofp, offset_t *offp, offset_t *nextp, void *data, int flags) { zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; char snapname[ZFS_MAX_DATASET_NAME_LEN]; uint64_t id, cookie; boolean_t case_conflict; int error; ZFS_ENTER(zfsvfs); cookie = *offp; dsl_pool_config_enter(dmu_objset_pool(zfsvfs->z_os), FTAG); error = dmu_snapshot_list_next(zfsvfs->z_os, sizeof (snapname), snapname, &id, &cookie, &case_conflict); dsl_pool_config_exit(dmu_objset_pool(zfsvfs->z_os), FTAG); if (error) { ZFS_EXIT(zfsvfs); if (error == ENOENT) { *eofp = 1; return (0); } return (error); } if (flags & V_RDDIR_ENTFLAGS) { edirent_t *eodp = dp; (void) strcpy(eodp->ed_name, snapname); eodp->ed_ino = ZFSCTL_INO_SNAP(id); eodp->ed_eflags = case_conflict ? ED_CASE_CONFLICT : 0; } else { struct dirent64 *odp = dp; (void) strcpy(odp->d_name, snapname); odp->d_ino = ZFSCTL_INO_SNAP(id); } *nextp = cookie; ZFS_EXIT(zfsvfs); return (0); }
static int zcp_snapshots_iter(lua_State *state) { int err; char snapname[ZFS_MAX_DATASET_NAME_LEN]; uint64_t dsobj = lua_tonumber(state, lua_upvalueindex(1)); uint64_t cursor = lua_tonumber(state, lua_upvalueindex(2)); dsl_pool_t *dp = zcp_run_info(state)->zri_pool; dsl_dataset_t *ds; objset_t *os; char *p; err = dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds); if (err != 0) { return (luaL_error(state, "unexpected error %d from dsl_dataset_hold_obj(dsobj)", err)); } dsl_dataset_name(ds, snapname); VERIFY3U(sizeof (snapname), >, strlcat(snapname, "@", sizeof (snapname))); p = strchr(snapname, '\0'); VERIFY0(dmu_objset_from_ds(ds, &os)); err = dmu_snapshot_list_next(os, sizeof (snapname) - (p - snapname), p, NULL, &cursor, NULL); dsl_dataset_rele(ds, FTAG); if (err == ENOENT) { return (0); } else if (err != 0) { return (luaL_error(state, "unexpected error %d from dmu_snapshot_list_next()", err)); } lua_pushnumber(state, cursor); lua_replace(state, lua_upvalueindex(2)); (void) lua_pushstring(state, snapname); return (1); }
static int zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx) { zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode); fstrans_cookie_t cookie; char snapname[MAXNAMELEN]; boolean_t case_conflict; uint64_t id, pos; int error = 0; ZFS_ENTER(zsb); cookie = spl_fstrans_mark(); if (!dir_emit_dots(filp, ctx)) goto out; pos = ctx->pos; while (error == 0) { dsl_pool_config_enter(dmu_objset_pool(zsb->z_os), FTAG); error = -dmu_snapshot_list_next(zsb->z_os, MAXNAMELEN, snapname, &id, &pos, &case_conflict); dsl_pool_config_exit(dmu_objset_pool(zsb->z_os), FTAG); if (error) goto out; if (!dir_emit(ctx, snapname, strlen(snapname), ZFSCTL_INO_SHARES - id, DT_DIR)) goto out; ctx->pos = pos; } out: spl_fstrans_unmark(cookie); ZFS_EXIT(zsb); if (error == -ENOENT) return (0); return (error); }