diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/arch/i386/kernel/syscall_table.S vanilla-new/arch/i386/kernel/syscall_table.S
--- vanilla/arch/i386/kernel/syscall_table.S	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/arch/i386/kernel/syscall_table.S	2006-05-11 14:03:04.000000000 -0500
@@ -314,7 +314,9 @@
 	.long sys_openfh
 	.long sys_newstatlite
 	.long sys_newlstatlite
-	.long sys_newfstatlite
+	.long sys_newfstatlite /* 315 */
 	.long sys_statlite64
 	.long sys_lstatlite64
 	.long sys_fstatlite64
+	.long sys_getdents_plus
+	.long sys_getdents64_plus /* 320 */
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/arch/ia64/kernel/entry.S vanilla-new/arch/ia64/kernel/entry.S
--- vanilla/arch/ia64/kernel/entry.S	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/arch/ia64/kernel/entry.S	2006-05-11 14:10:30.000000000 -0500
@@ -1624,5 +1624,7 @@
 	data8 sys_newstatlite
 	data8 sys_newlstatlite
 	data8 sys_newfstatlite
+	data8 sys_getdents_plus
+	data8 sys_getdents64_plus
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/arch/powerpc/kernel/systbl.S vanilla-new/arch/powerpc/kernel/systbl.S
--- vanilla/arch/powerpc/kernel/systbl.S	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/arch/powerpc/kernel/systbl.S	2006-05-11 14:12:20.000000000 -0500
@@ -327,3 +327,5 @@
 SYSCALL(newstatlite)
 SYSCALL(newlstatlite)
 SYSCALL(newfstatlite)
+SYSCALL(sys_getdents_plus)
+SYSCALL(sys_getdents64_plus)
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/arch/x86_64/ia32/ia32entry.S vanilla-new/arch/x86_64/ia32/ia32entry.S
--- vanilla/arch/x86_64/ia32/ia32entry.S	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/arch/x86_64/ia32/ia32entry.S	2006-05-11 14:09:30.000000000 -0500
@@ -696,6 +696,8 @@
 	.quad sys32_statlite64
 	.quad sys32_lstatlite64
 	.quad sys32_fstatlite64
+	.quad sys_ni_syscall   /* getdents_plus */
+	.quad sys_ni_syscall   /* getdents64_plus */
 ia32_syscall_end:		
 	.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
 		.quad ni_syscall
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/fs/readdir.c vanilla-new/fs/readdir.c
--- vanilla/fs/readdir.c	2006-03-19 23:53:29.000000000 -0600
+++ vanilla-new/fs/readdir.c	2006-05-18 19:25:06.000000000 -0500
@@ -43,6 +43,32 @@
 
 EXPORT_SYMBOL(vfs_readdir);
 
