Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding zpool API to retrieve allocated and total size of a zpool #4

Merged
merged 1 commit into from
Sep 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/os/windows/zfs/sys/zfs_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,5 +184,7 @@ extern NTSTATUS ioctl_mountdev_query_stable_guid(PDEVICE_OBJECT, PIRP,
PIO_STACK_LOCATION);
extern NTSTATUS ioctl_query_stable_guid(PDEVICE_OBJECT, PIRP,
PIO_STACK_LOCATION);
extern NTSTATUS zpool_get_size_stats(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp);

#endif
20 changes: 16 additions & 4 deletions include/sys/zfs_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,18 @@ typedef struct zfs_useracct {
uint64_t zu_space;
} zfs_useracct_t;

#define ZPOOL_GET_SIZE_STATS CTL_CODE(ZFSIOCTL_TYPE, 0xFFF, \
METHOD_BUFFERED, FILE_ANY_ACCESS)

// Input/Output for IOCTL - ZPOOL_GET_SIZE_STATS
typedef struct {
uint8_t targetid;
uint8_t lun;
char zpool_name[MAXNAMELEN];
uint64_t size;
uint64_t alloc;
} zpool_size_stats;

typedef struct
{
uint64_t total;
Expand Down Expand Up @@ -597,9 +609,9 @@ typedef struct {
uint64_t arcstat_l2_write_bytes;
uint64_t arcstat_l2_access_ps;

/*
* ZIL and SLOG counters
*/
/*
* ZIL and SLOG counters
*/
uint64_t zil_commit_count;
uint64_t zil_commit_writer_count;
uint64_t zil_itx_count;
Expand Down Expand Up @@ -636,7 +648,7 @@ extern void zfs_unmount_snap(const char *);
extern void zfs_destroy_unmount_origin(const char *);
extern int getzfsvfs_impl(struct objset *, struct zfsvfs **);
extern int getzfsvfs(const char *, struct zfsvfs **);
extern void latency_stats(uint64_t* histo, unsigned int buckets,
extern void latency_stats(uint64_t *histo, unsigned int buckets,
stat_pair* lat);

datacore-rm marked this conversation as resolved.
Show resolved Hide resolved
enum zfsdev_state_type {
Expand Down
48 changes: 30 additions & 18 deletions module/os/windows/zfs/zfs_vnops_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,8 @@ zfs_find_dvp_vp(zfsvfs_t *zfsvfs, char *filename, int finalpartmaynotexist,
zp->z_size, '!FSZ');
zfs_uio_t uio;
struct iovec iov = { rpb, zp->z_size };
zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, zp->z_size, 0);
zfs_uio_iovec_init(&uio, &iov, 1, 0,
UIO_SYSSPACE, zp->z_size, 0);
zfs_readlink(vp, &uio, NULL);
VN_RELE(vp);

Expand Down Expand Up @@ -2379,11 +2380,13 @@ zfswin_insert_xattrname(struct vnode *vp, char *xattrname, uint8_t *outbuffer,
iov.iov_len = roomforvalue;

zfs_uio_t uio;
zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, roomforvalue, 0);
zfs_uio_iovec_init(&uio, &iov, 1, 0,
UIO_SYSSPACE, roomforvalue, 0);

zfs_read(VTOZ(vp), &uio, 0, NULL);
// Consume as many bytes as we read
*spaceused += roomforvalue - zfs_uio_resid(&uio);
*spaceused += roomforvalue -
zfs_uio_resid(&uio);
// Set the valuelen, should this be the full
// value or what we would need?
// That is how the names work.
Expand Down Expand Up @@ -2626,7 +2629,8 @@ get_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp,
iov.iov_len = size;

zfs_uio_t uio;
zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, size, 0);
zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE,
size, 0);
err = zfs_readlink(vp, &uio, NULL);

if (outlen < zp->z_size)
Expand Down Expand Up @@ -2990,13 +2994,14 @@ query_directory_FileFullDirectoryInformation(PDEVICE_OBJECT DeviceObject,
// Did last call complete listing?
if (zccb->dir_eof)
return (STATUS_NO_MORE_FILES);
struct iovec iov;
struct iovec iov;
void *SystemBuffer = MapUserBuffer(Irp);
iov.iov_base = (void *)SystemBuffer;
iov.iov_len = IrpSp->Parameters.QueryDirectory.Length;
iov.iov_base = (void *)SystemBuffer;
iov.iov_len = IrpSp->Parameters.QueryDirectory.Length;

zfs_uio_t uio;
zfs_uio_iovec_init(&uio, &iov, 1, zccb->uio_offset, UIO_SYSSPACE, IrpSp->Parameters.QueryDirectory.Length, 0);
zfs_uio_t uio;
zfs_uio_iovec_init(&uio, &iov, 1, zccb->uio_offset, UIO_SYSSPACE,
IrpSp->Parameters.QueryDirectory.Length, 0);

// Grab the root zp
zmo = DeviceObject->DeviceExtension;
Expand Down Expand Up @@ -3057,7 +3062,8 @@ query_directory_FileFullDirectoryInformation(PDEVICE_OBJECT DeviceObject,

// Set correct buffer size returned.
Irp->IoStatus.Information =
IrpSp->Parameters.QueryDirectory.Length - zfs_uio_resid(&uio);
IrpSp->Parameters.QueryDirectory.Length -
zfs_uio_resid(&uio);

dprintf("dirlist information in %d out size %d\n",
IrpSp->Parameters.QueryDirectory.Length,
Expand Down Expand Up @@ -3439,9 +3445,9 @@ fs_read(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
} // !nocache


struct iovec iov;
iov.iov_base = (void *)SystemBuffer;
iov.iov_len = bufferLength;
struct iovec iov;
iov.iov_base = (void *)SystemBuffer;
iov.iov_len = bufferLength;

zfs_uio_t uio;
zfs_uio_iovec_init(&uio, &iov, 1, byteOffset.QuadPart, UIO_SYSSPACE, bufferLength, 0);
Expand Down Expand Up @@ -3680,12 +3686,13 @@ fs_write(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
}
}

struct iovec iov;
iov.iov_base = (void *)SystemBuffer;
iov.iov_len = bufferLength;
struct iovec iov;
iov.iov_base = (void *)SystemBuffer;
iov.iov_len = bufferLength;

zfs_uio_t uio;
zfs_uio_iovec_init(&uio, &iov, 1, byteOffset.QuadPart, UIO_SYSSPACE, bufferLength, 0);
zfs_uio_t uio;
zfs_uio_iovec_init(&uio, &iov, 1, byteOffset.QuadPart, UIO_SYSSPACE,
bufferLength, 0);

// dprintf("%s: offset %llx size %lx\n", __func__,
// byteOffset.QuadPart, bufferLength);
Expand Down Expand Up @@ -4542,6 +4549,11 @@ _Function_class_(DRIVER_DISPATCH)
Status = spl_kstat_write(DeviceObject, Irp,
IrpSp);
break;
case ZPOOL_GET_SIZE_STATS:
dprintf("ZPOOL_GET_SIZE_STATS\n");
Status = zpool_get_size_stats(DeviceObject,
Irp, IrpSp);
break;
default:
dprintf("**** unknown Windows IOCTL: 0x%lx\n",
cmd);
Expand Down
4 changes: 2 additions & 2 deletions module/os/windows/zfs/zfs_windows_zvol_scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ wzvol_lock_target(zvol_state_t *zv)
return (FALSE);
}

static inline void
void
wzvol_unlock_target(zvol_state_t *zv)
{
wzvolContext* zvc = (pwzvolContext)zv->zv_zso->zso_target_context;
Expand Down Expand Up @@ -222,7 +222,7 @@ wzvol_assign_targetid(zvol_state_t *zv)
* note: find_target will lock the zv's remove lock. caller
* is responsible to unlock_target if a non-NULL zv pointer is returned
*/
static inline zvol_state_t *
zvol_state_t *
wzvol_find_target(uint8_t targetid, uint8_t lun)
{
wzvolContext *zv_targets = STOR_wzvolDriverInfo.zvContextArray;
Expand Down
67 changes: 67 additions & 0 deletions module/os/windows/zfs/zvol_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -1035,3 +1035,70 @@ zvol_fini(void)
zvol_fini_impl();
taskq_destroy(zvol_taskq);
}

/* Returns 1 on failure; Returns 0 on success */
int
fetch_zpool_stats(zpool_size_stats *zstats) {
int ret = 1;

// If 'zpool/zvol' name is provided, truncating it to zpool name only
char *slash = strchr(zstats->zpool_name, '/');
if (slash)
*slash = '\0';

mutex_enter(&spa_namespace_lock);
spa_t *spa;
if ((spa = spa_lookup(zstats->zpool_name)) != NULL) {
mutex_enter(&spa->spa_props_lock);
metaslab_class_t *mc = spa_normal_class(spa);

zstats->alloc = metaslab_class_get_alloc(mc);
zstats->alloc +=
metaslab_class_get_alloc(spa_special_class(spa));
zstats->alloc +=
metaslab_class_get_alloc(spa_dedup_class(spa));

zstats->size = metaslab_class_get_space(mc);
zstats->size +=
metaslab_class_get_space(spa_special_class(spa));
zstats->size += metaslab_class_get_space(spa_dedup_class(spa));
mutex_exit(&spa->spa_props_lock);
ret = 0;
}
mutex_exit(&spa_namespace_lock);
return (ret);
}

extern zvol_state_t *wzvol_find_target(uint8_t targetid, uint8_t lun);
extern void wzvol_unlock_target(zvol_state_t *zv);

NTSTATUS
zpool_get_size_stats(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof (zpool_size_stats)) {
Irp->IoStatus.Information = sizeof (zpool_size_stats);
return (STATUS_BUFFER_TOO_SMALL);
}

zpool_size_stats *zpool_stats =
(zpool_size_stats *)Irp->AssociatedIrp.SystemBuffer;
if (!zpool_stats)
return (STATUS_INVALID_PARAMETER);

zvol_state_t *zv = NULL;
zv = wzvol_find_target(zpool_stats->targetid, zpool_stats->lun);
if (zv == NULL)
return (STATUS_INVALID_PARAMETER);

size_t len = sizeof (zpool_stats->zpool_name);
strncpy_s(zpool_stats->zpool_name, len, zv->zv_name, len - 1);
wzvol_unlock_target(zv);

if (fetch_zpool_stats(zpool_stats))
return (STATUS_NOT_FOUND);

Irp->IoStatus.Information = sizeof (zpool_size_stats);
return (STATUS_SUCCESS);
}