Beispiel #1
0
static void
np_tpool_destroy(Nptpool *tp)
{
	Npsrv *srv = tp->srv;
	Npwthread *wt, *next;
	void *retval;
	int err, i;

	for(wt = tp->wthreads; wt != NULL; wt = wt->next) {
		wt->shutdown = 1;
	}
	xpthread_cond_broadcast(&tp->reqcond);
	for (i = 0, wt = tp->wthreads; wt != NULL; wt = next, i++) {
		next = wt->next;
		if ((err = pthread_join (wt->thread, &retval))) {
			np_uerror (err);
			np_logerr(srv, "%s: join thread %d", tp->name, i);
		} else if (retval == PTHREAD_CANCELED) {
			np_logmsg(srv, "%s: join thread %d: cancelled",
					tp->name, i);
		} else if (retval != NULL) {
			np_logmsg(srv, "%s: join thread %d: non-NULL return",
					tp->name, i);
		}
		free (wt);
	}
	pthread_cond_destroy (&tp->reqcond);
	pthread_mutex_destroy (&tp->lock);
	if (tp->name)
		free (tp->name);
	free (tp);
}
Beispiel #2
0
static Npuser *
_alloc_user (Npsrv *srv, struct passwd *pwd)
{
    Npuser *u;

    if (!(u = malloc (sizeof (*u)))) {
        np_uerror (ENOMEM);
        np_logerr (srv, "_alloc_user: %s", pwd->pw_name);
        goto error;
    }
    u->sg = NULL;
    u->nsg = 0;
    if (!(u->uname = strdup (pwd->pw_name))) {
        np_uerror (ENOMEM);
        np_logerr (srv, "_alloc_user: %s", pwd->pw_name);
        goto error;
    }
    u->uid = pwd->pw_uid;
    u->gid = pwd->pw_gid;
    if (u->uid != 0 && _getgrouplist(srv, u) < 0)
        goto error;
    pthread_mutex_init (&u->lock, NULL);
    u->refcount = 0;
    u->t = time (NULL);
    u->next = NULL;
    if (srv->flags & SRV_FLAGS_DEBUG_USER)
        np_logmsg (srv, "user lookup: %d", u->uid);
    return u;
error:
    if (u)
        _free_user (u);
    return NULL;
}
Beispiel #3
0
static void
np_conn_destroy(Npconn *conn)
{
    int n;

    NP_ASSERT(conn != NULL);
    NP_ASSERT(conn->refcount == 0);
    /* issue 83: remove from srv->conns before destroying fidpool
     */
    np_srv_remove_conn (conn->srv, conn);
    if (conn->fidpool) {
        if ((n = np_fidpool_destroy(conn->fidpool)) > 0) {
            np_logmsg (conn->srv, "%s: connection closed with "
                       "%d unclunked fids",
                       np_conn_get_client_id (conn), n);
        }
        conn->fidpool = NULL;
    }
    if (conn->trans) {
        np_trans_destroy (conn->trans);
        conn->trans = NULL;
    }
    pthread_mutex_destroy(&conn->lock);
    pthread_mutex_destroy(&conn->wlock);
    pthread_cond_destroy(&conn->refcond);

    free(conn);
}
Beispiel #4
0
/* Create a fid with initial refcount of 1.
 */
Npfid *
np_fid_create (Npconn *conn, u32 fid)
{
	Npsrv *srv = conn->srv;
	Npfidpool *pool = conn->fidpool;
	int hash = fid % pool->size;
	Npfid *f;

	xpthread_mutex_lock(&pool->lock);
	if ((f = _lookup_fid (&pool->htable[hash], fid))) {
		np_logmsg (srv, "np_fid_create: unclunked fid %d (%s): %d refs",
			   f->fid, srv->get_path ? srv->get_path (f) : "<nil>",
			   f->refcount);
		if ((srv->flags & SRV_FLAGS_LOOSEFID)) {
			f->flags |= FID_FLAGS_ZOMBIE;
		} else {
			np_uerror (EEXIST);
			f = NULL;
			goto done;
		}
	}
	if ((f = _create_fid (conn, fid))) {
		np_fid_incref (f);
		_link_fid (&pool->htable[hash], f);
	}
done:
	xpthread_mutex_unlock(&pool->lock);

	return f;
}
Beispiel #5
0
static void
_debug_trace (Npsrv *srv, Npfcall *fc)
{
	char s[512];

	np_snprintfcall(s, sizeof (s), fc);
	np_logmsg(srv, "%s", s);
}
Beispiel #6
0
static void
_debug_trace (Npsrv *srv, Npfcall *fc)
{
    if ((srv->flags & SRV_FLAGS_DEBUG_9PTRACE)) {
        char s[512];
        static struct timeval b = { 0, 0 };
        struct timeval a, c;

        np_snprintfcall(s, sizeof (s), fc);
        if ((srv->flags & SRV_FLAGS_DEBUG_TIMES)) {
            if (b.tv_sec == 0)
                (void)gettimeofday(&b, NULL);
            (void)gettimeofday(&a, NULL);
            timersub(&a, &b, &c);
            np_logmsg(srv, "[%lu.%-3lu] %s",
                      c.tv_sec, c.tv_usec/1000, s);
        } else
            np_logmsg(srv, "%s", s);
    }
}
Beispiel #7
0
/* Create an Npuser struct for a user, without requiring
 * that user to be in the password/group file.
 * N.B. gid is assumed to be same as uid.
 */
