--- aoedev.c.orig 2006-05-22 18:01:13 UTC +++ aoedev.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,8 @@ SYSCTL_OID(_net_aoe, OID_AUTO, devices, CTLTYPE_STRING|CTLFLAG_RD, NULL, 0, sysctl_aoe_devices, "A", "AoE Device Info"); + +// this method should be called with locked devlist_mtx! static struct aoedev * aoedev_newdev(u_long nframes, u_long unit) { @@ -69,9 +72,21 @@ struct frame *f, *e; char buf[16]; + // check first if we already know this device unit + for (d=devlist; d; d=d->ad_next) { + if (d->ad_unit == unit + /* || memcmp(d->ad_addr, addr, sizeof d->ad_addr) == 0 */ ) { + return (d); + } + } + + // not found, then create a new d + + d = (struct aoedev *) malloc(sizeof *d, M_AOEDEV, M_NOWAIT | M_ZERO); - if (d == NULL) + if (d == NULL) { return (NULL); + } f = (struct frame *) malloc(nframes * sizeof *f, M_AOEFRAME, M_NOWAIT | M_ZERO); if (f == NULL) { free(d, M_AOEDEV); @@ -89,11 +104,10 @@ snprintf(buf, sizeof buf, "aoed%ld", unit); mtx_init(&d->ad_mtx, buf, NULL, MTX_DEF); - mtx_lock(&devlist_mtx); + d->ad_next = devlist; devlist = d; - mtx_unlock(&devlist_mtx); - + return (d); } @@ -153,21 +167,17 @@ { struct aoedev *d; - mtx_lock(&devlist_mtx); - for (d=devlist; d; d=d->ad_next) - if (d->ad_unit == unit - /* || memcmp(d->ad_addr, addr, sizeof d->ad_addr) == 0 */ ) - break; - mtx_unlock(&devlist_mtx); + // make new device, if not already known by unit + mtx_lock(&devlist_mtx); + d = aoedev_newdev(bufcnt, unit); if (d == NULL) { - d = aoedev_newdev(bufcnt, unit); - if (d == NULL) { - IPRINTK("aoedev_newdev failure.\n"); - return (NULL); - } + mtx_unlock(&devlist_mtx); + IPRINTK("aoedev_newdev failure.\n"); + return (NULL); } - + + mtx_lock(&d->ad_mtx); d->ad_ifp = ifp; @@ -182,7 +192,9 @@ d->ad_minor = AOEMINOR(unit); } + mtx_unlock(&d->ad_mtx); + mtx_unlock(&devlist_mtx); return (d); } @@ -239,9 +251,10 @@ static int sysctl_aoe_devices(SYSCTL_HANDLER_ARGS) { - char *buf; + struct sbuf buf; struct aoedev *d; - register int n; + int n, error; + enum { LINESZ = 64 }; mtx_lock(&devlist_mtx); @@ -249,33 +262,32 @@ mtx_unlock(&devlist_mtx); return (SYSCTL_OUT(req, "\0", 1)); } - + + // determine the size of the output n = 0; for (d=devlist; d; d=d->ad_next) n += LINESZ; - buf = (char *) malloc(n+1, M_TEMP, M_NOWAIT | M_ZERO); - if (buf == NULL) { - IPRINTK("could not malloc " - "buffer size %d to print device list\n", n); - mtx_unlock(&devlist_mtx); - return (ENOMEM); - } - - n = 0; + error = sysctl_wire_old_buffer(req, 0); + if (error != 0) + return (error); + sbuf_new_for_sysctl(&buf, NULL, n, req); + for (d=devlist; d; d=d->ad_next) { - n += snprintf(buf+n, LINESZ, "\naoed%-6ld\t%s\t%s%s%s\t(%d)", - d->ad_unit, - d->ad_ifp->if_xname, - (d->ad_flags & DEVFL_UP) ? "UP" : "DOWN", - (d->ad_flags & DEVFL_OPEN) ? ",OPEN" : "", - (d->ad_flags & DEVFL_CLOSEWAIT) ? ",CLOSEWAIT" : "", - d->ad_disk->d_maxsize); + sbuf_printf(&buf, "\naoed%-6ld\t%s\t%s%s%s\t(%d)\t(%ld)", + d->ad_unit, + d->ad_ifp->if_xname, + (d->ad_flags & DEVFL_UP) ? "UP" : "DOWN", + (d->ad_flags & DEVFL_OPEN) ? ",OPEN" : "", + (d->ad_flags & DEVFL_CLOSEWAIT) ? ",CLOSEWAIT" : "", + (d->ad_flags & DEVFL_UP) ? d->ad_disk->d_maxsize : -1, + (d->ad_flags & DEVFL_UP) ? d->ad_disk->d_mediasize : -1 + ); } mtx_unlock(&devlist_mtx); - n = SYSCTL_OUT(req, buf, n+1); - free(buf, M_TEMP); - return (n); + error = sbuf_finish(&buf); + sbuf_delete(&buf); + return (error); } /* @@ -315,6 +327,7 @@ tsleep(d, 0, "aoeunl", hz>>1); aoedev_freedev(d); } + devlist = NULL; mtx_destroy(&devlist_mtx); }