Date: Tue, 8 Nov 2011 13:49:10 -0500 From: Arnaud Lacombe <lacombar@gmail.com> To: Attilio Rao <attilio@freebsd.org> Cc: "K. Macy" <kmacy@freebsd.org>, Alan Cox <alc@rice.edu>, Andriy Gapon <avg@freebsd.org>, freebsd-current@freebsd.org, Benjamin Kaduk <kaduk@mit.edu>, Kostik Belousov <kostikbel@gmail.com>, Penta Upa <bsdboot@gmail.com> Subject: Using Instruction Pointer address in debug interfaces [Was: Re: vm_page_t related KBI [Was: Re: panic at vm_page_wire with FreeBSD 9.0 Beta 3]] Message-ID: <CACqU3MU_Bk%2BcObCiUa2XtM7fLkSpSDzOZqoZ=khNOR-_6ptYYQ@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
Hi, On Mon, Nov 7, 2011 at 2:03 PM, Arnaud Lacombe <lacombar@gmail.com> wrote: > On Mon, Nov 7, 2011 at 4:36 AM, Attilio Rao <attilio@freebsd.org> wrote: >> 2011/11/7 Arnaud Lacombe <lacombar@gmail.com>: >>> Hi, >>> >>> On Sat, Nov 5, 2011 at 10:13 AM, Kostik Belousov <kostikbel@gmail.com> = wrote: >>>> On Fri, Nov 04, 2011 at 06:03:39PM +0200, Kostik Belousov wrote: >>>> >>>> Below is the KBI patch after vm_page_bits_t merge is done. >>>> Again, I did not spent time converting all in-tree consumers >>>> from the (potentially) loadable modules to the new KPI until it >>>> is agreed upon. >>>> >>>> diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c >>>> index 305c189..7264cd1 100644 >>>> --- a/sys/nfsclient/nfs_bio.c >>>> +++ b/sys/nfsclient/nfs_bio.c >>>> @@ -128,7 +128,7 @@ nfs_getpages(struct vop_getpages_args *ap) >>>> =A0 =A0 =A0 =A0 * can only occur at the file EOF. >>>> =A0 =A0 =A0 =A0 */ >>>> =A0 =A0 =A0 =A0VM_OBJECT_LOCK(object); >>>> - =A0 =A0 =A0 if (pages[ap->a_reqpage]->valid !=3D 0) { >>>> + =A0 =A0 =A0 if (vm_page_read_valid(pages[ap->a_reqpage]) !=3D 0) { >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0for (i =3D 0; i < npages; ++i) { >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (i !=3D ap->a_reqpag= e) { >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0vm_page= _lock(pages[i]); >>>> @@ -198,16 +198,16 @@ nfs_getpages(struct vop_getpages_args *ap) >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * Read operation fille= d an entire page >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */ >>>> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 m->valid =3D VM_PAGE_BIT= S_ALL; >>>> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 KASSERT(m->dirty =3D=3D = 0, >>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vm_page_write_valid(m, V= M_PAGE_BITS_ALL); >>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 KASSERT(vm_page_read_dir= ty(m) =3D=3D 0, >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0("nfs_getpages:= page %p is dirty", m)); >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else if (size > toff) { >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * Read operation fille= d a partial page. >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */ >>>> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 m->valid =3D 0; >>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vm_page_write_valid(m, 0= ); >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0vm_page_set_valid(m, 0,= size - toff); >>>> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 KASSERT(m->dirty =3D=3D = 0, >>>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 KASSERT(vm_page_read_dir= ty(m) =3D=3D 0, >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0("nfs_getpages:= page %p is dirty", m)); >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else { >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* >>>> diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c >>>> index 389aea5..2f41e70 100644 >>>> --- a/sys/vm/vm_page.c >>>> +++ b/sys/vm/vm_page.c >>>> @@ -2677,6 +2677,66 @@ vm_page_test_dirty(vm_page_t m) >>>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0vm_page_dirty(m); >>>> =A0} >>>> >>>> +void >>>> +vm_page_lock_func(vm_page_t m, const char *file, int line) >>>> +{ >>>> + >>>> +#if LOCK_DEBUG > 0 || defined(MUTEX_NOINLINE) >>>> + =A0 =A0 =A0 _mtx_lock_flags(vm_page_lockptr(m), 0, file, line); >>>> +#else >>>> + =A0 =A0 =A0 __mtx_lock(vm_page_lockptr(m), 0, file, line); >>>> +#endif >>>> +} >>>> + >>> Why do you re-implement the wheel ? all the point of these assessors >>> is to hide implementation detail. IMO, you should restrict yourself to >>> the documented API from mutex(9), only. >>> >>> Oh, wait, you end-up using LOCK_FILE instead of just __FILE__, but >>> wait LOCK_FILE is either just __FILE__, or NULL, depending on >>> LOCK_DEBUG, but you wouldn't have those function without >>> INVARIANTS.... This whole LOCK_FILE/LOCK_LINE seem completely >>> fracked-up... If you don't want this code in INVARIANTS, but in >>> LOCK_DEBUG, only make it live only in the LOCK_DEBUG case. >>> >>> Btw, let me also question the use of non-inline functions. >> >> My impression is that you don't really understand the patch, thus your >> disrespectful words used here are really unjustified. >> > Well, unfortunately, I wasn't around to comment 10 years ago when this go= t in. > >> I think that kib@ intention is just to get "the most official way" to >> pass down file and line to locking functions from the consumers. >> His patch is "technically right", but I would prefer something >> different (see below). >> > Yes, and that's not an excuse to use the _internal_ implementation > details of mutex(9), and not the exposed API. This is especially true > when applied to someone so eager to follow "standards". > >> LOCK_FILE and LOCK_LINE exist for reducing the space in .rodata >> section. Without INVARIANTS/WITNESS/etc. they will just be NULL and >> not pointing to a lot of datas that won't be used in the opposite >> case. >> > You comment just as if __FILE__ and __LINE__ were mandatory in a debug > interface. This is _not_ true. __FILE__ and __LINE__ are just hideous > for debugging of anything but early alpha code. LOCK_FILE and > LOCK_LINE are a bad answer to a bad interface. Even if you just pass > NULL and 0 as argument, you've got the bloat of passing unused > argument. You might as well just pass a single argument that would do > the exact same job and be _always_ available, eg. the IP of the > caller, or the first return address. KDB magic still let you translate > to something humanly understandable. If the toolchain does not support > the feature on all supported platform, well, fix the toolchain. > To avoid future complaints about the fact that I would be only "talk" without "action", I did implement what I suggested above. As it is quite a large patch-set, I will not post it directly here, however, it is available on github: https://github.com/lacombar/freebsd/tree/master/topic/kern-lock-debug It convert a bunch of debug interface to use the caller instruction pointer, as well as a proof-of-concept teaching printf(9) to convert IP to symbol_name+offset. It translates in a direct saving of about +250kB on i386's GENERIC, just in kernel text size. Even the worst case, ie LOCK_DEBUG =3D=3D 0, translates to a save of +80kB. Please note that this is still WIP code. Comments welcome. - Arnaud
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CACqU3MU_Bk%2BcObCiUa2XtM7fLkSpSDzOZqoZ=khNOR-_6ptYYQ>