Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144463942
D35830.id108279.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D35830.id108279.diff
View Options
diff --git a/lib/libcuse/cuse.3 b/lib/libcuse/cuse.3
--- a/lib/libcuse/cuse.3
+++ b/lib/libcuse/cuse.3
@@ -1,6 +1,6 @@
.\" $FreeBSD$
.\"
-.\" Copyright (c) 2010-2013 Hans Petter Selasky
+.\" Copyright (c) 2010-2022 Hans Petter Selasky
.\"
.\" All rights reserved.
.\"
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 17, 2019
+.Dd July 18, 2022
.Dt CUSE 3
.Os
.Sh NAME
@@ -124,6 +124,11 @@
This function returns a valid data pointer on success or
.Dv NULL
on failure.
+The returned pointer is always aligned to the system page size.
+The number and size of allocations is limited by the
+.Xr mmap 2
+offset having to fit into a 32-bit variable typically for 32-bit
+applications.
.Pp
.Ft "int"
.Fn "cuse_is_vmalloc_addr" "void *"
@@ -136,16 +141,12 @@
.Fn "cuse_vmfree" "void *"
This function frees memory allocated by
.Fn cuse_vmalloc .
-Note that the
-cuse library will internally not free the memory until the
-.Fn cuse_uninit
-function is called and that the number of unique
-allocations is limited.
.Pp
.Ft "unsigned long"
.Fn "cuse_vmoffset" "void *"
-This function returns the mmap offset that the client must use to
+This function returns the mmap offset the client must use to
access the allocated memory.
+The passed pointer must be aligned to the system page size.
.Pp
.Ft "struct cuse_dev *"
.Fn "cuse_dev_create" "const struct cuse_methods *mtod" "void *priv0" "void *priv1" "uid_t" "gid_t" "int permission" "const char *fmt" "..."
diff --git a/lib/libcuse/cuse_lib.c b/lib/libcuse/cuse_lib.c
--- a/lib/libcuse/cuse_lib.c
+++ b/lib/libcuse/cuse_lib.c
@@ -145,7 +145,7 @@
unsigned long n;
CUSE_LOCK();
- for (n = 0; n != CUSE_ALLOC_UNIT_MAX; n++) {
+ for (n = remainder = 0; n != CUSE_ALLOC_UNIT_MAX; n++) {
if (a_cuse[n].ptr == NULL)
continue;
@@ -153,20 +153,13 @@
ptr_max = a_cuse[n].ptr + a_cuse[n].size - 1;
if ((ptr >= ptr_min) && (ptr <= ptr_max)) {
-
- CUSE_UNLOCK();
-
remainder = (ptr - ptr_min);
-
- remainder -= remainder %
- (unsigned long)getpagesize();
-
- return ((n * CUSE_ALLOC_BYTES_MAX) + remainder);
+ break;
}
}
CUSE_UNLOCK();
- return (0x80000000UL); /* failure */
+ return ((n << CUSE_ALLOC_UNIT_SHIFT) + remainder);
}
void *
@@ -174,70 +167,70 @@
{
struct cuse_alloc_info info;
unsigned long pgsize;
+ unsigned long x;
+ unsigned long m;
unsigned long n;
void *ptr;
int error;
- if (f_cuse < 0)
+ /* some sanity checks */
+ if (f_cuse < 0 || size < 1 || (unsigned long)size > CUSE_ALLOC_BYTES_MAX)
return (NULL);
memset(&info, 0, sizeof(info));
- if (size < 1)
- return (NULL);
-
pgsize = getpagesize();
info.page_count = howmany(size, pgsize);
- CUSE_LOCK();
- for (n = 0; n != CUSE_ALLOC_UNIT_MAX; n++) {
+ /* compute how many units the allocation needs */
+ m = howmany(size, 1 << CUSE_ALLOC_UNIT_SHIFT);
+ if (m == 0 || m > CUSE_ALLOC_UNIT_MAX)
+ return (NULL);
- if (a_cuse[n].ptr != NULL)
+ CUSE_LOCK();
+ for (n = 0; n <= CUSE_ALLOC_UNIT_MAX - m; ) {
+ if (a_cuse[n].size != 0) {
+ /* skip to next available unit, depending on allocation size */
+ n += howmany(a_cuse[n].size, 1 << CUSE_ALLOC_UNIT_SHIFT);
continue;
-
- a_cuse[n].ptr = ((uint8_t *)1); /* reserve */
- a_cuse[n].size = 0;
-
+ }
+ /* check if there are "m" free units ahead */
+ for (x = 1; x != m; x++) {
+ if (a_cuse[n + x].size != 0)
+ break;
+ }
+ if (x != m) {
+ /* skip to next available unit, if any */
+ n += x + 1;
+ continue;
+ }
+ /* reserve this unit by setting the size to a non-zero value */
+ a_cuse[n].size = size;
CUSE_UNLOCK();
info.alloc_nr = n;
error = ioctl(f_cuse, CUSE_IOCTL_ALLOC_MEMORY, &info);
- if (error) {
-
- CUSE_LOCK();
-
- a_cuse[n].ptr = NULL;
-
- if (errno == EBUSY)
- continue;
- else
- break;
- }
- ptr = mmap(NULL, info.page_count * pgsize,
- PROT_READ | PROT_WRITE,
- MAP_SHARED, f_cuse, CUSE_ALLOC_BYTES_MAX * n);
-
- if (ptr == MAP_FAILED) {
+ if (error == 0) {
+ ptr = mmap(NULL, info.page_count * pgsize,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, f_cuse, n << CUSE_ALLOC_UNIT_SHIFT);
- error = ioctl(f_cuse, CUSE_IOCTL_FREE_MEMORY, &info);
+ if (ptr != MAP_FAILED) {
+ CUSE_LOCK();
+ a_cuse[n].ptr = ptr;
+ CUSE_UNLOCK();
- if (error) {
- /* ignore */
+ return (ptr); /* success */
}
- CUSE_LOCK();
-
- a_cuse[n].ptr = NULL;
- break;
+ (void) ioctl(f_cuse, CUSE_IOCTL_FREE_MEMORY, &info);
}
- CUSE_LOCK();
- a_cuse[n].ptr = ptr;
- a_cuse[n].size = size;
- CUSE_UNLOCK();
- return (ptr); /* success */
+ CUSE_LOCK();
+ a_cuse[n].size = 0;
+ n++;
}
CUSE_UNLOCK();
return (NULL); /* failure */
@@ -269,7 +262,7 @@
int error;
int n;
- if (f_cuse < 0)
+ if (f_cuse < 0 || ptr == NULL)
return;
CUSE_LOCK();
diff --git a/sys/fs/cuse/cuse.c b/sys/fs/cuse/cuse.c
--- a/sys/fs/cuse/cuse.c
+++ b/sys/fs/cuse/cuse.c
@@ -1159,7 +1159,7 @@
error = ENOMEM;
break;
}
- if (pai->page_count >= CUSE_ALLOC_PAGES_MAX) {
+ if (pai->page_count > CUSE_ALLOC_PAGES_MAX) {
error = ENOMEM;
break;
}
@@ -1329,50 +1329,57 @@
}
static int
-cuse_server_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
- vm_size_t size, struct vm_object **object, int nprot)
+cuse_common_mmap_single(struct cuse_server *pcs,
+ vm_ooffset_t *offset, vm_size_t size, struct vm_object **object)
{
- uint32_t page_nr = *offset / PAGE_SIZE;
- uint32_t alloc_nr = page_nr / CUSE_ALLOC_PAGES_MAX;
- struct cuse_memory *mem;
- struct cuse_server *pcs;
+ struct cuse_memory *mem;
int error;
- error = cuse_server_get(&pcs);
- if (error != 0)
- return (error);
+ /* verify size */
+ if ((size % PAGE_SIZE) != 0 || (size < PAGE_SIZE))
+ return (EINVAL);
cuse_server_lock(pcs);
- /* lookup memory structure */
+ error = ENOMEM;
+
+ /* lookup memory structure, if any */
TAILQ_FOREACH(mem, &pcs->hmem, entry) {
- if (mem->alloc_nr == alloc_nr)
+ vm_ooffset_t min_off;
+ vm_ooffset_t max_off;
+
+ min_off = (mem->alloc_nr << CUSE_ALLOC_UNIT_SHIFT);
+ max_off = min_off + (PAGE_SIZE * mem->page_count);
+
+ if (*offset >= min_off && *offset < max_off) {
+ /* range check size */
+ if (size > (max_off - *offset)) {
+ error = EINVAL;
+ } else {
+ /* get new VM object offset to use */
+ *offset -= min_off;
+ vm_object_reference(mem->object);
+ *object = mem->object;
+ error = 0;
+ }
break;
+ }
}
- if (mem == NULL) {
- cuse_server_unlock(pcs);
- return (ENOMEM);
- }
- /* verify page offset */
- page_nr %= CUSE_ALLOC_PAGES_MAX;
- if (page_nr >= mem->page_count) {
- cuse_server_unlock(pcs);
- return (ENXIO);
- }
- /* verify mmap size */
- if ((size % PAGE_SIZE) != 0 || (size < PAGE_SIZE) ||
- (size > ((mem->page_count - page_nr) * PAGE_SIZE))) {
- cuse_server_unlock(pcs);
- return (EINVAL);
- }
- vm_object_reference(mem->object);
- *object = mem->object;
cuse_server_unlock(pcs);
+ return (error);
+}
+
+static int
+cuse_server_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
+ vm_size_t size, struct vm_object **object, int nprot)
+{
+ struct cuse_server *pcs;
+ int error;
- /* set new VM object offset to use */
- *offset = page_nr * PAGE_SIZE;
+ error = cuse_server_get(&pcs);
+ if (error != 0)
+ return (error);
- /* success */
- return (0);
+ return (cuse_common_mmap_single(pcs, offset, size, object));
}
/*------------------------------------------------------------------------*
@@ -1811,50 +1818,14 @@
cuse_client_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
vm_size_t size, struct vm_object **object, int nprot)
{
- uint32_t page_nr = *offset / PAGE_SIZE;
- uint32_t alloc_nr = page_nr / CUSE_ALLOC_PAGES_MAX;
- struct cuse_memory *mem;
struct cuse_client *pcc;
- struct cuse_server *pcs;
int error;
error = cuse_client_get(&pcc);
if (error != 0)
return (error);
- pcs = pcc->server;
-
- cuse_server_lock(pcs);
- /* lookup memory structure */
- TAILQ_FOREACH(mem, &pcs->hmem, entry) {
- if (mem->alloc_nr == alloc_nr)
- break;
- }
- if (mem == NULL) {
- cuse_server_unlock(pcs);
- return (ENOMEM);
- }
- /* verify page offset */
- page_nr %= CUSE_ALLOC_PAGES_MAX;
- if (page_nr >= mem->page_count) {
- cuse_server_unlock(pcs);
- return (ENXIO);
- }
- /* verify mmap size */
- if ((size % PAGE_SIZE) != 0 || (size < PAGE_SIZE) ||
- (size > ((mem->page_count - page_nr) * PAGE_SIZE))) {
- cuse_server_unlock(pcs);
- return (EINVAL);
- }
- vm_object_reference(mem->object);
- *object = mem->object;
- cuse_server_unlock(pcs);
-
- /* set new VM object offset to use */
- *offset = page_nr * PAGE_SIZE;
-
- /* success */
- return (0);
+ return (cuse_common_mmap_single(pcc->server, offset, size, object));
}
static void
diff --git a/sys/fs/cuse/cuse_defs.h b/sys/fs/cuse/cuse_defs.h
--- a/sys/fs/cuse/cuse_defs.h
+++ b/sys/fs/cuse/cuse_defs.h
@@ -27,7 +27,7 @@
#ifndef _CUSE_DEFS_H_
#define _CUSE_DEFS_H_
-#define CUSE_VERSION 0x000124
+#define CUSE_VERSION 0x000125
#define CUSE_ERR_NONE 0
#define CUSE_ERR_BUSY -1
diff --git a/sys/fs/cuse/cuse_ioctl.h b/sys/fs/cuse/cuse_ioctl.h
--- a/sys/fs/cuse/cuse_ioctl.h
+++ b/sys/fs/cuse/cuse_ioctl.h
@@ -34,9 +34,11 @@
#define CUSE_DEVICES_MAX 64 /* units */
#define CUSE_BUF_MIN_PTR 0x10000UL
#define CUSE_BUF_MAX_PTR 0x20000UL
-#define CUSE_ALLOC_UNIT_MAX 128 /* units */
+#define CUSE_ALLOC_UNIT_MAX 128UL /* units */
+#define CUSE_ALLOC_UNIT_SHIFT 24 /* bits */
/* All memory allocations must be less than the following limit */
-#define CUSE_ALLOC_BYTES_MAX (1UL << 24) /* bytes */
+#define CUSE_ALLOC_BYTES_MAX \
+ (CUSE_ALLOC_UNIT_MAX << CUSE_ALLOC_UNIT_SHIFT) /* bytes */
struct cuse_dev;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 2:10 PM (18 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28587172
Default Alt Text
D35830.id108279.diff (9 KB)
Attached To
Mode
D35830: cuse(3): Allow shared memory allocations up to and including 2 GBytes.
Attached
Detach File
Event Timeline
Log In to Comment