PERFORCE change 125011 for review
Xin LI
delphij at FreeBSD.org
Fri Aug 10 05:32:32 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=125011
Change 125011 by delphij at charlie on 2007/08/10 12:31:55
IFC
Affected files ...
.. //depot/projects/delphij_fork/etc/rc.d/nscd#2 integrate
.. //depot/projects/delphij_fork/sbin/fsck_ffs/main.c#2 integrate
.. //depot/projects/delphij_fork/share/man/man4/ddb.4#2 integrate
.. //depot/projects/delphij_fork/share/man/man9/locking.9#2 integrate
.. //depot/projects/delphij_fork/sys/dev/wi/if_wi.c#3 integrate
.. //depot/projects/delphij_fork/sys/fs/tmpfs/tmpfs.h#5 integrate
.. //depot/projects/delphij_fork/sys/fs/tmpfs/tmpfs_subr.c#5 integrate
.. //depot/projects/delphij_fork/sys/fs/tmpfs/tmpfs_vfsops.c#6 integrate
.. //depot/projects/delphij_fork/sys/fs/tmpfs/tmpfs_vnops.c#4 integrate
.. //depot/projects/delphij_fork/sys/i386/i386/machdep.c#2 integrate
.. //depot/projects/delphij_fork/sys/i386/include/cpufunc.h#2 integrate
.. //depot/projects/delphij_fork/tools/regression/tmpfs/h_tools.c#2 integrate
.. //depot/projects/delphij_fork/tools/regression/tmpfs/t_mount#2 integrate
.. //depot/projects/delphij_fork/tools/regression/tmpfs/t_rename#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/Makefile#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/agent.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/cachelib.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/cacheplcs.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/config.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/debug.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/log.c#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/log.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/mp_rs_query.c#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/mp_rs_query.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/mp_ws_query.c#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/mp_ws_query.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/nscd.8#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/nscd.c#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/nscd.conf.5#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/nscdcli.c#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/nscdcli.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/parser.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/protocol.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/query.c#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/query.h#2 integrate
.. //depot/projects/delphij_fork/usr.sbin/nscd/singletons.h#2 integrate
Differences ...
==== //depot/projects/delphij_fork/etc/rc.d/nscd#2 (text+ko) ====
@@ -1,32 +1,32 @@
#!/bin/sh
#
-# $FreeBSD: src/etc/rc.d/nscd,v 1.3 2006/06/06 15:34:50 ume Exp $
+# $FreeBSD: src/etc/rc.d/nscd,v 1.4 2007/08/09 13:06:11 bushman Exp $
#
-# PROVIDE: cached
+# PROVIDE: nscd
# REQUIRE: DAEMON
# BEFORE: LOGIN
#
# Add the following lines to /etc/rc.conf to enable cached:
#
-# cached_enable="YES"
+# nscd_enable="YES"
#
-# See cached(8) for flags
+# See nscd(8) for flags
#
. /etc/rc.subr
-name=cached
+name=nscd
rcvar=`set_rcvar`
-command=/usr/sbin/cached
+command=/usr/sbin/nscd
extra_commands="flush"
flush_cmd="${command} -I all"
-cached_enable=${cached_enable:-"NO"}
-cached_pidfile=${cached_pidfile:-"/var/run/cached.pid"}
-cached_flags=${cached_flags:-""}
+nscd_enable=${nscd_enable:-"NO"}
+nscd_pidfile=${nscd_pidfile:-"/var/run/nscd.pid"}
+nscd_flags=${nscd_flags:-""}
load_rc_config $name
run_rc_command "$1"
==== //depot/projects/delphij_fork/sbin/fsck_ffs/main.c#2 (text+ko) ====
@@ -39,7 +39,7 @@
#endif /* not lint */
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sbin/fsck_ffs/main.c,v 1.45 2006/10/31 22:06:56 pjd Exp $");
+__FBSDID("$FreeBSD: src/sbin/fsck_ffs/main.c,v 1.46 2007/08/10 06:29:54 pjd Exp $");
#include <sys/param.h>
#include <sys/stat.h>
@@ -67,6 +67,7 @@
static void usage(void) __dead2;
static int argtoi(int flag, const char *req, const char *str, int base);
static int checkfilesys(char *filesys);
+static int chkdoreload(struct statfs *mntp);
static struct statfs *getmntpt(const char *);
int
@@ -197,7 +198,7 @@
struct stat snapdir;
struct group *grp;
ufs2_daddr_t blks;
- int cylno, ret;
+ int cylno;
ino_t files;
size_t size;
@@ -253,7 +254,9 @@
}
if ((sblock.fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0) {
gjournal_check(filesys);
- exit(0);
+ if (chkdoreload(mntp) == 0)
+ exit(0);
+ exit(4);
} else {
pfatal("UNEXPECTED INCONSISTENCY, %s\n",
"CANNOT RUN FAST FSCK\n");
@@ -483,23 +486,7 @@
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
if (rerun)
printf("\n***** PLEASE RERUN FSCK *****\n");
- if (mntp != NULL) {
- /*
- * We modified a mounted file system. Do a mount update on
- * it unless it is read-write, so we can continue using it
- * as safely as possible.
- */
- if (mntp->f_flags & MNT_RDONLY) {
- args.fspec = 0;
- args.export.ex_flags = 0;
- args.export.ex_root = 0;
- ret = mount("ufs", mntp->f_mntonname,
- mntp->f_flags | MNT_UPDATE | MNT_RELOAD, &args);
- if (ret == 0)
- return (0);
- pwarn("mount reload of '%s' failed: %s\n\n",
- mntp->f_mntonname, strerror(errno));
- }
+ if (chkdoreload(mntp) != 0) {
if (!fsmodified)
return (0);
if (!preen)
@@ -510,6 +497,36 @@
return (0);
}
+static int
+chkdoreload(struct statfs *mntp)
+{
+ struct ufs_args args;
+
+ if (mntp == NULL)
+ return (0);
+ /*
+ * We modified a mounted file system. Do a mount update on
+ * it unless it is read-write, so we can continue using it
+ * as safely as possible.
+ */
+ if (mntp->f_flags & MNT_RDONLY) {
+ memset(&args, 0, sizeof args);
+ /*
+ * args.fspec = 0;
+ * args.export.ex_flags = 0;
+ * args.export.ex_root = 0;
+ */
+ if (mount("ufs", mntp->f_mntonname,
+ mntp->f_flags | MNT_UPDATE | MNT_RELOAD, &args) == 0) {
+ return (0);
+ }
+ pwarn("mount reload of '%s' failed: %s\n\n",
+ mntp->f_mntonname, strerror(errno));
+ return (1);
+ }
+ return (0);
+}
+
/*
* Get the mount point information for name.
*/
==== //depot/projects/delphij_fork/share/man/man4/ddb.4#2 (text+ko) ====
@@ -57,9 +57,9 @@
.\" Created.
.\" [90/08/30 dbg]
.\"
-.\" $FreeBSD: src/share/man/man4/ddb.4,v 1.41 2006/10/30 12:55:06 ru Exp $
+.\" $FreeBSD: src/share/man/man4/ddb.4,v 1.42 2007/08/09 20:14:35 njl Exp $
.\"
-.Dd October 27, 2006
+.Dd August 6, 2007
.Dt DDB 4
.Os
.Sh NAME
@@ -522,6 +522,12 @@
modifier depends on the machine.
If not supported, incorrect information will be displayed.
.Pp
+.It Ic show Cm sysregs
+Show system registers (e.g.,
+.Li cr0-4
+on i386.)
+Not present on some platforms.
+.Pp
.It Ic show Cm geom Op Ar addr
If the
.Ar addr
==== //depot/projects/delphij_fork/share/man/man9/locking.9#2 (text+ko) ====
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/share/man/man9/locking.9,v 1.10 2007/06/21 16:39:25 brueffer Exp $
+.\" $FreeBSD: src/share/man/man9/locking.9,v 1.11 2007/08/09 21:09:56 julian Exp $
.\"
.Dd March 14, 2007
.Dt LOCKING 9
@@ -67,7 +67,8 @@
.El
.Pp
The primitives interact and have a number of rules regarding how
-they can and can not be combined. There are too many for the average
+they can and can not be combined.
+There are too many for the average
human mind and they keep changing.
(if you disagree, please write replacement text) :-)
.Pp
@@ -85,63 +86,70 @@
If you don't own it then you just spin, waiting for the holder (on
another CPU) to release it.
Hopefully they are doing something fast.
-You can not do anything that deschedules the thread while you
+You
+.Em must not
+do anything that deschedules the thread while you
are holding a SPIN mutex.
-.Ss Sleep Mutexes
-Basically sleep (regular) mutexes will deschedule the thread if the
+.Ss Mutexes
+Basically (regular) mutexes will deschedule the thread if the
mutex can not be acquired.
+A non-spin mutex can be considered to be equivalent
+to getting a write lock on an
+.Em rw_lock
+(see below), and in fact non-spin mutexes and rw_locks may soon become the same thing.
As in spin mutexes, you either get it or you don't.
-You may call the
+You may only call the
.Xr sleep 9
-call
+call via
.Fn msleep
or the new
.Fn mtx_sleep
-variant. These will atomically drop the mutex and reacquire it
+variant.
+These will atomically drop the mutex and reacquire it
as part of waking up.
+This is often however a
+.Em BAD
+idea because it generally relies on you having
+such a good knowledge of all the call graph above you
+and what assumptions it is making that there are a lot
+of ways to make hard-to-find mistakes.
+For example you MUST re-test all the assumptions you made before,
+all the way up the call graph to where you got the lock.
+You can not just assume that mtx_sleep can be inserted anywhere.
+If any caller above you has any mutex or
+rwlock, your sleep, will cause a panic.
+If the sleep only happens rarely it may be years before the
+bad code path is found.
.Ss Pool Mutexes
-A variant of SLEEP mutexes where the allocation of the mutex is handled
+A variant of regular mutexes where the allocation of the mutex is handled
more by the system.
-.Ss Sx_locks
-Shared/exclusive locks are used to protect data that are read far more often
-than they are written.
-Mutexes are inherently more efficient than shared/exclusive locks, so
-shared/exclusive locks should be used prudently.
-A thread may hold a shared or exclusive lock on an
-.Em sx_lock
-lock while sleeping.
-As a result, an
-.Em sx_lock
-lock may not be acquired while holding a mutex.
-Otherwise, if one thread slept while holding an
-.Em sx_lock
-lock while another thread blocked on the same
-.Em sx_lock
-lock after acquiring a mutex, then the second thread would effectively
-end up sleeping while holding a mutex, which is not allowed.
.Ss Rw_locks
Reader/writer locks allow shared access to protected data by multiple threads,
or exclusive access by a single thread.
The threads with shared access are known as
.Em readers
-since they only read the protected data.
+since they should only read the protected data.
A thread with exclusive access is known as a
.Em writer
-since it can modify protected data.
+since it may modify protected data.
.Pp
Although reader/writer locks look very similar to
.Xr sx 9
-locks, their usage pattern is different.
-Reader/writer locks can be treated as mutexes (see
+(see below) locks, their usage pattern is different.
+Reader/writer locks can be treated as mutexes (see above and
.Xr mutex 9 )
with shared/exclusive semantics.
-Unlike
-.Xr sx 9 ,
-an
+More specifically, regular mutexes can be
+considered to be equivalent to a write-lock on an
+.Em rw_lock.
+In the future this may in fact
+become literally the fact.
+An
.Em rw_lock
-can be locked while holding a non-spin mutex, and an
-.Em rw_lock
-cannot be held while sleeping.
+can be locked while holding a regular mutex, but
+can
+.Em not
+be held while sleeping.
The
.Em rw_lock
locks have priority propagation like mutexes, but priority
@@ -150,8 +158,36 @@
are anonymous.
Another important property is that shared holders of
.Em rw_lock
-can recurse,
-but exclusive locks are not allowed to recurse.
+can recurse, but exclusive locks are not allowed to recurse.
+This ability should not be used lightly and
+.Em may go away.
+Users of recursion in any locks should be prepared to
+defend their decision against vigorous criticism.
+.Ss Sx_locks
+Shared/exclusive locks are used to protect data that are read far more often
+than they are written.
+Mutexes are inherently more efficient than shared/exclusive locks, so
+shared/exclusive locks should be used prudently.
+The main reason for using an
+.Em sx_lock
+is that a thread may hold a shared or exclusive lock on an
+.Em sx_lock
+lock while sleeping.
+As a consequence of this however, an
+.Em sx_lock
+lock may not be acquired while holding a mutex.
+The reason for this is that, if one thread slept while holding an
+.Em sx_lock
+lock while another thread blocked on the same
+.Em sx_lock
+lock after acquiring a mutex, then the second thread would effectively
+end up sleeping while holding a mutex, which is not allowed.
+The
+.Em sx_lock
+should be considered to be closely related to
+.Xr sleep 9 .
+In fact it could in some cases be
+considered a conditional sleep.
.Ss Turnstiles
Turnstiles are used to hold a queue of threads blocked on
non-sleepable locks.
@@ -160,6 +196,7 @@
are assigned to a lock held by an owning thread.
Thus, when one thread is enqueued onto a turnstile, it can lend its
priority to the owning thread.
+If this sounds confusing, we need to describe it better.
.Ss Semaphores
.Ss Condition variables
Condition variables are used in conjunction with mutexes to wait for
@@ -182,7 +219,7 @@
.It
You can sleep while it has recursed, but other recursive locks cannot.
.It
-Giant must be locked first.
+Giant must be locked first before other locks.
.It
There are places in the kernel that drop Giant and pick it back up
again.
@@ -249,7 +286,8 @@
mutex before the function returns.
.Pp
.Ss lockmanager locks
-Largely deprecated. See the
+Largely deprecated.
+See the
.Xr lock 9
page for more information.
I don't know what the downsides are but I'm sure someone will fill in this part.
@@ -269,10 +307,12 @@
.El
.Pp
.Em *1
-Recursion is defined per lock. Lock order is important.
+Recursion is defined per lock.
+Lock order is important.
.Pp
.Em *2
-readers can recurse though writers can not. Lock order is important.
+readers can recurse though writers can not.
+Lock order is important.
.Pp
.Em *3
There are calls atomically release this primitive when going to sleep
@@ -302,6 +342,7 @@
.Xr condvar 9 ,
.Xr lock 9 ,
.Xr mtx_pool 9 ,
+.Xr mutex 9 ,
.Xr rwlock 9 ,
.Xr sema 9 ,
.Xr sleep 9 ,
==== //depot/projects/delphij_fork/sys/dev/wi/if_wi.c#3 (text+ko) ====
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/wi/if_wi.c,v 1.211 2007/07/11 21:25:48 thompsa Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/wi/if_wi.c,v 1.212 2007/08/09 13:29:26 avatar Exp $");
#define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
#define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
@@ -267,12 +267,12 @@
int error;
ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
- ifp->if_softc = sc;
if (ifp == NULL) {
device_printf(dev, "can not if_alloc\n");
wi_free(dev);
return (ENOSPC);
}
+ ifp->if_softc = sc;
/*
* NB: no locking is needed here; don't put it here
==== //depot/projects/delphij_fork/sys/fs/tmpfs/tmpfs.h#5 (text+ko) ====
@@ -1,7 +1,7 @@
-/* $NetBSD: tmpfs.h,v 1.18 2006/03/31 20:27:49 riz Exp $ */
+/* $NetBSD: tmpfs.h,v 1.26 2007/02/22 06:37:00 thorpej Exp $ */
/*
- * Copyright (c) 2005 The NetBSD Foundation, Inc.
+ * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -36,7 +36,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/fs/tmpfs/tmpfs.h,v 1.9 2007/08/03 06:24:31 delphij Exp $
+ * $FreeBSD: src/sys/fs/tmpfs/tmpfs.h,v 1.11 2007/08/10 11:00:30 delphij Exp $
*/
#ifndef _FS_TMPFS_TMPFS_H_
@@ -97,11 +97,74 @@
* importantly, to remove redundancy. */
TAILQ_HEAD(tmpfs_dir, tmpfs_dirent);
-#define TMPFS_DIRCOOKIE(dirent) ((off_t)(uintptr_t)(dirent))
+/* Each entry in a directory has a cookie that identifies it. Cookies
+ * supersede offsets within directories because, given how tmpfs stores
+ * directories in memory, there is no such thing as an offset. (Emulating
+ * a real offset could be very difficult.)
+ *
+ * The '.', '..' and the end of directory markers have fixed cookies which
+ * cannot collide with the cookies generated by other entries. The cookies
+ * fot the other entries are generated based on the memory address on which
+ * stores their information is stored.
+ *
+ * Ideally, using the entry's memory pointer as the cookie would be enough
+ * to represent it and it wouldn't cause collisions in any system.
+ * Unfortunately, this results in "offsets" with very large values which
+ * later raise problems in the Linux compatibility layer (and maybe in other
+ * places) as described in PR kern/32034. Hence we need to workaround this
+ * with a rather ugly hack.
+ *
+ * Linux 32-bit binaries, unless built with _FILE_OFFSET_BITS=64, have off_t
+ * set to 'long', which is a 32-bit *signed* long integer. Regardless of
+ * the macro value, GLIBC (2.3 at least) always uses the getdents64
+ * system call (when calling readdir) which internally returns off64_t
+ * offsets. In order to make 32-bit binaries work, *GLIBC* converts the
+ * 64-bit values returned by the kernel to 32-bit ones and aborts with
+ * EOVERFLOW if the conversion results in values that won't fit in 32-bit
+ * integers (which it assumes is because the directory is extremely large).
+ * This wouldn't cause problems if we were dealing with unsigned integers,
+ * but as we have signed integers, this check fails due to sign expansion.
+ *
+ * For example, consider that the kernel returns the 0xc1234567 cookie to
+ * userspace in a off64_t integer. Later on, GLIBC casts this value to
+ * off_t (remember, signed) with code similar to:
+ * system call returns the offset in kernel_value;
+ * off_t casted_value = kernel_value;
+ * if (sizeof(off_t) != sizeof(off64_t) &&
+ * kernel_value != casted_value)
+ * error!
+ * In this case, casted_value still has 0xc1234567, but when it is compared
+ * for equality against kernel_value, it is promoted to a 64-bit integer and
+ * becomes 0xffffffffc1234567, which is different than 0x00000000c1234567.
+ * Then, GLIBC assumes this is because the directory is very large.
+ *
+ * Given that all the above happens in user-space, we have no control over
+ * it; therefore we must workaround the issue here. We do this by
+ * truncating the pointer value to a 32-bit integer and hope that there
+ * won't be collisions. In fact, this will not cause any problems in
+ * 32-bit platforms but some might arise in 64-bit machines (I'm not sure
+ * if they can happen at all in practice).
+ *
+ * XXX A nicer solution shall be attempted. */
+#ifdef _KERNEL
#define TMPFS_DIRCOOKIE_DOT 0
#define TMPFS_DIRCOOKIE_DOTDOT 1
#define TMPFS_DIRCOOKIE_EOF 2
+static __inline
+off_t
+tmpfs_dircookie(struct tmpfs_dirent *de)
+{
+ off_t cookie;
+
+ cookie = ((off_t)(uintptr_t)de >> 1) & 0x7FFFFFFF;
+ MPASS(cookie != TMPFS_DIRCOOKIE_DOT);
+ MPASS(cookie != TMPFS_DIRCOOKIE_DOTDOT);
+ MPASS(cookie != TMPFS_DIRCOOKIE_EOF);
+ return cookie;
+}
+#endif
+
/* --------------------------------------------------------------------- */
/*
@@ -353,8 +416,8 @@
const char *, uint16_t, struct tmpfs_dirent **);
void tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *,
boolean_t);
-int tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, struct vnode **,
- struct thread *td);
+int tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, int,
+ struct vnode **, struct thread *);
void tmpfs_free_vp(struct vnode *);
int tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
struct componentname *, char *);
@@ -408,7 +471,7 @@
MPASS((node)->tn_type == VDIR); \
MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
MPASS((node)->tn_dir.tn_readdir_lastp == NULL || \
- TMPFS_DIRCOOKIE((node)->tn_dir.tn_readdir_lastp) == (node)->tn_dir.tn_readdir_lastn);
+ tmpfs_dircookie((node)->tn_dir.tn_readdir_lastp) == (node)->tn_dir.tn_readdir_lastn);
/* --------------------------------------------------------------------- */
==== //depot/projects/delphij_fork/sys/fs/tmpfs/tmpfs_subr.c#5 (text+ko) ====
@@ -1,4 +1,4 @@
-/* $NetBSD: tmpfs_subr.c,v 1.21 2006/06/07 22:33:39 kardel Exp $ */
+/* $NetBSD: tmpfs_subr.c,v 1.35 2007/07/09 21:10:50 ad Exp $ */
/*
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
* Efficient memory file system supporting functions.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/fs/tmpfs/tmpfs_subr.c,v 1.10 2007/08/03 06:24:31 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/fs/tmpfs/tmpfs_subr.c,v 1.12 2007/08/10 11:00:30 delphij Exp $");
#include <sys/param.h>
#include <sys/namei.h>
@@ -188,6 +188,12 @@
{
size_t pages = 0;
+#ifdef INVARIANTS
+ TMPFS_NODE_LOCK(node);
+ MPASS(node->tn_vnode == NULL);
+ TMPFS_NODE_UNLOCK(node);
+#endif
+
TMPFS_LOCK(tmp);
LIST_REMOVE(node, tn_entries);
tmp->tm_nodes_inuse--;
@@ -302,17 +308,20 @@
* Returns zero on success or an appropriate error code on failure.
*/
int
-tmpfs_alloc_vp(struct mount *mp, struct tmpfs_node *node, struct vnode **vpp,
- struct thread *td)
+tmpfs_alloc_vp(struct mount *mp, struct tmpfs_node *node, int lkflag,
+ struct vnode **vpp, struct thread *td)
{
- int error;
+ int error = 0;
struct vnode *vp;
loop:
+ TMPFS_NODE_LOCK(node);
if ((vp = node->tn_vnode) != NULL) {
- error = vget(vp, LK_EXCLUSIVE | LK_RETRY, td);
- if (error)
- return error;
+ VI_LOCK(vp);
+ TMPFS_NODE_UNLOCK(node);
+ vholdl(vp);
+ (void) vget(vp, lkflag | LK_INTERLOCK | LK_RETRY, td);
+ vdrop(vp);
/*
* Make sure the vnode is still there after
@@ -330,12 +339,11 @@
* otherwise lock the vp list while we call getnewvnode
* since that can block.
*/
- TMPFS_NODE_LOCK(node);
if (node->tn_vpstate & TMPFS_VNODE_ALLOCATING) {
node->tn_vpstate |= TMPFS_VNODE_WANT;
error = msleep((caddr_t) &node->tn_vpstate,
TMPFS_NODE_MTX(node), PDROP | PCATCH,
- "tmpfs_vplock", 0);
+ "tmpfs_alloc_vp", 0);
if (error)
return error;
@@ -351,13 +359,7 @@
goto unlock;
MPASS(vp != NULL);
- error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- if (error != 0) {
- vp->v_data = NULL;
- vput(vp);
- vp = NULL;
- goto unlock;
- }
+ (void) vn_lock(vp, lkflag | LK_RETRY, td);
vp->v_data = node;
vp->v_type = node->tn_type;
@@ -386,23 +388,15 @@
vnode_pager_setsize(vp, node->tn_size);
error = insmntque(vp, mp);
- if (error) {
- node->tn_vnode = NULL;
- TMPFS_NODE_LOCK(node);
- if (node->tn_vpstate & TMPFS_VNODE_WANT) {
- node->tn_vpstate &= ~TMPFS_VNODE_WANT;
- TMPFS_NODE_UNLOCK(node);
- wakeup((caddr_t) &node->tn_vpstate);
- } else
- TMPFS_NODE_UNLOCK(node);
- return error;
- }
- node->tn_vnode = vp;
+ if (error)
+ vp = NULL;
unlock:
TMPFS_NODE_LOCK(node);
+
MPASS(node->tn_vpstate & TMPFS_VNODE_ALLOCATING);
node->tn_vpstate &= ~TMPFS_VNODE_ALLOCATING;
+ node->tn_vnode = vp;
if (node->tn_vpstate & TMPFS_VNODE_WANT) {
node->tn_vpstate &= ~TMPFS_VNODE_WANT;
@@ -415,7 +409,11 @@
*vpp = vp;
MPASS(IFF(error == 0, *vpp != NULL && VOP_ISLOCKED(*vpp, td)));
+#ifdef INVARIANTS
+ TMPFS_NODE_LOCK(node);
MPASS(*vpp == node->tn_vnode);
+ TMPFS_NODE_UNLOCK(node);
+#endif
return error;
}
@@ -433,8 +431,10 @@
node = VP_TO_TMPFS_NODE(vp);
+ TMPFS_NODE_LOCK(node);
node->tn_vnode = NULL;
vp->v_data = NULL;
+ TMPFS_NODE_UNLOCK(node);
}
/* --------------------------------------------------------------------- */
@@ -499,7 +499,8 @@
}
/* Allocate a vnode for the new file. */
- error = tmpfs_alloc_vp(dvp->v_mount, node, vpp, cnp->cn_thread);
+ error = tmpfs_alloc_vp(dvp->v_mount, node, LK_EXCLUSIVE, vpp,
+ cnp->cn_thread);
if (error != 0) {
tmpfs_free_dirent(tmp, de, TRUE);
tmpfs_free_node(tmp, node);
@@ -672,7 +673,7 @@
if (de == NULL)
uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
else
- uio->uio_offset = TMPFS_DIRCOOKIE(de);
+ uio->uio_offset = tmpfs_dircookie(de);
}
}
@@ -697,7 +698,7 @@
}
TAILQ_FOREACH(de, &node->tn_dir.tn_dirhead, td_entries) {
- if (TMPFS_DIRCOOKIE(de) == cookie) {
+ if (tmpfs_dircookie(de) == cookie) {
break;
}
}
@@ -805,7 +806,7 @@
node->tn_dir.tn_readdir_lastn = 0;
node->tn_dir.tn_readdir_lastp = NULL;
} else {
- node->tn_dir.tn_readdir_lastn = uio->uio_offset = TMPFS_DIRCOOKIE(de);
+ node->tn_dir.tn_readdir_lastn = uio->uio_offset = tmpfs_dircookie(de);
node->tn_dir.tn_readdir_lastp = de;
}
==== //depot/projects/delphij_fork/sys/fs/tmpfs/tmpfs_vfsops.c#6 (text+ko) ====
@@ -48,7 +48,7 @@
* allocate and release resources.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/fs/tmpfs/tmpfs_vfsops.c,v 1.8 2007/07/24 17:14:53 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/fs/tmpfs/tmpfs_vfsops.c,v 1.9 2007/08/10 05:24:49 delphij Exp $");
#include <sys/param.h>
#include <sys/limits.h>
@@ -390,7 +390,7 @@
tmpfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td)
{
int error;
- error = tmpfs_alloc_vp(mp, VFS_TO_TMPFS(mp)->tm_root, vpp, td);
+ error = tmpfs_alloc_vp(mp, VFS_TO_TMPFS(mp)->tm_root, flags, vpp, td);
if (!error)
(*vpp)->v_vflag |= VV_ROOT;
@@ -429,7 +429,10 @@
}
TMPFS_UNLOCK(tmp);
- return found ? tmpfs_alloc_vp(mp, node, vpp, curthread) : EINVAL;
+ if (found)
+ return (tmpfs_alloc_vp(mp, node, LK_EXCLUSIVE, vpp, curthread));
+
+ return (EINVAL);
}
/* --------------------------------------------------------------------- */
==== //depot/projects/delphij_fork/sys/fs/tmpfs/tmpfs_vnops.c#4 (text+ko) ====
@@ -1,7 +1,7 @@
-/* $NetBSD: tmpfs_vnops.c,v 1.35 2007/01/04 15:42:37 elad Exp $ */
+/* $NetBSD: tmpfs_vnops.c,v 1.39 2007/07/23 15:41:01 jmmv Exp $ */
/*
- * Copyright (c) 2005 The NetBSD Foundation, Inc.
+ * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -41,7 +41,7 @@
* tmpfs vnode interface.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/fs/tmpfs/tmpfs_vnops.c,v 1.8 2007/07/19 03:34:50 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/fs/tmpfs/tmpfs_vnops.c,v 1.10 2007/08/10 11:00:30 delphij Exp $");
#include <sys/param.h>
#include <sys/fcntl.h>
@@ -95,12 +95,17 @@
!(cnp->cn_flags & ISDOTDOT)));
if (cnp->cn_flags & ISDOTDOT) {
+ int ltype = 0;
+
+ ltype = VOP_ISLOCKED(dvp, td);
+ vhold(dvp);
VOP_UNLOCK(dvp, 0, td);
-
/* Allocate a new vnode on the matching entry. */
- error = tmpfs_alloc_vp(dvp->v_mount, dnode->tn_dir.tn_parent, vpp, td);
+ error = tmpfs_alloc_vp(dvp->v_mount, dnode->tn_dir.tn_parent,
+ cnp->cn_lkflags, vpp, td);
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
+ vn_lock(dvp, ltype | LK_RETRY, td);
+ vdrop(dvp);
dnode->tn_dir.tn_parent->tn_lookup_dirent = NULL;
} else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
@@ -160,7 +165,8 @@
goto out;
/* Allocate a new vnode on the matching entry. */
- error = tmpfs_alloc_vp(dvp->v_mount, tnode, vpp, td);
+ error = tmpfs_alloc_vp(dvp->v_mount, tnode,
+ cnp->cn_lkflags, vpp, td);
if (error != 0)
goto out;
@@ -174,10 +180,10 @@
}
tnode->tn_lookup_dirent = de;
cnp->cn_flags |= SAVENAME;
+ } else {
+ error = tmpfs_alloc_vp(dvp->v_mount, tnode,
+ cnp->cn_lkflags, vpp, td);
}
- else
- error = tmpfs_alloc_vp(dvp->v_mount, tnode, vpp, td);
-
}
}
@@ -478,7 +484,7 @@
vm_page_wakeup(m);
VM_OBJECT_UNLOCK(vobj);
return (error);
- }
+ }
VM_OBJECT_UNLOCK(vobj);
nocache:
VM_OBJECT_LOCK(tobj);
@@ -886,13 +892,13 @@
struct vnode *tdvp = v->a_tdvp;
struct vnode *tvp = v->a_tvp;
struct componentname *tcnp = v->a_tcnp;
- struct tmpfs_node *tnode = 0; /* pacify gcc */
char *newname;
int error;
struct tmpfs_dirent *de;
struct tmpfs_node *fdnode;
struct tmpfs_node *fnode;
+ struct tmpfs_node *tnode;
struct tmpfs_node *tdnode;
MPASS(VOP_ISLOCKED(tdvp, tcnp->cn_thread));
@@ -902,6 +908,7 @@
fdnode = VP_TO_TMPFS_DIR(fdvp);
fnode = VP_TO_TMPFS_NODE(fvp);
+ tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
de = fnode->tn_lookup_dirent;
/* Disallow cross-device renames.
@@ -934,7 +941,7 @@
* Kern_rename gurantees the destination to be a directory
* if the source is one. */
if (tvp != NULL) {
- tnode = VP_TO_TMPFS_NODE(tvp);
+ MPASS(tnode != NULL);
if ((tnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
(tdnode->tn_flags & (APPEND | IMMUTABLE))) {
@@ -942,9 +949,20 @@
goto out;
}
- if ((de->td_node->tn_type == VDIR) && (tnode->tn_size > 0)) {
- error = ENOTEMPTY;
+ if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) {
+ if (tnode->tn_size > 0) {
+ error = ENOTEMPTY;
+ goto out;
+ }
+ } else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) {
+ error = ENOTDIR;
+ goto out;
+ } else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) {
+ error = EISDIR;
goto out;
+ } else {
+ MPASS(fnode->tn_type != VDIR &&
+ tnode->tn_type != VDIR);
}
}
@@ -1190,50 +1208,36 @@
int error;
off_t startoff;
- off_t cnt;
+ off_t cnt = 0;
struct tmpfs_node *node;
/* This operation only makes sense on directory nodes. */
- if (vp->v_type != VDIR) {
- error = ENOTDIR;
- goto out;
- }
+ if (vp->v_type != VDIR)
+ return ENOTDIR;
node = VP_TO_TMPFS_DIR(vp);
startoff = uio->uio_offset;
- cnt = 0;
- if (uio->uio_offset == TMPFS_DIRCOOKIE_DOT) {
+ switch (startoff) {
+ case TMPFS_DIRCOOKIE_DOT:
error = tmpfs_dir_getdotdent(node, uio);
- if (error == -1) {
- error = 0;
- goto outok;
- } else if (error != 0)
- goto outok;
- cnt++;
- }
-
- if (uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT) {
+ if (error == 0)
+ cnt++;
+ break;
+ case TMPFS_DIRCOOKIE_DOTDOT:
error = tmpfs_dir_getdotdotdent(node, uio);
- if (error == -1) {
- error = 0;
- goto outok;
- } else if (error != 0)
- goto outok;
- cnt++;
+ if (error == 0)
+ cnt++;
+ break;
+ default:
+ error = tmpfs_dir_getdents(node, uio, &cnt);
+ MPASS(error >= -1);
}
- error = tmpfs_dir_getdents(node, uio, &cnt);
if (error == -1)
error = 0;
- MPASS(error >= 0);
-outok:
- /* This label assumes that startoff has been
- * initialized. If the compiler didn't spit out warnings, we'd
- * simply make this one be 'out' and drop 'outok'. */
-
if (eofflag != NULL)
*eofflag =
(error == 0 && uio->uio_offset == TMPFS_DIRCOOKIE_EOF);
@@ -1262,11 +1266,10 @@
MPASS(de != NULL);
de = TAILQ_NEXT(de, td_entries);
}
- if (de == NULL) {
+ if (de == NULL)
off = TMPFS_DIRCOOKIE_EOF;
- } else {
- off = TMPFS_DIRCOOKIE(de);
- }
+ else
+ off = tmpfs_dircookie(de);
}
(*cookies)[i] = off;
@@ -1274,7 +1277,6 @@
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list