+int vfs_readdirplus(struct file *file, filldirplus_t fillerplus, void *buf)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int res = -ENOTDIR;
+	if (!file->f_op || !file->f_op->readdirplus)
+		goto out;
+
+	res = security_file_permission(file, MAY_READ);
+	if (res)
+		goto out;
+
+	mutex_lock(&inode->i_mutex);
+	res = -ENOENT;
+	if (!IS_DEADDIR(inode)) {
+		res = file->f_op->readdirplus(file, buf, fillerplus);
+		file_accessed(file);
+	}
+	mutex_unlock(&inode->i_mutex);
+out:
+	if (file->f_op && file->f_op->readdir && !file->f_op->readdirplus)
+		res = -EOPNOTSUPP;
+	return res;
+}
+
+EXPORT_SYMBOL_GPL(vfs_readdirplus);
+
 /*
  * Traditional linux readdir() handling..
  *
@@ -212,6 +238,111 @@
 	return error;
 }
 
+/* getdents_plus implementation */
+#define DIRENT_OFFSET(de) ((unsigned long) &((de)->dp_dirent) - (unsigned long) (char __user *) (de))
+
+struct linux_dirent_plus {
+	struct stat          dp_stat;
+	int                  dp_stat_err;
+	struct linux_dirent  dp_dirent;
+};
+
+struct getdentsplus_callback {
+	struct linux_dirent_plus __user * current_dir;
+	struct linux_dirent_plus __user * previous;
+	int count;
+	int error;
+};
+
+static int filldirplus(void * __buf, const char * name, int namlen, loff_t offset,
+		   ino_t ino, unsigned int d_type, struct kstat *statp)
+{
+	struct linux_dirent __user *de;
+	struct linux_dirent_plus __user * dirent;
+	struct getdentsplus_callback * buf = (struct getdentsplus_callback *) __buf;
+	int err, reclen = ROUND_UP(NAME_OFFSET(de) + namlen + DIRENT_OFFSET(dirent) + 2);
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent) {
+		if (__put_user(offset, &dirent->dp_dirent.d_off))
+			goto efault;
+	}
+	dirent = buf->current_dir;
+	err = 0;
+	if (IS_ERR(statp)) {
+		err = PTR_ERR(statp);
+		if (__put_user(err, &dirent->dp_stat_err))
+			goto efault;
+	}
+	else {
+		if (__put_user(err, &dirent->dp_stat_err))
+			goto efault;
+		if (cp_new_stat(statp, &dirent->dp_stat))
+			goto efault;
+	}
+	if (__put_user(ino, &dirent->dp_dirent.d_ino))
+		goto efault;
+	if (__put_user(reclen, &dirent->dp_dirent.d_reclen))
+		goto efault;
+	if (copy_to_user(dirent->dp_dirent.d_name, name, namlen))
+		goto efault;
+	if (__put_user(0, dirent->dp_dirent.d_name + namlen))
+		goto efault;
+	if (__put_user(d_type, (char __user *) dirent + reclen - 1))
+		goto efault;
+	buf->previous = dirent;
+	dirent = (void __user *)dirent + reclen;
+	buf->current_dir = dirent;
+	buf->count -= reclen;
+	return 0;
+efault:
+	buf->error = -EFAULT;
+	return -EFAULT;
+}
+
+asmlinkage long sys_getdents_plus(unsigned int fd, struct linux_dirent_plus __user * dirent, unsigned int count)
+{
+	struct file * file;
+	struct linux_dirent_plus __user * lastdirent;
+	struct getdentsplus_callback buf;
+	int error;
+
+	error = -EFAULT;
+	if (!access_ok(VERIFY_WRITE, dirent, count))
+		goto out;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.current_dir = dirent;
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+
+	error = vfs_readdirplus(file, filldirplus, &buf);
+	if (error < 0)
+		goto out_putf;
+	error = buf.error;
+	lastdirent = buf.previous;
+	if (lastdirent) {
+		typeof(lastdirent->dp_dirent.d_off) d_off = file->f_pos;
+		error = -EFAULT;
+		if (__put_user(d_off, &lastdirent->dp_dirent.d_off))
+			goto out_putf;
+		error = count - buf.count;
+	}
+
+out_putf:
+	fput(file);
+out:
+	return error;
+}
+
 #define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
 
 struct getdents_callback64 {
@@ -298,3 +429,105 @@
 out:
 	return error;
 }
