PERFORCE change 82811 for review

Peter Wemm peter at FreeBSD.org
Tue Aug 30 00:09:16 GMT 2005


http://perforce.freebsd.org/chv.cgi?CH=82811

Change 82811 by peter at peter_daintree on 2005/08/30 00:08:21

	IFC @82810

Affected files ...

.. //depot/projects/hammer/bin/sh/sh.1#18 integrate
.. //depot/projects/hammer/lib/libc/string/strcspn.3#2 integrate
.. //depot/projects/hammer/lib/libc/string/strspn.3#2 integrate
.. //depot/projects/hammer/sys/dev/wi/if_wi.c#42 integrate
.. //depot/projects/hammer/sys/kern/uipc_mbuf.c#31 integrate
.. //depot/projects/hammer/sys/sys/mbuf.h#43 integrate
.. //depot/projects/hammer/tools/tools/recoverdisk/README#3 integrate
.. //depot/projects/hammer/tools/tools/recoverdisk/recoverdisk.c#4 integrate

Differences ...

==== //depot/projects/hammer/bin/sh/sh.1#18 (text+ko) ====

@@ -30,7 +30,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	from: @(#)sh.1	8.6 (Berkeley) 5/4/95
-.\" $FreeBSD: src/bin/sh/sh.1,v 1.104 2005/08/29 06:47:43 jcamou Exp $
+.\" $FreeBSD: src/bin/sh/sh.1,v 1.105 2005/08/29 21:28:12 jcamou Exp $
 .\"
 .Dd August 17, 2005
 .Dt SH 1
@@ -426,7 +426,8 @@
 .Pp
 An alias name may be escaped in a command line, so that it is not
 replaced by its alias value, by using quoting characters within or
-adjacent to the alias name.  This is most often done by prefixing
+adjacent to the alias name.  
+This is most often done by prefixing
 an alias name with a backslash to execute a function, built-in, or
 normal program with the same name.
 See the

==== //depot/projects/hammer/lib/libc/string/strcspn.3#2 (text+ko) ====

@@ -34,7 +34,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)strcspn.3	8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strcspn.3,v 1.7 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strcspn.3,v 1.8 2005/08/29 20:41:58 garys Exp $
 .\"
 .Dd June 4, 1993
 .Dt STRCSPN 3
@@ -63,6 +63,13 @@
 .Em complement
 of
 .Fa charset ) .
+In other words, it computes the string array index in
+.Fa s
+of the first character of
+.Fa s
+which is also in
+.Fa charset ,
+else the index of the first null character.
 .Sh RETURN VALUES
 The
 .Fn strcspn

==== //depot/projects/hammer/lib/libc/string/strspn.3#2 (text+ko) ====

@@ -34,7 +34,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)strspn.3	8.1 (Berkeley) 6/4/93
-.\" $FreeBSD: src/lib/libc/string/strspn.3,v 1.8 2001/10/01 16:09:00 ru Exp $
+.\" $FreeBSD: src/lib/libc/string/strspn.3,v 1.9 2005/08/29 20:41:58 garys Exp $
 .\"
 .Dd June 4, 1993
 .Dt STRSPN 3
@@ -56,8 +56,15 @@
 .Fa s
 as long as the characters from
 .Fa s
-occur in string
+occur in the null-terminated string
 .Fa charset .
+In other words, it computes the string array index in
+.Fa s
+of the first character of
+.Fa s
+which is not in
+.Fa charset ,
+else the index of the first null character.
 .Sh RETURN VALUES
 The
 .Fn strspn

==== //depot/projects/hammer/sys/dev/wi/if_wi.c#42 (text+ko) ====

@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/wi/if_wi.c,v 1.188 2005/08/29 15:46:41 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/wi/if_wi.c,v 1.189 2005/08/29 20:06:02 scottl Exp $");
 
 #define WI_HERMES_AUTOINC_WAR	/* Work around data write autoinc bug. */
 #define WI_HERMES_STATS_WAR	/* Work around stats counter bug. */
@@ -2444,7 +2444,6 @@
 	if (i == 0) {
 		device_printf(sc->sc_dev, "wi_cmd: busy bit won't clear.\n" );
 		sc->wi_gone = 1;
-		count--;
 		return(ETIMEDOUT);
 	}
 
@@ -2468,7 +2467,6 @@
 			s = CSR_READ_2(sc, WI_STATUS);
 			CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
 			if (s & WI_STAT_CMD_RESULT) {
-				count--;
 				return(EIO);
 			}
 			break;
