From owner-p4-projects@FreeBSD.ORG Wed Jul 20 12:31:03 2011 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 0A6BF1065673; Wed, 20 Jul 2011 12:31:03 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C111B106566C for ; Wed, 20 Jul 2011 12:31:02 +0000 (UTC) (envelope-from ilya@FreeBSD.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id AD4328FC12 for ; Wed, 20 Jul 2011 12:31:02 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id p6KCV2PF071502 for ; Wed, 20 Jul 2011 12:31:02 GMT (envelope-from ilya@FreeBSD.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id p6KCV2NU071497 for perforce@freebsd.org; Wed, 20 Jul 2011 12:31:02 GMT (envelope-from ilya@FreeBSD.org) Date: Wed, 20 Jul 2011 12:31:02 GMT Message-Id: <201107201231.p6KCV2NU071497@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to ilya@FreeBSD.org using -f From: Ilya Putsikau To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 196439 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Jul 2011 12:31:03 -0000 http://p4web.freebsd.org/@@196439?ac=10 Change 196439 by ilya@ilya_triton2011 on 2011/07/20 12:30:00 Count ticket references, use uma zone to allocate tickets Ticket can have up to 3 references: * Owned by fuse_dispatcher. Released by fdisp_destroy() which is called the same function fdisp_init() was * When added to answer or message list (can be on both). Reference is not automatically released when ticket removed from list. Function that removed ticket from list should release reference after processing. Affected files ... .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse.h#15 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_device.c#13 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_file.c#13 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.c#18 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.h#19 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#19 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_ipc.c#13 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_ipc.h#14 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_main.c#9 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#19 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vfsops.c#22 edit .. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#42 edit Differences ... ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse.h#15 (text+ko) ==== @@ -166,3 +166,6 @@ FUSE_OP_BACKGROUNDED = 0, FUSE_OP_FOREGROUNDED = 1, } fuse_op_waitfor_t; + +void fuse_ipc_init(void); +void fuse_ipc_destroy(void); ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_device.c#13 (text+ko) ==== @@ -133,6 +133,10 @@ tick->tk_aw_errno = ENOTCONN; wakeup(tick); fuse_lck_mtx_unlock(tick->tk_aw_mtx); + fuse_lck_mtx_unlock(data->aw_mtx); + FUSE_ASSERT_AW_DONE(tick); + fuse_ticket_drop(tick); + fuse_lck_mtx_lock(data->aw_mtx); } fuse_lck_mtx_unlock(data->aw_mtx); @@ -201,7 +205,7 @@ return (ENODEV); } - if ( ! (tick = fuse_ms_pop(data))) { + if (!(tick = fuse_ms_pop(data))) { /* check if we may block */ if (ioflag & O_NONBLOCK) { /* get outa here soon */ @@ -217,7 +221,7 @@ tick = fuse_ms_pop(data); } } - if (! tick) { + if (!tick) { /* * We can get here if fuse daemon suddenly terminates, * eg, by being hit by a SIGKILL @@ -237,7 +241,8 @@ DEBUG2G("reader is to be sacked\n"); if (tick) { DEBUG2G("weird -- \"kick\" is set tho there is message\n"); - fuse_ticket_drop_invalid(tick); + FUSE_ASSERT_MS_DONE(tick); + fuse_ticket_drop(tick); } return (ENODEV); /* This should make the daemon get off of us */ } @@ -284,12 +289,8 @@ break; } - /* - * fuse_device_read will drop "not owned" tickets - * (used when the one who inserted the message thinks the daemon - * won't aswer) - */ - fuse_ticket_drop_invalid(tick); + FUSE_ASSERT_MS_DONE(tick); + fuse_ticket_drop(tick); return (err); } @@ -332,7 +333,7 @@ struct fuse_ticket *tick, *x_tick; int found = 0; - DEBUG("Fuse write -- resid: %zd, iovcnt: %d, thread: %d\n", + DEBUG("resid: %zd, iovcnt: %d, thread: %d\n", uio->uio_resid, uio->uio_iovcnt, uio->uio_td->td_tid); data = fuse_get_devdata(dev); @@ -383,15 +384,15 @@ * (Then, by all chance, she'll just get that's done * via ticket_drop(), so no manual mucking around...) */ + DEBUG("pass ticket to a callback\n"); memcpy(&tick->tk_aw_ohead, &ohead, sizeof(ohead)); err = tick->tk_aw_handler(tick, uio); - DEBUG("stuff been passed over to a callback\n"); } else { /* pretender doesn't wanna do anything with answer */ DEBUG("stuff devalidated, so we drop it\n"); - fuse_ticket_drop(tick); - return (err); } + FUSE_ASSERT_AW_DONE(tick); + fuse_ticket_drop(tick); } else { /* no callback at all! */ DEBUG("erhm, no handler for this response\n"); ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_file.c#13 (text+ko) ==== @@ -86,7 +86,7 @@ if (err == ENOENT) { fuse_internal_vnode_disappear(vp); } - return err; + goto out; } foo = fdi.answ; @@ -94,9 +94,9 @@ fuse_filehandle_init(vp, fufh_type, fufhp, foo->fh); fuse_vnode_open(vp, foo->open_flags, td); - fuse_ticket_drop(fdi.tick); - - return 0; +out: + fdisp_destroy(&fdi); + return err; } int @@ -141,15 +141,12 @@ fri->flags = fuse_filehandle_xlate_to_oflags(fufh_type); if (waitfor == FUSE_OP_FOREGROUNDED) { - if ((err = fdisp_wait_answ(&fdi))) { - goto out; - } else { - fuse_ticket_drop(fdi.tick); - } + err = fdisp_wait_answ(&fdi); } else { fuse_insert_callback(fdi.tick, NULL); fuse_insert_message(fdi.tick); } + fdisp_destroy(&fdi); out: atomic_subtract_acq_int(&fuse_fh_count, 1); ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.c#18 (text+ko) ==== @@ -144,9 +144,8 @@ fai->mask = F_OK; fai->mask |= mask; - if (!(err = fdisp_wait_answ(&fdi))) { - fuse_ticket_drop(fdi.tick); - } + err = fdisp_wait_answ(&fdi); + fdisp_destroy(&fdi); if (err == ENOSYS) { fuse_get_mpdata(mp)->dataflags |= FSESS_NOACCESS; @@ -168,8 +167,6 @@ FSESS_NOFSYNC : FSESS_NOFSYNCDIR; } - fuse_ticket_drop(tick); - return 0; } @@ -177,29 +174,29 @@ fuse_internal_fsync(struct vnode *vp, struct thread *td, struct ucred *cred, - struct fuse_filehandle *fufh, - void *param) + struct fuse_filehandle *fufh) { int op = FUSE_FSYNC; struct fuse_fsync_in *ffsi; - struct fuse_dispatcher *fdip = param; + struct fuse_dispatcher fdi; fuse_trace_printf_func(); - fdip->iosize = sizeof(*ffsi); - fdip->tick = NULL; if (vnode_isdir(vp)) { op = FUSE_FSYNCDIR; } - fdisp_make_vp(fdip, op, vp, td, cred); - ffsi = fdip->indata; + fdisp_init(&fdi, sizeof(*ffsi)); + fdisp_make_vp(&fdi, op, vp, td, cred); + ffsi = fdi.indata; ffsi->fh = fufh->fh_id; ffsi->fsync_flags = 1; /* datasync */ - fuse_insert_callback(fdip->tick, fuse_internal_fsync_callback); - fuse_insert_message(fdip->tick); + fuse_insert_callback(fdi.tick, fuse_internal_fsync_callback); + fuse_insert_message(fdi.tick); + + fdisp_destroy(&fdi); return 0; @@ -236,7 +233,7 @@ fri->size = min(uio_resid(uio), FUSE_DEFAULT_IOSIZE); // mp->max_read if ((err = fdisp_wait_answ(&fdi))) { - goto out; + break; } if ((err = fuse_internal_readdir_processdata(uio, fri->size, fdi.answ, @@ -245,9 +242,7 @@ } } - fuse_ticket_drop(fdi.tick); - -out: + fdisp_destroy(&fdi); return ((err == -1) ? 0 : err); } @@ -385,9 +380,8 @@ } #endif - if (!(err = fdisp_wait_answ(&fdi))) { - fuse_ticket_drop(fdi.tick); - } + err = fdisp_wait_answ(&fdi); + fdisp_destroy(&fdi); fuse_invalidate_attr(dvp); fuse_invalidate_attr(vp); @@ -437,9 +431,8 @@ ((char *)fdi.indata)[sizeof(*fri) + fcnp->cn_namelen + tcnp->cn_namelen + 1] = '\0'; - if (!(err = fdisp_wait_answ(&fdi))) { - fuse_ticket_drop(fdi.tick); - } + err = fdisp_wait_answ(&fdi); + fdisp_destroy(&fdi); fuse_invalidate_attr(fdvp); if (tdvp != fdvp) { @@ -490,20 +483,18 @@ feo = fdip->answ; if ((err = fuse_internal_checkentry(feo, vtyp))) { - goto out; + return err; } err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, vtyp, 0); if (err) { - fuse_internal_forget_send(mp, cnp->cn_thread, cnp->cn_cred, feo->nodeid, 1, fdip); + fuse_internal_forget_send(mp, cnp->cn_thread, cnp->cn_cred, + feo->nodeid, 1); return err; } cache_attrs(*vpp, feo); -out: - fuse_ticket_drop(fdip->tick); - return err; } @@ -524,6 +515,7 @@ fuse_internal_newentry_makerequest(mp, VTOI(dvp), cnp, op, buf, bufsize, &fdi); err = fuse_internal_newentry_core(dvp, vpp, cnp, vtype, &fdi); + fdisp_destroy(&fdi); fuse_invalidate_attr(dvp); return err; @@ -534,12 +526,8 @@ int fuse_internal_forget_callback(struct fuse_ticket *ftick, struct uio *uio) { - struct fuse_dispatcher fdi; - - fdi.tick = ftick; - fuse_internal_forget_send(ftick->tk_data->mp, curthread, NULL, - ((struct fuse_in_header *)ftick->tk_ms_fiov.base)->nodeid, 1, &fdi); + ((struct fuse_in_header *)ftick->tk_ms_fiov.base)->nodeid, 1); return 0; } @@ -549,27 +537,29 @@ struct thread *td, struct ucred *cred, uint64_t nodeid, - uint64_t nlookup, - struct fuse_dispatcher *fdip) + uint64_t nlookup) { + + struct fuse_dispatcher fdi; struct fuse_forget_in *ffi; - debug_printf("mp=%p, nodeid=%jd, nlookup=%jd, fdip=%p\n", - mp, (uintmax_t)nodeid, (uintmax_t)nlookup, fdip); + debug_printf("mp=%p, nodeid=%jd, nlookup=%jd\n", + mp, (uintmax_t)nodeid, (uintmax_t)nlookup); /* * KASSERT(nlookup > 0, ("zero-times forget for vp #%llu", * (long long unsigned) nodeid)); */ - fdisp_init(fdip, sizeof(*ffi)); - fdisp_make(fdip, FUSE_FORGET, mp, nodeid, td, cred); + fdisp_init(&fdi, sizeof(*ffi)); + fdisp_make(&fdi, FUSE_FORGET, mp, nodeid, td, cred); - ffi = fdip->indata; + ffi = fdi.indata; ffi->nlookup = nlookup; - fticket_invalidate(fdip->tick); - fuse_insert_message(fdip->tick); + fticket_invalidate(fdi.tick); + fuse_insert_message(fdi.tick); + fdisp_destroy(&fdi); } void @@ -623,8 +613,6 @@ } out: - fuse_ticket_drop(tick); - if (err) { fdata_set_dead(data); } @@ -653,6 +641,7 @@ fuse_insert_callback(fdi.tick, fuse_internal_init_callback); fuse_insert_message(fdi.tick); + fdisp_destroy(&fdi); } #ifdef ZERO_PAD_INCOMPLETE_BUFS ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.h#19 (text+ko) ==== @@ -220,8 +220,7 @@ fuse_internal_fsync(struct vnode *vp, struct thread *td, struct ucred *cred, - struct fuse_filehandle *fufh, - void *param); + struct fuse_filehandle *fufh); int fuse_internal_fsync_callback(struct fuse_ticket *tick, struct uio *uio); @@ -332,8 +331,7 @@ struct thread *td, struct ucred *cred, uint64_t nodeid, - uint64_t nlookup, - struct fuse_dispatcher *fdip); + uint64_t nlookup); /* fuse start/stop */ ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#19 (text+ko) ==== @@ -253,7 +253,7 @@ break; } - fuse_ticket_drop(fdi.tick); + fdisp_destroy(&fdi); out: return (err); @@ -270,7 +270,7 @@ int diff; int err = 0; - if (! uio->uio_resid) + if (!uio->uio_resid) return (0); fdisp_init(&fdi, 0); @@ -292,7 +292,7 @@ break; if ((err = fdisp_wait_answ(&fdi))) - return(err); + break; diff = chunksize - ((struct fuse_write_out *)fdi.answ)->size; if (diff < 0) { @@ -306,7 +306,7 @@ fuse_vnode_setsize(vp, cred, uio->uio_offset); } - fuse_ticket_drop(fdi.tick); + fdisp_destroy(&fdi); return (err); } ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_ipc.c#13 (text+ko) ==== @@ -22,6 +22,7 @@ #include #include #include +#include #include "fuse.h" #include "fuse_node.h" @@ -37,15 +38,7 @@ static int fticket_wait_answer(struct fuse_ticket *ftick); static __inline__ int fticket_aw_pull_uio(struct fuse_ticket *ftick, struct uio *uio); -static __inline__ void fuse_push_freeticks(struct fuse_ticket *ftick); - -static __inline__ struct fuse_ticket * -fuse_pop_freeticks(struct fuse_data *data); -static __inline__ void fuse_push_allticks(struct fuse_ticket *ftick); -static __inline__ void fuse_remove_allticks(struct fuse_ticket *ftick); -static struct fuse_ticket *fuse_pop_allticks(struct fuse_data *data); - static int fuse_body_audit(struct fuse_ticket *ftick, size_t blen); static __inline__ void fuse_setup_ihead(struct fuse_in_header *ihead, struct fuse_ticket *ftick, @@ -60,9 +53,9 @@ SYSCTL_NODE(_vfs, OID_AUTO, fuse, CTLFLAG_RW, 0, "FUSE tunables"); SYSCTL_STRING(_vfs_fuse, OID_AUTO, fuse4bsd_version, CTLFLAG_RD, FUSE4BSD_VERSION, 0, "fuse4bsd version"); -static int fuse_max_freetickets = 1024; -SYSCTL_INT(_vfs_fuse, OID_AUTO, max_freetickets, CTLFLAG_RW, - &fuse_max_freetickets, 0, "limit for number of free tickets kept"); +static int fuse_ticket_count = 0; +SYSCTL_INT(_vfs_fuse, OID_AUTO, ticket_count, CTLFLAG_RW, + &fuse_ticket_count, 0, "number of allocated tickets"); static long fuse_iov_permanent_bufsize = 1 << 19; SYSCTL_LONG(_vfs_fuse, OID_AUTO, iov_permanent_bufsize, CTLFLAG_RW, &fuse_iov_permanent_bufsize, 0, @@ -71,12 +64,9 @@ SYSCTL_INT(_vfs_fuse, OID_AUTO, iov_credit, CTLFLAG_RW, &fuse_iov_credit, 0, "how many times is an oversized fuse_iov tolerated"); -static unsigned maxtickets = 0; -SYSCTL_UINT(_vfs_fuse, OID_AUTO, maxtickets, CTLFLAG_RW, - &maxtickets, 0, "limit how many tickets are tolerated"); -MALLOC_DEFINE(M_FUSEMSG, "fuse_messaging", - "buffer for fuse messaging related things"); +MALLOC_DEFINE(M_FUSEMSG, "fuse_msgbuf", "fuse message buffer"); +static uma_zone_t ticket_zone; void fiov_init(struct fuse_iov *fiov, size_t size) @@ -98,6 +88,7 @@ { debug_printf("fiov=%p\n", fiov); + MPASS(fiov->base != NULL); free(fiov->base, M_FUSEMSG); } @@ -133,20 +124,55 @@ fiov_adjust(fiov, 0); } -static struct fuse_ticket * -fticket_alloc(struct fuse_data *data) +static int +fticket_ctor(void *mem, int size, void *arg, int flags) { - struct fuse_ticket *ftick; + struct fuse_ticket *ftick = mem; + struct fuse_data *data = arg; - ftick = malloc(sizeof(*ftick), M_FUSEMSG, M_WAITOK | M_ZERO); + debug_printf("ftick=%p data=%p\n", ftick, data); - debug_printf("ftick=%p data=%p\n", ftick, data); + FUSE_ASSERT_MS_DONE(ftick); + FUSE_ASSERT_AW_DONE(ftick); - mtx_lock(&data->ticket_mtx); - ftick->tk_unique = data->ticketer++; - mtx_unlock(&data->ticket_mtx); ftick->tk_data = data; + if (ftick->tk_unique != 0) + fticket_refresh(ftick); + + /* May be truncated to 32 bits */ + ftick->tk_unique = atomic_fetchadd_long(&data->ticketer, 1); + if (ftick->tk_unique == 0) + ftick->tk_unique = atomic_fetchadd_long(&data->ticketer, 1); + + refcount_init(&ftick->tk_refcount, 1); + atomic_add_acq_int(&fuse_ticket_count, 1); + + return 0; +} + +static void +fticket_dtor(void *mem, int size, void *arg) +{ + struct fuse_ticket *ftick = mem; + + debug_printf("ftick=%p\n", ftick); + + FUSE_ASSERT_MS_DONE(ftick); + FUSE_ASSERT_AW_DONE(ftick); + + atomic_subtract_acq_int(&fuse_ticket_count, 1); +} + +static int +fticket_init(void *mem, int size, int flags) +{ + struct fuse_ticket *ftick = mem; + + DEBUG("ftick=%p\n", ftick); + + bzero(ftick, sizeof(struct fuse_ticket)); + fiov_init(&ftick->tk_ms_fiov, sizeof(struct fuse_in_header)); ftick->tk_ms_type = FT_M_FIOV; @@ -154,7 +180,31 @@ fiov_init(&ftick->tk_aw_fiov, 0); ftick->tk_aw_type = FT_A_FIOV; - return ftick; + return 0; +} + +static void +fticket_fini(void *mem, int size) +{ + struct fuse_ticket *ftick = mem; + + DEBUG("ftick=%p\n", ftick); + + fiov_teardown(&ftick->tk_ms_fiov); + fiov_teardown(&ftick->tk_aw_fiov); + mtx_destroy(&ftick->tk_aw_mtx); +} + +static __inline struct fuse_ticket * +fticket_alloc(struct fuse_data *data) +{ + return uma_zalloc_arg(ticket_zone, data, M_WAITOK); +} + +static __inline void +fticket_destroy(struct fuse_ticket *ftick) +{ + return uma_zfree(ticket_zone, ftick); } static __inline__ @@ -163,6 +213,9 @@ { debug_printf("ftick=%p\n", ftick); + FUSE_ASSERT_MS_DONE(ftick); + FUSE_ASSERT_AW_DONE(ftick); + fiov_refresh(&ftick->tk_ms_fiov); ftick->tk_ms_bufdata = NULL; ftick->tk_ms_bufsize = 0; @@ -177,26 +230,6 @@ ftick->tk_aw_type = FT_A_FIOV; ftick->tk_flag = 0; - ftick->tk_age++; -} - -static void -fticket_destroy(struct fuse_ticket *ftick) -{ - debug_printf("ftick=%p\n", ftick); - - KASSERT(ftick->tk_ms_link.stqe_next == NULL, - ("FUSE: destroying ticket still on message list %p", ftick)); - KASSERT(ftick->tk_aw_link.tqe_next == NULL && - ftick->tk_aw_link.tqe_prev == NULL, - ("FUSE: destroying ticket still on answer delivery list %p", ftick)); - - fiov_teardown(&ftick->tk_ms_fiov); - - mtx_destroy(&ftick->tk_aw_mtx); - fiov_teardown(&ftick->tk_aw_fiov); - - free(ftick, M_FUSEMSG); } static int @@ -315,12 +348,9 @@ STAILQ_INIT(&data->ms_head); mtx_init(&data->ticket_mtx, "fuse ticketer mutex", NULL, MTX_DEF); debug_printf("ALLOC_INIT data=%p ticket_mtx=%p\n", data, &data->ticket_mtx); - STAILQ_INIT(&data->freetickets_head); - TAILQ_INIT(&data->alltickets_head); mtx_init(&data->aw_mtx, "fuse answer list mutex", NULL, MTX_DEF); TAILQ_INIT(&data->aw_head); data->ticketer = 0; - data->freeticket_counter = 0; data->daemoncred = crhold(cred); data->daemon_timeout = FUSE_DEFAULT_DAEMON_TIMEOUT; @@ -334,8 +364,6 @@ void fdata_destroy(struct fuse_data *data) { - struct fuse_ticket *ftick; - debug_printf("data=%p, destroy.mntco = %d\n", data, data->mntco); /* Driving off stage all that stuff thrown at device... */ @@ -346,10 +374,6 @@ sx_destroy(&data->rename_lock); #endif - while ((ftick = fuse_pop_allticks(data))) { - fticket_destroy(ftick); - } - crfree(data->daemoncred); free(data,M_FUSEMSG); @@ -376,71 +400,6 @@ fuse_lck_mtx_unlock(data->ticket_mtx); } -static __inline__ -void -fuse_push_freeticks(struct fuse_ticket *ftick) -{ - debug_printf("ftick=%p\n", ftick); - - STAILQ_INSERT_TAIL(&ftick->tk_data->freetickets_head, ftick, - tk_freetickets_link); - ftick->tk_data->freeticket_counter++; -} - -static __inline__ -struct fuse_ticket * -fuse_pop_freeticks(struct fuse_data *data) -{ - struct fuse_ticket *ftick; - - debug_printf("data=%p\n", data); - - if ((ftick = STAILQ_FIRST(&data->freetickets_head))) { - STAILQ_REMOVE_HEAD(&data->freetickets_head, tk_freetickets_link); - data->freeticket_counter--; - } - - if (STAILQ_EMPTY(&data->freetickets_head) && - (data->freeticket_counter != 0)) { - panic("FUSE: ticket count mismatch!"); - } - - return ftick; -} - -static __inline__ -void -fuse_push_allticks(struct fuse_ticket *ftick) -{ - debug_printf("ftick=%p\n", ftick); - - TAILQ_INSERT_TAIL(&ftick->tk_data->alltickets_head, ftick, - tk_alltickets_link); -} - -static __inline__ -void -fuse_remove_allticks(struct fuse_ticket *ftick) -{ - debug_printf("ftick=%p\n", ftick); - - TAILQ_REMOVE(&ftick->tk_data->alltickets_head, ftick, tk_alltickets_link); -} - -static struct fuse_ticket * -fuse_pop_allticks(struct fuse_data *data) -{ - struct fuse_ticket *ftick; - - debug_printf("data=%p\n", data); - - if ((ftick = TAILQ_FIRST(&data->alltickets_head))) { - fuse_remove_allticks(ftick); - } - - return ftick; -} - struct fuse_ticket * fuse_ticket_fetch(struct fuse_data *data) { @@ -449,31 +408,17 @@ debug_printf("data=%p\n", data); - fuse_lck_mtx_lock(data->ticket_mtx); + ftick = fticket_alloc(data); - if (data->freeticket_counter == 0) { - fuse_lck_mtx_unlock(data->ticket_mtx); - ftick = fticket_alloc(data); - if (!ftick) { - panic("ticket allocation failed"); - } + if (!(data->dataflags & FSESS_INITED) && data->ticketer > 2) { + /* Sleep until get answer for INIT messsage */ fuse_lck_mtx_lock(data->ticket_mtx); - fuse_push_allticks(ftick); - } else { - /* locked here */ - ftick = fuse_pop_freeticks(data); - if (!ftick) { - panic("no free ticket despite the counter's value"); + if (!(data->dataflags & FSESS_INITED) && data->ticketer > 2) { + err = msleep(&data->ticketer, &data->ticket_mtx, PCATCH | PDROP, + "fu_ini", 0); } } - if (!(data->dataflags & FSESS_INITED) && data->ticketer > 1) { - err = msleep(&data->ticketer, &data->ticket_mtx, PCATCH | PDROP, - "fu_ini", 0); - } else { - fuse_lck_mtx_unlock(data->ticket_mtx); - } - if (err) { fdata_set_dead(data); } @@ -481,50 +426,23 @@ return ftick; } -void +int fuse_ticket_drop(struct fuse_ticket *ftick) { - int die = 0; + int die; - debug_printf("ftick=%p\n", ftick); - - fuse_lck_mtx_lock(ftick->tk_data->ticket_mtx); - - if (fuse_max_freetickets >= 0 && - fuse_max_freetickets <= ftick->tk_data->freeticket_counter) { - die = 1; - } else { - fuse_lck_mtx_unlock(ftick->tk_data->ticket_mtx); - fticket_refresh(ftick); - fuse_lck_mtx_lock(ftick->tk_data->ticket_mtx); - } - - /* locked here */ - - if (die) { - fuse_remove_allticks(ftick); - fuse_lck_mtx_unlock(ftick->tk_data->ticket_mtx); + die = refcount_release(&ftick->tk_refcount); + debug_printf("ftick=%p refcount=%d\n", ftick, ftick->tk_refcount); + if (die) fticket_destroy(ftick); - } else { - fuse_push_freeticks(ftick); - fuse_lck_mtx_unlock(ftick->tk_data->ticket_mtx); - } -} -void -fuse_ticket_drop_invalid(struct fuse_ticket *ftick) -{ - debug_printf("ftick=%p\n", ftick); - - if (ftick->tk_flag & FT_INVAL) { - fuse_ticket_drop(ftick); - } + return die; } void fuse_insert_callback(struct fuse_ticket *ftick, fuse_handler_t *handler) { - debug_printf("ftick=%p, handler=%p\n", ftick, handler); + debug_printf("ftick=%p, handler=%p data=%p\n", ftick, ftick->tk_data, handler); if (fdata_get_dead(ftick->tk_data)) { return; @@ -760,7 +678,6 @@ fuse_standard_handler(struct fuse_ticket *ftick, struct uio *uio) { int err = 0; - int dropflag = 0; debug_printf("ftick=%p, uio=%p\n", ftick, uio); @@ -768,13 +685,7 @@ fuse_lck_mtx_lock(ftick->tk_aw_mtx); - if (fticket_answered(ftick)) { - /* The requester was interrupted and she set the "answered" flag - * to notify us. In this case, we don't have to care about - * anything, just drop the ticket and get out as fast as we can. - */ - dropflag = 1; - } else { + if (!fticket_answered(ftick)) { fticket_set_answered(ftick); ftick->tk_aw_errno = err; wakeup(ftick); @@ -782,10 +693,6 @@ fuse_lck_mtx_unlock(ftick->tk_aw_mtx); - if (dropflag) { - fuse_ticket_drop(ftick); - } - return err; } @@ -808,10 +715,6 @@ fdip->tick = fuse_ticket_fetch(data); } - if (fdip->tick == 0) { - panic("fuse_ticket_fetch() failed"); - } - FUSE_DIMALLOC(&fdip->tick->tk_ms_fiov, fdip->finh, fdip->indata, fdip->iosize); @@ -915,7 +818,20 @@ out: debug_printf("IPC: dropping ticket, err = %d\n", err); - fuse_ticket_drop(fdip->tick); return err; } + +void +fuse_ipc_init(void) +{ + ticket_zone = uma_zcreate("fuse_ticket", sizeof(struct fuse_ticket), + fticket_ctor, fticket_dtor, fticket_init, fticket_fini, + UMA_ALIGN_PTR, 0); +} + +void +fuse_ipc_destroy(void) +{ + uma_zdestroy(ticket_zone); +} ==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_ipc.h#14 (text+ko) ==== @@ -6,6 +6,9 @@ #ifndef _FUSE_IPC_H_ #define _FUSE_IPC_H_ +#include +#include + struct fuse_iov { void *base; size_t len; @@ -27,6 +30,15 @@ #define FU_AT_LEAST(siz) max((siz), 160) +#define FUSE_ASSERT_AW_DONE(ftick) \ + KASSERT((ftick)->tk_aw_link.tqe_next == NULL && \ + (ftick)->tk_aw_link.tqe_prev == NULL, \ + ("FUSE: ticket still on answer delivery list %p", (ftick))) \ + +#define FUSE_ASSERT_MS_DONE(ftick) \ + KASSERT((ftick)->tk_ms_link.stqe_next == NULL, \ + ("FUSE: ticket still on message list %p", (ftick))) + struct fuse_ticket; struct fuse_data; @@ -37,22 +49,19 @@ uint64_t tk_unique; struct fuse_data *tk_data; int tk_flag; - uint32_t tk_age; + u_int tk_refcount; - STAILQ_ENTRY(fuse_ticket) tk_freetickets_link; - TAILQ_ENTRY(fuse_ticket) tk_alltickets_link; - /* fields for initiating an upgoing message */ struct fuse_iov tk_ms_fiov; void *tk_ms_bufdata; - unsigned long tk_ms_bufsize; + size_t tk_ms_bufsize; enum { FT_M_FIOV, FT_M_BUF } tk_ms_type; STAILQ_ENTRY(fuse_ticket) tk_ms_link; /* fields for handling answers coming from userspace */ struct fuse_iov tk_aw_fiov; void *tk_aw_bufdata; - unsigned long tk_aw_bufsize; + size_t tk_aw_bufsize; enum { FT_A_FIOV, FT_A_BUF } tk_aw_type; struct fuse_out_header tk_aw_ohead; @@ -70,7 +79,6 @@ struct fuse_iov * fticket_resp(struct fuse_ticket *ftick) { - DEBUGX(FUSE_DEBUG_IPC, "-> ftick=%p\n", ftick); return (&ftick->tk_aw_fiov); } @@ -131,10 +139,7 @@ TAILQ_HEAD(, fuse_ticket) aw_head; struct mtx ticket_mtx; - STAILQ_HEAD(, fuse_ticket) freetickets_head; - TAILQ_HEAD(, fuse_ticket) alltickets_head; - uint32_t freeticket_counter; - uint64_t ticketer; + u_long ticketer; #ifdef FUSE_EXPLICIT_RENAME_LOCK struct sx rename_lock; @@ -183,7 +188,6 @@ fuse_get_mpdata(struct mount *mp) { struct fuse_data *data = mp->mnt_data; - DEBUGX(FUSE_DEBUG_IPC, "-> mp=%p\n", mp); return (data->mpri == FM_PRIMARY ? data : NULL); } @@ -191,8 +195,10 @@ void fuse_ms_push(struct fuse_ticket *ftick) { - DEBUGX(FUSE_DEBUG_IPC, "-> ftick=%p\n", ftick); + DEBUGX(FUSE_DEBUG_IPC, "ftick=%p refcount=%d\n", + ftick, ftick->tk_refcount + 1); mtx_assert(&ftick->tk_data->ms_mtx, MA_OWNED); + refcount_acquire(&ftick->tk_refcount); STAILQ_INSERT_TAIL(&ftick->tk_data->ms_head, ftick, tk_ms_link); } @@ -202,7 +208,6 @@ { struct fuse_ticket *ftick = NULL; >>> TRUNCATED FOR MAIL (1000 lines) <<<