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

[RFC] create-namespace: Add percentage option #209

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
64 changes: 64 additions & 0 deletions ndctl/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,64 @@ static int validate_available_capacity(struct ndctl_region *region,
return 0;
}

static int validate_available_percentage(struct ndctl_region *region,
struct parsed_parameters *p)
{
unsigned long long available, max, pct;
unsigned long region_align;

pct = p->size;

if (p->size == 0) {
debug("%s: non-zero percentage of total region size required for namespace creation\n",
ndctl_region_get_devname(region));
return -EINVAL;
}

max = ndctl_region_get_size(region);

if (ndctl_region_get_nstype(region) == ND_DEVICE_NAMESPACE_IO)
available = ndctl_region_get_size(region);
else {
available = ndctl_region_get_max_available_extent(region);
if (available == ULLONG_MAX)
available = ndctl_region_get_available_size(region);
}

/* percentage is expressed in terms of the total region size */
p->size = (unsigned long long) (max * ((double) pct / 100));

region_align = ndctl_region_get_align(region);
if (p->size % region_align) {
/* only round up if rounded up size would use the available region capacity */
if (p->size + region_align - (p->size % region_align) == available) {
debug("%s: percentage %llu of total region size: %#llx results in unaligned size: %#llx (align setting %#lx) rounding up to size: %#llx\n",
ndctl_region_get_devname(region), pct, max,
p->size, region_align,
p->size + region_align - (p->size % region_align));
p->size += region_align - (p->size % region_align);
}
/* otherwise round down */
else {
debug("%s: percentage %llu of total region size: %#llx results in unaligned size: %#llx (align setting %#lx) rounding down to size: %#llx\n",
ndctl_region_get_devname(region), pct, max,
p->size, region_align,
p->size & (~(region_align - 1)));
p->size &= ~(region_align - 1);
}
}

if (!available || p->size > available) {
debug("%s: insufficient capacity size: %llx avail: %llx\n",
ndctl_region_get_devname(region), p->size, available);
return -EAGAIN;
}

debug("%s: percentage requested: %llu of total region size: %llx size requested: %llx avail: %llx\n",
ndctl_region_get_devname(region), pct, max, p->size, available);
return 0;
}

/*
* validate_namespace_options - init parameters for setup_namespace
* @region: parent of the namespace to create / reconfigure
Expand Down Expand Up @@ -671,6 +729,12 @@ static int validate_namespace_options(struct ndctl_region *region,
else
default_size = true;

if (units == SZ_PCT) {
rc = validate_available_percentage(region, p);
if (rc)
return rc;
}

/*
* Validate available capacity in the create case, in the
* reconfigure case the capacity is already allocated. A default
Expand Down
5 changes: 5 additions & 0 deletions util/size.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ unsigned long long __parse_size64(const char *str, unsigned long long *units)
val *= SZ_1T;
end++;
break;
case '%':
if (units)
*units = SZ_PCT;
end++;
break;
default:
if (units)
*units = 1;
Expand Down
1 change: 1 addition & 0 deletions util/size.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define SZ_256M 0x10000000
#define SZ_1G 0x40000000
#define SZ_1T 0x10000000000ULL
#define SZ_PCT 0x0

unsigned long long parse_size64(const char *str);
unsigned long long __parse_size64(const char *str, unsigned long long *units);
Expand Down