summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_uuid.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2005-09-18 21:40:15 +0000
committermarcel <marcel@FreeBSD.org>2005-09-18 21:40:15 +0000
commitb00bab4473d1ad8864c379bad245e4dac451d2c4 (patch)
tree0911dd1b024a567c2cd8b992d6febc27f797fd04 /sys/kern/kern_uuid.c
parentbfb05b4b93adffb0e9783a141f4a30195b6a6cb9 (diff)
downloadFreeBSD-src-b00bab4473d1ad8864c379bad245e4dac451d2c4.zip
FreeBSD-src-b00bab4473d1ad8864c379bad245e4dac451d2c4.tar.gz
Move the UUID generator into its own function, called kern_uuidgen(),
so that UUIDs can be generated from within the kernel. The uuidgen(2) syscall now allocates kernel memory, calls the generator, and does a copyout() for the whole UUID store. This change is in support of GPT.
Diffstat (limited to 'sys/kern/kern_uuid.c')
-rw-r--r--sys/kern/kern_uuid.c68
1 files changed, 39 insertions, 29 deletions
diff --git a/sys/kern/kern_uuid.c b/sys/kern/kern_uuid.c
index de47158..6205bfb 100644
--- a/sys/kern/kern_uuid.c
+++ b/sys/kern/kern_uuid.c
@@ -131,30 +131,12 @@ uuid_time(void)
return (time & ((1LL << 60) - 1LL));
}
-#ifndef _SYS_SYSPROTO_H_
-struct uuidgen_args {
- struct uuid *store;
- int count;
-};
-#endif
-
-int
-uuidgen(struct thread *td, struct uuidgen_args *uap)
+struct uuid *
+kern_uuidgen(struct uuid *store, size_t count)
{
struct uuid_private uuid;
uint64_t time;
- int error;
-
- /*
- * Limit the number of UUIDs that can be created at the same time
- * to some arbitrary number. This isn't really necessary, but I
- * like to have some sort of upper-bound that's less than 2G :-)
- * XXX needs to be tunable.
- */
- if (uap->count < 1 || uap->count > 2048)
- return (EINVAL);
-
- /* XXX: pre-validate accessibility to the whole of the UUID store? */
+ size_t n;
mtx_lock(&uuid_mutex);
@@ -171,25 +153,53 @@ uuidgen(struct thread *td, struct uuidgen_args *uap)
uuid.seq = uuid_last.seq;
uuid_last = uuid;
- uuid_last.time.ll = (time + uap->count - 1) & ((1LL << 60) - 1LL);
+ uuid_last.time.ll = (time + count - 1) & ((1LL << 60) - 1LL);
mtx_unlock(&uuid_mutex);
/* Set sequence and variant and deal with byte order. */
uuid.seq = htobe16(uuid.seq | 0x8000);
- /* XXX: this should copyout larger chunks at a time. */
- do {
- /* Set time and version (=1) and deal with byte order. */
+ for (n = 0; n < count; n++) {
+ /* Set time and version (=1). */
uuid.time.x.low = (uint32_t)time;
uuid.time.x.mid = (uint16_t)(time >> 32);
uuid.time.x.hi = ((uint16_t)(time >> 48) & 0xfff) | (1 << 12);
- error = copyout(&uuid, uap->store, sizeof(uuid));
- uap->store++;
- uap->count--;
+ store[n] = *(struct uuid *)&uuid;
time++;
- } while (uap->count > 0 && !error);
+ }
+
+ return (store);
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct uuidgen_args {
+ struct uuid *store;
+ int count;
+};
+#endif
+
+int
+uuidgen(struct thread *td, struct uuidgen_args *uap)
+{
+ struct uuid *store;
+ size_t count;
+ int error;
+
+ /*
+ * Limit the number of UUIDs that can be created at the same time
+ * to some arbitrary number. This isn't really necessary, but I
+ * like to have some sort of upper-bound that's less than 2G :-)
+ * XXX probably needs to be tunable.
+ */
+ if (uap->count < 1 || uap->count > 2048)
+ return (EINVAL);
+ count = uap->count;
+ store = malloc(count * sizeof(struct uuid), M_TEMP, M_WAITOK);
+ kern_uuidgen(store, count);
+ error = copyout(store, uap->store, count * sizeof(struct uuid));
+ free(store, M_TEMP);
return (error);
}
OpenPOWER on IntegriCloud