socsvn commit: r223369 - in soc2011/gk/ino64-head/sys: compat/freebsd32 kern sys

gk at FreeBSD.org gk at FreeBSD.org
Fri Jun 17 22:29:34 UTC 2011


Author: gk
Date: Fri Jun 17 22:29:32 2011
New Revision: 223369
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=223369

Log:
  Change dirent struct to use ino_t and add dir offset field; Add new syscalls

Modified:
  soc2011/gk/ino64-head/sys/compat/freebsd32/freebsd32_misc.c
  soc2011/gk/ino64-head/sys/compat/freebsd32/syscalls.master
  soc2011/gk/ino64-head/sys/kern/syscalls.master
  soc2011/gk/ino64-head/sys/kern/vfs_syscalls.c
  soc2011/gk/ino64-head/sys/sys/dirent.h
  soc2011/gk/ino64-head/sys/sys/syscallsubr.h

Modified: soc2011/gk/ino64-head/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- soc2011/gk/ino64-head/sys/compat/freebsd32/freebsd32_misc.c	Fri Jun 17 22:29:18 2011	(r223368)
+++ soc2011/gk/ino64-head/sys/compat/freebsd32/freebsd32_misc.c	Fri Jun 17 22:29:32 2011	(r223369)
@@ -1478,6 +1478,42 @@
 }
 #endif
 
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) || \
+    defined(COMPAT_FREEBSD8)
+int
+freebsd8_freebsd32_getdirentries(struct thread *td,
+    struct freebsd8_freebsd32_getdirentries_args *uap)
+{
+	long base;
+	int32_t base32;
+	int error;
+
+	error = freebsd8_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
+	    &base, NULL);
+	if (error)
+		return (error);
+	if (uap->basep != NULL) {
+		base32 = base;
+		error = copyout(&base32, uap->basep, sizeof(int32_t));
+	}
+	return (error);
+}
+
+int
+freebsd8_freebsd32_getdents(struct thread *td,
+    struct freebsd8_freebsd32_getdents_args *uap)
+{
+	struct freebsd8_freebsd32_getdirentries_args ap;
+
+	ap.fd = uap->fd;
+	ap.buf = uap->buf;
+	ap.count = uap->count;
+	ap.basep = NULL;
+	return (freebsd8_freebsd32_getdirentries(td, &ap));
+}
+#endif /* COMPAT_FREEBSD8 */
+
 int
 freebsd32_getdirentries(struct thread *td,
     struct freebsd32_getdirentries_args *uap)

Modified: soc2011/gk/ino64-head/sys/compat/freebsd32/syscalls.master
==============================================================================
--- soc2011/gk/ino64-head/sys/compat/freebsd32/syscalls.master	Fri Jun 17 22:29:18 2011	(r223368)
+++ soc2011/gk/ino64-head/sys/compat/freebsd32/syscalls.master	Fri Jun 17 22:29:32 2011	(r223369)
@@ -359,7 +359,7 @@
 195	AUE_SETRLIMIT	NOPROTO	{ int setrlimit(u_int which, \
 				    struct rlimit *rlp); } setrlimit \
 				    __setrlimit_args int
