PERFORCE change 125109 for review
Sonja Milicic
smilicic at FreeBSD.org
Mon Aug 13 11:39:03 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=125109
Change 125109 by smilicic at 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) <<<
More information about the p4-projects
mailing list