Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 13 Aug 2007 18:39:02 GMT
From:      Sonja Milicic <smilicic@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 125109 for review
Message-ID:  <200708131839.l7DId2SJ088088@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=125109

Change 125109 by smilicic@tanarri_marilith on 2007/08/13 18:38:46

	   allocation table structure for keeping track of what's in the log file
	   reading (from log and disk) and committing to disk
	   fixed memory leaks

Affected files ...

.. //depot/projects/soc2007/smilicic_glog/sys/geom/log/geom_log_so.c#3 edit
.. //depot/projects/soc2007/smilicic_glog/sys/geom/log/glog.c#8 edit
.. //depot/projects/soc2007/smilicic_glog/sys/geom/log/glog.h#3 edit
.. //depot/projects/soc2007/smilicic_glog/sys/geom/log/glog_alloctable.c#1 add
.. //depot/projects/soc2007/smilicic_glog/sys/geom/log/glog_alloctable.h#1 add
.. //depot/projects/soc2007/smilicic_glog/sys/geom/log/glog_fileops.c#3 edit
.. //depot/projects/soc2007/smilicic_glog/sys/geom/log/glog_fileops.h#3 edit

Differences ...

==== //depot/projects/soc2007/smilicic_glog/sys/geom/log/geom_log_so.c#3 (text+ko) ====

@@ -76,7 +76,13 @@
         },
         "[-v] prov ..."
     },
-
+    { "dump", G_FLAG_VERBOSE, NULL,
+        {
+            { 'n', "nidx", NULL, G_TYPE_NUMBER },
+            G_OPT_SENTINEL
+        },
+        "[-n nidx] prov ..."
+    },
     G_CMD_SENTINEL
 };
 

==== //depot/projects/soc2007/smilicic_glog/sys/geom/log/glog.c#8 (text+ko) ====

@@ -44,16 +44,15 @@
 #include <sys/kthread.h>
 #include <geom/geom.h>
 #include <sys/fcntl.h>
+#include <sys/stat.h>
 #include <sys/namei.h>
 
 #include "glog.h"
 #include "glog_fileops.h"
- 
+#include "glog_alloctable.h"
 static MALLOC_DEFINE(M_GLOG, "glog", "GEOM_LOG Data");
+static uma_zone_t g_log_alloctable_zone;
 
-static uma_zone_t g_log_io_zone;
-/*static uma_zone_t g_log_hl_zone;*/
-
 static void g_log_ctlreq(struct gctl_req *req, struct g_class *mp, const char 
 	    *verb);
 static enum gctl_verb g_log_verb_id(const char* verb);
@@ -73,6 +72,8 @@
 static struct g_log_event* g_log_get_event(struct g_log_event_sink *es);
 static void g_log_write(struct bio *bp);
 static void g_log_read(struct bio *bp);
+static void g_log_rollback(struct g_log_softc *sc);
+static void g_log_commit(struct g_log_softc *sc);
 static void g_log_dumpconf(struct sbuf *sb, const char *indent, 
 	    struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp);
 static void g_log_ctl_destroy(struct gctl_req *req, struct g_class *mp);
@@ -82,7 +83,7 @@
 SYSCTL_DECL(_kern_geom);
 SYSCTL_NODE(_kern_geom, OID_AUTO, log, CTLFLAG_RW, 0, "GEOM_LOG information");
 
-static u_int g_log_debug = 10; /* XXX: lower when released to public */
+u_int g_log_debug; 
 TUNABLE_INT("kern.geom.log.debug", &g_log_debug);
 SYSCTL_UINT(_kern_geom_log, OID_AUTO, debug, CTLFLAG_RW, &g_log_debug, 0,
 	    "Debug level");
@@ -96,12 +97,7 @@
 TUNABLE_INT("kern.geom.log.maxmem", &g_log_maxmem);
 SYSCTL_UINT(_kern_geom_log, OID_AUTO, maxmem, CTLFLAG_RD, &g_log_maxmem,
 	0, "Maximum memory that can be allocated for I/O (in bytes)");
-/*
-extern u_int _hl_stat_hinted_lookups;
-SYSCTL_UINT(_kern_geom_log, OID_AUTO, hl_hinted_lookups,
-	CTLFLAG_RD, &_hl_stat_hinted_lookups, 0, 
-	"Number of hint cache hits for hinted interval list");
-*/
+
 static u_int g_log_alloc_failed = 0;
 SYSCTL_UINT(_kern_geom_log, OID_AUTO, alloc_failed, CTLFLAG_RD,
 	&g_log_alloc_failed, 0, "How many times I/O allocation failed");