-196	AUE_GETDIRENTRIES	STD	{ int freebsd32_getdirentries(int fd, \
+196	AUE_GETDIRENTRIES	COMPAT8	{ int freebsd32_getdirentries(int fd, \
 				    char *buf, u_int count, int32_t *basep); }
 197	AUE_MMAP	COMPAT6	{ caddr_t freebsd32_mmap(caddr_t addr, \
 				    size_t len, int prot, int flags, int fd, \
@@ -485,7 +485,7 @@
 269	AUE_NULL	UNIMPL	nosys
 270	AUE_NULL	UNIMPL	nosys
 271	AUE_NULL	UNIMPL	nosys
-272	AUE_O_GETDENTS	NOPROTO	{ int getdents(int fd, char *buf, \
+272	AUE_O_GETDENTS	COMPAT8	{ int freebsd32_getdents(int fd, char *buf, \
 				    size_t count); }
 273	AUE_NULL	UNIMPL	nosys
 274	AUE_LCHMOD	NOPROTO	{ int lchmod(char *path, mode_t mode); }
@@ -1002,3 +1002,7 @@
 				    struct stat32 *sb); }
 536	AUE_FSTATAT	STD	{ int freebsd32_fstatat(int fd, char *path, \
 				    struct stat32 *buf, int flag); }
+537	AUE_O_GETDENTS	NOPROTO	{ int getdents(int fd, char *buf, \
+				    size_t count); }
+538	AUE_GETDIRENTRIES	STD	{ int freebsd32_getdirentries(int fd, \
+				    char *buf, u_int count, int32_t *basep); }

Modified: soc2011/gk/ino64-head/sys/kern/syscalls.master
==============================================================================
--- soc2011/gk/ino64-head/sys/kern/syscalls.master	Fri Jun 17 22:29:18 2011	(r223368)
+++ soc2011/gk/ino64-head/sys/kern/syscalls.master	Fri Jun 17 22:29:32 2011	(r223369)
@@ -379,7 +379,7 @@
 195	AUE_SETRLIMIT	STD	{ int setrlimit(u_int which, \
 				    struct rlimit *rlp); } setrlimit \
 				    __setrlimit_args int
-196	AUE_GETDIRENTRIES	STD	{ int getdirentries(int fd, char *buf, \
+196	AUE_GETDIRENTRIES	COMPAT8	{ int getdirentries(int fd, char *buf, \
 				    u_int count, long *basep); }
 197	AUE_MMAP	STD	{ caddr_t freebsd6_mmap(caddr_t addr, \
 				    size_t len, int prot, int flags, int fd, \
@@ -496,7 +496,7 @@
 269	AUE_NULL	UNIMPL	nosys
 270	AUE_NULL	UNIMPL	nosys
 271	AUE_NULL	UNIMPL	nosys
-272	AUE_O_GETDENTS	STD	{ int getdents(int fd, char *buf, \
+272	AUE_O_GETDENTS	COMPAT8	{ int getdents(int fd, char *buf, \
 				    size_t count); }
 273	AUE_NULL	UNIMPL	nosys
 274	AUE_LCHMOD	STD	{ int lchmod(char *path, mode_t mode); }
@@ -958,5 +958,9 @@
 				    struct stat *sb); }
 536	AUE_FSTATAT	STD	{ int fstatat(int fd, char *path, \
 				    struct stat *buf, int flag); }
+537	AUE_O_GETDENTS	STD	{ int getdents(int fd, char *buf, \
+				    size_t count); }
+538	AUE_GETDIRENTRIES	STD	{ int getdirentries(int fd, char *buf, \
+				    u_int count, long *basep); }
 ; Please copy any additions and changes to the following compatability tables:
 ; sys/compat/freebsd32/syscalls.master

Modified: soc2011/gk/ino64-head/sys/kern/vfs_syscalls.c
==============================================================================
--- soc2011/gk/ino64-head/sys/kern/vfs_syscalls.c	Fri Jun 17 22:29:18 2011	(r223368)
+++ soc2011/gk/ino64-head/sys/kern/vfs_syscalls.c	Fri Jun 17 22:29:32 2011	(r223369)
@@ -4006,7 +4006,85 @@
 	return (error);
 }
 
+#if defined(COMPAT_43) || defined(COMPAT_FREEBSD4) || \
+    defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD6) || \
+    defined(COMPAT_FREEBSD7) || defined(COMPAT_FREEBSD8)
+int
+freebsd8_kern_getdirentries(struct thread *td, int fd, char *ubuf, u_int count,
+    long *basep, void (*func)(struct freebsd8_dirent *))
+{
+	struct freebsd8_dirent dstdp;
+	struct dirent *dp, *edp;
+	char *dirbuf;
+	ssize_t resid, ucount;
+	int error;
+
+	/* XXX arbitrary sanity limit on `count'. */
+	count = min(count, 64 * 1024);
+
+	dirbuf = malloc(count, M_TEMP, M_WAITOK);
+
+	error = kern_getdirentries(td, fd, dirbuf, count, basep, &resid,
+	    UIO_SYSSPACE);
+	if (error != 0)
+		goto done;
+
+	ucount = 0;
+	for (dp = (struct dirent *)dirbuf,
+	    edp = (struct dirent *)&dirbuf[count - resid];
+	    ucount < count && dp < edp; ) {
+		if (dp->d_reclen == 0)
+			break;
+		if (dp->d_namlen > sizeof(dstdp.d_name) - 1)
+			continue;
+		dstdp.d_type = dp->d_type;
+		dstdp.d_namlen = dp->d_namlen;
+		dstdp.d_fileno = dp->d_fileno;		/* truncate */
+		dstdp.d_reclen = sizeof(dstdp) - sizeof(dstdp.d_name) +
+		    ((dp->d_namlen + 1 + 3) &~ 3);
+		bcopy(dp->d_name, dstdp.d_name, dstdp.d_namlen);
+		bzero(dstdp.d_name + dstdp.d_namlen,
+		    dstdp.d_reclen - offsetof(struct freebsd8_dirent, d_name) -
+		    dstdp.d_namlen);
+		MPASS(dstdp.d_reclen <= dp->d_reclen);
+		MPASS(ucount + dstdp.d_reclen <= count);
+		if (func != NULL)
+			func(&dstdp);
+		error = copyout(&dstdp, ubuf + ucount, dstdp.d_reclen);
+		if (error != 0)
+			break;
+		dp = (struct dirent *)((char *)dp + dp->d_reclen);
+		ucount += dstdp.d_reclen;
+	}
+
+done:
+	free(dirbuf, M_TEMP);
+	if (error == 0)
+		td->td_retval[0] = ucount;
+	return (error);
+}
+#endif /* COMPAT */
+
 #ifdef COMPAT_43
+static void
+ogetdirentries_cvt(struct freebsd8_dirent *dp)
+{
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+	/*
+	 * The expected low byte of dp->d_namlen is our dp->d_type.
+	 * The high MBZ byte of dp->d_namlen is our dp->d_namlen.
+	 */
+	dp->d_type = dp->d_namlen;
+	dp->d_namlen = 0;
+#else
+	/*
+	 * The dp->d_type is the high byte of the expected dp->d_namlen,
+	 * so must be zero'ed.
+	 */
+	dp->d_type = 0;
+#endif
+}
+
 /*
  * Read a block of directory entries in a filesystem independent format.
  */
@@ -4034,131 +4112,69 @@
 kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
     long *ploff)
 {
-	struct vnode *vp;
-	struct file *fp;
-	struct uio auio, kuio;
-	struct iovec aiov, kiov;
-	struct dirent *dp, *edp;
-	caddr_t dirbuf;
-	int error, eofflag, readcnt, vfslocked;
-	long loff;
+	long base;
+	int error;
 
 	/* XXX arbitrary sanity limit on `count'. */
 	if (uap->count > 64 * 1024)
 		return (EINVAL);
-	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
-		return (error);
-	if ((fp->f_flag & FREAD) == 0) {
-		fdrop(fp, td);
-		return (EBADF);
-	}
-	vp = fp->f_vnode;
-unionread:
-	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
-	if (vp->v_type != VDIR) {
-		VFS_UNLOCK_GIANT(vfslocked);
-		fdrop(fp, td);
-		return (EINVAL);
-	}
-	aiov.iov_base = uap->buf;
-	aiov.iov_len = uap->count;
-	auio.uio_iov = &aiov;
-	auio.uio_iovcnt = 1;
-	auio.uio_rw = UIO_READ;
-	auio.uio_segflg = UIO_USERSPACE;
-	auio.uio_td = td;
-	auio.uio_resid = uap->count;
-	vn_lock(vp, LK_SHARED | LK_RETRY);
-	loff = auio.uio_offset = fp->f_offset;
-#ifdef MAC
-	error = mac_vnode_check_readdir(td->td_ucred, vp);
-	if (error) {
-		VOP_UNLOCK(vp, 0);
-		VFS_UNLOCK_GIANT(vfslocked);
-		fdrop(fp, td);
-		return (error);
-	}
-#endif
-#	if (BYTE_ORDER != LITTLE_ENDIAN)
-		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
-			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
-			    NULL, NULL);
-			fp->f_offset = auio.uio_offset;
-		} else
-#	endif
-	{
-		kuio = auio;
-		kuio.uio_iov = &kiov;
-		kuio.uio_segflg = UIO_SYSSPACE;
-		kiov.iov_len = uap->count;
-		dirbuf = malloc(uap->count, M_TEMP, M_WAITOK);
-		kiov.iov_base = dirbuf;
-		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
-			    NULL, NULL);
-		fp->f_offset = kuio.uio_offset;
-		if (error == 0) {
-			readcnt = uap->count - kuio.uio_resid;
-			edp = (struct dirent *)&dirbuf[readcnt];
-			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
-#				if (BYTE_ORDER == LITTLE_ENDIAN)
-					/*
-					 * The expected low byte of
-					 * dp->d_namlen is our dp->d_type.
-					 * The high MBZ byte of dp->d_namlen
-					 * is our dp->d_namlen.
-					 */
-					dp->d_type = dp->d_namlen;
-					dp->d_namlen = 0;
-#				else
-					/*
-					 * The dp->d_type is the high byte
-					 * of the expected dp->d_namlen,
-					 * so must be zero'ed.
-					 */
-					dp->d_type = 0;
-#				endif
-				if (dp->d_reclen > 0) {
-					dp = (struct dirent *)
-					    ((char *)dp + dp->d_reclen);
-				} else {
-					error = EIO;
-					break;
-				}
-			}
-			if (dp >= edp)
-				error = uiomove(dirbuf, readcnt, &auio);
-		}
-		free(dirbuf, M_TEMP);
-	}
-	if (error) {
-		VOP_UNLOCK(vp, 0);
-		VFS_UNLOCK_GIANT(vfslocked);
-		fdrop(fp, td);
-		return (error);
-	}
-	if (uap->count == auio.uio_resid &&
-	    (vp->v_vflag & VV_ROOT) &&
-	    (vp->v_mount->mnt_flag & MNT_UNION)) {
-		struct vnode *tvp = vp;
-		vp = vp->v_mount->mnt_vnodecovered;
-		VREF(vp);
-		fp->f_vnode = vp;
-		fp->f_data = vp;
-		fp->f_offset = 0;
-		vput(tvp);
-		VFS_UNLOCK_GIANT(vfslocked);
-		goto unionread;
-	}
-	VOP_UNLOCK(vp, 0);
-	VFS_UNLOCK_GIANT(vfslocked);
-	fdrop(fp, td);
-	td->td_retval[0] = uap->count - auio.uio_resid;
-	if (error == 0)
-		*ploff = loff;
+
+	error = freebsd8_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
+	    &base, ogetdirentries_cvt);
+
+	if (error == 0 && uap->basep != NULL)
+		error = copyout(&base, uap->basep, sizeof(long));
+
 	return (error);
 }
 #endif /* COMPAT_43 */
 
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) || \
+    defined(COMPAT_FREEBSD8)
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd8_getdirentries_args {
+	int	fd;
+	char	*buf;
+	u_int	count;
+	long	*basep;
+};
+#endif
+int
+freebsd8_getdirentries(struct thread *td,
+    struct freebsd8_getdirentries_args *uap)
+{
+	long base;
+	int error;
+
+	error = freebsd8_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
+	    &base, NULL);
+
+	if (error == 0 && uap->basep != NULL)
+		error = copyout(&base, uap->basep, sizeof(long));
+	return (error);
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct freebsd8_getdents_args {
+	int fd;
+	char *buf;
+	size_t count;
+};
+#endif
+int
+freebsd8_getdents(struct thread *td, struct freebsd8_getdents_args *uap)
+{
+	struct freebsd8_getdirentries_args ap;
+
+	ap.fd = uap->fd;
+	ap.buf = uap->buf;
+	ap.count = uap->count;
+	ap.basep = NULL;
+	return (freebsd8_getdirentries(td, &ap));
+}
+#endif /* COMPAT_FREEBSD8 */
+
 /*
  * Read a block of directory entries in a filesystem independent format.
  */

