From owner-freebsd-arch@FreeBSD.ORG Mon Aug 11 23:55:01 2003 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 23C0737B401 for ; Mon, 11 Aug 2003 23:55:01 -0700 (PDT) Received: from ns1.gnf.org (ns1.gnf.org [63.196.132.67]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2DBA943F3F for ; Mon, 11 Aug 2003 23:55:00 -0700 (PDT) (envelope-from gtetlow@gnf.org) Received: from EXCHCLUSTER01.lj.gnf.org (exch02.lj.gnf.org [172.25.10.20]) by ns1.gnf.org (8.12.8p1/8.12.8) with ESMTP id h7C6sttF050166 for ; Mon, 11 Aug 2003 23:54:55 -0700 (PDT) (envelope-from gtetlow@gnf.org) Received: from roark.gnf.org ([172.25.24.15]) by EXCHCLUSTER01.lj.gnf.org with Microsoft SMTPSVC(5.0.2195.5329); Mon, 11 Aug 2003 23:54:59 -0700 Received: from roark.gnf.org (localhost [127.0.0.1]) by roark.gnf.org (8.12.9/8.12.9) with ESMTP id h7C6sxxO012793 for ; Mon, 11 Aug 2003 23:54:59 -0700 (PDT) (envelope-from gtetlow@gnf.org) Received: (from gtetlow@localhost) by roark.gnf.org (8.12.9/8.12.9/Submit) id h7C6sxqU012792 for arch@FreeBSD.org; Mon, 11 Aug 2003 23:54:59 -0700 (PDT) (envelope-from gtetlow) Date: Mon, 11 Aug 2003 23:54:59 -0700 From: Gordon Tetlow To: arch@FreeBSD.org Message-ID: <20030812065459.GR4672@roark.gnf.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="HACzHn9G0kmbdSJa" Content-Disposition: inline User-Agent: Mutt/1.4i X-Habeas-SWE-1: winter into spring X-Habeas-SWE-2: brightly anticipated X-Habeas-SWE-3: like Habeas SWE (tm) X-Habeas-SWE-4: Copyright 2002 Habeas (tm) X-Habeas-SWE-5: Sender Warranted Email (SWE) (tm). The sender of this X-Habeas-SWE-6: email in exchange for a license for this Habeas X-Habeas-SWE-7: warrant mark warrants that this is a Habeas Compliant X-Habeas-SWE-8: Message (HCM) and not spam. Please report use of this X-Habeas-SWE-9: mark in spam to . X-OriginalArrivalTime: 12 Aug 2003 06:54:59.0954 (UTC) FILETIME=[A5D0F520:01C3609E] Subject: CFR: dynamically-linked root patch X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Aug 2003 06:55:01 -0000 --HACzHn9G0kmbdSJa Content-Type: text/plain; charset=us-ascii Content-Disposition: inline I've put up what I hope to be my final patch for a dynamically linked world. Here's my plan for rolling it into place with as little fuss as possible (hopefully): 1) Add /lib and /libexec to mtree along with the tweaks to rtld-elf to prepend /lib to the search path. Add necessary make-goo to strap /lib into buildworld. 2) Make rtld installed into /libexec with a compatibility symlink in /usr/libexec so existing binaries continue to work. 3) Kick over all the libraries needed to run /bin and /sbin into /lib. Only the versioned binaries will be in /lib, the .so symlink will continue to live in /usr/lib so the toolchain doesn't need to be modified. 4) Add support of a WITH_DYNAMICROOT knob that will make /bin and /sbin dynamic. If things go badly, that's what /rescue is for. 5) Optionally, make WITH_DYANMICROOT default (reverse the logic actually). http://people.freebsd.org/~gordon/patches/dynamic.patch Please look over this patch, if I don't hear any objections or any ideas as to a better way to integrate in order to keep the potential for foot shooting down, I'll start integrating them. -gordon --HACzHn9G0kmbdSJa Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (FreeBSD) iD8DBQE/OI9DRu2t9DV9ZfsRAoHHAKCCzUSr7aMjCM5iEhUcdVwtwQm8ygCgkIvL R2p1gpOhQkTqI9fVPhiD3tw= =N8n4 -----END PGP SIGNATURE----- --HACzHn9G0kmbdSJa-- From owner-freebsd-arch@FreeBSD.ORG Tue Aug 12 12:06:33 2003 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 56CD837B401 for ; Tue, 12 Aug 2003 12:06:33 -0700 (PDT) Received: from gurney.bluecom.no (gurney.bluecom.no [217.118.32.13]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4362C43F85 for ; Tue, 12 Aug 2003 12:06:32 -0700 (PDT) (envelope-from eirikn@bluezone.no) Received: from eirikn.net (a217-118-47-91.bluecom.no [217.118.47.91]) by gurney.bluecom.no (Postfix) with ESMTP id 271F9A7B06 for ; Tue, 12 Aug 2003 21:06:29 +0200 (CEST) Received: by eirikn.net (Postfix, from userid 1001) id B1FB171; Tue, 12 Aug 2003 21:06:24 +0200 (CEST) Date: Tue, 12 Aug 2003 21:06:24 +0200 From: Eirik Nygaard To: arch@freebsd.org Message-ID: <20030812190624.GA10954@eirikn.net> Mail-Followup-To: arch@freebsd.org References: <20030723100444.GA83571@eirikn.net> <20030803120321.GA26612@eirikn.net> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="24zk1gE8NUlDmwG9" Content-Disposition: inline In-Reply-To: <20030803120321.GA26612@eirikn.net> User-Agent: Mutt/1.5.4i Subject: Re: module opt_* building X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: eirikn@bluezone.no List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Aug 2003 19:06:33 -0000 --24zk1gE8NUlDmwG9 Content-Type: multipart/mixed; boundary="h31gzZEtNLTqOjlF" Content-Disposition: inline --h31gzZEtNLTqOjlF Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sun, Aug 03, 2003 at 02:03:21PM +0200, Eirik Nygaard wrote: > On Wed, Jul 23, 2003 at 12:04:44PM +0200, Eirik Nygaard wrote: > > I did not come up with another way to do it so I used the described > > approach. Did not attach the patch, but it can be found at > > http://kerneled.com/eirikn/freebsd/kmod_modules.diff >=20 > Since kerneled.com went down for a unknow reason you I uploaded the patch > to another website. > http://eirikn.net/bsd/kmod_modules.diff >=20 Now I am really sorry, here is the patch. kmod_modules.diff is still to be added to the modules. --=20 Eirik Nygaard PGP Key: 83C55EDE --h31gzZEtNLTqOjlF Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="kmod.diff" Content-Transfer-Encoding: quoted-printable Index: kern.pre.mk =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/sys/conf/kern.pre.mk,v retrieving revision 1.27 diff -u -d -r1.27 kern.pre.mk --- kern.pre.mk 11 Jul 2003 07:13:42 -0000 1.27 +++ kern.pre.mk 23 Jul 2003 19:26:15 -0000 @@ -87,7 +87,8 @@ # MKMODULESENV is set here so that port makefiles can augment # them. =20 -MKMODULESENV=3D MAKEOBJDIRPREFIX=3D${.OBJDIR}/modules KMODDIR=3D${KODIR} +MKMODULESENV=3D MAKEOBJDIRPREFIX=3D${.OBJDIR}/modules MAKEOBJDIR=3D${.OBJD= IR} \ + KMODDIR=3D${KODIR} .if (${KERN_IDENT} =3D=3D LINT) MKMODULESENV+=3D ALL_MODULES=3DLINT .endif Index: kmod.mk =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/sys/conf/kmod.mk,v retrieving revision 1.137 diff -u -d -r1.137 kmod.mk --- kmod.mk 3 Mar 2003 22:51:22 -0000 1.137 +++ kmod.mk 23 Jul 2003 19:26:15 -0000 @@ -241,9 +241,27 @@ .for _src in ${SRCS:Mopt_*.h} CLEANFILES+=3D ${_src} .if !target(${_src}) +.if defined(MAKEOBJDIR) +.if exists(${MAKEOBJDIR}/${_src}) +${_src}: + rm -f ${.TARGET} && ln -s ${MAKEOBJDIR}/${_src} +.else +.if target(${_src}_def) +${_src}: ${_src}_def +.else +${_src}: +.endif + touch ${.TARGET} +.endif +.else +.if target(${_src}_def) +${_src}: ${_src}_def +.else ${_src}: +.endif touch ${.TARGET} .endif +.endif .endfor =20 MFILES?=3D kern/bus_if.m kern/device_if.m dev/iicbus/iicbb_if.m \ @@ -267,7 +285,15 @@ .if exists(@) ${_src}: @/tools/makeobjops.awk @/${_srcsrc} .endif +.if defined(MAKEOBJDIR) +.if exists(${MAKEOBJDIR}/${_src}) + ln -sf ${MAKEOBJDIR}/${_src} +.else + ${AWK} -f @/tools/makeobjops.awk @/${_srcsrc} -${_ext} +.endif +.else ${AWK} -f @/tools/makeobjops.awk @/${_srcsrc} -${_ext} +.endif .endif .endfor # _src .endfor # _ext --h31gzZEtNLTqOjlF-- --24zk1gE8NUlDmwG9 Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.2 (FreeBSD) iD8DBQE/OTqw1JB0Z4PFXt4RAhY0AJwKX7sYXPRlmtM44M4bpD5WG3wRmwCdHlSr JsQRserM8EinWZCANHPzuLo= =mvDn -----END PGP SIGNATURE----- --24zk1gE8NUlDmwG9-- From owner-freebsd-arch@FreeBSD.ORG Thu Aug 14 12:52:19 2003 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2111337B401 for ; Thu, 14 Aug 2003 12:52:19 -0700 (PDT) Received: from hysteria.spc.org (hysteria.spc.org [195.206.69.234]) by mx1.FreeBSD.org (Postfix) with SMTP id 9798A43F75 for ; Thu, 14 Aug 2003 12:52:17 -0700 (PDT) (envelope-from bms@hysteria.spc.org) Received: (qmail 29789 invoked by uid 5013); 14 Aug 2003 19:49:29 -0000 Date: Thu, 14 Aug 2003 20:49:29 +0100 From: Bruce M Simpson To: freebsd-arch@freebsd.org Message-ID: <20030814194929.GO1409@spc.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="hOcCNbCCxyk/YU74" Content-Disposition: inline User-Agent: Mutt/1.4.1i Organization: SPC Subject: Unified getcwd() implementation X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Aug 2003 19:52:19 -0000 --hOcCNbCCxyk/YU74 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hello all, I've had the attached patch in my tree for a 1 month period without any panics or other adverse effects that I could see. This is from one of phk's JKH todo list items. It merges the Linux in-kernel scanning-based getcwd() with our namei cache based implementation, in a way which tries to use the cache efficiently, but will use directory scanning upon a cache miss. This also has the advantage that scandir() games are no longer needed in libc. Please let me know your thoughts on this. This is my first real bit of vfs related work, so I have no immediate plans to commit it until I can get concrete review going forward. Kind regards BMS --hOcCNbCCxyk/YU74 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="vfs_getcwd.patch" This is a revised patch against 2003.05.08.00.00.00 which implements getcwd() in a more efficient way. Instead of discarding the entire result if each successive component can't be found in the cache, it checks the cache on a component-by-component basis. diff -uN sys/kern/vfs_cache.c.orig sys/kern/vfs_cache.c --- sys/kern/vfs_cache.c.orig Wed May 21 23:37:47 2003 +++ sys/kern/vfs_cache.c Sat May 24 14:12:44 2003 @@ -36,6 +36,7 @@ * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95 * $FreeBSD: src/sys/kern/vfs_cache.c,v 1.82 2003/03/20 10:40:45 phk Exp $ */ +#include "opt_mac.h" #include #include @@ -53,6 +54,11 @@ #include #include +#include +#include +#include +#include +#include /* XXX only for DIRBLKSIZ */ /* * This structure describes the elements in the cache of recent * names looked up by namei. @@ -695,6 +701,13 @@ }; #endif +static int getcwd_impl(struct vnode *lvp, struct vnode *rvp, char **bpp, + char *bufp, struct thread *td); +static int getcwd_scandir(struct vnode **, struct vnode **, char **, char *, + struct thread *); + +#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4) + /* * XXX All of these sysctls would probably be more productive dead. */ @@ -708,6 +721,7 @@ static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2); static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3); static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4); +static u_long numcwdfail5; STATNODE(CTLFLAG_RD, numcwdfail5, &numcwdfail5); static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound); /* Implementation of the getcwd syscall */ @@ -720,14 +734,20 @@ return (kern___getcwd(td, uap->buf, UIO_USERSPACE, uap->buflen)); } +/* + * Find pathname of process's current directory. + * + * Use vfs vnode-to-name reverse cache; if that fails, fall back + * to reading directory contents. + */ int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg, u_int buflen) { - char *bp, *tmpbuf; - int error, i, slash_prefixed; + char *bp, *bufp; + int error; struct filedesc *fdp; - struct namecache *ncp; - struct vnode *vp; + struct vnode *rvp; + struct vnode *lvp; numcwdcalls++; if (disablecwd) @@ -736,77 +756,414 @@ return (EINVAL); if (buflen > MAXPATHLEN) buflen = MAXPATHLEN; + + buflen *= 4; /* XXX */ + error = 0; - tmpbuf = bp = malloc(buflen, M_TEMP, M_WAITOK); + bufp = bp = malloc(buflen, M_TEMP, M_WAITOK); bp += buflen - 1; *bp = '\0'; + fdp = td->td_proc->p_fd; - slash_prefixed = 0; FILEDESC_LOCK(fdp); - mp_fixme("No vnode locking done!"); - for (vp = fdp->fd_cdir; vp != fdp->fd_rdir && vp != rootvnode;) { - if (vp->v_vflag & VV_ROOT) { - if (vp->v_mount == NULL) { /* forced unmount */ - FILEDESC_UNLOCK(fdp); - free(tmpbuf, M_TEMP); - return (EBADF); - } - vp = vp->v_mount->mnt_vnodecovered; - continue; - } - if (vp->v_dd->v_id != vp->v_ddid) { - FILEDESC_UNLOCK(fdp); + + rvp = fdp->fd_rdir; + if (rvp == NULL) + rvp = rootvnode; + VREF(rvp); + + lvp = fdp->fd_cdir; + + error = getcwd_impl(lvp, rvp, &bp, bufp, td); + if (!error) { + numcwdfound++; + if (bufseg == UIO_SYSSPACE) + bcopy(bp, buf, strlen(bp) + 1); + else + error = copyout(bp, buf, strlen(bp) + 1); + } else { +#if DIAGNOSTIC + printf("getcwd: error %d\n", error); +#endif + } + + vrele(rvp); + FILEDESC_UNLOCK(fdp); + free(bufp, M_TEMP); + return (error); +} + +/* + * Recursively advance up the directory hierarchy from lvp to rvp. + * Look in the namecache first for each path component; if it cannot + * be found, use scandir to find it. Copy the result into the buffer + * pointed to by bufp from *bpp onwards. + */ + +static int +getcwd_impl(lvp, rvp, bpp, bufp, td) + struct vnode *lvp; + struct vnode *rvp; + char **bpp; + char *bufp; + struct thread *td; +{ + int i, error, slash_prefixed; + struct namecache *ncp; + struct vnode *uvp; + struct vnode *tvp; + char *bp; + + error = slash_prefixed = 0; + uvp = NULL; + + VREF(lvp); + error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td); + if (error) { + numcwdfail5++; + vrele(lvp); + lvp = NULL; + goto out; + } + if (bufp) + bp = *bpp; + + while (lvp != rvp) { +#if 1 + if (lvp->v_type != VDIR) { numcwdfail1++; - free(tmpbuf, M_TEMP); - return (ENOTDIR); + error = ENOTDIR; + goto out; } - ncp = TAILQ_FIRST(&vp->v_cache_dst); - if (!ncp) { - FILEDESC_UNLOCK(fdp); - numcwdfail2++; - free(tmpbuf, M_TEMP); - return (ENOENT); +#else + if (lvp->v_dd->v_id != lvp->v_ddid) { + numcwdfail1++; + error = ENOTDIR; + goto out; } - if (ncp->nc_dvp != vp->v_dd) { - FILEDESC_UNLOCK(fdp); - numcwdfail3++; - free(tmpbuf, M_TEMP); - return (EBADF); - } - for (i = ncp->nc_nlen - 1; i >= 0; i--) { - if (bp == tmpbuf) { - FILEDESC_UNLOCK(fdp); - numcwdfail4++; - free(tmpbuf, M_TEMP); - return (ENOMEM); +#endif + /* + * step up if we're a covered vnode. + */ + while (lvp->v_vflag & VV_ROOT) { + if (lvp == rvp) + goto out; + tvp = lvp; + lvp = lvp->v_mount->mnt_vnodecovered; + vput(tvp); + if (lvp == NULL) { + numcwdfail3++; + error = ENOENT; + goto out; + } + VREF(lvp); + error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td); + if (error != 0) { + numcwdfail5++; + vrele(lvp); + lvp = NULL; + goto out; } - *--bp = ncp->nc_name[i]; } - if (bp == tmpbuf) { - FILEDESC_UNLOCK(fdp); - numcwdfail4++; - free(tmpbuf, M_TEMP); - return (ENOMEM); + /* + * look in the cache first + */ + ncp = TAILQ_FIRST(&lvp->v_cache_dst); +#if DIAGNOSTIC + /* XXX simulate cache failure every 10 lookups */ + if ((numcwdcalls % 10) == 0) + ncp = NULL; +#endif + if (ncp) { + if (ncp->nc_dvp != lvp->v_dd) { + numcwdfail3++; + error = EBADF; + goto out; + } + for (i = ncp->nc_nlen - 1; i >= 0; i--) { + if (bp == bufp) { + numcwdfail4++; + error = ENOMEM; + goto out; + } + *--bp = ncp->nc_name[i]; + } + /* + * must ensure lvp is always locked and ref'd + */ + tvp = lvp; + lvp = lvp->v_dd; + vput(tvp); + if (lvp == NULL) { + numcwdfail3++; + error = ENOENT; + goto out; + } + VREF(lvp); + error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td); + if (error != 0) { + numcwdfail5++; + vrele(lvp); + lvp = NULL; + goto out; + } + } else { + numcwdfail2++; +#if DIAGNOSTIC + printf("getcwd: using scandir\n"); +#endif + error = getcwd_scandir(&lvp, &uvp, &bp, bufp, td); + if (error) { +#if DIAGNOSTIC + printf("getcwd_scandir returned %d\n", error); +#endif + goto out; + } +#if DIAGNOSTIC + if (lvp != NULL) + panic("getcwd: oops, forgot to null lvp"); +#endif + lvp = uvp; + uvp = NULL; } +#if DIAGNOSTIC + if (bufp && (bp <= bufp)) + panic("getcwd: oops, went back too far"); +#endif *--bp = '/'; slash_prefixed = 1; - vp = vp->v_dd; } - FILEDESC_UNLOCK(fdp); + if (!slash_prefixed) { - if (bp == tmpbuf) { + if (bp == bufp) { numcwdfail4++; - free(tmpbuf, M_TEMP); - return (ENOMEM); + error = ENOMEM; + goto out; } *--bp = '/'; } - numcwdfound++; - if (bufseg == UIO_SYSSPACE) - bcopy(bp, buf, strlen(bp) + 1); - else - error = copyout(bp, buf, strlen(bp) + 1); - free(tmpbuf, M_TEMP); +out: + if (bpp) + *bpp = bp; + if (uvp) + vput(uvp); + if (lvp) + vput(lvp); + return (error); +} + +/* + * Vnode variable naming conventions in this file: + * + * rvp: the current root we're aiming towards. + * lvp, *lvpp: the "lower" vnode + * uvp, *uvpp: the "upper" vnode. + * + * Since all the vnodes we're dealing with are directories, and the + * lookups are going *up* in the filesystem rather than *down*, the + * usual "pvp" (parent) or "dvp" (directory) naming conventions are + * too confusing. + */ + +/* + * XXX Will infinite loop in certain cases if a directory read reliably + * returns EINVAL on last block. + * XXX is EINVAL the right thing to return if a directory is malformed? + */ + +/* + * XXX Untested vs. mount -o union; probably does the wrong thing. + */ + +/* + * Find parent vnode of *lvpp, return in *uvpp + * + * If we care about the name, scan it looking for name of directory + * entry pointing at lvp. + * + * Place the name in the buffer which starts at bufp, immediately + * before *bpp, and move bpp backwards to point at the start of it. + * + * On entry, *lvpp is a locked vnode reference; on exit, it is vput and NULL'ed + * On exit, *uvpp is either NULL or is a locked vnode reference. + */ + +static int +getcwd_scandir(lvpp, uvpp, bpp, bufp, td) + struct vnode **lvpp; + struct vnode **uvpp; + char **bpp; + char *bufp; + struct thread *td; +{ + int error = 0; + int eofflag; + off_t off; + int tries; + struct uio uio; + struct iovec iov; + char *dirbuf = NULL; + int dirbuflen; + ino_t fileno; + struct vattr va; + struct vnode *uvp = NULL; + struct vnode *lvp = *lvpp; + struct componentname cn; + int len, reclen; + tries = 0; + + /* + * If we want the filename, get some info we need while the + * current directory is still locked. + */ + if (bufp != NULL) { + error = VOP_GETATTR(lvp, &va, td->td_ucred, td); + if (error) { + vput(lvp); + *lvpp = NULL; + *uvpp = NULL; +#if DIAGNOSTICS + printf("VOP_GETATTR returned %d", error); +#endif + return error; + } + } + + /* + * Ok, we have to do it the hard way.. + * Next, get parent vnode using lookup of .. + */ + cn.cn_nameiop = LOOKUP; + cn.cn_flags = ISLASTCN | ISDOTDOT | RDONLY; + cn.cn_thread = td; + cn.cn_cred = td->td_ucred; + cn.cn_pnbuf = NULL; + cn.cn_nameptr = ".."; + cn.cn_namelen = 2; + cn.cn_consume = 0; + + /* + * At this point, lvp is locked and will be unlocked by the lookup. + * On successful return, *uvpp will be locked + */ + error = VOP_LOOKUP(lvp, uvpp, &cn); + if (error) { + vput(lvp); + *lvpp = NULL; + *uvpp = NULL; + return error; + } + uvp = *uvpp; + + /* If we don't care about the pathname, we're done */ + if (bufp == NULL) { + vrele(lvp); + *lvpp = NULL; + return 0; + } + + fileno = va.va_fileid; + + dirbuflen = DIRBLKSIZ; + if (dirbuflen < va.va_blocksize) + dirbuflen = va.va_blocksize; + dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK); + +#if 0 +unionread: +#endif + off = 0; + do { + /* call VOP_READDIR of parent */ + iov.iov_base = dirbuf; + iov.iov_len = dirbuflen; + + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = off; + uio.uio_resid = dirbuflen; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_READ; + uio.uio_td = td; + + eofflag = 0; + +#ifdef MAC + error = mac_check_vnode_readdir(td->td_ucred, uvp); + if (error == 0) +#endif /* MAC */ + error = VOP_READDIR(uvp, &uio, td->td_ucred, &eofflag, + 0, 0); + + off = uio.uio_offset; + + /* + * Try again if NFS tosses its cookies. + * XXX this can still loop forever if the directory is busted + * such that the second or subsequent page of it always + * returns EINVAL + */ + if ((error == EINVAL) && (tries < 3)) { + off = 0; + tries++; + continue; /* once more, with feeling */ + } + + if (!error) { + char *cpos; + struct dirent *dp; + + cpos = dirbuf; + tries = 0; + + /* scan directory page looking for matching vnode */ + for (len = (dirbuflen - uio.uio_resid); + len > 0; + len -= reclen) + { + dp = (struct dirent *) cpos; + reclen = dp->d_reclen; + + /* check for malformed directory.. */ + if (reclen < DIRENT_MINSIZE) { + error = EINVAL; + goto out; + } + /* + * XXX should perhaps do VOP_LOOKUP to + * check that we got back to the right place, + * but getting the locking games for that + * right would be heinous. + */ + if ((dp->d_type != DT_WHT) && + (dp->d_fileno == fileno)) { + char *bp = *bpp; + bp -= dp->d_namlen; +#if DIAGNOSTIC + printf("bp: %p bufp: %p dp->d_name: %s" + " (%d)\n", + bp, bufp, + dp->d_name, dp->d_namlen); +#endif + if (bp <= bufp) { + error = ERANGE; + goto out; + } + bcopy(dp->d_name, bp, dp->d_namlen); + error = 0; + *bpp = bp; + goto out; + } + cpos += reclen; + } + } + } while (!eofflag); + error = ENOENT; + +out: + vrele(lvp); + *lvpp = NULL; + free(dirbuf, M_TEMP); return (error); } diff -uN sys/compat/linux/linux_getcwd.c.orig sys/compat/linux/linux_getcwd.c --- sys/compat/linux/linux_getcwd.c.orig Wed May 21 23:38:05 2003 +++ sys/compat/linux/linux_getcwd.c Wed May 21 23:38:15 2003 @@ -38,431 +38,27 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include "opt_compat.h" -#include "opt_mac.h" #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include /* XXX only for DIRBLKSIZ */ +#include #include #include #include -static int -linux_getcwd_scandir(struct vnode **, struct vnode **, - char **, char *, struct thread *); -static int -linux_getcwd_common(struct vnode *, struct vnode *, - char **, char *, int, int, struct thread *); - -#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4) - -/* - * Vnode variable naming conventions in this file: - * - * rvp: the current root we're aiming towards. - * lvp, *lvpp: the "lower" vnode - * uvp, *uvpp: the "upper" vnode. - * - * Since all the vnodes we're dealing with are directories, and the - * lookups are going *up* in the filesystem rather than *down*, the - * usual "pvp" (parent) or "dvp" (directory) naming conventions are - * too confusing. - */ - -/* - * XXX Will infinite loop in certain cases if a directory read reliably - * returns EINVAL on last block. - * XXX is EINVAL the right thing to return if a directory is malformed? - */ - -/* - * XXX Untested vs. mount -o union; probably does the wrong thing. - */ - -/* - * Find parent vnode of *lvpp, return in *uvpp - * - * If we care about the name, scan it looking for name of directory - * entry pointing at lvp. - * - * Place the name in the buffer which starts at bufp, immediately - * before *bpp, and move bpp backwards to point at the start of it. - * - * On entry, *lvpp is a locked vnode reference; on exit, it is vput and NULL'ed - * On exit, *uvpp is either NULL or is a locked vnode reference. - */ -static int -linux_getcwd_scandir(lvpp, uvpp, bpp, bufp, td) - struct vnode **lvpp; - struct vnode **uvpp; - char **bpp; - char *bufp; - struct thread *td; -{ - int error = 0; - int eofflag; - off_t off; - int tries; - struct uio uio; - struct iovec iov; - char *dirbuf = NULL; - int dirbuflen; - ino_t fileno; - struct vattr va; - struct vnode *uvp = NULL; - struct vnode *lvp = *lvpp; - struct componentname cn; - int len, reclen; - tries = 0; - - /* - * If we want the filename, get some info we need while the - * current directory is still locked. - */ - if (bufp != NULL) { - error = VOP_GETATTR(lvp, &va, td->td_ucred, td); - if (error) { - vput(lvp); - *lvpp = NULL; - *uvpp = NULL; - return error; - } - } - - /* - * Ok, we have to do it the hard way.. - * Next, get parent vnode using lookup of .. - */ - cn.cn_nameiop = LOOKUP; - cn.cn_flags = ISLASTCN | ISDOTDOT | RDONLY; - cn.cn_thread = td; - cn.cn_cred = td->td_ucred; - cn.cn_pnbuf = NULL; - cn.cn_nameptr = ".."; - cn.cn_namelen = 2; - cn.cn_consume = 0; - - /* - * At this point, lvp is locked and will be unlocked by the lookup. - * On successful return, *uvpp will be locked - */ - error = VOP_LOOKUP(lvp, uvpp, &cn); - if (error) { - vput(lvp); - *lvpp = NULL; - *uvpp = NULL; - return error; - } - uvp = *uvpp; - - /* If we don't care about the pathname, we're done */ - if (bufp == NULL) { - vrele(lvp); - *lvpp = NULL; - return 0; - } - - fileno = va.va_fileid; - - dirbuflen = DIRBLKSIZ; - if (dirbuflen < va.va_blocksize) - dirbuflen = va.va_blocksize; - dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK); - -#if 0 -unionread: -#endif - off = 0; - do { - /* call VOP_READDIR of parent */ - iov.iov_base = dirbuf; - iov.iov_len = dirbuflen; - - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = off; - uio.uio_resid = dirbuflen; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_READ; - uio.uio_td = td; - - eofflag = 0; - -#ifdef MAC - error = mac_check_vnode_readdir(td->td_ucred, uvp); - if (error == 0) -#endif /* MAC */ - error = VOP_READDIR(uvp, &uio, td->td_ucred, &eofflag, - 0, 0); - - off = uio.uio_offset; - - /* - * Try again if NFS tosses its cookies. - * XXX this can still loop forever if the directory is busted - * such that the second or subsequent page of it always - * returns EINVAL - */ - if ((error == EINVAL) && (tries < 3)) { - off = 0; - tries++; - continue; /* once more, with feeling */ - } - - if (!error) { - char *cpos; - struct dirent *dp; - - cpos = dirbuf; - tries = 0; - - /* scan directory page looking for matching vnode */ - for (len = (dirbuflen - uio.uio_resid); len > 0; len -= reclen) { - dp = (struct dirent *) cpos; - reclen = dp->d_reclen; - - /* check for malformed directory.. */ - if (reclen < DIRENT_MINSIZE) { - error = EINVAL; - goto out; - } - /* - * XXX should perhaps do VOP_LOOKUP to - * check that we got back to the right place, - * but getting the locking games for that - * right would be heinous. - */ - if ((dp->d_type != DT_WHT) && - (dp->d_fileno == fileno)) { - char *bp = *bpp; - bp -= dp->d_namlen; - - if (bp <= bufp) { - error = ERANGE; - goto out; - } - bcopy(dp->d_name, bp, dp->d_namlen); - error = 0; - *bpp = bp; - goto out; - } - cpos += reclen; - } - } - } while (!eofflag); - error = ENOENT; - -out: - vrele(lvp); - *lvpp = NULL; - free(dirbuf, M_TEMP); - return error; -} - - -/* - * common routine shared by sys___getcwd() and linux_vn_isunder() - */ - -#define GETCWD_CHECK_ACCESS 0x0001 - -static int -linux_getcwd_common (lvp, rvp, bpp, bufp, limit, flags, td) - struct vnode *lvp; - struct vnode *rvp; - char **bpp; - char *bufp; - int limit; - int flags; - struct thread *td; -{ - struct filedesc *fdp = td->td_proc->p_fd; - struct vnode *uvp = NULL; - char *bp = NULL; - int error; - int perms = VEXEC; - - if (rvp == NULL) { - rvp = fdp->fd_rdir; - if (rvp == NULL) - rvp = rootvnode; - } - - VREF(rvp); - VREF(lvp); - - /* - * Error handling invariant: - * Before a `goto out': - * lvp is either NULL, or locked and held. - * uvp is either NULL, or locked and held. - */ - - error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td); - if (error) { - vrele(lvp); - lvp = NULL; - goto out; - } - if (bufp) - bp = *bpp; - /* - * this loop will terminate when one of the following happens: - * - we hit the root - * - getdirentries or lookup fails - * - we run out of space in the buffer. - */ - if (lvp == rvp) { - if (bp) - *(--bp) = '/'; - goto out; - } - do { - if (lvp->v_type != VDIR) { - error = ENOTDIR; - goto out; - } - - /* - * access check here is optional, depending on - * whether or not caller cares. - */ - if (flags & GETCWD_CHECK_ACCESS) { - error = VOP_ACCESS(lvp, perms, td->td_ucred, td); - if (error) - goto out; - perms = VEXEC|VREAD; - } - - /* - * step up if we're a covered vnode.. - */ - while (lvp->v_vflag & VV_ROOT) { - struct vnode *tvp; - - if (lvp == rvp) - goto out; - - tvp = lvp; - lvp = lvp->v_mount->mnt_vnodecovered; - vput(tvp); - /* - * hodie natus est radici frater - */ - if (lvp == NULL) { - error = ENOENT; - goto out; - } - VREF(lvp); - error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td); - if (error != 0) { - vrele(lvp); - lvp = NULL; - goto out; - } - } - error = linux_getcwd_scandir(&lvp, &uvp, &bp, bufp, td); - if (error) - goto out; -#if DIAGNOSTIC - if (lvp != NULL) - panic("getcwd: oops, forgot to null lvp"); - if (bufp && (bp <= bufp)) { - panic("getcwd: oops, went back too far"); - } -#endif - if (bp) - *(--bp) = '/'; - lvp = uvp; - uvp = NULL; - limit--; - } while ((lvp != rvp) && (limit > 0)); - -out: - if (bpp) - *bpp = bp; - if (uvp) - vput(uvp); - if (lvp) - vput(lvp); - vrele(rvp); - return error; -} - - /* * Find pathname of process's current directory. - * - * Use vfs vnode-to-name reverse cache; if that fails, fall back - * to reading directory contents. + * Simply use the new, complete getcwd() implementation. */ int linux_getcwd(struct thread *td, struct linux_getcwd_args *args) { - caddr_t bp, bend, path; - int error, len, lenused; - #ifdef DEBUG printf("Linux-emul(%ld): getcwd(%p, %ld)\n", (long)td->td_proc->p_pid, args->buf, (long)args->bufsize); #endif - - len = args->bufsize; - - if (len > MAXPATHLEN*4) - len = MAXPATHLEN*4; - else if (len < 2) - return ERANGE; - - path = (char *)malloc(len, M_TEMP, M_WAITOK); - - error = kern___getcwd(td, path, UIO_SYSSPACE, len); - if (!error) { - lenused = strlen(path) + 1; - if (lenused <= args->bufsize) { - td->td_retval[0] = lenused; - error = copyout(path, args->buf, lenused); - } - else - error = ERANGE; - } else { - bp = &path[len]; - bend = bp; - *(--bp) = '\0'; - - /* - * 5th argument here is "max number of vnodes to traverse". - * Since each entry takes up at least 2 bytes in the output buffer, - * limit it to N/2 vnodes for an N byte buffer. - */ - - error = linux_getcwd_common (td->td_proc->p_fd->fd_cdir, NULL, - &bp, path, len/2, GETCWD_CHECK_ACCESS, td); - - if (error) - goto out; - lenused = bend - bp; - td->td_retval[0] = lenused; - /* put the result into user buffer */ - error = copyout(bp, args->buf, lenused); - } -out: - free(path, M_TEMP); - return (error); + return (kern___getcwd(td, args->buf, UIO_USERSPACE, args->bufsize)); } - --hOcCNbCCxyk/YU74-- From owner-freebsd-arch@FreeBSD.ORG Sat Aug 16 13:49:01 2003 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id F1B6137B401 for ; Sat, 16 Aug 2003 13:49:00 -0700 (PDT) Received: from postfix3-2.free.fr (postfix3-2.free.fr [213.228.0.169]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3D10743F3F for ; Sat, 16 Aug 2003 13:49:00 -0700 (PDT) (envelope-from nsouch@free.fr) Received: from armor.fastether (nas-cbv-7-62-147-152-131.dial.proxad.net [62.147.152.131]) by postfix3-2.free.fr (Postfix) with SMTP id D2CB2C087 for ; Sat, 16 Aug 2003 22:48:58 +0200 (CEST) Received: (qmail 6208 invoked by uid 1001); 16 Aug 2003 23:03:58 -0000 Date: Sat, 16 Aug 2003 23:03:58 +0000 From: Nicolas Souchu To: freebsd-arch@freebsd.org Message-ID: <20030816230358.B5747@armor.free.fr> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i Subject: Loadable VM pager X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 16 Aug 2003 20:49:01 -0000 Hi folks, I'm wondering if being able to load dynamically a pager in FreeBSD VM would be worth and even possible with kobj. Of course that would introduce some overhead to the page fault handling... Nicholas -- Nicholas Souchu - nsouch@free.fr - nsouch@FreeBSD.org