From owner-svn-src-user@FreeBSD.ORG Thu Jan 8 18:24:05 2009 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F2BF01065687; Thu, 8 Jan 2009 18:24:04 +0000 (UTC) (envelope-from luigi@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E18268FC0C; Thu, 8 Jan 2009 18:24:04 +0000 (UTC) (envelope-from luigi@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n08IO4hQ030197; Thu, 8 Jan 2009 18:24:04 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n08IO4Em030195; Thu, 8 Jan 2009 18:24:04 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <200901081824.n08IO4Em030195@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 8 Jan 2009 18:24:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r186908 - in user/luigi/geom_sched/sys/geom: . sched X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Jan 2009 18:24:05 -0000 Author: luigi Date: Thu Jan 8 18:24:04 2009 New Revision: 186908 URL: http://svn.freebsd.org/changeset/base/186908 Log: make it work with a stock kernel Modified: user/luigi/geom_sched/sys/geom/geom_io.c user/luigi/geom_sched/sys/geom/sched/g_sched.c Modified: user/luigi/geom_sched/sys/geom/geom_io.c ============================================================================== --- user/luigi/geom_sched/sys/geom/geom_io.c Thu Jan 8 17:51:15 2009 (r186907) +++ user/luigi/geom_sched/sys/geom/geom_io.c Thu Jan 8 18:24:04 2009 (r186908) @@ -369,6 +369,7 @@ g_io_request(struct bio *bp, struct g_co bp->bio_error = 0; bp->bio_completed = 0; +#if 0 /* * Scheduler support: if this is the first element in the geom * chain (we know from bp->bio_parent == NULL), store @@ -382,6 +383,7 @@ g_io_request(struct bio *bp, struct g_co else bp->bio_caller1 = (void *)curthread->td_tid; } +#endif KASSERT(!(bp->bio_flags & BIO_ONQUEUE), ("Bio already on queue bp=%p", bp)); Modified: user/luigi/geom_sched/sys/geom/sched/g_sched.c ============================================================================== --- user/luigi/geom_sched/sys/geom/sched/g_sched.c Thu Jan 8 17:51:15 2009 (r186907) +++ user/luigi/geom_sched/sys/geom/sched/g_sched.c Thu Jan 8 18:24:04 2009 (r186908) @@ -35,6 +35,7 @@ #include #include #include +#include /* we access curthread */ #include #include "g_gsched.h" #include "g_sched.h" @@ -396,18 +397,103 @@ g_sched_destroy_geom(struct gctl_req *re return (g_sched_destroy(gp, 0)); } +/* + * The code below patches g_io_request() to call g_new_io_request() first. + * We must be careful with the compiler, as it may clobber the + * parameters on the stack so they are not preserved for the + * continuation of the original function. + * Ideally we should write everything in assembler: + + mov 0x8(%esp), %edx // load bp + mov 0x64(%edx),%eax // load bp->bio_parent + test %eax,%eax + jne 1f + mov 0x30(%edx),%eax // load bp->bio_caller1 + test %eax,%eax + jne 1f + mov %fs:0x0,%eax // pcpu pointer + mov 0x34(%eax),%eax // curthread + mov %eax,0x30(%edx) // store in bp->bio_caller1 + 1: // old function + push %ebp + mov %esp, %ebp + push %edi + push %esi + jmp x+5 + + */ + +static unsigned char +g_io_trampoline[] = { + 0xe8, 0x00, 0x00, 0x00, 0x00, /* call foo */ + 0x55, /* push %ebp */ + 0x89, 0xe5, /* mov %esp,%ebp */ + 0x57, /* push %edi */ + 0x56, /* push %esi */ + 0xe9, 0x00, 0x00, 0x00, 0x00, /* jmp x+5 */ +}; + +static void +g_new_io_request(const char *ret, struct bio *bp, struct g_consumer *cp) +{ + + /* + * Scheduler support: if this is the first element in the geom + * chain (we know from bp->bio_parent == NULL), store + * the thread that originated the request in bp->bio_caller1, + * which should be unused in this particular entry (at least + * with the code in 7.1/8.0). + */ + if (bp->bio_parent == NULL && bp->bio_caller1 == NULL) + bp->bio_caller1 = (void *)curthread->td_tid; +} + +static int g_io_patched = 0; +static int +g_io_patch(void *f, void *p, void *new_f) +{ + int found = bcmp(f, (const char *)p + 5, 5); + printf("match result %d\n", found); + if (found == 0) { + int ofs; + + printf("patching function\n"); + /* link the trampoline to the new function */ + ofs = (int)new_f - ((int)p + 5); + bcopy(&ofs, (char *)p + 1, 4); + /* jump back to the original + 5 */ + ofs = ((int)f + 5) - ((int)p + 15); + bcopy(&ofs, (char *)p + 11, 4); + /* patch the original address with a jump to the trampoline */ + *(unsigned char *)f = 0xe9; /* jump opcode */ + ofs = (int)p - ((int)f + 5); + bcopy(&ofs, (char *)f + 1, 4); + g_io_patched = 1; + } + return 0; +} + static void g_sched_init(struct g_class *mp) { mtx_init(&g_gsched_mtx, "gsched", NULL, MTX_DEF); LIST_INIT(&gsched_list); + + printf("%s loading...\n", __FUNCTION__); + /* patch g_io_request to set the thread */ + g_io_patch(g_io_request, g_io_trampoline, g_new_io_request); } static void g_sched_fini(struct g_class *mp) { + if (g_io_patched) { + /* restore the original g_io_request */ + bcopy(g_io_trampoline + 5, (char *)g_io_request, 5); + } + printf("%s unloading...\n", __FUNCTION__); KASSERT(LIST_EMPTY(&gsched_list), ("still registered schedulers")); mtx_destroy(&g_gsched_mtx); }