Modified: soc2011/gk/ino64-head/sys/sys/dirent.h
==============================================================================
--- soc2011/gk/ino64-head/sys/sys/dirent.h	Fri Jun 17 22:29:18 2011	(r223368)
+++ soc2011/gk/ino64-head/sys/sys/dirent.h	Fri Jun 17 22:29:32 2011	(r223369)
@@ -36,6 +36,16 @@
 #include <sys/cdefs.h>
 #include <sys/_types.h>
 
+#ifndef _INO_T_DECLARED
+typedef	__ino_t		ino_t;
+#define	_INO_T_DECLARED
+#endif
+
+#ifndef _OFF_T_DECLARED
+typedef	__off_t		off_t;
+#define	_OFF_T_DECLARED
+#endif
+
 /*
  * The dirent structure defines the format of directory entries returned by
  * the getdirentries(2) system call.
@@ -48,10 +58,13 @@
  */
 
 struct dirent {
-	__uint32_t d_fileno;		/* file number of entry */
+	ino_t      d_fileno;		/* file number of entry */
+	off_t      d_off__unused;	/* directory offset of entry */
 	__uint16_t d_reclen;		/* length of this record */
+	__uint16_t d_namlen;		/* length of string in d_name */
 	__uint8_t  d_type; 		/* file type, see below */
-	__uint8_t  d_namlen;		/* length of string in d_name */
+	__uint8_t  d_unused1;
+	__uint16_t d_unused2;
 #if __BSD_VISIBLE
 #define	MAXNAMLEN	255
 	char	d_name[MAXNAMLEN + 1];	/* name must be no longer than this */
@@ -61,6 +74,14 @@
 };
 
 #if __BSD_VISIBLE
