Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Jul 2011 12:31:02 GMT
From:      Ilya Putsikau <ilya@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 196439 for review
Message-ID:  <201107201231.p6KCV2NU071497@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <sys/mount.h>
 #include <sys/vnode.h>
 #include <sys/sysctl.h>
+#include <vm/uma.h>
 
 #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 <sys/param.h>
+#include <sys/refcount.h>
+
 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) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107201231.p6KCV2NU071497>