@@ -2476,7 +2474,6 @@
 		DELAY(WI_DELAY);
 	}
 
-	count--;
 	if (i == WI_TIMEOUT) {
 		device_printf(sc->sc_dev,
 		    "timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s);

==== //depot/projects/hammer/sys/kern/uipc_mbuf.c#31 (text+ko) ====

@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/uipc_mbuf.c,v 1.149 2005/07/30 01:32:16 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/uipc_mbuf.c,v 1.152 2005/08/29 20:15:33 andre Exp $");
 
 #include "opt_mac.h"
 #include "opt_param.h"
@@ -270,6 +270,125 @@
 }
 
 /*
+ * Clean up mbuf (chain) from any tags and packet headers.
+ * If "all" is set then the first mbuf in the chain will be
+ * cleaned too.
+ */
+void
+m_demote(struct mbuf *m0, int all)
+{
+	struct mbuf *m;
+
+	for (m = all ? m0 : m0->m_next; m != NULL; m = m->m_next) {
+		if (m->m_flags & M_PKTHDR) {
+			m_tag_delete_chain(m, NULL);
+			m->m_flags &= ~M_PKTHDR;
+			bzero(&m->m_pkthdr, sizeof(struct pkthdr));
+		}
+		if (m->m_type & MT_HEADER)
+			m->m_type = MT_DATA;
+		if (m != m0 && m->m_nextpkt)
+			m->m_nextpkt = NULL;
+		m->m_flags = m->m_flags & (M_EXT|M_EOR|M_RDONLY|M_FREELIST);
+	}
+}
+
+/*
+ * Sanity checks on mbuf (chain).
+ * Returns 0 bad, 1 good, panic worse.
+ * sanitize, 0 run M_SANITY_ACTION, 1 garble things so they blow up later.
+ */
+int
+m_sanity(struct mbuf *m0, int sanitize)
+{
+	struct mbuf *m;
+	caddr_t a, b;
+	int pktlen = 0;
+
+#define	M_SANITY_ACTION(s)	return (0)
+/* #define	M_SANITY_ACTION(s)	panic("mbuf %p: " s, m) */
+
+	m = m0;
+	while (m) {
+		/*
+		 * Basic pointer checks.  If any of these fails then some
+		 * unrelated kernel memory before or after us is trashed.
+		 * No way to recover from that.
+		 */
+		a = (m->m_flags & M_EXT ? m->m_ext.ext_buf :
+			(m->m_flags & M_PKTHDR ? (caddr_t)(&m->m_pktdat) :
+			 (caddr_t)(&m->m_dat)) );
+		b = (caddr_t)(a + (m->m_flags & M_EXT ? m->m_ext.ext_size :
+			(m->m_flags & M_PKTHDR ? MHLEN : MLEN)));
+		if ((caddr_t)m->m_data < a)
+			M_SANITY_ACTION("m_data outside mbuf data range left");
+		if ((caddr_t)m->m_data > b)
+			M_SANITY_ACTION("m_data outside mbuf data range right");
+		if ((caddr_t)m->m_data + m->m_len > b)
+			M_SANITY_ACTION("m_data + m_len exeeds mbuf space");
+		if (m->m_flags & M_PKTHDR && m->m_pkthdr.header) {
+			if ((caddr_t)m->m_pkthdr.header < a ||
+			    (caddr_t)m->m_pkthdr.header > b)
+				M_SANITY_ACTION("m_pkthdr.header outside mbuf data range");
+		}
+
+		/* m->m_nextpkt may only be set on first mbuf in chain. */
+		if (m != m0 && m->m_nextpkt) {
+			if (sanitize) {
+				m_freem(m->m_nextpkt);
+				m->m_nextpkt = (struct mbuf *)0xDEADC0DE;
+			} else
+				M_SANITY_ACTION("m->m_nextpkt on in-chain mbuf");
+		}
+
+		/* correct type correlations. */
+		if (m->m_type == MT_HEADER && !(m->m_flags & M_PKTHDR)) {
+			if (sanitize)
+				m->m_type = MT_DATA;
+			else
+				M_SANITY_ACTION("MT_HEADER set but not M_PKTHDR");
+		}
+
+		/* packet length (not mbuf length!) calculation */
+		if (m0->m_flags & M_PKTHDR)
+			pktlen += m->m_len;
+
+		/* m_tags may only be attached to first mbuf in chain. */
+		if (m != m0 && m->m_flags & M_PKTHDR &&
+		    !SLIST_EMPTY(&m->m_pkthdr.tags)) {
+			if (sanitize) {
+				m_tag_delete_chain(m, NULL);
+				/* put in 0xDEADC0DE perhaps? */
+			}
+			else
+				M_SANITY_ACTION("m_tags on in-chain mbuf");
+		}
+
+		/* M_PKTHDR may only be set on first mbuf in chain */
+		if (m != m0 && m->m_flags & M_PKTHDR) {
+			if (sanitize) {
+				bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
+				m->m_flags &= ~M_PKTHDR;
+				/* put in 0xDEADCODE and leave hdr flag in */
+			} else
+				M_SANITY_ACTION("M_PKTHDR on in-chain mbuf");
+		}
+
+		m = m->m_next;
+	}
+	if (pktlen && pktlen != m0->m_pkthdr.len) {
+		if (sanitize)
+			m0->m_pkthdr.len = 0;
+		else
+			M_SANITY_ACTION("m_pkthdr.len != mbuf chain length");
+	}
+#undef	M_SANITY_ACTION
+
+	return 1;
+}
+
+
+/*
  * "Move" mbuf pkthdr from "from" to "to".
  * "from" must have M_PKTHDR set, and "to" must be empty.
  */
@@ -439,6 +558,151 @@
 }
 
 /*
+ * Returns mbuf chain with new head for the prepending case.
+ * Copies from mbuf (chain) n from off for len to mbuf (chain) m
+ * either prepending or appending the data.
+ * The resulting mbuf (chain) m is fully writeable.
+ * m is destination (is made writeable)
+ * n is source, off is offset in source, len is len from offset
+ * dir, 0 append, 1 prepend
+ * how, wait or nowait
+ */
+
+static int
+m_bcopyxxx(void *s, void *t, u_int len)
+{
+	bcopy(s, t, (size_t)len);
+	return 0;
+}
+
+struct mbuf *
+m_copymdata(struct mbuf *m, struct mbuf *n, int off, int len,
+    int prep, int how)
+{
+	struct mbuf *mm, *x, *z;
+	caddr_t p;
+	int i, mlen, nlen = 0;
+	caddr_t buf[MLEN];
+
+	KASSERT(m != NULL && n != NULL, ("m_copymdata, no target or source"));
+	KASSERT(off >= 0, ("m_copymdata, negative off %d", off));
+	KASSERT(len >= 0, ("m_copymdata, negative len %d", len));
+	KASSERT(prep == 0 || prep == 1, ("m_copymdata, unknown direction %d", prep));
+
+	/* Make sure environment is sane. */
+	for (z = m; z != NULL; z = z->m_next) {
+		mlen += z->m_len;
+		if (!M_WRITABLE(z)) {
+			/* Make clusters writeable. */
+			if (z->m_flags & M_RDONLY)
+				return NULL;	/* Can't handle ext ref. */
+			x = m_getcl(how, MT_DATA, 0);
+			if (!x)
+				return NULL;
+			bcopy(z->m_ext.ext_buf, x->m_ext.ext_buf, x->m_ext.ext_size);
+			p = x->m_ext.ext_buf + (z->m_data - z->m_ext.ext_buf);
+			MEXT_REM_REF(z);	/* XXX */
+			z->m_data = p;
+			x->m_flags &= ~M_EXT;
+			(void)m_free(x);
+		}
+	}
+	mm = prep ? m : z;
+	for (z = n; z != NULL; z = z->m_next)
+		nlen += z->m_len;
+	if (len == M_COPYALL)
+		len = nlen - off;
+	if (off + len > nlen || len < 1)
+		return NULL;
+
+	/*
+	 * Append/prepend the data.  Allocating mbufs as necessary.
+	 */
+	/* Shortcut if enough free space in first/last mbuf. */
+	if (!prep && M_TRAILINGSPACE(mm) >= len) {
+		m_apply(n, off, len, m_bcopyxxx, mtod(mm, caddr_t) +
+			 mm->m_len);
+		mm->m_len += len;
+		mm->m_pkthdr.len += len;
+		return m;
+	}
+	if (prep && M_LEADINGSPACE(mm) >= len) {
+		mm->m_data = mtod(mm, caddr_t) - len;
+		m_apply(n, off, len, m_bcopyxxx, mtod(mm, caddr_t));
+		mm->m_len += len;
+		mm->m_pkthdr.len += len;
+		return mm;
+	}
+
+	/* Expand first/last mbuf to cluster if possible. */
+	if (!prep && !(mm->m_flags & M_EXT) && len > M_TRAILINGSPACE(mm)) {
+		bcopy(mm->m_data, &buf, mm->m_len);
+		m_clget(mm, how);
+		if (!(mm->m_flags & M_EXT))
+			return NULL;
+		bcopy(&buf, mm->m_ext.ext_buf, mm->m_len);
+		mm->m_data = mm->m_ext.ext_buf;
+		mm->m_pkthdr.header = NULL;
+	}
+	if (prep && !(mm->m_flags & M_EXT) && len > M_LEADINGSPACE(mm)) {
+		bcopy(mm->m_data, &buf, mm->m_len);
+		m_clget(mm, how);
+		if (!(mm->m_flags & M_EXT))
+			return NULL;
+		bcopy(&buf, (caddr_t *)mm->m_ext.ext_buf +
+		       mm->m_ext.ext_size - mm->m_len, mm->m_len);
+		mm->m_data = (caddr_t)mm->m_ext.ext_buf +
+			      mm->m_ext.ext_size - mm->m_len;
+		mm->m_pkthdr.header = NULL;
+	}
+
+	/* Append/prepend as many mbuf (clusters) as necessary to fit len. */
+	if (!prep && len > M_TRAILINGSPACE(mm)) {
+		if (!m_getm(mm, len - M_TRAILINGSPACE(mm), how, MT_DATA))
+			return NULL;
+	}
+	if (prep && len > M_LEADINGSPACE(mm)) {
+		if (!(z = m_getm(NULL, len - M_LEADINGSPACE(mm), how, MT_DATA)))
+			return NULL;
+		i = 0;
+		for (x = z; x != NULL; x = x->m_next) {
+			i += x->m_flags & M_EXT ? x->m_ext.ext_size :
+			      (x->m_flags & M_PKTHDR ? MHLEN : MLEN);
+			if (!x->m_next)
+				break;
+		}
+		z->m_data += i - len;
+		m_move_pkthdr(mm, z);
+		x->m_next = mm;
+		mm = z;
+	}
+
+	/* Seek to start position in source mbuf. Optimization for long chains. */
+	while (off > 0) {
+		if (off < n->m_len)
+			break;
+		off -= n->m_len;
+		n = n->m_next;
+	}
+
+	/* Copy data into target mbuf. */
+	z = mm;
+	while (len > 0) {
+		KASSERT(z != NULL, ("m_copymdata, falling off target edge"));
+		i = M_TRAILINGSPACE(z);
+		m_apply(n, off, i, m_bcopyxxx, mtod(z, caddr_t) + z->m_len);
+		z->m_len += i;
+		/* fixup pkthdr.len if necessary */
+		if ((prep ? mm : m)->m_flags & M_PKTHDR)
+			(prep ? mm : m)->m_pkthdr.len += i;
+		off += i;
+		len -= i;
+		z = z->m_next;
+	}
+	return (prep ? mm : m);
+}
+
+/*
  * Copy an entire packet, including header (which must be present).
  * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
  * Note that the copy is read-only, because clusters are not copied,

==== //depot/projects/hammer/sys/sys/mbuf.h#43 (text+ko) ====

@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)mbuf.h	8.5 (Berkeley) 2/19/95
- * $FreeBSD: src/sys/sys/mbuf.h,v 1.172 2005/07/30 01:32:16 sam Exp $
+ * $FreeBSD: src/sys/sys/mbuf.h,v 1.175 2005/08/29 20:15:33 andre Exp $
  */
 
 #ifndef _SYS_MBUF_H_