@@ -118,25 +114,23 @@
 
 /* gctl verb IDs */
 enum gctl_verb { GCTL_INVALID, GCTL_COMMIT, GCTL_ROLLBACK, GCTL_START, 
-	GCTL_STOP};
+	GCTL_STOP, GCTL_DUMP};
 
 static void
 g_log_init(struct g_class *mp __unused)
 {
-	g_log_io_zone = uma_zcreate("glog.io", MAXPHYS, NULL, NULL, NULL, NULL, 
-		    0, UMA_ALIGN_CACHE);
+	g_log_debug = 10;
+	g_log_alloctable_zone = uma_zcreate("glog.alloctable", MAXPHYS, NULL, 
+	    NULL, NULL, NULL, 0, UMA_ALIGN_CACHE);
 	g_log_maxmem -= g_log_maxmem % MAXPHYS;
-	uma_zone_set_max(g_log_io_zone, g_log_maxmem / MAXPHYS);
-   /* g_log_hl_zone = uma_zcreate("glog.hl", sizeof(struct hl_entry), NULL, NULL, 
-	    NULL, NULL, UMA_ALIGN_PTR, 0);*/
+	uma_zone_set_max(g_log_alloctable_zone, g_log_maxmem / MAXPHYS);
 	G_LOG_DEBUG(DBG_NOTICE, "%s", __func__);
 }
 
 static void
 g_log_fini(struct g_class *mp __unused)
 {
-	uma_zdestroy(g_log_io_zone);
-	/*uma_zdestroy(g_log_hl_zone);*/
+	uma_zdestroy(g_log_alloctable_zone);
 	G_LOG_DEBUG(DBG_NOTICE, "%s", __func__);
 }
 
@@ -155,16 +149,18 @@
 }
 
 static struct g_geom *