+struct freebsd8_dirent {
+	__uint32_t d_fileno;		/* file number of entry */
+	__uint16_t d_reclen;		/* length of this record */
+	__uint8_t  d_type; 		/* file type, see below */
+	__uint8_t  d_namlen;		/* length of string in d_name */
+	char	d_name[255 + 1];	/* name must be no longer than this */
+};
+
 /*
  * File types
  */

Modified: soc2011/gk/ino64-head/sys/sys/syscallsubr.h
==============================================================================
--- soc2011/gk/ino64-head/sys/sys/syscallsubr.h	Fri Jun 17 22:29:18 2011	(r223368)
+++ soc2011/gk/ino64-head/sys/sys/syscallsubr.h	Fri Jun 17 22:29:32 2011	(r223369)
@@ -238,4 +238,9 @@
 #define	KSA_OSIGSET	0x0001	/* uses osigact_t */
 #define	KSA_FREEBSD4	0x0002	/* uses ucontext4 */
 
+struct freebsd8_dirent;
+
+int	freebsd8_kern_getdirentries(struct thread *td, int fd, char *ubuf, u_int
+	    count, long *basep, void (*func)(struct freebsd8_dirent *));
+
 #endif /* !_SYS_SYSCALLSUBR_H_ */


More information about the svn-soc-all mailing list