@@ -573,10 +573,13 @@
 void		 m_copyback(struct mbuf *, int, int, c_caddr_t);
 void		 m_copydata(const struct mbuf *, int, int, caddr_t);
 struct	mbuf	*m_copym(struct mbuf *, int, int, int);
+struct	mbuf	*m_copymdata(struct mbuf *, struct mbuf *,
+		    int, int, int, int);
 struct	mbuf	*m_copypacket(struct mbuf *, int);
 void		 m_copy_pkthdr(struct mbuf *, struct mbuf *);
 struct	mbuf	*m_copyup(struct mbuf *n, int len, int dstoff);
 struct	mbuf	*m_defrag(struct mbuf *, int);
+void		 m_demote(struct mbuf *, int);
 struct	mbuf	*m_devget(char *, int, int, struct ifnet *,
 		    void (*)(char *, caddr_t, u_int));
 struct	mbuf	*m_dup(struct mbuf *, int);
@@ -592,6 +595,7 @@
 void		 m_print(const struct mbuf *, int);
 struct	mbuf	*m_pulldown(struct mbuf *, int, int, int *);
 struct	mbuf	*m_pullup(struct mbuf *, int);
+int		m_sanity(struct mbuf *, int);
 struct	mbuf	*m_split(struct mbuf *, int, int);
 struct	mbuf	*m_uiotombuf(struct uio *, int, int, int);
 