+
+struct getdentsplus_callback64 {
+	struct linux_dirent64_plus __user * current_dir;
+	struct linux_dirent64_plus __user * previous;
+	int count;
+	int error;
+};
+
+static int filldir64_plus(void * __buf, const char * name, int namlen, loff_t offset,
+		     ino_t ino, unsigned int d_type, struct kstat *statp)
+{
+	struct linux_dirent64 __user *de;
+	struct linux_dirent64_plus __user *dirent;
+	struct getdentsplus_callback64 * buf = (struct getdentsplus_callback64 *) __buf;
+	int err, reclen = ROUND_UP64(NAME_OFFSET(de) + namlen + 1 + DIRENT_OFFSET(dirent));
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent) {
+		if (__put_user(offset, &dirent->dp_dirent.d_off))
+			goto efault;
+	}
+	dirent = buf->current_dir;
+	err = 0;
+	if (IS_ERR(statp)) {
+		err = PTR_ERR(statp);
+		if (__put_user(err, &dirent->dp_stat_err))
+			goto efault;
+	}
+	else {
+		if (__put_user(err, &dirent->dp_stat_err))
+			goto efault;
+#ifdef __ARCH_WANT_STAT64
+		if (cp_new_stat64(statp, &dirent->dp_stat))
+#else
+		if (cp_new_stat(statp, &dirent->dp_stat))
+#endif
+			goto efault;
+	}
+	if (__put_user(ino, &dirent->dp_dirent.d_ino))
+		goto efault;
+	if (__put_user(0, &dirent->dp_dirent.d_off))
+		goto efault;
+	if (__put_user(reclen, &dirent->dp_dirent.d_reclen))
+		goto efault;
+	if (__put_user(d_type, &dirent->dp_dirent.d_type))
+		goto efault;
+	if (copy_to_user(dirent->dp_dirent.d_name, name, namlen))
+		goto efault;
+	if (__put_user(0, dirent->dp_dirent.d_name + namlen))
+		goto efault;
+	buf->previous = dirent;
+	dirent = (void __user *)dirent + reclen;
+	buf->current_dir = dirent;
+	buf->count -= reclen;
+	return 0;
+efault:
+	buf->error = -EFAULT;
+	return -EFAULT;
+}
+
+asmlinkage long sys_getdents64_plus(unsigned int fd, struct linux_dirent64_plus __user * dirent, unsigned int count)
+{
+	struct file * file;
+	struct linux_dirent64_plus __user * lastdirent;
+	struct getdentsplus_callback64 buf;
+	int error;
+
+	error = -EFAULT;
+	if (!access_ok(VERIFY_WRITE, dirent, count))
+		goto out;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.current_dir = dirent;
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+
+	error = vfs_readdirplus(file, filldir64_plus, &buf);
+	if (error < 0)
+		goto out_putf;
+	error = buf.error;
+	lastdirent = buf.previous;
+	if (lastdirent) {
+		typeof(lastdirent->dp_dirent.d_off) d_off = file->f_pos;
+		error = -EFAULT;
+		if (__put_user(d_off, &lastdirent->dp_dirent.d_off))
+			goto out_putf;
+		error = count - buf.count;
+	}
+
+out_putf:
+	fput(file);
+out:
+	return error;
+}
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/fs/stat.c vanilla-new/fs/stat.c
--- vanilla/fs/stat.c	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/fs/stat.c	2006-05-11 13:35:08.000000000 -0500
@@ -297,7 +297,7 @@
 
 #endif /* __ARCH_WANT_OLD_STAT */
 
