svn commit: r261286 - stable/9/sys/geom
Andrey V. Elsukov
ae at FreeBSD.org
Thu Jan 30 10:54:12 UTC 2014
Author: ae
Date: Thu Jan 30 10:54:11 2014
New Revision: 261286
URL: http://svnweb.freebsd.org/changeset/base/261286
Log:
MFC r261084:
malloc() with M_WAITOK doesn't return NULL.
MFC r261085:
Fix typo in r261084.
Add to the gctl_error() an ability to specify error description even
if numeric error code is already specified. Also by default set
error code to EINVAL.
PR: 185852
MFC r261086:
In gctl_copyin() remove unused error variable.
geom_alloc_copyin() can't return ENOMEM, so describe its fail as bad
control request. Add check for NULL pointer in gctl_dump(), since it
can be NULL when geom_alloc_copyin() failed.
MFC r261089:
Remove another unneeded NULL check from geom_alloc_copyin().
Do copyout in case of gctl version mismatch and fix sbuf leak in
g_ctl_ioctl_ctl().
MFC r261091:
Always free sbuf in gctl_free().
Modified:
stable/9/sys/geom/geom_ctl.c
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/geom/geom_ctl.c
==============================================================================
--- stable/9/sys/geom/geom_ctl.c Thu Jan 30 10:53:29 2014 (r261285)
+++ stable/9/sys/geom/geom_ctl.c Thu Jan 30 10:54:11 2014 (r261286)
@@ -84,8 +84,8 @@ g_ctl_init(void)
}
/*
- * Report an error back to the user in ascii format. Return whatever copyout
- * returned, or EINVAL if it succeeded.
+ * Report an error back to the user in ascii format. Return nerror
+ * or EINVAL if nerror isn't specified.
*/
int
gctl_error(struct gctl_req *req, const char *fmt, ...)
@@ -99,9 +99,10 @@ gctl_error(struct gctl_req *req, const c
if (sbuf_done(req->serror)) {
if (!req->nerror)
req->nerror = EEXIST;
- }
- if (req->nerror)
return (req->nerror);
+ }
+ if (!req->nerror)
+ req->nerror = EINVAL;
va_start(ap, fmt);
sbuf_vprintf(req->serror, fmt, ap);
@@ -109,7 +110,7 @@ gctl_error(struct gctl_req *req, const c
sbuf_finish(req->serror);
if (g_debugflags & G_F_CTLDUMP)
printf("gctl %p error \"%s\"\n", req, sbuf_data(req->serror));
- return (0);
+ return (req->nerror);
}
/*
@@ -122,27 +123,23 @@ geom_alloc_copyin(struct gctl_req *req,
void *ptr;
ptr = g_malloc(len, M_WAITOK);
- if (ptr == NULL)
- req->nerror = ENOMEM;
- else
- req->nerror = copyin(uaddr, ptr, len);
+ req->nerror = copyin(uaddr, ptr, len);
if (!req->nerror)
return (ptr);
- if (ptr != NULL)
- g_free(ptr);
+ g_free(ptr);
return (NULL);
}
static void
gctl_copyin(struct gctl_req *req)
{
- int error, i;
struct gctl_req_arg *ap;
char *p;
+ int i;
ap = geom_alloc_copyin(req, req->arg, req->narg * sizeof(*ap));
if (ap == NULL) {
- req->nerror = ENOMEM;
+ gctl_error(req, "bad control request");
req->arg = NULL;
return;
}
@@ -154,10 +151,9 @@ gctl_copyin(struct gctl_req *req)
ap[i].kvalue = NULL;
}
- error = 0;
for (i = 0; i < req->narg; i++) {
if (ap[i].nlen < 1 || ap[i].nlen > SPECNAMELEN) {
- error = gctl_error(req,
+ gctl_error(req,
"wrong param name length %d: %d", i, ap[i].nlen);
break;
}
@@ -165,14 +161,14 @@ gctl_copyin(struct gctl_req *req)
if (p == NULL)
break;
if (p[ap[i].nlen - 1] != '\0') {
- error = gctl_error(req, "unterminated param name");
+ gctl_error(req, "unterminated param name");
g_free(p);
break;
}
ap[i].name = p;
ap[i].flag |= GCTL_PARAM_NAMEKERNEL;
if (ap[i].len <= 0) {
- error = gctl_error(req, "negative param length");
+ gctl_error(req, "negative param length");
break;
}
p = geom_alloc_copyin(req, ap[i].value, ap[i].len);
@@ -180,7 +176,7 @@ gctl_copyin(struct gctl_req *req)
break;
if ((ap[i].flag & GCTL_PARAM_ASCII) &&
p[ap[i].len - 1] != '\0') {
- error = gctl_error(req, "unterminated param value");
+ gctl_error(req, "unterminated param value");
g_free(p);
break;
}
@@ -218,6 +214,7 @@ gctl_free(struct gctl_req *req)
{
int i;
+ sbuf_delete(req->serror);
if (req->arg == NULL)
return;
for (i = 0; i < req->narg; i++) {
@@ -228,15 +225,14 @@ gctl_free(struct gctl_req *req)
g_free(req->arg[i].kvalue);
}
g_free(req->arg);
- sbuf_delete(req->serror);
}
static void
gctl_dump(struct gctl_req *req)
{
+ struct gctl_req_arg *ap;
u_int i;
int j;
- struct gctl_req_arg *ap;
printf("Dump of gctl request at %p:\n", req);
if (req->nerror > 0) {
@@ -244,6 +240,8 @@ gctl_dump(struct gctl_req *req)
if (sbuf_len(req->serror) > 0)
printf(" error:\t\"%s\"\n", sbuf_data(req->serror));
}
+ if (req->arg == NULL)
+ return;
for (i = 0; i < req->narg; i++) {
ap = &req->arg[i];
if (!(ap->flag & GCTL_PARAM_NAMEKERNEL))
@@ -464,30 +462,31 @@ g_ctl_ioctl_ctl(struct cdev *dev, u_long
req = (void *)data;
req->nerror = 0;
- req->serror = sbuf_new_auto();
/* It is an error if we cannot return an error text */
if (req->lerror < 2)
return (EINVAL);
if (!useracc(req->error, req->lerror, VM_PROT_WRITE))
return (EINVAL);
+ req->serror = sbuf_new_auto();
/* Check the version */
- if (req->version != GCTL_VERSION)
- return (gctl_error(req,
- "kernel and libgeom version mismatch."));
-
- /* Get things on board */
- gctl_copyin(req);
-
- if (g_debugflags & G_F_CTLDUMP)
- gctl_dump(req);
-
- if (!req->nerror) {
- g_waitfor_event(g_ctl_req, req, M_WAITOK, NULL);
- gctl_copyout(req);
+ if (req->version != GCTL_VERSION) {
+ gctl_error(req, "kernel and libgeom version mismatch.");
+ req->arg = NULL;
+ } else {
+ /* Get things on board */
+ gctl_copyin(req);
+
+ if (g_debugflags & G_F_CTLDUMP)
+ gctl_dump(req);
+
+ if (!req->nerror) {
+ g_waitfor_event(g_ctl_req, req, M_WAITOK, NULL);
+ gctl_copyout(req);
+ }
}
if (sbuf_done(req->serror)) {
- req->nerror = copyout(sbuf_data(req->serror), req->error,
+ copyout(sbuf_data(req->serror), req->error,
imin(req->lerror, sbuf_len(req->serror) + 1));
}
More information about the svn-src-stable-9
mailing list