==== //depot/projects/hammer/tools/tools/recoverdisk/README#3 (text+ko) ====

@@ -1,7 +1,7 @@
-$FreeBSD: src/tools/tools/recoverdisk/README,v 1.2 2005/02/07 11:26:53 obrien Exp $
+$FreeBSD: src/tools/tools/recoverdisk/README,v 1.3 2005/08/29 23:08:01 sobomax Exp $
 
-This is a small tool which will read an entire disk(partition) using
-1M blocks and optionally write the read data to a file or disk.
+This is a small tool which will read an entire disk(partition) or file
+using 1M blocks and optionally write the read data to a file or disk.
  
 If a read error happens, the 1M block gets put on the end of the worklist
 and will be retried with 64k blocksize.
@@ -20,3 +20,6 @@
 	touch myfloppy.flp
 	recoverdisk /dev/fd0 myfloppy.flp
 
+or recover a single file from the unreadable media:
+
+	recoverdisk /cdrom/file.avi file.avi

==== //depot/projects/hammer/tools/tools/recoverdisk/recoverdisk.c#4 (text+ko) ====

@@ -6,7 +6,7 @@
  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
  * ----------------------------------------------------------------------------
  *
- * $FreeBSD: src/tools/tools/recoverdisk/recoverdisk.c,v 1.4 2004/10/23 15:58:50 des Exp $
+ * $FreeBSD: src/tools/tools/recoverdisk/recoverdisk.c,v 1.5 2005/08/29 23:08:01 sobomax Exp $
  */
 #include <stdio.h>
 #include <stdint.h>