-g_log_create_geom(const char *prov, const char *file, struct g_class *mp, int *err)
+g_log_create_geom(const char *prov, const char *file, struct g_class *mp, 
+    int *err)
 {
 	struct g_geom *gp;
 	struct g_provider *pp_log, *pp_disk;
-       	struct g_consumer *cp_disk;
+	struct g_consumer *cp_disk;
 	struct g_log_softc *sc;
-	
+	struct g_log_header head;
+	int max_elements;
 	/*initialize softc*/
 	sc = malloc(sizeof(*sc), M_GLOG, M_WAITOK | M_ZERO);
-	
+
 	/*create geom for log*/
 	gp = g_new_geomf(mp, "%s.log", prov);
 
@@ -173,38 +169,98 @@
 	gp->orphan = g_log_orphan;
 	gp->access = g_log_access;
 	gp->dumpconf = g_log_dumpconf;
-	if (gp == NULL)
+	if (gp == NULL) {
 		*err=3;
+		return (NULL);
+	}
 	
 	/* get provider and consumer for disk*/
+	G_LOG_DEBUG(0, "Getting provider and consumer for disk");
 	if (strncmp(prov, "/dev/", strlen("/dev/")) == 0)
 		prov += strlen("/dev/");
 	pp_disk = g_provider_by_name(prov);
-	if (pp_disk == NULL)
+	if (pp_disk == NULL){
 		*err = 1;
+		return (NULL);
+	}
 	cp_disk = g_new_consumer(gp);
-	if (g_attach(cp_disk, pp_disk) != 0)
+	if (g_attach(cp_disk, pp_disk) != 0) {
 		*err = 2;
+		return (NULL);
+	}
+	g_error_provider(pp_disk, 0);
 	sc->sc_prov_disk = pp_disk;
 	sc->sc_cons_disk = cp_disk;
 	
-	/*create provider and consumer for log*/
+	/*create provider for log*/
+	G_LOG_DEBUG(0, "Creating provider for log");
 	pp_log = g_new_providerf(gp, "%s.log", prov);
 	pp_log->mediasize = pp_disk->mediasize;
 	pp_log->sectorsize = pp_disk->sectorsize;
 	g_error_provider(pp_log, 0);
+	sc->sc_prov_log = pp_log;
 	
-	sc->sc_prov_log = pp_log;
-	if (g_log_event_sink_init(sc, &sc->sc_events, g_log_worker, "events") !=0){
-		*err=4;
-		g_log_event_sink_destroy(&sc->sc_events);
+	/*initialize alloc table*/
+	G_LOG_DEBUG(0, "Initializing allocation table");
+	sc->sc_alloctable = malloc(sizeof(*sc->sc_alloctable), M_GLOG, 
+	    M_WAITOK | M_ZERO);	
+	g_log_alloctable_init(sc, M_GLOG);
+
+	/*initialize request sublist*/
+	G_LOG_DEBUG(0, "Initializing request sublist");
+	max_elements = (int)(MAXPHYS / sc->sc_prov_log->sectorsize);
+	sc->sc_req_sublist = malloc (max_elements * sizeof(
+	    struct g_log_data), M_GLOG, M_WAITOK | M_ZERO);
+	sc->sc_req_sublist_size = 0;
+	
+	/*open file*/
+	G_LOG_DEBUG(0, "Opening log file");
+	sc->sc_vn = g_log_open_file(file, FWRITE | FREAD | O_CREAT | O_TRUNC, 
+	    S_IRUSR | S_IWUSR);
+	/*see if the file can be used as a log file (has to be either empty or 
+	 *have geom log header), add header if the file's empty, exit with an 
+	 *error if file is neither empty nor has header
+	 */
+ 	G_LOG_DEBUG(0, "Checking log file");
+	if (g_log_get_size(sc->sc_vn) > 0) {
+	 	G_LOG_DEBUG(0, "Reading header");
+		g_log_read_data(sc->sc_vn, &head, sizeof(head), 0);
+		if (strcmp(head.text,"GEOM_LOG")!=0) {
+			*err = 1;
+			return (NULL);
+		}
+		/*warn if the log file was made with different version of glog*/
+		if (head.version != G_LOG_VERSION)
+			G_LOG_DEBUG(0, "Header version: %d\nCurrent version: %d"
+			    , head.version, G_LOG_VERSION);
+		/*restore alloc table from file*/
+		G_LOG_DEBUG(0, "Restoring alloctable from file");
+		sc->sc_curr_offset = sizeof(head);
+		g_log_alloctable_restore(sc, M_GLOG);
+	}
+	else {
+	 	G_LOG_DEBUG(0, "Writing header");
+		G_LOG_DEBUG(0, "Log file empty, writing header.");
+		g_log_write_header(sc->sc_vn); 
+		sc->sc_curr_offset = sizeof(head);
+	}
+	
+	if (sc->sc_vn == NULL) {
+		*err = 5;
+		return (NULL);
 	}
-	/*open file*/
-	sc->sc_vn = glog_open_file(file, FWRITE | O_TRUNC | O_CREAT);
+	sc->sc_file_name = strdup(file, M_GLOG);
+
 	sc->sc_geom_log = gp;
 	gp->softc = sc;
 	G_LOG_DEBUG(0, "Created geom %s", gp->name);
-
+	/*initialize worker thread*/
+	if (g_log_event_sink_init(sc, &sc->sc_events, g_log_worker, "events") 
+		    != 0){
+		*err=4;
+		g_log_event_sink_destroy(&sc->sc_events);
+		return (NULL);
+	}
 	return gp;
 }
 
@@ -217,8 +273,8 @@
 	es->sc = sc;
 	mtx_init(&es->eventq_mtx, "glog:event_sink", NULL, MTX_DEF);
 	TAILQ_INIT(&es->eventq);
-	if ((err = kthread_create(func, es, &es->worker_thread, 0, 0, "g_log %s", 
-		    name)) != 0)
+	if ((err = kthread_create(func, es, &es->worker_thread, 0, 0, "g_log %s"
+		    , name)) != 0)
 	return err;
 	es->flags = 0;   
     
@@ -229,22 +285,73 @@
 static void
 g_log_event_sink_destroy(struct g_log_event_sink *es) 
 {
-    g_log_post_event(es, GLOG_EVSTOP, GLOG_FLAG_WAKEUP_SC, NULL, 0);
-    while (es->worker_thread != NULL) /* wait for the worker thread to die */
-        tsleep(&es->worker_thread, PRIBIO, "wrkoff", hz/5);
-    mtx_destroy(&es->eventq_mtx);
-    bzero(es, sizeof(*es));
+	g_log_post_event(es, GLOG_EVSTOP, GLOG_FLAG_WAKEUP_SC, NULL, 0);
+
+	/* wait for the worker thread to die */
+	while (es->worker_thread != NULL) 
+        	tsleep(&es->worker_thread, PRIBIO, "wrkoff", hz/5);
+
+	mtx_destroy(&es->eventq_mtx);
+	bzero(es, sizeof(*es));
+}
+
+/* Find the geom we handle */
+static struct g_log_softc *
+g_log_find(struct g_class *mp, const char *name)
+{
+	struct g_geom *gp;
+
+	LIST_FOREACH(gp, &mp->geom, geom) {
+		if (strcmp(gp->name, name) == 0)
+			return (gp->softc);
+	}
+	return (NULL);
+}
+
+
+static char *
+g_log_dump_alloctable(struct g_log_softc *sc, int icp)
+{
+	struct g_log_alloc_element *ae;
+	struct g_log_alloc_table_element *te;
+
+	KASSERT ( sc != NULL, ("sc is null in %s", __func__));
+	if ((icp < 0) || (icp > sc->sc_alloctable->tablesize))
+		return "Offset out of range.";
+
+	G_LOG_DEBUG(0, "Dumping compartment #%d", icp);
+	te = &sc->sc_alloctable->table[icp];
+	SLIST_FOREACH(ae, &te->allocq, linkage) {
+		if (ae->offset_log != -1)
+			G_LOG_DEBUG(0, " %p: LOG: offset_disk=%d\t"
+			    "offset_log=%d\tdata_size=%d",
+			    ae, 
+			    (int)ae->offset_disk, 
+			    (int)ae->offset_log, 
+			    (int)ae->data_size);
+		else
+			G_LOG_DEBUG(0, " %p: DISK: offset_disk=%d\t"
+			    "data_size=%d", 
+			    ae,
+			    (int)ae->offset_disk, 
+			    (int)ae->data_size);
+	}
+	return NULL;
 }
 
+
 /*process ctl requests*/
 static void
 g_log_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
 {
 	struct g_geom *gp=NULL;
+	struct g_log_softc *sc;
 	const char *prov, *file;
+	long long *icp;
 	int *num_arg;
 	int err = 0;
 	char *err_text=NULL;
+	/*char confirm;*/
 	
 	g_topology_assert();
 	num_arg = gctl_get_paraml(req, "nargs", sizeof(*num_arg));
@@ -253,37 +360,70 @@
 		if (*num_arg == 2) {
 			prov = gctl_get_asciiparam(req, "arg0");
 			file = gctl_get_asciiparam(req, "arg1");
+			G_LOG_DEBUG(0, "Start");
 			gp = g_log_create_geom(prov, file, mp, &err);
-			
+			sc = gp->softc;
+			KASSERT(sc != NULL, ("%s: sc is null", __func__));
 			if (err != 0){
 				switch (err){
 				case 1:
-					err_text="Cannot open provider";
+					err_text = "Can not open provider";
 					break;
 				case 2:
-					err_text="Cannot attach consumer to provider";
+					err_text = "Can not attach consumer to " 
+					    "provider";
 					break;
 				case 3:
-					err_text="Can not create geom";
+					err_text = "Can not create geom";
 					break;
 				case 4:
-					err_text="Can not start worker thread";
+					err_text = "Can not start worker "
+					    "thread";
+					break;
+				case 5:
+					err_text = "Can not open log file.";
 					break;
 				}
-				gctl_error(req, "Error starting geom log: %s", err_text);
+				gctl_error(req, "Error starting geom log: %s", 
+				    err_text);
 			}
 		} else
 			gctl_error(req, "Wrong number of parameters.");
 		break;
 	case GCTL_COMMIT:
 		if (*num_arg == 1) {
+			/*printf("Are you sure (y/n)?");
+			scanf("%c", &confirm);
+			if (confirm != 'y')
+				break;*/
 			prov = gctl_get_asciiparam(req, "arg0");
+			sc = g_log_find(mp, prov);
+			if (sc == NULL) {
+				G_LOG_DEBUG(0, "Geom not found.");
+				break;
+			}
+			g_log_post_event(&sc->sc_events, GLOG_EVCOMMIT, 
+			    GLOG_FLAG_WAKEUP_SC, sc, 0);
 			
-			
 		 } else
 			gctl_error(req, "Wrong number of parameters.");
 		break;
 	case GCTL_ROLLBACK:
+		if (*num_arg ==1){
+			/*printf("Are you sure (y/n)?");
+			scanf("%c", &confirm);
+			if (confirm != 'y')
+				break;*/
+			prov = gctl_get_asciiparam(req, "arg0");    
+			sc = g_log_find(mp, prov);
+			if (sc == NULL) {
+				G_LOG_DEBUG(0, "Geom not found.");
+				break;
+			}
+			g_log_post_event(&sc->sc_events, GLOG_EVROLLBACK, 
+			    GLOG_FLAG_WAKEUP_SC, sc, 0);
+		} else
+			gctl_error(req, "Wrong number of parameters.");
 		break;
 	case GCTL_STOP:
 		if (*num_arg == 1) {
@@ -291,10 +431,25 @@
 		} else
 			gctl_error(req, "Wrong number of parameters.");
 		break;
+	case GCTL_DUMP:
+		prov = gctl_get_asciiparam(req, "arg0"); 
+		icp = gctl_get_paraml(req, "nidx", sizeof(*icp));
+		if (icp == NULL) {
+			gctl_error(req, "Missing argument: nidx");
+			return;
+		}
+		sc = g_log_find(mp, prov);
+		if (sc == NULL) {
+			G_LOG_DEBUG(0, "Geom %s not found", prov);
+			gctl_error(req, "Geom %s not found", prov);
+			break;
+		}
+		g_log_dump_alloctable(sc, *icp);		
+		break;	
 	default:
-		panic("Unknown verb!");
+		gctl_error(req, "Unknown verb.");
+		break;
 	}
-	G_LOG_DEBUG(0, "ctlreq done");
 }
 
 /*start geom*/
