From: adilger Date: Mon, 19 Aug 2002 21:51:33 +0000 (+0000) Subject: Add some basic data integrity checking to obdecho. X-Git-Tag: 0.5.5~127 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=6aea6cf0aecb1f819bb8a0e9cf546d26b653e2b4;p=fs%2Flustre-release.git Add some basic data integrity checking to obdecho. This puts the offset and objid into the first 16 bytes and last 16 bytes of the bulk transfer. These are in HTON__u64() format. The lctl command for test_brw now takes an objid instead of an obdo count, so that you can (potentially) use lctl with test_brw on a real OBD instead of just obdecho. That has not been tested yet. --- diff --git a/lustre/include/linux/lustre_debug.h b/lustre/include/linux/lustre_debug.h index a31430d..756d32e 100644 --- a/lustre/include/linux/lustre_debug.h +++ b/lustre/include/linux/lustre_debug.h @@ -48,4 +48,6 @@ int dump_rniobuf(struct niobuf_remote *rnb); int dump_ioo(struct obd_ioobj *nb); int dump_req(struct ptlrpc_request *req); int dump_obdo(struct obdo *oa); +int page_debug_setup(void *addr, int len, __u64 off, __u64 id); +int page_debug_check(char *who, void *addr, int len, __u64 off, __u64 id); #endif diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index 0b17ad4..8474b78 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -278,4 +278,9 @@ struct obd_ops { int (*o_cancel)(struct lustre_handle *, struct lov_stripe_md *md, __u32 mode, struct lustre_handle *); }; +/* FIXME: for 64-bit arch */ +#define LPU64 "%Lu" +#define LPD64 "%Ld" +#define LPX64 "%Lx" + #endif diff --git a/lustre/lib/debug.c b/lustre/lib/debug.c index c3a2721..cd0d5e2 100644 --- a/lustre/lib/debug.c +++ b/lustre/lib/debug.c @@ -12,8 +12,10 @@ #define DEBUG_SUBSYSTEM D_OTHER +#define EXPORT_SYMTAB #include #include +#include int dump_ioo(struct obd_ioobj *ioo) { @@ -73,17 +75,78 @@ int dump_obdo(struct obdo *oa) } /* XXX assumes only a single page in request */ +/* int dump_req(struct ptlrpc_request *req) { struct ost_body *body = lustre_msg_buf(req->rq_reqmsg, 0); struct obd_ioobj *ioo = lustre_msg_buf(req->rq_reqmsg, 1); //struct niobuf *nb = lustre_msg_buf(req->rq_reqmsg, 2); - CERROR("ost_body: connid = %d, data = %d\n", body->connid, body->data); dump_obdo(&body->oa); //dump_niobuf(nb); dump_ioo(ioo); return -EINVAL; } +*/ +#define LPDS sizeof(__u64) +int page_debug_setup(void *addr, int len, __u64 off, __u64 id) +{ + LASSERT(addr); + + off = HTON__u64(off); + id = HTON__u64(id); + memcpy(addr, (char *)&off, LPDS); + memcpy(addr + LPDS, (char *)&id, LPDS); + + addr += len - LPDS - LPDS; + memcpy(addr, (char *)&off, LPDS); + memcpy(addr + LPDS, (char *)&id, LPDS); + + return 0; +} + +int page_debug_check(char *who, void *addr, int end, __u64 off, __u64 id) +{ + __u64 ne_off; + int err = 0; + + LASSERT(addr); + + ne_off = HTON__u64(off); + id = HTON__u64(id); + if (memcmp(addr, (char *)&ne_off, LPDS)) { + CERROR("%s: for offset "LPU64" off: "LPX64" != "LPX64"\n", + who, off, *(__u64 *)addr, ne_off); + err = -EINVAL; + } + if (memcmp(addr + LPDS, (char *)&id, LPDS)) { + CERROR("%s: for offset "LPU64" id: "LPX64" != "LPX64"\n", + who, off, *(__u64 *)(addr + LPDS), id); + err = -EINVAL; + } + + addr += end - LPDS - LPDS; + if (memcmp(addr, (char *)&ne_off, LPDS)) { + CERROR("%s: for offset "LPU64" end off: "LPX64" != "LPX64"\n", + who, off, *(__u64 *)addr, ne_off); + err = -EINVAL; + } + if (memcmp(addr + LPDS, (char *)&id, LPDS)) { + CERROR("%s: for offset "LPU64" end id: "LPX64" != "LPX64"\n", + who, off, *(__u64 *)(addr + LPDS), id); + err = -EINVAL; + } + + return err; +} +#undef LPDS + +EXPORT_SYMBOL(dump_lniobuf); +EXPORT_SYMBOL(dump_rniobuf); +EXPORT_SYMBOL(dump_ioo); +//EXPORT_SYMBOL(dump_req); +EXPORT_SYMBOL(dump_obdo); +EXPORT_SYMBOL(page_debug_setup); +EXPORT_SYMBOL(page_debug_check); diff --git a/lustre/obdclass/Makefile.am b/lustre/obdclass/Makefile.am index bfb8e15..40f997f 100644 --- a/lustre/obdclass/Makefile.am +++ b/lustre/obdclass/Makefile.am @@ -2,7 +2,11 @@ DEFS= MODULE = obdclass modulefs_DATA = obdclass.o EXTRA_PROGRAMS = obdclass -obdclass_SOURCES = genops.c proc_lustre.c class_obd.c sysctl.c page.c uuid.c +LINX=page.c debug.c +obdclass_SOURCES = genops.c proc_lustre.c class_obd.c sysctl.c uuid.c $(LINX) + +debug.c: + test -e debug.c || ln -sf $(top_srcdir)/lib/debug.c page.c: test -e page.c || ln -sf $(top_srcdir)/lib/page.c diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index d140511..69a99eb 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -40,6 +40,7 @@ #include #include +#include #include struct semaphore obd_conf_sem; /* serialize configuration commands */ @@ -99,6 +100,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, int len = 0; struct obd_ioctl_data *data; struct obd_device *obd = filp->private_data; + struct lustre_handle conn; int rw = OBD_BRW_READ; int err = 0; @@ -480,17 +482,17 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, struct lov_stripe_md smd; struct io_cb_data *cbd = ll_init_cb(); obd_count pages = 0; - struct brw_page *pga; + struct brw_page *pga, *pgp; int j; unsigned long off; - void *from; - + __u64 id; + if (!cbd) - GOTO(out, -ENOMEM); + GOTO(out, err = -ENOMEM); obd_data2conn(&conn, data); - pages = data->ioc_plen1 / PAGE_SIZE; + pages = data->ioc_count / PAGE_SIZE; CDEBUG(D_INODE, "BRW %s with %d pages\n", rw == OBD_BRW_READ ? "read" : "write", pages); @@ -501,37 +503,47 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, } memset(&smd, 0, sizeof(smd)); - smd.lmd_object_id = data->ioc_obdo1.o_id; + id = smd.lmd_object_id = data->ioc_obdo1.o_id; - from = (&data->ioc_pbuf1)[0]; off = data->ioc_offset; - for (j = 0; j < pages; - j++, off += PAGE_SIZE, from += PAGE_SIZE) { + for (j = 0, pgp = pga; j < pages; j++, off += PAGE_SIZE, pgp++){ unsigned long to; to = __get_free_pages(GFP_KERNEL, 0); if (!to) { - /* || - copy_from_user((void - *)to,from,PAGE_SIZE)) - free_pages(to, 0); - */ CERROR("no memory for brw pages\n"); GOTO(brw_cleanup, err = -ENOMEM); } - pga[j].pg = virt_to_page(to); - pga[j].count = PAGE_SIZE; - pga[j].off = off; - pga[j].flag = 0; + pgp->pg = virt_to_page(to); + pgp->count = PAGE_SIZE; + pgp->off = off; + pgp->flag = 0; + + if (rw == OBD_BRW_WRITE) { + void *addr = kmap(pgp->pg); + + LASSERT(addr == (void *)to); + + page_debug_setup(addr, PAGE_SIZE, off, id); + kunmap(pgp->pg); + } } err = obd_brw(rw, &conn, &smd, j, pga, ll_sync_io_cb, cbd); EXIT; brw_cleanup: - for (j = 0; j < pages; j++) - if (pga[j].pg != NULL) - __free_pages(pga[j].pg, 0); + for (j = 0, pgp = pga; j < pages; j++) { + if (pgp->pg != NULL) { + void *addr = kmap(pgp->pg); + + page_debug_check("test_brw", addr, PAGE_SIZE, + pgp->off, id); + kunmap(pgp->pg); + + __free_pages(pgp->pg, 0); + } + } brw_free: OBD_FREE(pga, pages * sizeof(*pga)); GOTO(out, err); diff --git a/lustre/obdecho/echo.c b/lustre/obdecho/echo.c index dc4b3e7..be305f3 100644 --- a/lustre/obdecho/echo.c +++ b/lustre/obdecho/echo.c @@ -11,8 +11,8 @@ * by Peter Braam */ -static char rcsid[] __attribute ((unused)) = "$Id: echo.c,v 1.22 2002/08/12 22:25:53 pschwan Exp $"; -#define OBDECHO_VERSION "$Revision: 1.22 $" +static char rcsid[] __attribute ((unused)) = "$Id: echo.c,v 1.23 2002/08/19 21:51:33 adilger Exp $"; +#define OBDECHO_VERSION "$Revision: 1.23 $" #define EXPORT_SYMTAB @@ -32,6 +32,7 @@ static char rcsid[] __attribute ((unused)) = "$Id: echo.c,v 1.22 2002/08/12 22:2 #include #include #include +#include #include extern struct obd_device obd_dev[MAX_OBD_DEVICES]; @@ -50,13 +51,13 @@ echo_proc_read (char *page, char **start, off_t off, int count, int *eof, void * int len; int attrs = atomic_read (&echo_getattrs); int pages = atomic_read (&echo_page_rws); - + *eof = 1; if (off != 0) return (0); - + len = sprintf (page, "%d %d\n", pages, attrs); - + *start = page; return (len); } @@ -67,17 +68,18 @@ echo_proc_write (struct file *file, const char *ubuffer, unsigned long count, vo /* Ignore what we've been asked to write, and just zero the stats counters */ atomic_set (&echo_page_rws, 0); atomic_set (&echo_getattrs, 0); - + return (count); } void echo_proc_init(void) { - struct proc_dir_entry *entry = create_proc_entry (ECHO_PROC_STAT, S_IFREG | S_IRUGO | S_IWUSR, NULL); + struct proc_dir_entry *entry; + + entry = create_proc_entry(ECHO_PROC_STAT, S_IFREG|S_IRUGO|S_IWUSR,NULL); - if (entry == NULL) - { + if (entry == NULL) { CERROR("couldn't create proc entry %s\n", ECHO_PROC_STAT); return; } @@ -87,8 +89,7 @@ echo_proc_init(void) entry->write_proc = echo_proc_write; } -void -echo_proc_fini(void) +void echo_proc_fini(void) { remove_proc_entry(ECHO_PROC_STAT, 0); } @@ -118,7 +119,7 @@ static int echo_disconnect(struct lustre_handle *conn) return rc; } -static int echo_getattr(struct lustre_handle *conn, struct obdo *oa, +static int echo_getattr(struct lustre_handle *conn, struct obdo *oa, struct lov_stripe_md *md) { memcpy(oa, &OA, sizeof(*oa)); @@ -150,11 +151,10 @@ int echo_preprw(int cmd, struct lustre_handle *conn, int objcount, for (j = 0 ; j < obj->ioo_bufcnt ; j++, nb++, r++) { unsigned long address; - address = get_zeroed_page(GFP_KERNEL); + address = __get_free_pages(GFP_KERNEL, 0); if (!address) { - CERROR("can't get new page %d/%d for id %Ld\n", - j, obj->ioo_bufcnt, - (unsigned long long)obj->ioo_id); + CERROR("can't get page %d/%d for id "LPU64"\n", + j, obj->ioo_bufcnt, obj->ioo_id); GOTO(preprw_cleanup, rc = -ENOMEM); } echo_pages++; @@ -163,6 +163,10 @@ int echo_preprw(int cmd, struct lustre_handle *conn, int objcount, r->page = virt_to_page(address); r->addr = kmap(r->page); r->len = nb->len; + + if (cmd & OBD_BRW_READ) + page_debug_setup(r->addr, r->len, r->offset, + obj->ioo_id); } } CDEBUG(D_PAGE, "%ld pages allocated after prep\n", echo_pages); @@ -214,14 +218,17 @@ int echo_commitrw(int cmd, struct lustre_handle *conn, int objcount, !(addr = (unsigned long)page_address(page)) || !kern_addr_valid(addr)) { - CERROR("bad page %p, id %Ld (%d), buf %d/%d\n", - page, (unsigned long long)obj->ioo_id, i, - j, obj->ioo_bufcnt); + CERROR("bad page "LPU64":%p, buf %d/%d\n", + obj->ioo_id, page, j,obj->ioo_bufcnt); GOTO(commitrw_cleanup, rc = -EFAULT); } atomic_inc (&echo_page_rws); - + + if (cmd & OBD_BRW_WRITE) + page_debug_check("echo", (void *)addr,PAGE_SIZE, + r->offset, obj->ioo_id); + kunmap(page); __free_pages(page, 0); echo_pages--; @@ -281,21 +288,21 @@ static int __init obdecho_init(void) printk(KERN_INFO "Echo OBD driver " OBDECHO_VERSION " info@clusterfs.com\n"); echo_proc_init(); - + return class_register_type(&echo_obd_ops, OBD_ECHO_DEVICENAME); } static void __exit obdecho_exit(void) { echo_proc_fini (); - + CERROR("%ld prep/commitrw pages leaked\n", echo_pages); class_unregister_type(OBD_ECHO_DEVICENAME); } MODULE_AUTHOR("Cluster Filesystems Inc. "); MODULE_DESCRIPTION("Lustre Testing Echo OBD driver " OBDECHO_VERSION); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL"); module_init(obdecho_init); module_exit(obdecho_exit); diff --git a/lustre/utils/lctl.c b/lustre/utils/lctl.c index bcd723a..8197dc8 100644 --- a/lustre/utils/lctl.c +++ b/lustre/utils/lctl.c @@ -130,7 +130,7 @@ command_t cmdlist[] = { "usage: test_getattr [verbose]"}, {"test_brw", jt_obd_test_brw, 0, "perform count number of bulk read/writes\n" - "usage: test_brw [write [verbose [pages [obdos]]]]"}, + "usage: test_brw [write [verbose [pages [objid]]]]"}, {"test_ldlm", jt_obd_test_ldlm, 0, "perform lock manager test\n" "usage: test_ldlm"}, {"ldlm_regress_start", jt_obd_ldlm_regress_start, 0, diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index 7c628d3..e114989 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -957,10 +957,10 @@ int jt_obd_test_brw(int argc, char **argv) { struct obd_ioctl_data data; struct timeval start, next_time; - char *bulk, *b; - int pages = 1, obdos = 1, count, next_count; + int pages = 1, objid = 3, count, next_count; int verbose = 1, write = 0, rw; - int i, o, p; + long long offset; + int i; int len; int rc = 0; @@ -981,65 +981,26 @@ int jt_obd_test_brw(int argc, char **argv) if (argc >= 5) pages = strtoul(argv[4], NULL, 0); if (argc >= 6) - obdos = strtoul(argv[5], NULL, 0); - - if (obdos != 1 && obdos != 2) { - fprintf(stderr, "error: %s: only 1 or 2 obdos supported\n", - cmdname(argv[0])); - return -2; - } + objid = strtoul(argv[5], NULL, 0); len = pages * PAGE_SIZE; - bulk = calloc(obdos, len); - if (!bulk) { - fprintf(stderr, "error: %s: no memory allocating %dx%d pages\n", - cmdname(argv[0]), obdos, pages); - return -2; - } IOCINIT(data); - data.ioc_obdo1.o_id = 2; + data.ioc_obdo1.o_id = objid; data.ioc_count = len; data.ioc_offset = 0; - data.ioc_plen1 = len; - data.ioc_pbuf1 = bulk; - if (obdos > 1) { - data.ioc_obdo2.o_id = 3; - data.ioc_plen2 = len; - data.ioc_pbuf2 = bulk + len; - } gettimeofday(&start, NULL); next_time.tv_sec = start.tv_sec - verbose; next_time.tv_usec = start.tv_usec; if (verbose != 0) - printf("%s: %s %d (%dx%d pages) (testing only): %s", + printf("%s: %s %dx%d pages (testing only): %s", cmdname(argv[0]), write ? "writing" : "reading", - count, obdos, pages, ctime(&start.tv_sec)); - - /* - * We will put in the start time (and loop count inside the loop) - * at the beginning of each page so that we will be able to validate - * (at some later time) whether the data actually made it or not. - * - * XXX we do not currently use any of this memory in OBD_IOC_BRW_* - * just to avoid the overhead of the copy_{to,from}_user. It - * can be fixed if we ever need to send real data around. - */ - for (o = 0, b = bulk; o < obdos; o++) - for (p = 0; p < pages; p++, b += PAGE_SIZE) - memcpy(b, &start, sizeof(start)); + count, pages, ctime(&start.tv_sec)); rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ; - for (i = 1, next_count = verbose; i <= count; i++) { - if (write) { - b = bulk + sizeof(struct timeval); - for (o = 0; o < obdos; o++) - for (p = 0; p < pages; p++, b += PAGE_SIZE) - memcpy(b, &count, sizeof(count)); - } - + for (i = 1, next_count = verbose, offset = 0; i <= count; i++) { rc = ioctl(fd, rw, &data); SHMEM_BUMP(); if (rc) { @@ -1051,9 +1012,9 @@ int jt_obd_test_brw(int argc, char **argv) (verbose, &next_time, i, &next_count, count)) printf("%s: %s number %d\n", cmdname(argv[0]), write ? "write" : "read", i); - } - free(bulk); + data.ioc_offset += len; + } if (!rc) { struct timeval end; @@ -1065,10 +1026,9 @@ int jt_obd_test_brw(int argc, char **argv) --i; if (verbose != 0) - printf("%s: %s %dx%dx%d pages in %.4gs (%.4g pg/s): %s", + printf("%s: %s %dx%d pages in %.4gs (%.4g pg/s): %s", cmdname(argv[0]), write ? "wrote" : "read", - obdos, pages, i, diff, - (double)obdos * i * pages / diff, + i, pages, diff, (double)i * pages / diff, ctime(&end.tv_sec)); } return rc; diff --git a/lustre/utils/obdctl.c b/lustre/utils/obdctl.c index 6714200..241bc30 100644 --- a/lustre/utils/obdctl.c +++ b/lustre/utils/obdctl.c @@ -70,7 +70,7 @@ command_t cmdlist[] = { {"setattr", jt_obd_setattr, 0, "setattr "}, {"newconn", jt_obd_newconn, 0, "newconn [newuuid]"}, {"test_getattr", jt_obd_test_getattr, 0, "test_getattr [verbose]"}, - {"test_brw", jt_obd_test_brw, 0, "test_brw [write [verbose]]"}, + {"test_brw", jt_obd_test_brw, 0, "test_brw [write [verbose [pages [objid]]]]"}, {"test_ldlm", jt_obd_test_ldlm, 0, "test lock manager (no args)"}, {"dump_ldlm", jt_obd_dump_ldlm, 0, "dump all lock manager state (no args)"},