@@ -18,9 +18,11 @@
 #include <unistd.h>
 #include <sys/queue.h>
 #include <sys/disk.h>
+#include <sys/stat.h>
 
 #define BIGSIZE		(1024 * 1024)
 #define MEDIUMSIZE	(64 * 1024)
+#define MINSIZE		(512)
 
 struct lump {
 	off_t			start;
@@ -53,10 +55,11 @@
 	struct lump *lp;
 	off_t 	t, d;
 	size_t i, j;
-	int error;
+	int error, flags;
 	u_char *buf;
-	u_int sectorsize;
+	u_int sectorsize, minsize;
 	time_t t1, t2;
+	struct stat sb;
 
 
 	if (argc < 2)
@@ -68,22 +71,35 @@
 	fdr = open(argv[1], O_RDONLY);
 	if (fdr < 0)
 		err(1, "Cannot open read descriptor %s", argv[1]);
+
+	error = fstat(fdr, &sb);
+	if (error < 0)
+		err(1, "fstat failed");
+	flags = O_WRONLY;
+	if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
+		error = ioctl(fdr, DIOCGSECTORSIZE, &sectorsize);
+		if (error < 0)
+			err(1, "DIOCGSECTORSIZE failed");
+		minsize = sectorsize;
+
+		error = ioctl(fdr, DIOCGMEDIASIZE, &t);
+		if (error < 0)
+			err(1, "DIOCGMEDIASIZE failed");
+	} else {
+		sectorsize = 1;
+		t = sb.st_size;
+		minsize = MINSIZE;
+		flags |= O_CREAT | O_TRUNC;
+	}
+
 	if (argc > 2) {
-		fdw = open(argv[2], O_WRONLY);
+		fdw = open(argv[2], flags, DEFFILEMODE);
 		if (fdw < 0)
 			err(1, "Cannot open write descriptor %s", argv[2]);
 	} else {
 		fdw = -1;
 	}
 
-	error = ioctl(fdr, DIOCGSECTORSIZE, &sectorsize);
-	if (error < 0)
-		err(1, "DIOCGSECTORSIZE failed");
-
-	error = ioctl(fdr, DIOCGMEDIASIZE, &t);
-	if (error < 0)
-		err(1, "DIOCGMEDIASIZE failed");
-
 	new_lump(0, t, 0);
 	d = 0;
 
@@ -100,7 +116,7 @@
 			if (lp->state == 1)
 				i = MEDIUMSIZE;
 			if (lp->state > 1)
-				i = sectorsize;
+				i = minsize;
 			time(&t2);
 			if (t1 != t2 || lp->len < BIGSIZE) {
 				printf("\r%13jd %7zu %13jd %3d %13jd %13jd %.8f",


More information about the p4-projects mailing list