static Npuser *
_alloc_nouserdb (Npsrv *srv, uid_t uid, char *name)
{
    Npuser *u = NULL;
    char ustr[32] = "root";

    if (name) {
        if (strcmp (name, "root") != 0) {
            np_uerror (EPERM);
            goto error;
        }
        uid = 0;
    }
    if (uid != 0)
        snprintf (ustr, sizeof (ustr), "%d", uid);
    if (!(u = malloc (sizeof (*u)))) {
        np_uerror (ENOMEM);
        np_logerr (srv, "_alloc_nouserdb: %s", ustr);
        goto error;
    }
    u->sg = NULL;
    if (!(u->uname = strdup (ustr))) {
        np_uerror (ENOMEM);
        np_logerr (srv, "_alloc_nouserdb: %s", ustr);
        goto error;
    }
    u->uid = uid;
    u->gid = (gid_t)uid;
    u->nsg = 1;
    if (!(u->sg = malloc (sizeof (gid_t) * u->nsg))) {
        np_uerror (ENOMEM);
        np_logerr (srv, "_alloc_nouserdb: %s", ustr);
        goto error;
    }
    u->sg[0] = u->gid;
    pthread_mutex_init (&u->lock, NULL);
    if (srv->flags & SRV_FLAGS_DEBUG_USER)
        np_logmsg (srv, "user lookup: %d", u->uid);
    u->refcount = 0;
    u->t = time (NULL);
    u->next = NULL;
    return u;
error:
    if (u)
        _free_user (u);
    return NULL;
}
Beispiel #8
0
void
np_logerr(Npsrv *srv, const char *fmt, ...)
{
	va_list ap;

	if (srv->logmsg) {
		char buf[128];
		char ebuf[64];
		char *s = strerror_r (np_rerror (), ebuf, sizeof (ebuf));

		va_start (ap, fmt);
		vsnprintf (buf, sizeof(buf), fmt, ap);
		va_end (ap);

		np_logmsg (srv, "%s: %s", buf, s);
	}
}
Beispiel #9
0
static Npuser *
_real_lookup_byname (Npsrv *srv, char *uname)
{
    Npuser *u;
    int err, len;
    struct passwd pw, *pwd = NULL;
    char *buf = NULL;

    if (srv->flags & SRV_FLAGS_NOUSERDB) {
        if (!(u = _alloc_nouserdb (srv, P9_NONUNAME, uname)))
            goto error;
    } else {
        len= sysconf(_SC_GETPW_R_SIZE_MAX);
        if (len < 4096)
            len = 4096;
        if (!(buf = malloc (len))) {
            np_uerror (ENOMEM);
            np_logerr (srv, "uname2user: %s", uname);
            goto error;
        }
        if ((err = getpwnam_r (uname, &pw, buf, len, &pwd)) != 0) {
            np_uerror (err);
            np_logerr (srv, "uname2user: %s: getpwnam_r", uname);
            goto error;
        }
        if (!pwd) {
            np_logmsg (srv, "uname2user: %s lookup failure", uname);
            np_uerror (EPERM);
            goto error;
        }
        if (!(u = _alloc_user (srv, pwd)))
            goto error;
        free (buf);
    }
    return u;
error:
    if (buf)
        free (buf);
    return NULL;
}
Beispiel #10
0
static Npuser *
_real_lookup_byuid (Npsrv *srv, uid_t uid)
{
    Npuser *u;
    int err, len;
    struct passwd pw, *pwd;
    char *buf = NULL;

    if (srv->flags & SRV_FLAGS_NOUSERDB) {
        if (!(u = _alloc_nouserdb (srv, uid, NULL)))
            goto error;
    } else {
        len = sysconf(_SC_GETPW_R_SIZE_MAX);
        if (len < 4096)
            len = 4096;
        if (!(buf = malloc (len))) {
            np_uerror (ENOMEM);
            np_logerr (srv, "uid2user");
            goto error;
        }
        if ((err = getpwuid_r (uid, &pw, buf, len, &pwd)) != 0) {
            np_uerror (err);
            np_logerr (srv, "uid2user: unable to lookup %d", uid);
            goto error;
        }
        if (!pwd) {
            np_logmsg (srv, "uid2user: unable to lookup %d", uid);
            np_uerror (EPERM);
            goto error;
        }
        if (!(u = _alloc_user (srv, pwd)))
            goto error;
        free (buf);
    }
    return u;
error:
    if (buf)
        free (buf);
    return NULL;
}
Beispiel #11
0
static Npfid *
_destroy_fid (Npfid *f)
{
	Npsrv *srv;
	Npfid *next;

	NP_ASSERT(f != NULL);
	NP_ASSERT(f->magic == FID_MAGIC);

	srv = f->conn->srv;
	next = f->next;
	if (f->refcount > 0 && (srv->flags & SRV_FLAGS_DEBUG_FIDPOOL)) {
		np_logmsg (srv, "_destroy_fid: fid %d has %d refs",
			   f->fid, f->refcount);
	}
	if ((f->type & P9_QTAUTH)) {
		if (srv->auth && srv->auth->clunk)
			(*srv->auth->clunk)(f);
	} else if ((f->type & P9_QTTMP)) {
		np_ctl_fiddestroy (f);
	} else {
		if (srv->fiddestroy)
			(*srv->fiddestroy)(f);
	}	
	if (f->user)
		np_user_decref(f->user);
	if (f->tpool)
		np_tpool_decref(f->tpool);
	if (f->aname)
		free (f->aname);
	pthread_mutex_destroy (&f->lock);
	f->magic = FID_MAGIC_FREED;
	free(f);

	return next;
}
Beispiel #12
0
/* Per-connection read thread.
 */
