From e28c39c4fb5cfdba220fac525780e5bf15849bdf Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Mar 2013 01:29:10 +0100 Subject: [PATCH] uvt: ctx: add major/minor helpers Two new functions to retrieve the current major number and dynamically allocate minor numbers. This can be used by clients that allocate more than one CDEV for VTs to dynamically retrieve a new minor number. Signed-off-by: David Herrmann --- docs/sym/libuvt.sym | 3 +++ src/uvt.h | 4 ++++ src/uvt_ctx.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/uvt_internal.h | 4 ++++ 4 files changed, 56 insertions(+) diff --git a/docs/sym/libuvt.sym b/docs/sym/libuvt.sym index a747c43..c2bc069 100644 --- a/docs/sym/libuvt.sym +++ b/docs/sym/libuvt.sym @@ -30,6 +30,9 @@ global: uvt_ctx_unref; uvt_ctx_get_fd; uvt_ctx_dispatch; + uvt_ctx_get_major; + uvt_ctx_new_minor; + uvt_ctx_free_minor; uvt_cdev_new; uvt_cdev_ref; diff --git a/src/uvt.h b/src/uvt.h index e1b0efe..8c41aa6 100644 --- a/src/uvt.h +++ b/src/uvt.h @@ -261,6 +261,10 @@ void uvt_ctx_unref(struct uvt_ctx *ctx); int uvt_ctx_get_fd(struct uvt_ctx *ctx); void uvt_ctx_dispatch(struct uvt_ctx *ctx); +unsigned int uvt_ctx_get_major(struct uvt_ctx *ctx); +int uvt_ctx_new_minor(struct uvt_ctx *ctx, unsigned int *out); +void uvt_ctx_free_minor(struct uvt_ctx *ctx, unsigned int minor); + /* pty tty implementation */ struct uvt_tty_null; diff --git a/src/uvt_ctx.c b/src/uvt_ctx.c index 60185ec..ad1e534 100644 --- a/src/uvt_ctx.c +++ b/src/uvt_ctx.c @@ -33,9 +33,12 @@ #include #include #include +#include #include #include #include +#include "shl_array.h" +#include "shl_flagset.h" #include "shl_llog.h" #include "shl_misc.h" #include "uvt.h" @@ -60,6 +63,13 @@ int uvt_ctx_new(struct uvt_ctx **out, uvt_log_t log, void *log_data) ctx->llog = log; ctx->llog_data = log_data; + /* Default major/minor uses the TTY_MAJOR number with an offset of 2^15 + * to avoid ID-clashes with any in-kernel TTY driver. As kernel drivers + * use static IDs only, a lower number would be fine, too, but lets be + * safe and just use high numbers. */ + ctx->major = TTY_MAJOR; + ctx->minor_offset = 16384; + llog_debug(ctx, "new ctx %p", ctx); ret = ev_eloop_new(&ctx->eloop, ctx->llog, ctx->llog_data); @@ -72,9 +82,15 @@ int uvt_ctx_new(struct uvt_ctx **out, uvt_log_t log, void *log_data) goto err_eloop; } + ret = shl_flagset_new(&ctx->minors); + if (ret) + goto err_file; + *out = ctx; return 0; +err_file: + free(ctx->cuse_file); err_eloop: ev_eloop_unref(ctx->eloop); err_free: @@ -99,6 +115,7 @@ void uvt_ctx_unref(struct uvt_ctx *ctx) llog_debug(ctx, "free ctx %p", ctx); + shl_flagset_free(ctx->minors); free(ctx->cuse_file); ev_eloop_unref(ctx->eloop); free(ctx); @@ -121,3 +138,31 @@ void uvt_ctx_dispatch(struct uvt_ctx *ctx) ev_eloop_dispatch(ctx->eloop, 0); } + +SHL_EXPORT +unsigned int uvt_ctx_get_major(struct uvt_ctx *ctx) +{ + return ctx->major; +} + +SHL_EXPORT +int uvt_ctx_new_minor(struct uvt_ctx *ctx, unsigned int *out) +{ + int ret; + + ret = shl_flagset_alloc(ctx->minors, out); + if (ret) + return ret; + + *out += ctx->minor_offset; + return 0; +} + +SHL_EXPORT +void uvt_ctx_free_minor(struct uvt_ctx *ctx, unsigned int minor) +{ + if (!ctx || minor < ctx->minor_offset) + return; + + shl_flagset_unset(ctx->minors, minor - ctx->minor_offset); +} diff --git a/src/uvt_internal.h b/src/uvt_internal.h index 72d4edd..479cf2b 100644 --- a/src/uvt_internal.h +++ b/src/uvt_internal.h @@ -34,6 +34,7 @@ #include #include #include +#include "shl_array.h" #include "shl_dlist.h" #include "shl_hook.h" #include "shl_llog.h" @@ -53,6 +54,9 @@ struct uvt_ctx { struct ev_eloop *eloop; char *cuse_file; + unsigned int major; + unsigned int minor_offset; + struct shl_array *minors; }; /* character devices */