-static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
+int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
 {
 	struct stat tmp;
 
@@ -345,7 +345,7 @@
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-static int cp_new_statlite(struct kstat_lite *stat_lite, struct stat_lite __user *statlitebuf)
+int cp_new_statlite(struct kstat_lite *stat_lite, struct stat_lite __user *statlitebuf)
 {
 	struct stat_lite tmp;
 
@@ -545,7 +545,7 @@
 /* ---------- LFS-64 ----------- */
 #ifdef __ARCH_WANT_STAT64
 
-static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
+long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
 {
 	struct stat64 tmp;
 
@@ -580,7 +580,7 @@
 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-static long cp_new_stat64_lite(struct kstat_lite *stat_lite, struct stat64_lite __user *statlitebuf)
+long cp_new_stat64_lite(struct kstat_lite *stat_lite, struct stat64_lite __user *statlitebuf)
 {
 	struct stat64_lite tmp;
 
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-i386/dirent.h vanilla-new/include/asm-i386/dirent.h
--- vanilla/include/asm-i386/dirent.h	1969-12-31 18:00:00.000000000 -0600
+++ vanilla-new/include/asm-i386/dirent.h	2006-05-18 19:25:26.000000000 -0500
@@ -0,0 +1,28 @@
+#ifndef _I386_DIRENT_H
+#define _I386_DIRENT_H
+
+#include <asm/stat.h>
+
+struct dirent_plus {
+	struct stat   dp_stat;
+	int           dp_stat_err;
+	struct dirent dp_dirent;
+};
+
+struct dirent64_plus {
+	struct stat64   dp_stat;
+	int             dp_stat_err;
+	struct dirent64 dp_dirent;
+};
+
+#ifdef __KERNEL__
+
+struct linux_dirent64_plus {
+	struct stat64         dp_stat;
+	int                   dp_stat_err;
+	struct linux_dirent64 dp_dirent;
+};
+
+#endif
+
+#endif
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-i386/unistd.h vanilla-new/include/asm-i386/unistd.h
--- vanilla/include/asm-i386/unistd.h	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/include/asm-i386/unistd.h	2006-05-11 14:00:29.000000000 -0500
@@ -324,8 +324,10 @@
 #define __NR_statlite64  316
 #define __NR_lstatlite64 317
 #define __NR_fstatlite64 318
+#define __NR_getdents_plus 319
+#define __NR_getdents64_plus 320
 
-#define NR_syscalls 319
+#define NR_syscalls 321
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-ia64/unistd.h vanilla-new/include/asm-ia64/unistd.h
--- vanilla/include/asm-ia64/unistd.h	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/include/asm-ia64/unistd.h	2006-05-11 14:05:50.000000000 -0500
@@ -290,12 +290,14 @@
 #define __NR_statlite      1299
 #define __NR_lstatlite     1300
 #define __NR_fstatlite     1301
+#define __NR_getdents_plus 1302
+#define __NR_getdents64_plus 1303
 
 #ifdef __KERNEL__
 
 #include <linux/config.h>
 
-#define NR_syscalls			278 /* length of syscall table */
+#define NR_syscalls			280 /* length of syscall table */
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-powerpc/unistd.h vanilla-new/include/asm-powerpc/unistd.h
--- vanilla/include/asm-powerpc/unistd.h	2006-05-05 13:59:14.000000000 -0500
+++ vanilla-new/include/asm-powerpc/unistd.h	2006-05-11 14:14:28.000000000 -0500
@@ -303,8 +303,13 @@
 #define __NR_unshare		282
 #define __NR_openg		283
 #define __NR_openfh		284
+#define __NR_statlite      285
+#define __NR_lstatlite     286
+#define __NR_fstatlite     287
+#define __NR_getdents_plus 288
+#define __NR_getdents64_plus 289
 
-#define __NR_syscalls		285
+#define __NR_syscalls		290
 
 #ifdef __KERNEL__
 #define __NR__exit __NR_exit
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-x86_64/dirent.h vanilla-new/include/asm-x86_64/dirent.h
--- vanilla/include/asm-x86_64/dirent.h	1969-12-31 18:00:00.000000000 -0600
+++ vanilla-new/include/asm-x86_64/dirent.h	2006-05-18 19:25:47.000000000 -0500
@@ -0,0 +1,28 @@
+#ifndef _ASM_X86_64_DIRENT_H
+#define _ASM_X86_64_DIRENT_H
+
+#include <asm/stat.h>
+
+struct dirent_plus {
+	struct stat   dp_stat;
+	int           dp_stat_err;
+	struct dirent dp_dirent;
+};
+
+struct dirent64_plus {
+	struct stat     dp_stat;
+	int             dp_stat_err;
+	struct dirent64 dp_dirent;
+};
+
+#ifdef __KERNEL__
+
+struct linux_dirent64_plus {
+	struct stat           dp_stat;
+	int                   dp_stat_err;
+	struct linux_dirent64 dp_dirent;
+};
+
+#endif
+
+#endif
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-x86_64/unistd.h vanilla-new/include/asm-x86_64/unistd.h
--- vanilla/include/asm-x86_64/unistd.h	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/include/asm-x86_64/unistd.h	2006-05-11 14:04:27.000000000 -0500
@@ -615,8 +615,12 @@
 __SYSCALL(__NR_newlstatlite, sys_newlstatlite)
 #define __NR_newfstatlite  277
 __SYSCALL(__NR_newfstatlite, sys_newfstatlite)
+#define __NR_getdents_plus 278
+__SYSCALL(__NR_getdents_plus, sys_getdents_plus)
+#define __NR_getdents64_plus 279
+__SYSCALL(__NR_getdents64_plus, sys_getdents64_plus)
 
-#define __NR_syscall_max __NR_newfstatlite
+#define __NR_syscall_max __NR_getdents64_plus
 
 #ifndef __NO_STUBS
 
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/linux/dirent.h vanilla-new/include/linux/dirent.h
--- vanilla/include/linux/dirent.h	2006-03-19 23:53:29.000000000 -0600
+++ vanilla-new/include/linux/dirent.h	2006-05-18 19:29:03.000000000 -0500
@@ -28,5 +28,6 @@
 
 #endif	/* __KERNEL__ */
 
+#include <asm/dirent.h>
 
 #endif
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/linux/fs.h vanilla-new/include/linux/fs.h
--- vanilla/include/linux/fs.h	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/include/linux/fs.h	2006-05-18 19:28:16.000000000 -0500
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <linux/limits.h>
 #include <linux/ioctl.h>
+#include <linux/unistd.h>
 
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
@@ -951,6 +952,13 @@
  */
 typedef int (*filldir_t)(void *, const char *, int, loff_t, ino_t, unsigned);
 
+/*
+ * This is the "filldirplus" function type, used by readdirplus() to let
+ * the kernel specify the kind of dirent layout and the stat information
+ * all in one shot
+ */
+typedef int (*filldirplus_t)(void *, const char *, int, loff_t, ino_t, unsigned, struct kstat *);
+
 struct block_device_operations {
 	int (*open) (struct inode *, struct file *);
 	int (*release) (struct inode *, struct file *);
@@ -1025,6 +1033,7 @@
 	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
 	ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
 	int (*readdir) (struct file *, void *, filldir_t);
+	int (*readdirplus) (struct file *, void *, filldirplus_t);
 	unsigned int (*poll) (struct file *, struct poll_table_struct *);
 	int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
 	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
@@ -1712,7 +1721,13 @@
 void inode_set_bytes(struct inode *inode, loff_t bytes);
 
 extern int vfs_readdir(struct file *, filldir_t, void *);
-
+extern int vfs_readdirplus(struct file *, filldirplus_t, void *);
+extern int cp_new_stat(struct kstat *stat, struct stat __user *statbuf);
+extern int cp_new_statlite(struct kstat_lite *stat_lite, struct stat_lite __user *statlitebuf);
+#ifdef __ARCH_WANT_STAT64
+extern long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf);
+extern long cp_new_stat64_lite(struct kstat_lite *stat_lite, struct stat64_lite __user *statlitebuf);
+#endif
 extern int vfs_stat(char __user *, struct kstat *);
 extern int vfs_statlite(char __user *, struct kstat_lite *);
 extern int vfs_lstat(char __user *, struct kstat *);
diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/linux/syscalls.h vanilla-new/include/linux/syscalls.h
--- vanilla/include/linux/syscalls.h	2006-05-09 18:53:48.000000000 -0500
+++ vanilla-new/include/linux/syscalls.h	2006-05-11 14:01:51.000000000 -0500
@@ -22,6 +22,8 @@
 struct kexec_segment;
 struct linux_dirent;
 struct linux_dirent64;
+struct linux_dirent_plus;
+struct linux_dirent64_plus;
 struct list_head;
 struct msgbuf;
 struct msghdr;
@@ -418,6 +420,12 @@
 asmlinkage long sys_getdents64(unsigned int fd,
 				struct linux_dirent64 __user *dirent,
 				unsigned int count);
+asmlinkage long sys_getdents_plus(unsigned int fd,
+				struct linux_dirent_plus __user *dirent,
+				unsigned int count);
+asmlinkage long sys_getdents64_plus(unsigned int fd,
+				struct linux_dirent64_plus __user *dirent,
+				unsigned int count);
 
 asmlinkage long sys_setsockopt(int fd, int level, int optname,
 				char __user *optval, int optlen);