static void *
np_conn_read_proc(void *a)
{
    Npconn *conn = (Npconn *)a;
    Npsrv *srv = conn->srv;
    Npreq *req;
    Npfcall *fc;

    pthread_detach(pthread_self());

    for (;;) {
        if (np_trans_recv(conn->trans, &fc, conn->msize) < 0) {
            np_logerr (srv, "recv error - "
                       "dropping connection to '%s'",
                       conn->client_id);
            break;
        }
        if (!fc) /* EOF */
            break;
        _debug_trace (srv, fc);

        /* Encapsulate fc in a request and hand to srv worker threads.
         * In np_req_alloc, req->fid is looked up/initialized.
         */
        req = np_req_alloc(conn, fc);
        if (!req) {
            np_logmsg (srv, "out of memory in receive path - "
                       "dropping connection to '%s'",
                       conn->client_id);
            free (fc);
            break;
        }

        /* Enqueue request for processing by next available worker
         * thread, except P9_TFLUSH which is handled immediately.
         */
        if (fc->type == P9_TFLUSH) {
            if (np_flush (req, fc)) {
                np_req_respond_flush (req);
                np_req_unref(req);
            }
            xpthread_mutex_lock (&srv->lock);
            srv->tpool->stats.nreqs[P9_TFLUSH]++;
            xpthread_mutex_unlock (&srv->lock);
        } else {
            xpthread_mutex_lock(&srv->lock);
            np_srv_add_req(srv, req);
            xpthread_mutex_unlock(&srv->lock);
        }
    }
    /* Just got EOF on read, or some other fatal error for the
     * connection like out of memory.
     */

    np_conn_flush (conn);

    xpthread_mutex_lock(&conn->lock);
    while (conn->refcount > 0)
        xpthread_cond_wait(&conn->refcond, &conn->lock);
    xpthread_mutex_unlock(&conn->lock);
    np_conn_destroy(conn);

    return NULL;
}