@@ -302,23 +457,22 @@
 g_log_start(struct bio *bp) 
 {
 	struct g_log_softc *sc; 
-	G_LOG_DEBUG(0, "request received.");
 
 	sc = bp->bio_to->geom->softc;
 	KASSERT(sc != NULL,
 	    ("Provider's error should be set (error=%d)(device=%s).",
 	    bp->bio_to->error, bp->bio_to->name));
 
-	G_LOG_LOGREQ(DBG_NOTICE, bp, "Request received.");
 	switch(bp->bio_cmd) {
 	case BIO_WRITE:
 		G_LOG_DEBUG(0, "Write request received.");
-		g_log_post_event(&sc->sc_events, GLOG_EVWRITE, GLOG_FLAG_WAKEUP_SC, bp, 0);
+		g_log_post_event(&sc->sc_events, GLOG_EVWRITE, 
+		    GLOG_FLAG_WAKEUP_SC, bp, 0);
 		break;
 	case BIO_READ:
-		g_io_deliver(bp, ENXIO);
-		return;
-		g_log_post_event(&sc->sc_events, GLOG_EVREAD, GLOG_FLAG_WAKEUP_SC, bp, 0);
+		G_LOG_DEBUG(0, "Read request received.");
+		g_log_post_event(&sc->sc_events, GLOG_EVREAD, 
+		    GLOG_FLAG_WAKEUP_SC, bp, 0);
 		break;
 	default:
 		g_io_deliver(bp, ENXIO);
@@ -334,9 +488,10 @@
 	struct g_log_softc *sc;
 	struct g_provider *pp_disk, *pp_log;
 	struct g_consumer *cp_disk;
+	
 	sc=gp->softc;
 	
-       	g_topology_assert();
+	g_topology_assert();
 
 	if (sc==NULL)
 		return (ENXIO);
@@ -345,9 +500,11 @@
 	pp_disk = sc->sc_prov_disk;
 	cp_disk = sc->sc_cons_disk;
 	
-	if (pp_log != NULL && (pp_log->acr != 0 || pp_log->acw !=0 || pp_log->ace != 0)){
+	if (pp_log != NULL && (pp_log->acr != 0 || pp_log->acw !=0 || 
+	    pp_log->ace != 0)){
 		if (force)
-			G_LOG_DEBUG(0, "Device %s is still open.", pp_log->name);
+			G_LOG_DEBUG(0, "Device %s is still open.", 
+			    pp_log->name);
 		else {
 			G_LOG_DEBUG(1, "Device %s is still open(r%d, w%d, e%d)",
 			    pp_log->name,pp_log->acr,pp_log->acw,pp_log->ace);
@@ -355,14 +512,15 @@
 		}
 	}
 	/*close log file*/
-	G_LOG_DEBUG(0, "Closing log file.");
-	glog_close_file(sc->sc_vn, FWRITE);
+	g_log_close_file(sc->sc_vn, FWRITE | FREAD);
 	
 	/*destory worker thread*/
 	g_log_event_sink_destroy(&sc->sc_events);
 	
+	/*free allocation table*/
+	g_log_alloctable_free(sc->sc_alloctable, M_GLOG);
+		
 	/*clean up memory*/
-	G_LOG_DEBUG(0,"cleaning up mem.");
 	g_orphan_provider(pp_log, ENXIO);
 	if (cp_disk->acr > 0 ||cp_disk->acw > 0 ||cp_disk->ace > 0)
 		g_access(cp_disk, -cp_disk->acr, -cp_disk->acw, -cp_disk->ace);
@@ -370,10 +528,13 @@
 	g_detach(cp_disk);
 	g_destroy_consumer(cp_disk);
 	gp->softc = NULL;
+	free (sc->sc_alloctable, M_GLOG);
+	free (sc->sc_req_sublist, M_GLOG);
 	free(sc, M_GLOG);
-	
+
 	/*destroy geom*/
-	if (pp_log == NULL || (pp_log->acr == 0 && pp_log->acw == 0 && pp_log->ace == 0))
+	if (pp_log == NULL || (pp_log->acr == 0 && pp_log->acw == 0 && 
+	    pp_log->ace == 0))
 		G_LOG_DEBUG(0, "Device %s destroyed.", gp->name);
 	
 	g_wither_geom(gp, ENXIO);
@@ -392,7 +553,7 @@
 	gp = pp->geom;
 	sc = gp->softc;
 	cp = sc->sc_cons_disk;
-	G_LOG_DEBUG(DBG_IMPORTANT, "%s: %d %d %d", __func__, dr, dw, de);
+	G_LOG_DEBUG(DBG_IMPORTANT, "Access: %d %d %d", dr, dw, de);
 	
 	if (sc == NULL) {
 		/*
@@ -403,36 +564,35 @@
 		    ("Positive access request (device=%s).", pp->name));
 		if ((pp->acr + dr) == 0 && (pp->acw + dw) == 0 &&
 		    (pp->ace + de) == 0) {
-			    G_LOG_DEBUG(0, "Device %s definitely destroyed.", gp->name);
+			G_LOG_DEBUG(0, "Device %s definitely destroyed.", 
+			    gp->name);
 		}
 		return (0);
 	}
 	
 	
 	err = g_access(cp, dr ,dw, de);
-	
-	G_LOG_DEBUG(0, "access done, %d", err);
+
 	return err;
 }
 
 /* Empty the worker queue */
 static void
 g_log_empty_event_queue(struct g_log_event_sink *es) {
-    struct g_log_softc *sc;
-    struct g_log_event *ev;
+	struct g_log_softc *sc;
+	struct g_log_event *ev;
     
-    KASSERT(es != NULL, ("%s: event_sink is null", __func__));
-    sc = es->sc;
-    KASSERT(sc != NULL, ("%s: softc is null", __func__));
+	KASSERT(es != NULL, ("%s: event_sink is null", __func__));
+	sc = es->sc;
+	KASSERT(sc != NULL, ("%s: softc is null", __func__));
     
-    mtx_lock(&es->eventq_mtx);
-    while (!TAILQ_EMPTY(&es->eventq)) {
-        ev = TAILQ_FIRST(&es->eventq);
-        TAILQ_REMOVE(&es->eventq, ev, linkage);
-        free(ev, M_GLOG);
-    }
-    mtx_unlock(&es->eventq_mtx);
-    
+	mtx_lock(&es->eventq_mtx);
+	while (!TAILQ_EMPTY(&es->eventq)) {
+		ev = TAILQ_FIRST(&es->eventq);
+		TAILQ_REMOVE(&es->eventq, ev, linkage);
+		free(ev, M_GLOG);
+	}
+	mtx_unlock(&es->eventq_mtx);
 }
 
 /*worker thread*/
@@ -454,22 +614,21 @@
 			ev = g_log_get_event(es);
 		else
 			goto sleep;
-		G_LOG_DEBUG(0, "event: %d", ev->type);
 		bp = ev->data1;
 		switch (ev->type) {
 		case GLOG_EVCOMMIT:
+			g_log_commit(sc);
 			break; 
 		case GLOG_EVROLLBACK:
+			g_log_rollback(sc);
 			break;
 		case GLOG_EVREAD:
 			g_log_read(bp);
 			break;
 		case GLOG_EVWRITE:
-			G_LOG_DEBUG(0, "About to write data");
 			g_log_write(bp);
 			break;
 		case GLOG_EVSTOP:
-			G_LOG_DEBUG(DBG_DEBUG, "Worker thread exiting");
 			g_log_empty_event_queue(es);
 			es->worker_thread = NULL;
 			kthread_exit(0);
@@ -485,7 +644,7 @@
 /* adds event to event queue */
 static int
 g_log_post_event(struct g_log_event_sink *es, u_int type, u_int flags, 
-	    void* data1, int data2) 
+    void* data1, int data2) 
 {
 	struct g_log_softc *sc;
 	struct g_log_event *ev;
@@ -506,7 +665,6 @@
 	mtx_lock(&es->eventq_mtx);
 	TAILQ_INSERT_TAIL(&es->eventq, ev, linkage);
 	mtx_unlock(&es->eventq_mtx);
-	G_LOG_DEBUG (0, "posted event %d", ev->type);
 	if ( (flags & GLOG_FLAG_WAKEUP_SC) != 0)
 		wakeup(es);
 	return 0;
@@ -537,37 +695,153 @@
 g_log_write(struct bio *bp)
 {
 	struct g_log_softc *sc;
-	void *data;
+	struct g_log_alloc_element ae;
+	struct g_log_data *gd;
 	int err;
-	G_LOG_DEBUG(0, "starting to write");
+	
 	sc = bp->bio_to->geom->softc;
-	data = bp->bio_data;
-	err = glog_write_file(sc->sc_vn, data, bp->bio_length, 0);
+	
+	KASSERT(sc != NULL, ("%s: softc is null", __func__));
+	
+	/*create a g_log_data structure from bio*/
+	gd = malloc(sizeof(*gd), M_GLOG, M_WAITOK | M_ZERO);
+	gd->offset_disk = bp->bio_offset;
+	gd->offset_log = sc->sc_curr_offset+sizeof(*gd);
+	gd->data_size = bp->bio_length;
+	
+	/*add to allocation list*/
+	ae.offset_disk = bp->bio_offset;
+	ae.offset_log = sc->sc_curr_offset+sizeof(*gd);
+	ae.data_size = bp->bio_length;
+	g_log_alloctable_add(&ae, sc->sc_alloctable, M_GLOG);
+	
+	/*write g_log_data to file so we can later reconstruct an alloc table 
+	from it*/
+	err = g_log_write_file(sc->sc_vn, gd, sizeof(*gd), sc->sc_curr_offset);
+	if (err != 0)
+		G_LOG_DEBUG(0, "Write error: g_log_data");
+	sc->sc_curr_offset += sizeof(*gd);
+	/*write actual data to file*/
+	err = g_log_write_file(sc->sc_vn, bp->bio_data, bp->bio_length, 
+	    sc->sc_curr_offset);
 	if (err != 0)
-		G_LOG_DEBUG(0, "write error");
-	G_LOG_DEBUG(0, "done writing.");
+		G_LOG_DEBUG(0, "Write error: data");
+	sc->sc_curr_offset += bp->bio_length;
+	free(gd, M_GLOG);
+	bp->bio_completed = bp->bio_length;
+	g_io_deliver(bp,0);
 }
 
 /*reads data from log file and/or disk*/
 static void
 g_log_read(struct bio *bp)
 {
-       G_LOG_DEBUG(0,"Got a read request.");
+	struct g_log_softc *sc;
+	struct g_log_data *gd;
+	int err, i, max_elements, offset_buf;
+
+	sc = bp->bio_to->geom->softc;
+	KASSERT(sc != NULL, ("%s: softc is null", __func__));
+
+	/*clean up request sublist*/
+	free(sc->sc_req_sublist, M_GLOG);
+	max_elements = (int)(MAXPHYS / sc->sc_prov_log->sectorsize);
+	sc->sc_req_sublist = malloc (max_elements * sizeof(
+	    struct g_log_data), M_GLOG, M_WAITOK | M_ZERO);
+	sc->sc_req_sublist_size = 0;
+	
+	/*reset buffer offset*/
+	offset_buf = 0;
+	
+	G_LOG_DEBUG(0, "Requested %jd, %jd", bp->bio_offset, bp->bio_length);
+
+	/*retrieve request sublist*/
+	err = g_log_alloctable_get(sc, bp->bio_offset, (ssize_t)bp->bio_length);
 	
+	/*read requested data*/	
+	for (i = 0; i < sc->sc_req_sublist_size; i++) {
+		gd = &sc->sc_req_sublist[i];
+		/*in case of first or last element, check if only a part of
+		element was requested*/
+		if ((i == 0) && (gd->offset_disk < bp->bio_offset)) {
+			if (gd->offset_log != -1)
+				gd->offset_log += bp->bio_offset - 
+				    gd->offset_log;
+			gd->data_size = gd->offset_log + gd->data_size - 
+			    bp->bio_offset;
+			gd->offset_disk = bp->bio_offset;
+		}
+		if ((i == sc->sc_req_sublist_size -1) && (gd->offset_disk + 
+		    gd->data_size > bp->bio_length + bp->bio_offset)){
+			gd->data_size = bp->bio_offset + bp->bio_length - 
+		            gd->offset_disk;
+		}
+		g_log_read_element(sc, gd, (char *) bp->bio_data, &offset_buf, 
+		    M_GLOG);
+		
+	}
+	/*dumping bio_data*/
+	G_LOG_DEBUG(0, "Dumping bio data");
+	for (i = 0; i < bp->bio_length; i++)
+		printf("%c", (char)(bp->bio_data[i]));
+	bp->bio_completed = bp->bio_length;
+	g_io_deliver(bp, 0);
+	printf("\nDone.");
 }
 
 /*commits the log file*/
-/*static void
+static void
 g_log_commit(struct g_log_softc *sc)
 {
-}*/
+	struct g_log_alloc_table_element *te;
+	struct g_log_alloc_element *ae;
+	char *data;
+	int i, err;
+	
+	KASSERT(sc != NULL, ("%s: sc is null!", __func__));
+	G_LOG_DEBUG(0, "Starting commit...");
+	g_topology_assert();
+	err = g_access(sc->sc_cons_disk, 0, 1, 0);
+	g_topology_unlock();
+	if (err != 0) {
+		G_LOG_DEBUG(0, "Error accessing provider %s", sc->sc_cons_disk->provider->name);
+		return;
+	}
+	/*write contents of all compartments to disk*/
+	for (i = 0; i < sc->sc_alloctable->tablesize; i++) {
+		te = &sc->sc_alloctable->table[i];
+		SLIST_FOREACH(ae, &te->allocq, linkage) {
+			if (ae->offset_log != -1) {
+				data = malloc(ae->data_size * sizeof(char), M_GLOG, M_WAITOK | M_ZERO);
+				G_LOG_DEBUG(0, "Committing %jd, %jd, %d", ae->offset_disk, ae->offset_log, ae->data_size);
+				/*get data from log file*/
+				g_log_read_data(sc->sc_vn, (void*)data, ae->data_size, ae->offset_log);
+				
+				/*write it to disk*/
+				err = g_write_data(sc->sc_cons_disk, ae->offset_disk, data, ae->data_size);
+				g_topology_lock();
+				err = g_access(sc->sc_cons_disk, 0, -1, 0);
+				G_LOG_DEBUG(0, "Write error %d", err);
+				free(data, M_GLOG);
+			}
+		}	
+	}
+}
 
-/*deletes the log file*/
-/*static void
+/*drop the changes*/
+static void
 g_log_rollback(struct g_log_softc *sc)
 {
+	/*reset log file*/	
+	sc->sc_vn = g_log_empty_file(sc->sc_vn, sc->sc_file_name);
+	g_log_write_header(sc->sc_vn); 
+	sc->sc_curr_offset = sizeof(struct g_log_header);
+	
+	/*reset alloc table*/
+	g_log_alloctable_free(sc->sc_alloctable, M_GLOG);
+	g_log_alloctable_init(sc, M_GLOG);
 }
-*/
+
 
 static int
 g_log_destroy_geom(struct gctl_req *req __unused, struct g_class *mp __unused,
@@ -577,20 +851,6 @@
 	return 0;	
 }
 
-/* Find the geom we handle */
-static struct g_log_softc *
-g_log_find(struct g_class *mp, const char *name)
-{
-	struct g_geom *gp;
-
-	G_LOG_DEBUG(DBG_DEBUG, "%s: %s", __func__, name);
-	LIST_FOREACH(gp, &mp->geom, geom) {
-	if (strcmp(gp->name, name) == 0)
-		return (gp->softc);
-	}
-	return (NULL);
-}
-
 static void
 g_log_ctl_destroy(struct gctl_req *req, struct g_class *mp)
 {
@@ -609,7 +869,7 @@
 	force = gctl_get_paraml(req, "force", sizeof(int));
 	
 	sc = g_log_find(mp, prov);
-	KASSERT (sc != NULL, ("Softc is null in %s!", __func__));
+	KASSERT(sc != NULL, ("%s: softc is null", __func__));
 	g_log_stop(sc->sc_geom_log, *force);
 	
 }
@@ -636,10 +896,8 @@
 			sbuf_printf(sb, "UP");
 		else
 			sbuf_printf(sb, "DOWN");
-		G_LOG_DEBUG(0, "error=%d", sc->sc_prov_log->error);
 		sbuf_printf(sb, "</State>\n");
 	}
-	
 }
 		    
 /* Convert verb to number */
@@ -654,9 +912,9 @@
 		return GCTL_START;
 	else if (strcmp(verb, "stop") == 0)
 		return GCTL_STOP;
+	else if (strcmp(verb, "dump") == 0)
+		return GCTL_DUMP;
 	else
 		return GCTL_INVALID;
 };
-
 DECLARE_GEOM_CLASS(g_log_class, g_log);
-

==== //depot/projects/soc2007/smilicic_glog/sys/geom/log/glog.h#3 (text+ko) ====

@@ -2,6 +2,7 @@
 #define G_LOG_CLASS_NAME "LOG"
 
 #ifdef _KERNEL
+
 #define	G_LOG_BFLAG_FIRST	0x1
 
 #define	G_LOG_DEBUG(lvl, ...)	do {					\
@@ -32,7 +33,6 @@
 #define DBG_IMPORTANT 7
 #define DBG_DEBUG 10
 #define DBG_NOTICE 15
-#endif
 
 struct g_log_event {
         unsigned short int type;
@@ -58,11 +58,33 @@
 };
 
 struct g_log_softc {
-        struct g_geom	*sc_geom_log;
+        struct g_geom *sc_geom_log;
         struct g_provider *sc_prov_log;
         struct g_provider *sc_prov_disk;
         struct g_consumer *sc_cons_disk;
-        char *sc_file_name;
         struct vnode *sc_vn;
         struct g_log_event_sink sc_events;
+	struct g_log_alloc_table *sc_alloctable;
+	struct g_log_data *sc_req_sublist;
+	size_t sc_req_sublist_size;
+	off_t sc_curr_offset;
+	char *sc_file_name;
+};
+
+/*this is the structure that's written to the log file*/
+struct g_log_data {
+	off_t offset_disk;
+	off_t offset_log;
+	size_t data_size;
+};
+
+#endif /* _KERNEL */
+
+/*a header that's written at the start of log file, so that geom log can 
+ * recognize the file later*/
+struct g_log_header {
+	char text[9];
+	int version;
 };
+
+

==== //depot/projects/soc2007/smilicic_glog/sys/geom/log/glog_fileops.c#3 (text+ko) ====

@@ -33,17 +33,25 @@
 #include <sys/kernel.h>
 #include <sys/libkern.h>
 #include <sys/kthread.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
 #include <sys/namei.h>
 #include <sys/vnode.h>
 #include <sys/uio.h>
 #include <sys/lock.h>
 #include <sys/proc.h>
 #include <sys/filedesc.h>
+#include <geom/geom.h>
+
 
+#include "glog.h"
+#include "glog_alloctable.h"
 #include "glog_fileops.h"
 
+extern u_int g_log_debug; 
+
 struct vnode * 
-glog_open_file(const char *file, int uiflags)
+g_log_open_file(const char *file, int uiflags, int cmode)
 {
 	struct thread *td = curthread;
 	struct nameidata nd;
@@ -55,27 +63,40 @@
 		td->td_proc->p_fd->fd_cdir = rootvnode;
 
 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, file, td);
-	err = vn_open_cred(&nd, &uiflags, 0, td->td_ucred, -1);
+	KASSERT (file != NULL, ("No filename specified"));
+	err = vn_open_cred(&nd, &uiflags, cmode, td->td_ucred, -1);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	if (err != 0) 
 		return (NULL);
 
 	VOP_UNLOCK(nd.ni_vp, 0, td);
+
+	if (err == 1)
+		return (NULL);		
 	return (nd.ni_vp);
 }
-
+void
+g_log_write_header(struct vnode *vp) 
+{
+	struct g_log_header head;
+	
+	strcpy(head.text, "GEOM_LOG");
+	head.version = G_LOG_VERSION;
+	G_LOG_DEBUG(0, "Writing %s %d", head.text, head.version);
+	g_log_write_file(vp, &head, sizeof(head),0);
+}
 int 
-glog_close_file(struct vnode *vp, int uiflags)
+g_log_close_file(struct vnode *vp, int uiflags)
 {
 	/*closes a file*/
 	int err;
 	
 	err = vn_close(vp, uiflags, curthread->td_ucred, curthread);
-	return err;
+	return (err);
 }
 
 int 
-glog_write_file(struct vnode *vp, void *buf, size_t size, off_t off)
+g_log_write_file(struct vnode *vp, void *buf, size_t size, off_t off)
 {
 	struct thread *td = curthread;
 	struct mount *mp;
@@ -103,11 +124,11 @@
 	err = VOP_WRITE(vp, &auio, IO_UNIT | IO_SYNC, td->td_ucred);
 	VOP_UNLOCK(vp, 0, td);
 	vn_finished_write(mp);
-	return err;
+	return (err);

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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