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.
This commit is contained in:
parent
8434c29b28
commit
73130b2224
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=150303
@ -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);
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,8 @@ struct uuid {
|
||||
|
||||
struct sbuf;
|
||||
|
||||
struct uuid *kern_uuidgen(struct uuid *, size_t);
|
||||
|
||||
int snprintf_uuid(char *, size_t, struct uuid *);
|
||||
int printf_uuid(struct uuid *);
|
||||
int sbuf_printf_uuid(struct sbuf *, struct uuid *);
|
||||
|
Loading…
Reference in New Issue
Block a user