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>