[Pvfs2-cvs] commit by slang in pvfs2/patches/posix-ext: SERIES posix-direntplus-lite.patch posix-direntplus.patch posix-extensions-cvs.patch posix-readwritex.patch posix-statlite-fix.patch posix-statlite-x86_64.patch posix-statlite.patch

CVS commit program cvs at parl.clemson.edu
Mon Jan 7 17:27:26 EST 2008


Update of /projects/cvsroot/pvfs2/patches/posix-ext
In directory parlweb1:/tmp/cvs-serv26113/posix-ext

Added Files:
	SERIES posix-direntplus-lite.patch posix-direntplus.patch 
	posix-extensions-cvs.patch posix-readwritex.patch 
	posix-statlite-fix.patch posix-statlite-x86_64.patch 
	posix-statlite.patch 
Log Message:
Added Dean's cleaned up pNFS patches for PVFS to the patches directory, along with a brief description of each.  Thanks Dean!  Moved the posix extensions patches to a subdir.


--- /dev/null	2004-06-24 14:04:38.000000000 -0400
+++ SERIES	2008-01-07 17:27:26.000000000 -0500
@@ -0,0 +1,24 @@
+Apply the patches to a vanilla 2.6.16 kernel in the following order
+
+a) posix-extensions-cvs.patch : This implements the sys call stubs for
+   openg/openfh and the VFS hooks for file system specific implementations.
+
+b) posix-statlite.patch : This implements the sys call stubs for the statlite()
+   family of system calls and the VFS hooks for file system specific
+   implementations.
+
+c) posix-statlite-x86_64.patch : Bug fix/build fix patch for the x86-64 machine.
+
+d) posix-direntplus.patch: This implements the sys call stubs for the
+   readdir_plus() family of system calls and the corresponding VFS hooks for FS
+   specific implementations.
+
+e) posix-readwritex.patch: Implements the sys call stubs for the readx/writex
+   family of system calls and the corresponding VFS hooks for FS specific
+   implementations.
+
+f) posix-statlite-fix.patch: Bug fix for the statlite system call.
+
+g) posix-direntplus-lite.patch: Implements the syscall stubs for the
+   readdir_plus_lite() family of system calls and the corresponding VFS hooks
+   for FS specific implementations.

--- /dev/null	2004-06-24 14:04:38.000000000 -0400
+++ posix-direntplus-lite.patch	2008-01-07 17:27:26.000000000 -0500
@@ -0,0 +1,441 @@
+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-08-29 17:56:17.000000000 -0500
++++ vanilla-new/arch/i386/kernel/syscall_table.S	2006-09-04 05:03:44.000000000 -0500
+@@ -322,3 +322,5 @@
+ 	.long sys_getdents64_plus /* 320 */
+ 	.long sys_readx
+ 	.long sys_writex
++	.long sys_getdents_plus_lite
++	.long sys_getdents64_plus_lite
+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-05-24 16:19:07.000000000 -0500
++++ vanilla-new/fs/readdir.c	2006-09-04 04:49:14.000000000 -0500
+@@ -69,6 +69,33 @@
+ 
+ EXPORT_SYMBOL_GPL(vfs_readdirplus);
+ 
++int vfs_readdirplus_lite(struct file *file, unsigned long lite_mask,
++		filldirpluslite_t fillerpluslite, void *buf)
++{
++	struct inode *inode = file->f_dentry->d_inode;
++	int res = -ENOTDIR;
++	if (!file->f_op || !file->f_op->readdirplus_lite)
++		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_lite(file, lite_mask, buf, fillerpluslite);
++		file_accessed(file);
++	}
++	mutex_unlock(&inode->i_mutex);
++out:
++	if (file->f_op && file->f_op->readdir && !file->f_op->readdirplus_lite)
++		res = -EOPNOTSUPP;
++	return res;
++}
++
++EXPORT_SYMBOL_GPL(vfs_readdirplus_lite);
++
+ /*
+  * Traditional linux readdir() handling..
+  *
+@@ -343,6 +370,112 @@
+ 	return error;
+ }
+ 
++/* getdents_plus_lite implementation */
++#define DIRENT_OFFSET(de) ((unsigned long) &((de)->dp_dirent) - (unsigned long) (char __user *) (de))
++
++struct linux_dirent_plus_lite {
++	struct stat_lite     dp_stat_lite;
++	int                  dp_stat_lite_err;
++	struct linux_dirent  dp_dirent;
++};
++
++struct getdentspluslite_callback {
++	struct linux_dirent_plus_lite __user * current_dir;
++	struct linux_dirent_plus_lite __user * previous;
++	int count;
++	int error;
++};
++
++static int filldirpluslite(void * __buf, const char * name, int namlen, loff_t offset,
++		   ino_t ino, unsigned int d_type, struct kstat_lite *statp)
++{
++	struct linux_dirent __user *de;
++	struct linux_dirent_plus_lite __user * dirent;
++	struct getdentspluslite_callback * buf = (struct getdentspluslite_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_lite_err))
++			goto efault;
++	}
++	else {
++		if (__put_user(err, &dirent->dp_stat_lite_err))
++			goto efault;
++		if (cp_new_statlite(statp, &dirent->dp_stat_lite))
++			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_lite(unsigned int fd, unsigned long lite_mask, 
++		struct linux_dirent_plus_lite __user * dirent, unsigned int count)
++{
++	struct file * file;
++	struct linux_dirent_plus_lite __user * lastdirent;
++	struct getdentspluslite_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_lite(file, lite_mask, filldirpluslite, &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 {
+@@ -531,3 +664,106 @@
+ out:
+ 	return error;
+ }
++
++struct getdentspluslite_callback64 {
++	struct linux_dirent64_plus_lite __user * current_dir;
++	struct linux_dirent64_plus_lite __user * previous;
++	int count;
++	int error;
++};
++
++static int filldir64_plus_lite(void * __buf, const char * name, int namlen, loff_t offset,
++		     ino_t ino, unsigned int d_type, struct kstat_lite *statp)
++{
++	struct linux_dirent64 __user *de;
++	struct linux_dirent64_plus_lite __user *dirent;
++	struct getdentspluslite_callback64 * buf = (struct getdentspluslite_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_lite_err))
++			goto efault;
++	}
++	else {
++		if (__put_user(err, &dirent->dp_stat_lite_err))
++			goto efault;
++#ifdef __ARCH_WANT_STAT64
++		if (cp_new_stat64_lite(statp, &dirent->dp_stat_lite))
++#else
++		if (cp_new_statlite(statp, &dirent->dp_stat_lite))
++#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_lite(unsigned int fd, unsigned long lite_mask, 
++		struct linux_dirent64_plus_lite __user * dirent, unsigned int count)
++{
++	struct file * file;
++	struct linux_dirent64_plus_lite __user * lastdirent;
++	struct getdentspluslite_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_lite(file, lite_mask, filldir64_plus_lite, &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/include/asm-i386/dirent.h vanilla-new/include/asm-i386/dirent.h
+--- vanilla/include/asm-i386/dirent.h	2006-05-24 16:19:07.000000000 -0500
++++ vanilla-new/include/asm-i386/dirent.h	2006-09-04 04:59:36.000000000 -0500
+@@ -9,12 +9,24 @@
+ 	struct dirent dp_dirent;
+ };
+ 
++struct dirent_plus_lite {
++	struct stat_lite dp_stat_lite;
++	int              dp_stat_lite_err;
++	struct dirent    dp_dirent;
++};
++
+ struct dirent64_plus {
+ 	struct stat64   dp_stat;
+ 	int             dp_stat_err;
+ 	struct dirent64 dp_dirent;
+ };
+ 
++struct dirent64_plus_lite {
++	struct stat64_lite   dp_stat_lite;
++	int                  dp_stat_lite_err;
++	struct dirent64 	   dp_dirent;
++};
++
+ #ifdef __KERNEL__
+ 
+ struct linux_dirent64_plus {
+@@ -23,6 +35,12 @@
+ 	struct linux_dirent64 dp_dirent;
+ };
+ 
++struct linux_dirent64_plus_lite {
++	struct stat64_lite    dp_stat_lite;
++	int                   dp_stat_lite_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-08-29 17:56:17.000000000 -0500
++++ vanilla-new/include/asm-i386/unistd.h	2006-09-04 05:04:09.000000000 -0500
+@@ -328,8 +328,10 @@
+ #define __NR_getdents64_plus 320
+ #define __NR_readx      321
+ #define __NR_writex     322
++#define __NR_getdents_plus_lite 323
++#define __NR_getdents64_plus_lite 324
+ 
+-#define NR_syscalls 323
++#define NR_syscalls 325
+ 
+ /*
+  * 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-x86_64/dirent.h vanilla-new/include/asm-x86_64/dirent.h
+--- vanilla/include/asm-x86_64/dirent.h	2006-05-24 16:19:07.000000000 -0500
++++ vanilla-new/include/asm-x86_64/dirent.h	2006-09-04 04:57:56.000000000 -0500
+@@ -9,12 +9,24 @@
+ 	struct dirent dp_dirent;
+ };
+ 
++struct dirent_plus_lite {
++	struct stat_lite dp_stat_lite;
++	int              dp_stat_lite_err;
++	struct dirent    dp_dirent;
++};
++
+ struct dirent64_plus {
+ 	struct stat     dp_stat;
+ 	int             dp_stat_err;
+ 	struct dirent64 dp_dirent;
+ };
+ 
++struct dirent64_plus_lite {
++	struct stat_lite dp_stat_lite;
++	int              dp_stat_lite_err;
++	struct dirent64  dp_dirent;
++};
++
+ #ifdef __KERNEL__
+ 
+ struct linux_dirent64_plus {
+@@ -23,6 +35,12 @@
+ 	struct linux_dirent64 dp_dirent;
+ };
+ 
++struct linux_dirent64_plus_lite {
++	struct stat_lite      dp_stat_lite;
++	int                   dp_stat_lite_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-08-29 17:56:17.000000000 -0500
++++ vanilla-new/include/asm-x86_64/unistd.h	2006-09-04 05:04:44.000000000 -0500
+@@ -623,8 +623,12 @@
+ __SYSCALL(__NR_readx, sys_readx)
+ #define __NR_writex 281
+ __SYSCALL(__NR_writex, sys_writex)
++#define __NR_getdents_plus_lite 282
++__SYSCALL(__NR_getdents_plus_lite, sys_getdents_plus_lite)
++#define __NR_getdents64_plus_lite 283
++__SYSCALL(__NR_getdents64_plus_lite, sys_getdents64_plus_lite)
+ 
+-#define __NR_syscall_max __NR_writex
++#define __NR_syscall_max __NR_getdents64_plus_lite
+ 
+ #ifndef __NO_STUBS
+ 
+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-08-29 17:56:17.000000000 -0500
++++ vanilla-new/include/linux/fs.h	2006-09-04 04:55:48.000000000 -0500
+@@ -957,6 +957,13 @@
+  */
+ typedef int (*filldirplus_t)(void *, const char *, int, loff_t, ino_t, unsigned, struct kstat *);
+ 
++/* 
++ * This is the "filldirplus_lite function type, used by readdirplus_lite() to let
++ * the kernel specify the kind of dirent layout and the stat_lite information
++ * all in one shot
++ */
++typedef int (*filldirpluslite_t)(void *, const char *, int, loff_t, ino_t, unsigned, struct kstat_lite *);
++
+ struct block_device_operations {
+ 	int (*open) (struct inode *, struct file *);
+ 	int (*release) (struct inode *, struct file *);
+@@ -1032,6 +1039,7 @@
+ 	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);
++	int (*readdirplus_lite) (struct file *, unsigned long, void *, filldirpluslite_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);
+@@ -1728,6 +1736,7 @@
+ 
+ extern int vfs_readdir(struct file *, filldir_t, void *);
+ extern int vfs_readdirplus(struct file *, filldirplus_t, void *);
++extern int vfs_readdirplus_lite(struct file *file, unsigned long, filldirpluslite_t fillerpluslite, void *buf);
+ 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
+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-08-29 17:56:17.000000000 -0500
++++ vanilla-new/include/linux/syscalls.h	2006-09-04 05:00:20.000000000 -0500
+@@ -25,6 +25,8 @@
+ struct linux_dirent64;
+ struct linux_dirent_plus;
+ struct linux_dirent64_plus;
++struct linux_dirent_plus_lite;
++struct linux_dirent64_plus_lite;
+ struct list_head;
+ struct msgbuf;
+ struct msghdr;
+@@ -434,9 +436,15 @@
+ asmlinkage long sys_getdents_plus(unsigned int fd,
+ 				struct linux_dirent_plus __user *dirent,
+ 				unsigned int count);
++asmlinkage long sys_getdents_plus_lite(unsigned int fd, unsigned long lite_mask,
++				struct linux_dirent_plus_lite __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_getdents64_plus_lite(unsigned int fd, unsigned long lite_mask,
++				struct linux_dirent64_plus_lite __user *dirent,
++				unsigned int count);
+ 
+ asmlinkage long sys_setsockopt(int fd, int level, int optname,
+ 				char __user *optval, int optlen);

--- /dev/null	2004-06-24 14:04:38.000000000 -0400
+++ posix-direntplus.patch	2008-01-07 17:27:26.000000000 -0500
@@ -0,0 +1,555 @@
+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);

--- /dev/null	2004-06-24 14:04:38.000000000 -0400
+++ posix-extensions-cvs.patch	2008-01-07 17:27:26.000000000 -0500
@@ -0,0 +1,1038 @@
+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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/arch/i386/kernel/syscall_table.S	2006-04-07 10:28:39.000000000 -0500
+@@ -310,3 +310,5 @@
+ 	.long sys_pselect6
+ 	.long sys_ppoll
+ 	.long sys_unshare		/* 310 */
++	.long sys_openg
++	.long sys_openfh
+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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/arch/ia64/kernel/entry.S	2006-04-07 10:28:39.000000000 -0500
+@@ -1619,5 +1619,7 @@
+ 	data8 sys_ni_syscall			// reserved for pselect
+ 	data8 sys_ni_syscall			// 1295 reserved for ppoll
+ 	data8 sys_unshare
++	data8 sys_openg
++	data8 sys_openfh
+ 
+ 	.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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/arch/powerpc/kernel/systbl.S	2006-04-07 10:28:39.000000000 -0500
+@@ -322,3 +322,5 @@
+ COMPAT_SYS(pselect6)
+ COMPAT_SYS(ppoll)
+ SYSCALL(unshare)
++SYSCALL(openg)
++SYSCALL(openfh)
+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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/arch/x86_64/ia32/ia32entry.S	2006-04-07 10:28:39.000000000 -0500
+@@ -688,6 +688,8 @@
+ 	.quad sys_ni_syscall		/* pselect6 for now */
+ 	.quad sys_ni_syscall		/* ppoll for now */
+ 	.quad sys_unshare		/* 310 */
++	.quad compat_sys_openg
++	.quad compat_sys_openfh
+ 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/compat.c vanilla-new/fs/compat.c
+--- vanilla/fs/compat.c	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/fs/compat.c	2006-04-07 13:39:13.000000000 -0500
+@@ -1332,6 +1332,27 @@
+ }
+ 
+ /*
++ * Exactly like fs/open.c: sys_openg(), except that it doesn't set the 
++ * O_LARGEFILE flag.
++ */
++asmlinkage long
++compat_sys_openg(const char __user *pathname, void __user *uhandle, size_t __user *uhandle_len,
++		int flags, int mode)
++{
++	return do_sys_openg(pathname, uhandle, uhandle_len, flags, mode);
++}
++
++/*
++ * Exactly like fs/open.c: sys_openg(), except that it doesn't set the 
++ * O_LARGEFILE flag.
++ */
++asmlinkage long
++compat_sys_openfh(const char __user *uhandle, int uhandle_len)
++{
++	return do_sys_openfh(uhandle, uhandle_len);
++}
++
++/*
+  * compat_count() counts the number of arguments/envelopes. It is basically
+  * a copy of count() from fs/exec.c, except that it works with 32 bit argv
+  * and envp pointers.
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/fs/open.c vanilla-new/fs/open.c
+--- vanilla/fs/open.c	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/fs/open.c	2006-04-26 22:06:15.000000000 -0500
+@@ -27,9 +27,37 @@
+ #include <linux/pagemap.h>
+ #include <linux/syscalls.h>
+ #include <linux/rcupdate.h>
++#include <linux/scatterlist.h>
++#include <linux/crypto.h>
++#include <linux/types.h>
+ 
+ #include <asm/unistd.h>
+ 
++void get_filesystem(struct file_system_type *fs);
++void put_filesystem(struct file_system_type *fs);
++struct file_system_type *get_fs_type(const char *name);
++
++int vfs_statfs_lite(struct super_block *sb, struct kstatfs *buf, int statfs_mask)
++{
++	int retval = -ENODEV;
++
++	if (sb) {
++		retval = -ENOSYS;
++		if (sb->s_op->statfs_lite) {
++			memset(buf, 0, sizeof(*buf));
++			retval = security_sb_statfs(sb);
++			if (retval)
++				return retval;
++			retval = sb->s_op->statfs_lite(sb, buf, statfs_mask);
++			if (retval == 0 && buf->f_frsize == 0 && (statfs_mask & STATFS_M_FRSIZE) != 0)
++				buf->f_frsize = buf->f_bsize;
++		}
++	}
++	return retval;
++}
++
++EXPORT_SYMBOL(vfs_statfs_lite);
++
+ int vfs_statfs(struct super_block *sb, struct kstatfs *buf)
+ {
+ 	int retval = -ENODEV;
+@@ -1100,6 +1128,638 @@
+ }
+ EXPORT_SYMBOL_GPL(sys_openat);
+ 
++static unsigned int diff(struct timeval *end, struct timeval *begin)
++{
++    if (end->tv_usec < begin->tv_usec) {
++        end->tv_usec += 1000000; end->tv_sec--;
++    }
++    end->tv_sec  -= begin->tv_sec;
++    end->tv_usec -= begin->tv_usec;
++    return ((end->tv_sec * 1000000) + (end->tv_usec));
++}
++
++/*
++ * Compute a simple crc checksum
++ */
++static inline __u32 simple_crc_csum(struct file_handle *fhandle)
++{
++	struct file_handle_generic *fhg;
++	__le32 *u;
++	__u8 *c;
++	__u32 i, j;
++	
++	fhg = &fhandle->fh_generic;
++	/* upto and not including the fhg_crc_csum field */
++	for (i = 0, u = (__le32 *) fhg; u < (__le32 *)(&fhg->fhg_crc_csum); ++u)
++		i += le32_to_cpup(u);
++	/* and over the entire fh_private buffer */
++	c = (__u8 *) fhandle->fh_private;
++	for (j = 0; j < fhandle->fh_private_length; ++j) 
++		i += *(c + j);
++	return i;
++}
++
++/*
++ * Compute and return a crc32c checksum using the crypto subsystem
++ * API
++ */
++static __u32 compute_crc32_csum(struct file_handle *fhandle)
++{
++#define MAX_SG_LIST 8
++	__u32 csum;
++	__u32 i;
++	struct crypto_tfm *tfm;
++	struct scatterlist sg[MAX_SG_LIST];
++	struct timeval begin, end;
++
++	do_gettimeofday(&begin);
++	if (crypto_alg_available("crc32c", 0) == 0) {
++		csum = simple_crc_csum(fhandle);
++		do_gettimeofday(&end);
++		printk(KERN_DEBUG "compute_crc32_csum[simple]: took %d usecs\n", diff(&end, &begin));
++		goto out;
++	}
++
++	tfm = crypto_alloc_tfm("crc32c", 0);
++	if (tfm == NULL) {
++		csum = simple_crc_csum(fhandle);
++		goto out;
++	}
++
++	crypto_digest_init(tfm);
++
++	i = 0;
++	sg_set_buf(&sg[i++], &fhandle->fh_generic, 
++			offsetof(struct file_handle_generic, fhg_crc_csum));
++	sg_set_buf(&sg[i++], fhandle->fh_private, fhandle->fh_private_length);
++
++	crypto_digest_update(tfm, sg, i);
++	crypto_digest_final(tfm, (__u8*)&csum);
++	crypto_free_tfm(tfm);
++	do_gettimeofday(&end);
++	printk(KERN_DEBUG "compute_crc32_csum[tfm]: took %d usecs\n", diff(&end, &begin));
++out:
++	return csum;
++#undef MAX_SG_LIST
++}
++
++/* 
++ * Store a crc32 check sum into the handle buffer
++ * NOTE: We expect fhandle->fh_private and fhandle->fh_private_length
++ * to be initialized prior to this call!
++ */
++static inline void store_crc32_csum(struct file_handle *fhandle)
++{
++	/* Compute the CRC checksum over the handle buffer */
++	__u32 csum = compute_crc32_csum(fhandle);
++	/* Set the CRC checksum into the handle buffer */
++	set_fh_field(&fhandle->fh_generic, crc_csum, csum);
++	return;
++}
++
++/* 
++ * Verifies if a file handle's structure's check sum
++ * matches with what user-space indicates.
++ * This should catch most of the simple buffer handle corruption
++ * cases (but not the maliciously crafted ones!) for which
++ * we have the keyed SHA1 (HMAC-SHA1) algorithm verification.
++ * NOTE: We expect fhandle->fh_private and fhandle->fh_private_length
++ * to be initialized prior to this call!
++ * Returns 1 in case verification was successful and 0
++ * otherwise.
++ */
++static inline int verify_crc32_csum(struct file_handle *fhandle)
++{
++	__u32 csum, crc_csum;
++
++	/* Compute the CRC checksum over the handle buffer */
++	csum = compute_crc32_csum(fhandle);
++	/* Retrieve the CRC checksum from the handle buffer */
++	get_fh_field(&fhandle->fh_generic, crc_csum, crc_csum);
++	return (crc_csum == csum);
++}
++
++/* 
++ * Compute a hmac-sha1 crypto check sum using a specified
++ * key and store it in the buffer pointed to by result.
++ * NOTE: We assume that fhandle->fh_private and
++ * fhandle->fh_private_length are initialized prior to this call.
++ * Returns 0 in case SHA1/HMAC-SHA1 was not built-in/compiled
++ * for the kernel
++ * Else returns length of the digest generated.
++ */
++static unsigned int compute_hmac_sha1_csum(struct file_handle *fhandle, 
++		char *key, int keylen, char *result)
++{
++#define MAX_SG_LIST 8
++	__u32 i;
++	struct crypto_tfm *tfm;
++	struct scatterlist sg[MAX_SG_LIST];
++	unsigned int ret;
++	struct timeval begin, end;
++ 
++	do_gettimeofday(&begin);
++
++	/* SHA1 is not available */
++	if (crypto_alg_available("sha1", 0) == 0)
++		return 0;
++
++	tfm = crypto_alloc_tfm("sha1", 0);
++	if (tfm == NULL)
++		return 0;
++
++	i = 0;
++	sg_set_buf(&sg[i++], &fhandle->fh_generic, 
++			offsetof(struct file_handle_generic, fhg_hmac_sha1));
++	sg_set_buf(&sg[i++], fhandle->fh_private, fhandle->fh_private_length);
++
++	crypto_hmac(tfm, key, &keylen, sg, i, result);
++	ret = crypto_tfm_alg_digestsize(tfm);
++	crypto_free_tfm(tfm);
++	do_gettimeofday(&end);
++	printk(KERN_DEBUG "compute_hmac_sha1_csum: took %d usecs\n", diff(&end, &begin));
++	return ret;
++#undef MAX_SG_LIST
++}
++
++/*
++ * Store a hmac-sha1 crypto check sum into the handle
++ * buffer.
++ */
++static inline void store_hmac_csum(struct file_handle *fhandle,
++		char *key, int keylen)
++{
++	compute_hmac_sha1_csum(fhandle, key, keylen,
++			fhandle->fh_generic.fhg_hmac_sha1);
++	return;
++}
++
++/*
++ * Verifies if a file handle buffer's computed hmac-sha1 crypto
++ * check sum matches with whatever the user-space buffer claims
++ * Returns 1 in case verification was succesful and 0
++ * otherwise
++ */
++static int verify_hmac_csum(struct file_handle *fhandle, char *key, int keylen)
++{
++	__u8 result[24];
++	unsigned int result_len;
++
++	result_len = compute_hmac_sha1_csum(fhandle, key, keylen, result);
++	/* Crypto is not supported. deny verification */
++	if (result_len == 0) 
++		return 0;
++
++	/* Check if user has tampered with the buffer */
++	if (memcmp(fhandle->fh_generic.fhg_hmac_sha1, result, result_len) == 0)
++		return 1;
++	return 0;
++}
++
++/*
++ * Copy the constructed file handle to a user-specified buffer.
++ * NOTE: We assume that fhandle->fh_private and
++ * fhandle->fh_private_length have been initialized
++ * prior to this routine
++ */
++static int copy_handle(const void __user *uaddr, struct file_handle *fhandle)
++{
++	char __user *ptr = (char __user *) uaddr;
++	struct timeval begin, end;
++ 
++	do_gettimeofday(&begin);
++
++	/* Copy the VFS generic part of the handle */
++	if (copy_to_user(ptr, &fhandle->fh_generic, 
++				sizeof(struct file_handle_generic)))
++		return -EFAULT;
++
++	/* Advance the user-buffer pointer */
++	ptr += sizeof(struct file_handle_generic);
++	/* Copy the FS specific part of the handle */
++	if (copy_to_user(ptr, fhandle->fh_private, fhandle->fh_private_length))
++		return -EFAULT;
++	do_gettimeofday(&end);
++	printk(KERN_DEBUG "copy_handle: took %d usecs\n", diff(&end, &begin));
++	return 0;
++}
++
++/*
++ * Copy a user-specified handle buffer to a temporary
++ * kernel buffer.
++ */
++static void* move_handle_to_kernel(const void __user *uaddr, 
++		size_t ulen, void *kaddr)
++{
++	if (uaddr != NULL) {
++		if (copy_from_user(kaddr, uaddr, ulen))
++			return ERR_PTR(-EFAULT);
++	}
++	return kaddr;
++}
++
++/*
++ * Copy a specified size user-space handle buffer to a temporary
++ * kernel buffer and return a pointer to the kernel buffer.
++ * Encodes error in return pointer in case 
++ * operation failed for some reason.
++ */
++static void *gethandle(const void __user *uhandle, size_t uhandle_len)
++{
++	void *tmp = NULL, *result = ERR_PTR(-EINVAL);
++	struct timeval begin, end;
++ 
++	do_gettimeofday(&begin);
++
++	do {
++		if (uhandle_len <= 0 || uhandle_len > MAX_HANDLE_LEN) 
++			break;
++		result = ERR_PTR(-ENOMEM);
++		tmp = kmalloc(uhandle_len, GFP_KERNEL);
++		if (tmp == NULL) 
++			break;
++		result = move_handle_to_kernel(uhandle, uhandle_len, tmp);
++	} while (0);
++	do_gettimeofday(&end);
++	printk(KERN_DEBUG "gethandle: took %d usecs\n", diff(&end, &begin));
++	return result;
++}
++/*
++ * Frees memory allocated to a temporary kernel space buffer
++ * used for staging the handle copy from user-space.
++ */
++static void puthandle(void *handle)
++{
++	if (handle)
++		kfree(handle);
++	return;
++}
++
++/*
++ * Wrapper routine to obtain any FS specific keys that can be used
++ * for the HMAC-SHA1 calculation to make the handle returned
++ * by openg() tamper-proof or atleast tamper-detectable.
++ *	We dont use any keys in case FS does not provide one!
++ */
++static void get_fs_key(struct super_block *sb, char **ppkey, int *keylen)
++{
++	struct timeval begin, end;
++
++	*ppkey = NULL;
++	*keylen = 0;
++	do_gettimeofday(&begin);
++	/* underlying fs wishes to provide a key */
++	if (sb && sb->s_op && sb->s_op->get_fs_key)
++		sb->s_op->get_fs_key(sb, ppkey, keylen);
++	do_gettimeofday(&end);
++	printk(KERN_DEBUG "get_fs_key: took %d usecs\n", diff(&end, &begin));
++	return;
++}
++
++/*
++ * Free the memory allocated to fhandle->fh_private.
++ * This is done by either calling the provided destructor
++ * function if any (supplied by fill_handle callback of FS).
++ * or by calling kfree(). We expect FS to either use kmalloc()
++ * or supply a dtor function so that fh_private can be properly
++ * deallocated.
++ */
++static void drop_file_handle_private(struct file_handle *fhandle)
++{
++	if (!fhandle || !fhandle->fh_private)
++		return;
++	if (fhandle->fh_private_dtor) 
++		fhandle->fh_private_dtor(fhandle->fh_private);
++	else 
++		kfree(fhandle->fh_private);
++	fhandle->fh_private = NULL;
++	return;
++}
++
++/*
++ * Associate and establish a file handle to a struct file mapping.
++ * NOTE: Linux VFS is inherently based off a dentry cache model
++ * and since we dont have any pathnames/filenames we need to create a anon.
++ * dentry to represent files opened using this system call.
++ */
++static struct file *do_fh_open(const void *handle, size_t handle_len)
++{
++	struct file *filp = NULL;
++	struct super_block *sb;
++	struct inode *inode = NULL;
++	struct file_handle fhandle;
++	size_t min_len = sizeof(struct file_handle_generic);
++	char *key = NULL;
++	int   keylen = 0;
++	struct timeval begin, end;
++	
++	/* Do some sanity checks on the handle lengths and handle buffer */
++	if (handle_len <= min_len)
++		return ERR_PTR(-EINVAL);
++
++	memcpy(&fhandle.fh_generic, handle, min_len);
++	/* set the fields of the file handle prior to verification */
++	fhandle.fh_private = (char *) handle + min_len;
++	fhandle.fh_private_length = (handle_len - min_len);
++	fhandle.fh_private_dtor = NULL;
++	/* verify crc32 checksum on the handle buffer */
++	if (!verify_crc32_csum(&fhandle))
++		return ERR_PTR(-EACCES);
++
++	/*
++	 * Verification of HMAC SHA1 csum on the handle buffer cannot be 
++	 * done at this point  since we don't know which file
++	 * system/superblock it belongs to.
++	 */
++
++	/* Locate and get an active reference to a 
++	 * super-block that matches a given handle 
++	 */
++	do_gettimeofday(&begin);
++	sb = get_sb_handle(&fhandle);
++	/* could not find any valid FS that owns this handle */
++	if (!sb)
++		return ERR_PTR(-EINVAL);
++
++	do_gettimeofday(&end);
++	printk(KERN_DEBUG "get_sb_handle: took %d usecs\n", diff(&end, &begin));
++	/* FS has not implemented a routine to query inode based on handle */
++	if (!sb->s_op || !sb->s_op->find_inode_handle) {
++		filp = ERR_PTR(-EOPNOTSUPP);
++		goto out;
++	}
++	/* Check if underlying FS wishes to use a key */
++	get_fs_key(sb, &key, &keylen);
++	/* and verify the authenticity of the handle buffer */
++	if (verify_hmac_csum(&fhandle, key, keylen) == 0) {
++		/* Permission denied */
++		filp = ERR_PTR(-EACCES);
++		goto out;
++	}
++	do_gettimeofday(&begin);
++	/* find an inode or allocate/lookup an inode based on the handle */
++	inode = sb->s_op->find_inode_handle(sb, &fhandle);
++	if (!IS_ERR(inode)) {
++		struct dentry *anon_dentry;
++		int flags = 0;
++
++		do_gettimeofday(&end);
++		printk(KERN_DEBUG "s_op->find_inode_handle: took %d usecs\n", diff(&end, &begin));
++
++		get_fh_field(&fhandle.fh_generic, flags, flags);
++		/* 
++		 * Associate a anonymous dentry to this inode in case there is none.
++		 * d_prune_aliases() will take care of freeeing all these dentries
++		 * which is called when the last reference to iput() calls
++		 * put_inode() which in turn calls the above function.
++		 */
++		do_gettimeofday(&begin);
++		anon_dentry = d_alloc_anon(inode);
++		if (anon_dentry == NULL) {
++			filp = ERR_PTR(-ENOMEM);
++			goto drop_inode;
++		}
++		/* and setup file and inode mapping */
++		filp = get_empty_filp();
++		if (filp == NULL) {
++			filp = ERR_PTR(-ENFILE);
++			goto drop_dentry;
++		}
++		filp = __dentry_open(anon_dentry, NULL, flags, filp, NULL);
++		if (IS_ERR(filp)) {
++			/* in case of error __dentry_open drops the anon_dentry */
++			goto drop_inode;
++	drop_dentry:
++			dput(anon_dentry);
++	drop_inode:
++			iput(inode);
++		}
++		else {
++			do_gettimeofday(&end);
++			printk(KERN_DEBUG "d_alloc_anon + misc.: took %d usecs\n", diff(&end, &begin));
++		}
++	}
++	else {
++		/* in case of error */
++		filp = ERR_PTR(PTR_ERR(inode));
++	}
++out:
++	/* drop our active reference to sb */
++	drop_super(sb);
++	return filp;
++}
++
++long do_sys_openfh(const void __user *uhandle, size_t handle_len)
++{
++	void *tmp = gethandle(uhandle, handle_len);
++	int fd = PTR_ERR(tmp);
++
++	if (!IS_ERR(tmp)) {
++		struct timeval begin, end;
++
++		do_gettimeofday(&begin);
++		fd = get_unused_fd();
++		do_gettimeofday(&end);
++		printk(KERN_DEBUG "get_unused_fd: took %d usecs\n", diff(&end, &begin));
++		if (fd >= 0) {
++			struct file *f;
++
++			do_gettimeofday(&begin);
++			f = do_fh_open(tmp, handle_len);
++			if (IS_ERR(f)) {
++				put_unused_fd(fd);
++				fd = PTR_ERR(f);
++			} else {
++				do_gettimeofday(&end);
++				printk(KERN_DEBUG "do_fh_open: took %d usecs\n", diff(&end, &begin));
++				do_gettimeofday(&begin);
++				/* this file descriptor needs to be closed on exec */
++				set_close_on_exec(fd, 1);
++				fd_install(fd, f);
++				do_gettimeofday(&end);
++				printk(KERN_DEBUG "set_close, fd_install: took %d usecs\n", diff(&end, &begin));
++			}
++		}
++		puthandle(tmp);
++	}
++	return fd;
++}
++
++asmlinkage long sys_openfh(const void __user *uhandle, size_t handle_len)
++{
++	return do_sys_openfh(uhandle, handle_len);
++}
++
++EXPORT_SYMBOL_GPL(sys_openfh);
++
++long do_sys_openg(const char __user *pathname, void __user *uhandle,
++		size_t __user *uhandle_len, int flags, int mode)
++{
++	char *tmp = getname(pathname);
++	long err = PTR_ERR(tmp);
++
++	if (!IS_ERR(tmp)) 
++	{
++		struct file *f = NULL;
++		size_t handle_len = 0;
++		size_t min_len = sizeof(struct file_handle_generic);
++		struct file_handle fhandle;
++		struct timeval begin, end;
++
++		memset(&fhandle, 0, sizeof(fhandle));
++		if (get_user(handle_len, uhandle_len)) {
++			err = -EFAULT;
++			goto drop_name;
++		}
++		/* discard bogus values */
++		if (handle_len < 0)
++		{
++			err = -EINVAL;
++			goto drop_name;
++		}
++		/* or definitely insufficient buffer length */
++		else if (handle_len > 0 && 
++				handle_len < min_len)
++		{
++			err = -ERANGE;
++			goto drop_name;
++		}
++		err = 0;
++		do_gettimeofday(&begin);
++		/* Try to open the file now */
++		f = do_filp_open(AT_FDCWD, tmp, flags, mode);
++		if (IS_ERR(f)) {
++			/* File does not exist */
++			err = PTR_ERR(f);
++			goto drop_name;
++		}
++		else {
++			/* Is this even possible? */
++			if (!f->f_dentry || !f->f_dentry->d_inode)
++			{
++				err = -EINVAL;
++				goto drop_filp;
++			}
++			/* Diallow anything but regular files */
++			if (!S_ISREG(f->f_dentry->d_inode->i_mode)) {
++				err = -EACCES;
++				goto drop_filp;
++			}
++			else {
++				/* Does FS define callback for openg? */
++				if (!f->f_dentry->d_inode->i_op->fill_handle) {
++					/* not supported */
++					err = -EOPNOTSUPP;
++					goto drop_filp;
++				}
++				else {
++					do_gettimeofday(&end);
++					printk(KERN_DEBUG "do_filp_open: took %d usecs\n", diff(&end, &begin));
++					fhandle.fh_private = NULL;
++					fhandle.fh_private_length = 
++						handle_len ? (handle_len - min_len)	: 0;
++					fhandle.fh_private_dtor = NULL;
++					/* 
++					 * if handle_len == 0, 
++					 * FS is expected to give us the handle length it needs. 
++					 */
++					do_gettimeofday(&begin);
++					err = f->f_dentry->d_inode->i_op->fill_handle(
++								f->f_dentry->d_inode, &fhandle);
++					if (err)
++						goto drop_filp;
++
++					/* make sure that FS does not set it to an invalid length */
++					if (fhandle.fh_private_length <= 0) {
++						err = -EINVAL;
++						goto drop_private;
++					}
++					
++					/* try to copy the handle if requested */
++					if (handle_len > 0) {
++						__u32 magic, fsid;
++						struct kstatfs st;
++						char *key = NULL;
++						int  keylen = 0, statfs_mask = STATFS_M_TYPE | STATFS_M_FSID;
++						/*
++						 * Check if fhandle.fh_private was not set.
++						 */
++						if (fhandle.fh_private == NULL) {
++							err = -EINVAL;
++							goto drop_filp;
++						}
++						do_gettimeofday(&end);
++						printk(KERN_DEBUG "fill_handle: took %d usecs\n", diff(&end, &begin));
++						/*
++						 * Check if the underlying FS wishes to supply a key for 
++						 * the message authentication code.
++						 * If it does not or in case of errors, we use a NULL key
++						 * for the MAC
++						 */
++						get_fs_key(f->f_dentry->d_inode->i_sb, &key, &keylen);
++						/* 
++						 * Currently, we issue a statfs on the superblock to figure
++						 * out the magic number and fsid for the file system.
++						 * But this might translate to many network messages for many
++						 * distributed/parallel file systems. Therefore, we need a 
++						 * sb->statfs_lite() callback mechanism to get only those
++						 * fields that don't require a network message.
++						 * If FS does not support the callback, fallback to using statfs.
++						 */
++						do_gettimeofday(&begin);
++						if ((err = vfs_statfs_lite(f->f_dentry->d_inode->i_sb, &st, statfs_mask)) < 0) {
++							//err = vfs_statfs(f->f_dentry->d_inode->i_sb, &st);
++							//if (err) 
++								goto drop_private;
++						}
++						do_gettimeofday(&end);
++						printk(KERN_DEBUG "statfs_lite: took %d usecs\n", diff(&end, &begin));
++						magic = st.f_type;
++						memcpy(&fsid, &st.f_fsid, sizeof(__u32));
++						/* set magic number, fsid, flags */
++						set_fh_field(&fhandle.fh_generic, magic, magic);
++						set_fh_field(&fhandle.fh_generic, fsid,  fsid);
++						set_fh_field(&fhandle.fh_generic, flags, flags);
++
++						do_gettimeofday(&begin);
++						/* Compute and store crc check sum */
++						store_crc32_csum(&fhandle);
++						/* Compute and store HMAC-SHA1 crypto check sum */
++						store_hmac_csum(&fhandle, key, keylen);
++						/* copy opaque handle to user buffer */
++						err = copy_handle(uhandle, &fhandle);
++						if (err)
++							goto drop_private;
++						do_gettimeofday(&end);
++						printk(KERN_DEBUG "(crc, hmac, copy_handle): took %d usecs\n", diff(&end, &begin));
++					}
++					/* update the handle length reported to user-space */
++					handle_len = fhandle.fh_private_length + min_len;
++					/* and copy the new length to user space */
++					err = put_user(handle_len, uhandle_len);
++			drop_private:
++					drop_file_handle_private(&fhandle);
++				}
++			}
++drop_filp:
++			filp_close(f, NULL);
++		}
++drop_name:
++		putname(tmp);
++	}
++	return err;
++}
++
++asmlinkage long sys_openg(const char __user *pathname, void __user *uhandle, 
++		size_t __user *uhandle_len, int flags, int mode)
++{
++	if (force_o_largefile())
++		flags |= O_LARGEFILE;
++	return do_sys_openg(pathname, uhandle, uhandle_len, flags, mode);
++}
++
++EXPORT_SYMBOL_GPL(sys_openg);
++
+ #ifndef __alpha__
+ 
+ /*
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/fs/super.c vanilla-new/fs/super.c
+--- vanilla/fs/super.c	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/fs/super.c	2006-04-26 22:06:36.000000000 -0500
+@@ -799,6 +799,58 @@
+ 
+ EXPORT_SYMBOL(get_sb_single);
+ 
++struct super_block *get_sb_handle(const struct file_handle *fhandle)
++{
++	/* walk through the list of superblocks */
++	struct super_block *sb;
++
++	spin_lock(&sb_lock);
++	list_for_each_entry (sb, &super_blocks, s_list) {
++		struct kstatfs st;
++
++		sb->s_count++;
++		spin_unlock(&sb_lock);
++		down_read(&sb->s_umount);
++		if (sb->s_root)
++		{
++			int err, statfs_mask = STATFS_M_TYPE | STATFS_M_FSID;
++			/* 
++			 * Currently, we issue a statfs on the superblock to figure
++			 * out the type and fsid for the file system.
++			 * But this might translate to network messages for many
++			 * distributed/parallel file systems. Therefore, we need a 
++			 * statfs_lite() callback mechanism to get only those
++			 * fields that don't require a network message. We fall back to a
++			 * regular statfs in case the file system does not support a statfs_lite()
++			 * callback.
++			 */
++			if ((err = vfs_statfs_lite(sb, &st, statfs_mask)) < 0) {
++				//err = vfs_statfs(sb, &st);
++			}
++			
++			if (err == 0) {
++				__u32 fsid, magic; 
++
++				get_fh_field(&fhandle->fh_generic, fsid, fsid);
++				get_fh_field(&fhandle->fh_generic, magic, magic);
++				/* check if magic numbers and fsid matches */
++				if (st.f_type == magic
++						&& memcmp(&st.f_fsid, &fsid, sizeof(__u32)) == 0)
++				{
++					return sb;
++				}
++			}
++		}
++		drop_super(sb);
++		spin_lock(&sb_lock);
++	}
++	spin_unlock(&sb_lock);
++	/* This function will not create a new superblock! */
++	return NULL;
++}
++
++EXPORT_SYMBOL_GPL(get_sb_handle);
++
+ struct vfsmount *
+ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
+ {
+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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/asm-i386/unistd.h	2006-04-07 10:28:39.000000000 -0500
+@@ -316,8 +316,10 @@
+ #define __NR_pselect6		308
+ #define __NR_ppoll		309
+ #define __NR_unshare		310
++#define __NR_openg      311
++#define __NR_openfh     312
+ 
+-#define NR_syscalls 311
++#define NR_syscalls 313
+ 
+ /*
+  * 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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/asm-ia64/unistd.h	2006-04-07 10:28:39.000000000 -0500
+@@ -285,12 +285,14 @@
+ #define __NR_faccessat			1293
+ /* 1294, 1295 reserved for pselect/ppoll */
+ #define __NR_unshare			1296
++#define __NR_openg         1297
++#define __NR_openfh        1298
+ 
+ #ifdef __KERNEL__
+ 
+ #include <linux/config.h>
+ 
+-#define NR_syscalls			273 /* length of syscall table */
++#define NR_syscalls			275 /* 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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/asm-powerpc/unistd.h	2006-04-07 10:28:39.000000000 -0500
+@@ -301,8 +301,10 @@
+ #define __NR_pselect6		280
+ #define __NR_ppoll		281
+ #define __NR_unshare		282
++#define __NR_openg		283
++#define __NR_openfh		284
+ 
+-#define __NR_syscalls		283
++#define __NR_syscalls		285
+ 
+ #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/unistd.h vanilla-new/include/asm-x86_64/unistd.h
+--- vanilla/include/asm-x86_64/unistd.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/asm-x86_64/unistd.h	2006-04-07 10:28:39.000000000 -0500
+@@ -605,8 +605,12 @@
+ __SYSCALL(__NR_ppoll,	sys_ni_syscall)		/* for now */
+ #define __NR_unshare		272
+ __SYSCALL(__NR_unshare,	sys_unshare)
++#define __NR_openg      273
++__SYSCALL(__NR_openg,   sys_openg)
++#define __NR_openfh     274
++__SYSCALL(__NR_openfh,  sys_openfh)
+ 
+-#define __NR_syscall_max __NR_unshare
++#define __NR_syscall_max __NR_openfh
+ 
+ #ifndef __NO_STUBS
+ 
+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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/linux/fs.h	2006-04-17 13:35:37.000000000 -0500
+@@ -991,6 +991,27 @@
+ #define HAVE_COMPAT_IOCTL 1
+ #define HAVE_UNLOCKED_IOCTL 1
+ 
++struct file_handle_generic {
++	/* Filled by VFS */
++	__le32   fhg_magic; /* magic number */
++	__le32   fhg_fsid; /* file system identifier */
++	__le32   fhg_flags; 	/* flags associated with the file object */
++	__le32   fhg_crc_csum; /* crc32c check sum of the blob */
++	__u8     fhg_hmac_sha1[24]; /* hmac-sha1 message authentication code */
++};
++
++struct file_handle {
++	/* generic part filled by VFS */
++	struct file_handle_generic fh_generic;
++	/* FS specific part */
++	void                      *fh_private;
++	size_t							fh_private_length;
++	void                      (*fh_private_dtor)(void *);
++};
++
++#define set_fh_field(X, Y, Z) (X)->fhg_##Y = cpu_to_le32(Z)
++#define get_fh_field(X, Y, Z) Z = le32_to_cpu((X)->fhg_##Y)
++
+ /*
+  * NOTE:
+  * read, write, poll, fsync, readv, writev, unlocked_ioctl and compat_ioctl
+@@ -1049,6 +1070,8 @@
+ 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
+ 	int (*removexattr) (struct dentry *, const char *);
+ 	void (*truncate_range)(struct inode *, loff_t, loff_t);
++	/* method needed for filling up handle */
++	int (*fill_handle)(struct inode *, struct file_handle *);
+ };
+ 
+ struct seq_file;
+@@ -1065,12 +1088,12 @@
+  * without the big kernel lock held in all filesystems.
+  */
+ struct super_operations {
+-   	struct inode *(*alloc_inode)(struct super_block *sb);
++   struct inode *(*alloc_inode)(struct super_block *sb);
+ 	void (*destroy_inode)(struct inode *);
+ 
+ 	void (*read_inode) (struct inode *);
+   
+-   	void (*dirty_inode) (struct inode *);
++  	void (*dirty_inode) (struct inode *);
+ 	int (*write_inode) (struct inode *, int);
+ 	void (*put_inode) (struct inode *);
+ 	void (*drop_inode) (struct inode *);
+@@ -1081,6 +1104,7 @@
+ 	void (*write_super_lockfs) (struct super_block *);
+ 	void (*unlockfs) (struct super_block *);
+ 	int (*statfs) (struct super_block *, struct kstatfs *);
++	int (*statfs_lite) (struct super_block *, struct kstatfs *, int statfs_mask);
+ 	int (*remount_fs) (struct super_block *, int *, char *);
+ 	void (*clear_inode) (struct inode *);
+ 	void (*umount_begin) (struct super_block *);
+@@ -1089,6 +1113,8 @@
+ 
+ 	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
+ 	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
++	struct inode *(*find_inode_handle)(struct super_block *, const struct file_handle *);
++	void    (*get_fs_key)(struct super_block *, char **ppkey, int *keylen);
+ };
+ 
+ /* Inode state bits.  Protected by inode_lock. */
+@@ -1257,6 +1283,7 @@
+ struct super_block *get_sb_nodev(struct file_system_type *fs_type,
+ 	int flags, void *data,
+ 	int (*fill_super)(struct super_block *, void *, int));
++struct super_block *get_sb_handle(const struct file_handle *handle);
+ void generic_shutdown_super(struct super_block *sb);
+ void kill_block_super(struct super_block *sb);
+ void kill_anon_super(struct super_block *sb);
+@@ -1292,6 +1319,7 @@
+ 				  struct vfsmount *);
+ 
+ extern int vfs_statfs(struct super_block *, struct kstatfs *);
++extern int vfs_statfs_lite(struct super_block *, struct kstatfs *, int statfs_mask);
+ 
+ /* /sys/fs */
+ extern struct subsystem fs_subsys;
+@@ -1345,6 +1373,10 @@
+ 		       struct file *filp);
+ extern long do_sys_open(int fdf, const char __user *filename, int flags,
+ 			int mode);
++
++extern long do_sys_openfh(const void __user *uhandle, size_t handle_len);
++extern long do_sys_openg(const char __user *pathname, void __user *uhandle, 
++			size_t __user *uhandle_len, int flags, int mode);
+ extern struct file *filp_open(const char *, int, int);
+ extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
+ extern int filp_close(struct file *, fl_owner_t id);
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/linux/limits.h vanilla-new/include/linux/limits.h
+--- vanilla/include/linux/limits.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/linux/limits.h	2006-04-07 17:25:07.000000000 -0500
+@@ -16,6 +16,7 @@
+ #define XATTR_NAME_MAX   255	/* # chars in an extended attribute name */
+ #define XATTR_SIZE_MAX 65536	/* size of an extended attribute value (64k) */
+ #define XATTR_LIST_MAX 65536	/* size of extended attribute namelist (64k) */
++#define MAX_HANDLE_LEN   128  /* maximum size of a handle used by the openfh system call */
+ 
+ #define RTSIG_MAX	  32
+ 
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/linux/statfs.h vanilla-new/include/linux/statfs.h
+--- vanilla/include/linux/statfs.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/linux/statfs.h	2006-04-17 11:38:07.000000000 -0500
+@@ -5,6 +5,18 @@
+ 
+ #include <asm/statfs.h>
+ 
++/* Masks used by statfs_lite callback */
++#define STATFS_M_TYPE  		(1 << 0)
++#define STATFS_M_BSIZE  	(1 << 1)
++#define STATFS_M_BLOCKS		(1 << 2)
++#define STATFS_M_BFREE  	(1 << 3)
++#define STATFS_M_BAVAIL 	(1 << 4)
++#define STATFS_M_FILES  	(1 << 5)
++#define STATFS_M_FFREE  	(1 << 6)
++#define STATFS_M_FSID   	(1 << 7)
++#define STATFS_M_NAMELEN	(1 << 8)
++#define STATFS_M_FRSIZE    (1 << 9)
++
+ struct kstatfs {
+ 	long f_type;
+ 	long f_bsize;
+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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/linux/syscalls.h	2006-04-07 13:56:07.000000000 -0500
+@@ -327,6 +327,10 @@
+ asmlinkage long sys_creat(const char __user *pathname, int mode);
+ asmlinkage long sys_open(const char __user *filename,
+ 				int flags, int mode);
++asmlinkage long sys_openfh(const void __user *uhandle, 
++				size_t handle_len);
++asmlinkage long sys_openg(const char __user *pathname, void __user *uhandle, 
++				size_t *uhandle_len, int flags, int mode);
+ asmlinkage long sys_close(unsigned int fd);
+ asmlinkage long sys_access(const char __user *filename, int mode);
+ asmlinkage long sys_vhangup(void);
+@@ -566,7 +570,10 @@
+ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename,
+ 				      struct compat_stat __user *statbuf,
+ 				      int flag);
++asmlinkage long compat_sys_open(const char __user *filename, int flags, int mode);
+ asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
+ 				   int flags, int mode);
+-
++asmlinkage long compat_sys_openg(const char __user *pathname, void __user *uhandle,
++					size_t __user *uhandle_len, int flags, int mode);
++asmlinkage long compat_sys_openfh(const void __user *uhandle, size_t uhandle_len);
+ #endif

--- /dev/null	2004-06-24 14:04:38.000000000 -0400
+++ posix-readwritex.patch	2008-01-07 17:27:26.000000000 -0500
@@ -0,0 +1,898 @@
+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-24 16:19:07.000000000 -0500
++++ vanilla-new/arch/i386/kernel/syscall_table.S	2006-05-24 16:31:20.000000000 -0500
+@@ -320,3 +320,5 @@
+ 	.long sys_fstatlite64
+ 	.long sys_getdents_plus
+ 	.long sys_getdents64_plus /* 320 */
++	.long sys_readx
++	.long sys_writex
+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-24 16:19:07.000000000 -0500
++++ vanilla-new/arch/ia64/kernel/entry.S	2006-05-24 16:32:28.000000000 -0500
+@@ -1626,5 +1626,7 @@
+ 	data8 sys_newfstatlite
+ 	data8 sys_getdents_plus
+ 	data8 sys_getdents64_plus
++	data8 sys_readx
++	data8 sys_writex
+ 
+ 	.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-24 16:19:07.000000000 -0500
++++ vanilla-new/arch/powerpc/kernel/systbl.S	2006-05-24 16:34:44.000000000 -0500
+@@ -329,3 +329,5 @@
+ SYSCALL(newfstatlite)
+ SYSCALL(sys_getdents_plus)
+ SYSCALL(sys_getdents64_plus)
++SYSCALL(sys_readx)
++SYSCALL(sys_writex)
+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-24 16:19:07.000000000 -0500
++++ vanilla-new/arch/x86_64/ia32/ia32entry.S	2006-05-24 16:32:01.000000000 -0500
+@@ -698,6 +698,8 @@
+ 	.quad sys32_fstatlite64
+ 	.quad sys_ni_syscall   /* getdents_plus */
+ 	.quad sys_ni_syscall   /* getdents64_plus */
++	.quad compat_sys_readx 
++	.quad compat_sys_writex
+ 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/compat.c vanilla-new/fs/compat.c
+--- vanilla/fs/compat.c	2006-05-09 18:53:48.000000000 -0500
++++ vanilla-new/fs/compat.c	2006-05-24 16:26:00.000000000 -0500
+@@ -1344,6 +1344,322 @@
+ 	return ret;
+ }
+ 
++static ssize_t compat_do_readx_writex(int type, struct file *file,
++			       const struct compat_iovec __user * uvector,
++			       unsigned long nr_segs, 
++					 const struct compat_xtvec __user * xtuvector,
++					 unsigned long xtnr_segs)
++{
++	typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
++	typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
++	typedef ssize_t (*iox_fn_t)(struct file *, const struct iovec *, unsigned long, 
++			const struct xtvec *, unsigned long);
++
++	compat_ssize_t tot_len, tot_xtlen;
++	struct iovec iovstack[UIO_FASTIOV];
++	struct iovec *iov=iovstack;
++	struct xtvec xtvstack[UIO_FASTIOV];
++	struct xtvec *xtv=xtvstack;
++	ssize_t ret;
++	int seg;
++	io_fn_t fn = NULL;
++	iov_fn_t fnv = NULL;
++	iox_fn_t fnx = NULL;
++
++	/*
++	 * readx does not make much sense if nr_segs <= 0 (OR) xtnr_segs <= 0
++	 * We return 0 similar to how readv/writev do.
++	 */
++	ret = 0;
++	if (nr_segs == 0 || xtnr_segs == 0)
++		goto out;
++
++	/*
++	 * First get the "struct iovec" from user memory and
++	 * verify all the pointers
++	 */
++	ret = -EINVAL;
++	if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0))
++		goto out;
++	if ((xtnr_segs > UIO_MAXIOV) || (xtnr_segs <= 0))
++		goto out;
++	if (!file->f_op)
++		goto out;
++	if (nr_segs > UIO_FASTIOV) {
++		ret = -ENOMEM;
++		iov = kmalloc(nr_segs * sizeof(struct iovec), GFP_KERNEL);
++		if (!iov)
++			goto out;
++	}
++	if (xtnr_segs > UIO_FASTIOV) {
++		ret = -ENOMEM;
++		xtv = kmalloc(xtnr_segs * sizeof(struct xtvec), GFP_KERNEL);
++		if (!xtv) {
++			goto out;
++		}
++	}
++	ret = -EFAULT;
++	if (!access_ok(VERIFY_READ, uvector, nr_segs * sizeof(*uvector)))
++		goto out;
++	if (!access_ok(VERIFY_READ, xtuvector, xtnr_segs * sizeof(*xtuvector)))
++		goto out;
++
++	/*
++	 * Single unix specification:
++	 * We should -EINVAL if an element length is not >= 0 and fitting an
++	 * ssize_t.  The total length is fitting an ssize_t
++	 *
++	 * Be careful here because iov_len is a size_t not an ssize_t
++	 */
++	tot_len = 0;
++	ret = -EINVAL;
++	for (seg = 0; seg < nr_segs; seg++) {
++		compat_ssize_t tmp = tot_len, len;
++		compat_uptr_t buf;
++
++		if (__get_user(len, &uvector->iov_len) ||
++				__get_user(buf, &uvector->iov_base)) {
++			ret = -EFAULT;
++			goto out;
++		}
++		if (len < 0)	/* size_t not fitting an compat_ssize_t .. */
++			goto out;
++		tot_len += len;
++		if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
++			goto out;
++		iov[seg].iov_base = compat_ptr(buf);
++		iov[seg].iov_len  = (compat_size_t) len;
++		uvector++;
++	}
++	if (tot_len == 0) {
++		ret = 0;
++		goto out;
++	}
++	tot_xtlen = 0;
++	ret = -EINVAL;
++	for (seg = 0; seg < xtnr_segs; seg++) {
++		compat_ssize_t tmp = tot_xtlen, len;
++		compat_off_t off;
++		loff_t foff;
++
++		if (__get_user(off, &xtuvector->xtv_off) ||
++				__get_user(len, &xtuvector->xtv_len)) {
++			ret = -EFAULT;
++			goto out;
++		}
++		if (len < 0)	/* size_t not fitting an compat_ssize_t .. */
++			goto out;
++		if (off < 0)   /* off_t not fitting an loff_t */
++			goto out;
++		tot_xtlen += len;
++		if (tot_xtlen < tmp) /* overflow on the compat_ssize_t */
++			goto out;
++		foff = (loff_t) off;
++		ret = rw_verify_area(type, file, &foff, len);
++		if (ret < 0)
++			goto out;
++		xtv[seg].xtv_off = (compat_off_t) off;
++		xtv[seg].xtv_len = (compat_size_t) len;
++		xtuvector++;
++	}
++	/* if sizes of file and mem don't match up, error out */
++	if (tot_xtlen != tot_len) {
++		ret = -EINVAL;
++		goto out;
++	}
++
++	if (type == READ) {
++		fn = (io_fn_t)file->f_op->read;
++		fnv = (iov_fn_t)file->f_op->readv;
++		fnx = (iox_fn_t)file->f_op->readx;
++	} else {
++		fn = (io_fn_t)file->f_op->write;
++		fnv = (iov_fn_t)file->f_op->writev;
++		fnx = (iox_fn_t)file->f_op->writex;
++	}
++	/* if we had a scatter-gather callback in memory and file, go for it */
++	if (fnx) {
++		ret = fnx(file, iov, nr_segs, xtv, xtnr_segs);
++		goto out;
++	}
++	/* else try to do it by hand using readv/writev operations */
++	else if (fnv) {
++		unsigned long xtiov_index = 0, op_iov_index = 0, iov_index = 0;
++		struct iovec *op_iov = NULL, *copied_iovector = NULL;
++		struct xtvec *copied_xtvector = NULL;
++
++		ret = -ENOMEM;
++		op_iov = (struct iovec *) kmalloc(nr_segs * sizeof(struct iovec), GFP_KERNEL);
++		if (!op_iov) 
++			goto err_out1;
++		copied_iovector = (struct iovec *) kmalloc(nr_segs * sizeof(struct iovec), GFP_KERNEL);
++		if (!copied_iovector) 
++			goto err_out1;
++		copied_xtvector = (struct xtvec *) kmalloc(xtnr_segs * sizeof(struct xtvec), GFP_KERNEL);
++		if (!copied_xtvector)
++			goto err_out1;
++		memcpy(copied_iovector, iov, nr_segs * sizeof(struct iovec));
++		memcpy(copied_xtvector, xtv, xtnr_segs * sizeof(struct xtvec));
++		ret = 0;
++		iov_index = 0;
++		for (xtiov_index = 0; xtiov_index < xtnr_segs; xtiov_index++) {
++			loff_t pos;
++			ssize_t nr, tot_nr;
++
++			pos = copied_xtvector[xtiov_index].xtv_off;
++			op_iov_index = 0;
++			tot_nr = 0;
++			
++			/* Finish an entire stream and .. */
++			while (copied_xtvector[xtiov_index].xtv_len > 0) {
++				size_t min_len;
++				if (unlikely((iov_index >= nr_segs) || (op_iov_index >= nr_segs))) {
++					printk(KERN_ERR "iov_index %ld or op_iov_index %ld cannot exceed number of iov segments (%ld)\n",
++							iov_index, op_iov_index, nr_segs);
++					ret = -EINVAL;
++					goto err_out1;
++				}
++				min_len = min(copied_xtvector[xtiov_index].xtv_len, copied_iovector[iov_index].iov_len);
++				op_iov[op_iov_index].iov_base = copied_iovector[iov_index].iov_base;
++				op_iov[op_iov_index++].iov_len = min_len;
++				copied_xtvector[xtiov_index].xtv_len -= min_len;
++				copied_iovector[iov_index].iov_len -= min_len;
++				copied_iovector[iov_index].iov_base += min_len;
++				tot_nr += min_len;
++				/* Advance memory stream if we have exhausted it */
++				if (copied_iovector[iov_index].iov_len <= 0) {
++					iov_index++;
++				}
++			}
++			/* .. issue a vectored operation for that region */
++			nr = fnv(file, op_iov, op_iov_index, &pos);
++			if (nr < 0) {
++				if (!ret) ret = nr;
++				break;
++			}
++			ret += nr;
++			if (nr != tot_nr)
++				break;
++		}
++err_out1:
++		kfree(op_iov);
++		kfree(copied_iovector);
++		kfree(copied_xtvector);
++		goto out;
++	}
++	/* Do it by hand, with plain read/write operations */
++	else {
++		unsigned long mem_ct = 0, str_ct = 0;
++		struct xtvec *copied_xtvector = NULL;
++		struct iovec *copied_iovector = NULL;
++
++		ret = -ENOMEM;
++		copied_iovector = (struct iovec *) kmalloc(nr_segs * sizeof(struct iovec), GFP_KERNEL);
++		if (!copied_iovector)
++			goto err_out2;
++		copied_xtvector = (struct xtvec *) kmalloc(xtnr_segs * sizeof(struct xtvec), GFP_KERNEL);
++		if (!copied_xtvector)
++			goto err_out2;
++		memcpy(copied_iovector, iov, nr_segs * sizeof(struct iovec));
++		memcpy(copied_xtvector, xtv, xtnr_segs * sizeof(struct xtvec));
++
++		ret = 0;
++		mem_ct = 0;
++		str_ct = 0;
++		while ((mem_ct < nr_segs) && (str_ct < xtnr_segs)) {
++			size_t min_len;
++			loff_t pos;
++			ssize_t nr;
++			void __user *base;
++
++			pos = copied_xtvector[str_ct].xtv_off;
++			base = copied_iovector[mem_ct].iov_base;
++			min_len = min(copied_xtvector[str_ct].xtv_len, copied_iovector[mem_ct].iov_len);
++			copied_xtvector[str_ct].xtv_len -= min_len;
++			copied_xtvector[str_ct].xtv_off += min_len;
++			copied_iovector[mem_ct].iov_len -= min_len;
++			copied_iovector[mem_ct].iov_base += min_len;
++			if (copied_iovector[mem_ct].iov_len <= 0)
++				mem_ct++;
++			if (copied_xtvector[str_ct].xtv_len <= 0)
++				str_ct++;
++			/* Issue the smallest region that is contiguous in memory and on file */
++			nr = fn(file, base, min_len, &pos);
++			if (nr < 0) {
++				if (!ret) ret = nr;
++				break;
++			}
++			ret += nr;
++			if (nr != min_len)
++				break;
++		}
++err_out2:
++		kfree(copied_xtvector);
++		kfree(copied_iovector);
++	}
++out:
++	if (iov != iovstack)
++		kfree(iov);
++	if (xtv != xtvstack)
++		kfree(xtv);
++	if ((ret + (type == READ)) > 0) {
++		if (type == READ)
++			fsnotify_access(file->f_dentry);
++		else
++			fsnotify_modify(file->f_dentry);
++	}
++	return ret;
++}
++
++asmlinkage ssize_t
++compat_sys_readx(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen,
++		const struct compat_xtvec __user *xtv, unsigned long xtvlen)
++{
++	struct file *file;
++	ssize_t ret = -EBADF;
++
++	file = fget(fd);
++	if (!file)
++		return -EBADF;
++
++	if (!(file->f_mode & FMODE_READ))
++		goto out;
++
++	ret = -EINVAL;
++	if (!file->f_op || (!file->f_op->readx && !file->f_op->readv && !file->f_op->read))
++		goto out;
++
++	ret = compat_do_readx_writex(READ, file, vec, vlen, xtv, xtvlen);
++
++out:
++	fput(file);
++	return ret;
++}
++
++asmlinkage ssize_t
++compat_sys_writex(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen,
++		const struct compat_xtvec __user *xtv, unsigned long xtvlen)
++{
++	struct file *file;
++	ssize_t ret = -EBADF;
++
++	file = fget(fd);
++	if (!file)
++		return -EBADF;
++	if (!(file->f_mode & FMODE_WRITE))
++		goto out;
++
++	ret = -EINVAL;
++	if (!file->f_op || (!file->f_op->writex && !file->f_op->writev && !file->f_op->write))
++		goto out;
++
++	ret = compat_do_readx_writex(WRITE, file, vec, vlen, xtv, xtvlen);
++
++out:
++	fput(file);
++	return ret;
++}
++
+ /*
+  * Exactly like fs/open.c:sys_open(), except that it doesn't set the
+  * O_LARGEFILE flag.
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/fs/read_write.c vanilla-new/fs/read_write.c
+--- vanilla/fs/read_write.c	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/fs/read_write.c	2006-05-24 16:22:20.000000000 -0500
+@@ -374,6 +374,8 @@
+ 	return ret;
+ }
+ 
++EXPORT_SYMBOL_GPL(sys_write);
++
+ asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
+ 			     size_t count, loff_t pos)
+ {
+@@ -636,6 +638,334 @@
+ 	return ret;
+ }
+ 
++static ssize_t do_readx_writex(int type, struct file *file,
++			       const struct iovec __user * uvector,
++			       unsigned long nr_segs, 
++					 const struct xtvec __user * xtuvector,
++					 unsigned long xtnr_segs)
++{
++	typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
++	typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
++	typedef ssize_t (*iox_fn_t)(struct file *, const struct iovec *, unsigned long, 
++			const struct xtvec *, unsigned long);
++
++	size_t tot_len, tot_xtlen;
++	struct iovec iovstack[UIO_FASTIOV];
++	struct iovec *iov=iovstack;
++	struct xtvec xtvstack[UIO_FASTIOV];
++	struct xtvec *xtv=xtvstack;
++	ssize_t ret;
++	int seg;
++	io_fn_t fn = NULL;
++	iov_fn_t fnv = NULL;
++	iox_fn_t fnx = NULL;
++
++	/*
++	 * readx does not make much sense if nr_segs <= 0 (OR) xtnr_segs <= 0
++	 * We return 0 similar to how readv/writev do.
++	 */
++	ret = 0;
++	if (nr_segs == 0 || xtnr_segs == 0)
++		goto out;
++
++	/*
++	 * First get the "struct iovec" from user memory and
++	 * verify all the pointers
++	 */
++	ret = -EINVAL;
++	if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0))
++		goto out;
++	if ((xtnr_segs > UIO_MAXIOV) || (xtnr_segs <= 0))
++		goto out;
++	if (!file->f_op)
++		goto out;
++	if (nr_segs > UIO_FASTIOV) {
++		ret = -ENOMEM;
++		iov = kmalloc(nr_segs * sizeof(struct iovec), GFP_KERNEL);
++		if (!iov)
++			goto out;
++	}
++	if (xtnr_segs > UIO_FASTIOV) {
++		ret = -ENOMEM;
++		xtv = kmalloc(xtnr_segs * sizeof(struct xtvec), GFP_KERNEL);
++		if (!xtv) {
++			goto out;
++		}
++	}
++	ret = -EFAULT;
++	if (copy_from_user(iov, uvector, nr_segs * sizeof(*uvector)))
++		goto out;
++	if (copy_from_user(xtv, xtuvector, xtnr_segs * sizeof(*xtuvector)))
++		goto out;
++
++	/*
++	 * Single unix specification:
++	 * We should -EINVAL if an element length is not >= 0 and fitting an
++	 * ssize_t.  The total length is fitting an ssize_t
++	 *
++	 * Be careful here because iov_len is a size_t not an ssize_t
++	 */
++	tot_len = 0;
++	ret = -EINVAL;
++	for (seg = 0; seg < nr_segs; seg++) {
++		void __user *buf = iov[seg].iov_base;
++		ssize_t len = (ssize_t)iov[seg].iov_len;
++
++		if (len < 0)	/* size_t not fitting an ssize_t .. */
++			goto out;
++		if (unlikely(!access_ok(vrfy_dir(type), buf, len)))
++			goto Efault;
++		tot_len += len;
++		if ((ssize_t)tot_len < 0) /* maths overflow on the ssize_t */
++			goto out;
++	}
++	if (tot_len == 0) {
++		ret = 0;
++		goto out;
++	}
++	tot_xtlen = 0;
++	ret = -EINVAL;
++	for (seg = 0; seg < xtnr_segs; seg++) {
++		loff_t off = (loff_t) xtv[seg].xtv_off;
++		ssize_t len = (ssize_t)xtv[seg].xtv_len;
++
++		if (len < 0)	/* size_t not fitting an ssize_t .. */
++			goto out;
++		if (off < 0)   /* off_t not fitting an loff_t */
++			goto out;
++		tot_xtlen += len;
++		if ((ssize_t)tot_xtlen < 0) /* overflow on the ssize_t */
++			goto out;
++		ret = rw_verify_area(type, file, &off, len);
++		if (ret < 0)
++			goto out;
++	}
++	/* if sizes of file and mem don't match up, error out */
++	if (tot_xtlen != tot_len) {
++		ret = -EINVAL;
++		goto out;
++	}
++
++	ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE);
++	if (ret)
++		goto out;
++
++	if (type == READ) {
++		fn = (io_fn_t)file->f_op->read;
++		fnv = (iov_fn_t)file->f_op->readv;
++		fnx = (iox_fn_t)file->f_op->readx;
++	} else {
++		fn = (io_fn_t)file->f_op->write;
++		fnv = (iov_fn_t)file->f_op->writev;
++		fnx = (iox_fn_t)file->f_op->writex;
++	}
++	/* if we had a scatter-gather callback in memory and file, go for it */
++	if (fnx) {
++		ret = fnx(file, iov, nr_segs, xtv, xtnr_segs);
++		goto out;
++	}
++	/* else try to do it by hand using readv/writev operations */
++	else if (fnv) {
++		unsigned long xtiov_index = 0, op_iov_index = 0, iov_index = 0;
++		struct iovec *op_iov = NULL, *copied_iovector = NULL;
++		struct xtvec *copied_xtvector = NULL;
++
++		ret = -ENOMEM;
++		op_iov = (struct iovec *) kmalloc(nr_segs * sizeof(struct iovec), GFP_KERNEL);
++		if (!op_iov) 
++			goto err_out1;
++		copied_iovector = (struct iovec *) kmalloc(nr_segs * sizeof(struct iovec), GFP_KERNEL);
++		if (!copied_iovector) 
++			goto err_out1;
++		copied_xtvector = (struct xtvec *) kmalloc(xtnr_segs * sizeof(struct xtvec), GFP_KERNEL);
++		if (!copied_xtvector)
++			goto err_out1;
++		memcpy(copied_iovector, iov, nr_segs * sizeof(struct iovec));
++		memcpy(copied_xtvector, xtv, xtnr_segs * sizeof(struct xtvec));
++		ret = 0;
++		iov_index = 0;
++		for (xtiov_index = 0; xtiov_index < xtnr_segs; xtiov_index++) {
++			loff_t pos;
++			ssize_t nr, tot_nr;
++
++			pos = copied_xtvector[xtiov_index].xtv_off;
++			op_iov_index = 0;
++			tot_nr = 0;
++			
++			/* Finish an entire stream and .. */
++			while (copied_xtvector[xtiov_index].xtv_len > 0) {
++				size_t min_len;
++				if (unlikely((iov_index >= nr_segs) || (op_iov_index >= nr_segs))) {
++					printk(KERN_ERR "iov_index %ld or op_iov_index %ld cannot exceed number of iov segments (%ld)\n",
++							iov_index, op_iov_index, nr_segs);
++					ret = -EINVAL;
++					goto err_out1;
++				}
++				min_len = min(copied_xtvector[xtiov_index].xtv_len, copied_iovector[iov_index].iov_len);
++				op_iov[op_iov_index].iov_base = copied_iovector[iov_index].iov_base;
++				op_iov[op_iov_index++].iov_len = min_len;
++				copied_xtvector[xtiov_index].xtv_len -= min_len;
++				copied_iovector[iov_index].iov_len -= min_len;
++				copied_iovector[iov_index].iov_base += min_len;
++				tot_nr += min_len;
++				/* Advance memory stream if we have exhausted it */
++				if (copied_iovector[iov_index].iov_len <= 0) {
++					iov_index++;
++				}
++			}
++			/* .. issue a vectored operation for that region */
++			nr = fnv(file, op_iov, op_iov_index, &pos);
++			if (nr < 0) {
++				if (!ret) ret = nr;
++				break;
++			}
++			ret += nr;
++			if (nr != tot_nr)
++				break;
++		}
++err_out1:
++		kfree(op_iov);
++		kfree(copied_iovector);
++		kfree(copied_xtvector);
++		goto out;
++	}
++	/* Do it by hand, with plain read/write operations */
++	else {
++		unsigned long mem_ct = 0, str_ct = 0;
++		struct xtvec *copied_xtvector = NULL;
++		struct iovec *copied_iovector = NULL;
++
++		ret = -ENOMEM;
++		copied_iovector = (struct iovec *) kmalloc(nr_segs * sizeof(struct iovec), GFP_KERNEL);
++		if (!copied_iovector)
++			goto err_out2;
++		copied_xtvector = (struct xtvec *) kmalloc(xtnr_segs * sizeof(struct xtvec), GFP_KERNEL);
++		if (!copied_xtvector)
++			goto err_out2;
++		memcpy(copied_iovector, iov, nr_segs * sizeof(struct iovec));
++		memcpy(copied_xtvector, xtv, xtnr_segs * sizeof(struct xtvec));
++
++		ret = 0;
++		mem_ct = 0;
++		str_ct = 0;
++		while ((mem_ct < nr_segs) && (str_ct < xtnr_segs)) {
++			size_t min_len;
++			loff_t pos;
++			ssize_t nr;
++			void __user *base;
++
++			pos = copied_xtvector[str_ct].xtv_off;
++			base = copied_iovector[mem_ct].iov_base;
++			min_len = min(copied_xtvector[str_ct].xtv_len, copied_iovector[mem_ct].iov_len);
++			copied_xtvector[str_ct].xtv_len -= min_len;
++			copied_xtvector[str_ct].xtv_off += min_len;
++			copied_iovector[mem_ct].iov_len -= min_len;
++			copied_iovector[mem_ct].iov_base += min_len;
++			if (copied_iovector[mem_ct].iov_len <= 0)
++				mem_ct++;
++			if (copied_xtvector[str_ct].xtv_len <= 0)
++				str_ct++;
++			/* Issue the smallest region that is contiguous in memory and on file */
++			nr = fn(file, base, min_len, &pos);
++			if (nr < 0) {
++				if (!ret) ret = nr;
++				break;
++			}
++			ret += nr;
++			if (nr != min_len)
++				break;
++		}
++err_out2:
++		kfree(copied_xtvector);
++		kfree(copied_iovector);
++	}
++out:
++	if (iov != iovstack)
++		kfree(iov);
++	if (xtv != xtvstack)
++		kfree(xtv);
++	if ((ret + (type == READ)) > 0) {
++		if (type == READ)
++			fsnotify_access(file->f_dentry);
++		else
++			fsnotify_modify(file->f_dentry);
++	}
++	return ret;
++Efault:
++	ret = -EFAULT;
++	goto out;
++}
++
++ssize_t vfs_readx(struct file *file, const struct iovec __user *vec,
++		  unsigned long vlen, const struct xtvec __user *xtvec, unsigned long xtvlen)
++{
++	if (!(file->f_mode & FMODE_READ))
++		return -EBADF;
++	if (!file->f_op || (!file->f_op->readx && !file->f_op->readv && !file->f_op->read))
++		return -EINVAL;
++
++	return do_readx_writex(READ, file, vec, vlen, xtvec, xtvlen);
++}
++
++EXPORT_SYMBOL_GPL(vfs_readx);
++
++ssize_t vfs_writex(struct file *file, const struct iovec __user *vec,
++		   unsigned long vlen, const struct xtvec __user *xtvec, unsigned long xtvlen)
++{
++	if (!(file->f_mode & FMODE_WRITE))
++		return -EBADF;
++	if (!file->f_op || (!file->f_op->writex && !file->f_op->writev && !file->f_op->write))
++		return -EINVAL;
++
++	return do_readx_writex(WRITE, file, vec, vlen, xtvec, xtvlen);
++}
++
++EXPORT_SYMBOL_GPL(vfs_writex);
++
++asmlinkage ssize_t sys_readx(unsigned long fd,
++				const struct iovec __user *vec,
++				unsigned long vlen,
++				const struct xtvec __user *xtvec,
++				unsigned long xtvlen)
++{
++	struct file *file;
++	ssize_t ret = -EBADF;
++	int fput_needed;
++
++	file = fget_light(fd, &fput_needed);
++	if (file) {
++		ret = vfs_readx(file, vec, vlen, xtvec, xtvlen);
++		fput_light(file, fput_needed);
++	}
++
++	if (ret > 0)
++		current->rchar += ret;
++	current->syscr++;
++	return ret;
++}
++
++asmlinkage ssize_t sys_writex(unsigned long fd,
++				const struct iovec __user *vec,
++				unsigned long vlen,
++				const struct xtvec __user *xtvec,
++				unsigned long xtvlen)
++{
++	struct file *file;
++	ssize_t ret = -EBADF;
++	int fput_needed;
++
++	file = fget_light(fd, &fput_needed);
++	if (file) {
++		ret = vfs_writex(file, vec, vlen, xtvec, xtvlen);
++		fput_light(file, fput_needed);
++	}
++
++	if (ret > 0)
++		current->wchar += ret;
++	current->syscw++;
++	return ret;
++}
++
+ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
+ 			   size_t count, loff_t max)
+ {
+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-24 16:19:07.000000000 -0500
++++ vanilla-new/include/asm-i386/unistd.h	2006-05-24 16:27:28.000000000 -0500
+@@ -326,8 +326,10 @@
+ #define __NR_fstatlite64 318
+ #define __NR_getdents_plus 319
+ #define __NR_getdents64_plus 320
++#define __NR_readx      321
++#define __NR_writex     322
+ 
+-#define NR_syscalls 321
++#define NR_syscalls 323
+ 
+ /*
+  * 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-24 16:19:07.000000000 -0500
++++ vanilla-new/include/asm-ia64/unistd.h	2006-05-24 16:29:19.000000000 -0500
+@@ -292,12 +292,14 @@
+ #define __NR_fstatlite     1301
+ #define __NR_getdents_plus 1302
+ #define __NR_getdents64_plus 1303
++#define __NR_readx         1304
++#define __NR_writex        1305
+ 
+ #ifdef __KERNEL__
+ 
+ #include <linux/config.h>
+ 
+-#define NR_syscalls			280 /* length of syscall table */
++#define NR_syscalls			282 /* 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-24 16:19:07.000000000 -0500
++++ vanilla-new/include/asm-powerpc/unistd.h	2006-05-24 16:30:04.000000000 -0500
+@@ -308,8 +308,10 @@
+ #define __NR_fstatlite     287
+ #define __NR_getdents_plus 288
+ #define __NR_getdents64_plus 289
++#define __NR_readx         290
++#define __NR_writex        291
+ 
+-#define __NR_syscalls		290
++#define __NR_syscalls		292
+ 
+ #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/unistd.h vanilla-new/include/asm-x86_64/unistd.h
+--- vanilla/include/asm-x86_64/unistd.h	2006-05-24 16:19:07.000000000 -0500
++++ vanilla-new/include/asm-x86_64/unistd.h	2006-05-24 16:28:26.000000000 -0500
+@@ -619,8 +619,12 @@
+ __SYSCALL(__NR_getdents_plus, sys_getdents_plus)
+ #define __NR_getdents64_plus 279
+ __SYSCALL(__NR_getdents64_plus, sys_getdents64_plus)
++#define __NR_readx  280
++__SYSCALL(__NR_readx, sys_readx)
++#define __NR_writex 281
++__SYSCALL(__NR_writex, sys_writex)
+ 
+-#define __NR_syscall_max __NR_getdents64_plus
++#define __NR_syscall_max __NR_writex
+ 
+ #ifndef __NO_STUBS
+ 
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/linux/compat.h vanilla-new/include/linux/compat.h
+--- vanilla/include/linux/compat.h	2006-05-09 18:53:48.000000000 -0500
++++ vanilla-new/include/linux/compat.h	2006-05-24 16:26:29.000000000 -0500
+@@ -61,6 +61,11 @@
+ 	compat_size_t	iov_len;
+ };
+ 
++struct compat_xtvec {
++	compat_off_t  xtv_off;
++	compat_size_t xtv_len;
++};
++
+ struct compat_rlimit {
+ 	compat_ulong_t	rlim_cur;
+ 	compat_ulong_t	rlim_max;
+@@ -141,6 +146,13 @@
+ asmlinkage ssize_t compat_sys_writev(unsigned long fd,
+ 		const struct compat_iovec __user *vec, unsigned long vlen);
+ 
++asmlinkage ssize_t compat_sys_readx(unsigned long fd,
++		const struct compat_iovec __user *vec, unsigned long vlen,
++		const struct compat_xtvec __user *xtvec, unsigned long xtvlen);
++asmlinkage ssize_t compat_sys_writex(unsigned long fd,
++		const struct compat_iovec __user *vec, unsigned long vlen,
++		const struct compat_xtvec __user *xtvec, unsigned long xtvlen);
++
+ int compat_do_execve(char * filename, compat_uptr_t __user *argv,
+ 	        compat_uptr_t __user *envp, struct pt_regs * regs);
+ 
+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-24 16:19:07.000000000 -0500
++++ vanilla-new/include/linux/fs.h	2006-05-24 16:20:15.000000000 -0500
+@@ -226,6 +226,7 @@
+ 
+ struct hd_geometry;
+ struct iovec;
++struct xtvec;
+ struct nameidata;
+ struct kiocb;
+ struct pipe_inode_info;
+@@ -1048,6 +1049,8 @@
+ 	int (*lock) (struct file *, int, struct file_lock *);
+ 	ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
+ 	ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
++	ssize_t (*readx) (struct file *, const struct iovec *, unsigned long, const struct xtvec *, unsigned long);
++	ssize_t (*writex) (struct file *, const struct iovec *, unsigned long, const struct xtvec *, unsigned long);
+ 	ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
+ 	ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
+ 	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+@@ -1092,6 +1095,11 @@
+ 		unsigned long, loff_t *);
+ extern ssize_t vfs_writev(struct file *, const struct iovec __user *,
+ 		unsigned long, loff_t *);
++extern ssize_t vfs_readx(struct file *, const struct iovec __user *,
++		unsigned long, const struct xtvec __user *, unsigned long);
++extern ssize_t vfs_writex(struct file *, const struct iovec __user *,
++		unsigned long, const struct xtvec __user *, unsigned long);
++
+ 
+ /*
+  * NOTE: write_inode, delete_inode, clear_inode, put_inode can be called
+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-24 16:19:07.000000000 -0500
++++ vanilla-new/include/linux/syscalls.h	2006-05-24 16:23:31.000000000 -0500
+@@ -17,6 +17,7 @@
+ struct iocb;
+ struct io_event;
+ struct iovec;
++struct xtvec;
+ struct itimerspec;
+ struct itimerval;
+ struct kexec_segment;
+@@ -402,6 +403,16 @@
+ asmlinkage ssize_t sys_writev(unsigned long fd,
+ 				const struct iovec __user *vec,
+ 				unsigned long vlen);
++asmlinkage ssize_t sys_readx(unsigned long fd,
++				const struct iovec __user *vec,
++				unsigned long vlen,
++				const struct xtvec __user *xtvec,
++				unsigned long xtvlen);
++asmlinkage ssize_t sys_writex(unsigned long fd,
++				const struct iovec __user *vec,
++				unsigned long vlen,
++				const struct xtvec __user *xtvec,
++				unsigned long xtvlen);
+ asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
+ 				size_t count, loff_t pos);
+ asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf,
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/linux/uio.h vanilla-new/include/linux/uio.h
+--- vanilla/include/linux/uio.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/linux/uio.h	2006-05-24 16:24:20.000000000 -0500
+@@ -23,6 +23,12 @@
+ 	__kernel_size_t iov_len; /* Must be size_t (1003.1g) */
+ };
+ 
++struct xtvec 
++{
++	__kernel_off_t xtv_off;  /* must be off_t */
++	__kernel_size_t xtv_len; /* must be size_t */
++};
++
+ #ifdef __KERNEL__
+ 
+ struct kvec {
+@@ -30,6 +36,12 @@
+ 	size_t iov_len;
+ };
+ 
++struct kxtvec
++{
++	off_t xtv_off;
++	size_t xtv_len;
++};
++
+ #endif
+ 
+ /*

--- /dev/null	2004-06-24 14:04:38.000000000 -0400
+++ posix-statlite-fix.patch	2008-01-07 17:27:26.000000000 -0500
@@ -0,0 +1,125 @@
+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-24 16:19:07.000000000 -0500
++++ vanilla-new/fs/stat.c	2006-08-29 17:58:48.000000000 -0500
+@@ -345,6 +345,15 @@
+ 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+ }
+ 
++static long get_stat_lite_mask(struct stat_lite __user *statlitebuf)
++{
++	struct stat_lite tmp;
++
++	if (copy_from_user(&tmp,statlitebuf,sizeof(tmp)))
++		return -EFAULT;
++	return tmp.st_litemask;
++}
++
+ int cp_new_statlite(struct kstat_lite *stat_lite, struct stat_lite __user *statlitebuf)
+ {
+ 	struct stat_lite tmp;
+@@ -434,7 +443,13 @@
+ asmlinkage long sys_newstatlite(char __user *filename, struct stat_lite __user *statlitebuf)
+ {
+ 	struct kstat_lite stat_lite;
+-	int error = vfs_statlite_fd(AT_FDCWD, filename, &stat_lite);
++	int error;
++
++	stat_lite.lite_mask = get_stat_lite_mask(statlitebuf);
++	if (stat_lite.lite_mask < 0)
++		return stat_lite.lite_mask;
++
++	error = vfs_statlite_fd(AT_FDCWD, filename, &stat_lite);
+ 
+ 	if (!error)
+ 		error = cp_new_statlite(&stat_lite, statlitebuf);
+@@ -456,7 +471,13 @@
+ asmlinkage long sys_newlstatlite(char __user *filename, struct stat_lite __user *statlitebuf)
+ {
+ 	struct kstat_lite stat_lite;
+-	int error = vfs_lstatlite_fd(AT_FDCWD, filename, &stat_lite);
++	int error;
++	
++	stat_lite.lite_mask = get_stat_lite_mask(statlitebuf);
++	if (stat_lite.lite_mask < 0)
++		return stat_lite.lite_mask;
++
++	error = vfs_lstatlite_fd(AT_FDCWD, filename, &stat_lite);
+ 
+ 	if (!error)
+ 		error = cp_new_statlite(&stat_lite, statlitebuf);
+@@ -501,7 +522,13 @@
+ asmlinkage long sys_newfstatlite(unsigned int fd, struct stat_lite __user *statlitebuf)
+ {
+ 	struct kstat_lite stat_lite;
+-	int error = vfs_fstatlite(fd, &stat_lite);
++	int error;
++
++	stat_lite.lite_mask = get_stat_lite_mask(statlitebuf);
++	if (stat_lite.lite_mask < 0)
++		return stat_lite.lite_mask;
++
++	error = vfs_fstatlite(fd, &stat_lite);
+ 
+ 	if (!error)
+ 		error = cp_new_statlite(&stat_lite, statlitebuf);
+@@ -580,6 +607,15 @@
+ 	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+ }
+ 
++static long get_stat64_lite_mask(struct stat64_lite __user *statlitebuf)
++{
++	struct stat64_lite tmp;
++
++	if (copy_from_user(&tmp,statlitebuf,sizeof(tmp)))
++		return -EFAULT;
++	return tmp.st_litemask;
++}
++
+ long cp_new_stat64_lite(struct kstat_lite *stat_lite, struct stat64_lite __user *statlitebuf)
+ {
+ 	struct stat64_lite tmp;
+@@ -648,7 +684,13 @@
+ asmlinkage long sys_statlite64(char __user * filename, struct stat64_lite __user * statlitebuf)
+ {
+ 	struct kstat_lite stat_lite;
+-	int error = vfs_statlite(filename, &stat_lite);
++	int error;
++
++	stat_lite.lite_mask = get_stat64_lite_mask(statlitebuf);
++	if (stat_lite.lite_mask < 0)
++		return stat_lite.lite_mask;
++
++	error = vfs_statlite(filename, &stat_lite);
+ 
+ 	if (!error)
+ 		error = cp_new_stat64_lite(&stat_lite, statlitebuf);
+@@ -670,7 +712,13 @@
+ asmlinkage long sys_lstatlite64(char __user * filename, struct stat64_lite __user * statlitebuf)
+ {
+ 	struct kstat_lite stat_lite;
+-	int error = vfs_lstatlite(filename, &stat_lite);
++	int error;
++	
++	stat_lite.lite_mask = get_stat64_lite_mask(statlitebuf);
++	if (stat_lite.lite_mask < 0)
++		return stat_lite.lite_mask;
++
++	error = vfs_lstatlite(filename, &stat_lite);
+ 
+ 	if (!error)
+ 		error = cp_new_stat64_lite(&stat_lite, statlitebuf);
+@@ -692,7 +740,13 @@
+ asmlinkage long sys_fstatlite64(unsigned long fd, struct stat64_lite __user * statlitebuf)
+ {
+ 	struct kstat_lite stat_lite;
+-	int error = vfs_fstatlite(fd, &stat_lite);
++	int error;
++
++	stat_lite.lite_mask = get_stat64_lite_mask(statlitebuf);
++	if (stat_lite.lite_mask < 0)
++		return stat_lite.lite_mask;
++
++	error = vfs_fstatlite(fd, &stat_lite);
+ 
+ 	if (!error)
+ 		error = cp_new_stat64_lite(&stat_lite, statlitebuf);

--- /dev/null	2004-06-24 14:04:38.000000000 -0400
+++ posix-statlite-x86_64.patch	2008-01-07 17:27:26.000000000 -0500
@@ -0,0 +1,77 @@
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/arch/x86_64/ia32/sys_ia32.c vanilla-new/arch/x86_64/ia32/sys_ia32.c
+--- vanilla/arch/x86_64/ia32/sys_ia32.c	2006-05-09 18:53:48.000000000 -0500
++++ vanilla-new/arch/x86_64/ia32/sys_ia32.c	2006-05-18 20:35:24.000000000 -0500
+@@ -234,13 +234,13 @@
+ 			 return -EFAULT;
+ 	}
+ 	if (SLITE_MTIME(stat_lite->lite_mask)) {
+-	    if (__put_user (stat->mtime.tv_sec, &ubuf->st_mtime) ||
+-			 __put_user (stat->mtime.tv_nsec, &ubuf->st_mtime_nsec))
++	    if (__put_user (stat_lite->mtime.tv_sec, &ubuf->st_mtime) ||
++			 __put_user (stat_lite->mtime.tv_nsec, &ubuf->st_mtime_nsec))
+ 			 return -EFAULT;
+ 	}
+ 	if (SLITE_CTIME(stat_lite->lite_mask)) {
+-	    if (__put_user (stat->ctime.tv_sec, &ubuf->st_ctime) ||
+-			 __put_user (stat->ctime.tv_nsec, &ubuf->st_ctime_nsec))
++	    if (__put_user (stat_lite->ctime.tv_sec, &ubuf->st_ctime) ||
++			 __put_user (stat_lite->ctime.tv_nsec, &ubuf->st_ctime_nsec))
+ 			 return -EFAULT;
+ 	}
+ 	if (SLITE_BLKSIZE(stat_lite->lite_mask)) {
+@@ -248,7 +248,7 @@
+ 			 return -EFAULT;
+ 	}
+ 	if (SLITE_BLOCKS(stat_lite->lite_mask)) {
+-		 if (__put_user (stat->blocks, &ubuf->st_blocks))
++		 if (__put_user (stat_lite->blocks, &ubuf->st_blocks))
+ 			return -EFAULT;
+ 	}
+ 	return 0;
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-x86_64/ia32.h vanilla-new/include/asm-x86_64/ia32.h
+--- vanilla/include/asm-x86_64/ia32.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/asm-x86_64/ia32.h	2006-05-18 20:34:22.000000000 -0500
+@@ -78,6 +78,43 @@
+ 	unsigned long long	st_ino;
+ } __attribute__((packed));
+ 
++/* This matches struct stat64_lite in glibc2.2, hence the absolutely
++ * insane amounts of padding around dev_t's.
++ */
++struct stat64_lite {
++	unsigned long long	st_dev;
++	unsigned char		__pad0[4];
++
++#define STAT64_HAS_BROKEN_ST_INO	1
++	unsigned int		__st_ino;
++
++	unsigned int		st_mode;
++	unsigned int		st_nlink;
++
++	unsigned int		st_uid;
++	unsigned int		st_gid;
++
++	unsigned long long	st_rdev;
++	unsigned char		__pad3[4];
++
++	unsigned long  st_litemask;
++	unsigned char  __pad5[4];
++
++	long long		st_size;
++	unsigned int		st_blksize;
++
++	long long		st_blocks;/* Number 512-byte blocks allocated. */
++
++	unsigned 		st_atime;
++	unsigned 		st_atime_nsec;
++	unsigned 		st_mtime;
++	unsigned 		st_mtime_nsec;
++	unsigned 		st_ctime;
++	unsigned 		st_ctime_nsec;
++
++	unsigned long long	st_ino;
++} __attribute__((packed));
++
+ typedef struct compat_siginfo{
+ 	int si_signo;
+ 	int si_errno;

--- /dev/null	2004-06-24 14:04:38.000000000 -0400
+++ posix-statlite.patch	2008-01-07 17:27:26.000000000 -0500
@@ -0,0 +1,1112 @@
+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-05 13:59:14.000000000 -0500
++++ vanilla-new/arch/i386/kernel/syscall_table.S	2006-05-05 15:14:31.000000000 -0500
+@@ -312,3 +312,9 @@
+ 	.long sys_unshare		/* 310 */
+ 	.long sys_openg
+ 	.long sys_openfh
++	.long sys_newstatlite
++	.long sys_newlstatlite
++	.long sys_newfstatlite
++	.long sys_statlite64
++	.long sys_lstatlite64
++	.long sys_fstatlite64
+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-05 13:59:14.000000000 -0500
++++ vanilla-new/arch/ia64/kernel/entry.S	2006-05-05 15:29:07.000000000 -0500
+@@ -1621,5 +1621,8 @@
+ 	data8 sys_unshare
+ 	data8 sys_openg
+ 	data8 sys_openfh
++	data8 sys_newstatlite
++	data8 sys_newlstatlite
++	data8 sys_newfstatlite
+ 
+ 	.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-05 13:59:14.000000000 -0500
++++ vanilla-new/arch/powerpc/kernel/systbl.S	2006-05-05 17:02:20.000000000 -0500
+@@ -324,3 +324,6 @@
+ SYSCALL(unshare)
+ SYSCALL(openg)
+ SYSCALL(openfh)
++SYSCALL(newstatlite)
++SYSCALL(newlstatlite)
++SYSCALL(newfstatlite)
+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-05 13:59:14.000000000 -0500
++++ vanilla-new/arch/x86_64/ia32/ia32entry.S	2006-05-05 15:15:16.000000000 -0500
+@@ -690,6 +690,12 @@
+ 	.quad sys_unshare		/* 310 */
+ 	.quad compat_sys_openg
+ 	.quad compat_sys_openfh
++	.quad compat_sys_newstatlite
++	.quad compat_sys_newlstatlite
++	.quad compat_sys_newfstatlite
++	.quad sys32_statlite64
++	.quad sys32_lstatlite64
++	.quad sys32_fstatlite64
+ 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/arch/x86_64/ia32/sys_ia32.c vanilla-new/arch/x86_64/ia32/sys_ia32.c
+--- vanilla/arch/x86_64/ia32/sys_ia32.c	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/arch/x86_64/ia32/sys_ia32.c	2006-05-05 16:17:51.000000000 -0500
+@@ -106,6 +106,59 @@
+ 	return 0;
+ }
+ 
++int cp_compat_statlite(struct kstat_lite *kbuf, struct compat_stat_lite __user *ubuf)
++{
++	typeof(ubuf->st_uid) uid = 0;
++	typeof(ubuf->st_gid) gid = 0;
++	SET_UID(uid, kbuf->uid);
++	SET_GID(gid, kbuf->gid);
++	if (!old_valid_dev(kbuf->dev) || !old_valid_dev(kbuf->rdev))
++		return -EOVERFLOW;
++	if (SLITE_SIZET(kbuf->lite_mask) && kbuf->size >= 0x7fffffff)
++		return -EOVERFLOW;
++	if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct compat_stat_lite)) ||
++	    __put_user (old_encode_dev(kbuf->dev), &ubuf->st_dev) ||
++	    __put_user (kbuf->ino, &ubuf->st_ino) ||
++	    __put_user (kbuf->mode, &ubuf->st_mode) ||
++	    __put_user (kbuf->nlink, &ubuf->st_nlink) ||
++	    __put_user (uid, &ubuf->st_uid) ||
++	    __put_user (gid, &ubuf->st_gid) ||
++	    __put_user (old_encode_dev(kbuf->rdev), &ubuf->st_rdev))
++		return -EFAULT;
++
++	if (__put_user (kbuf->lite_mask, &ubuf->st_litemask))
++		return -EFAULT;
++
++	if (SLITE_SIZET(kbuf->lite_mask)) {
++	    if (__put_user (kbuf->size, &ubuf->st_size))
++			 return -EFAULT;
++	}
++	if (SLITE_ATIME(kbuf->lite_mask)) {
++	    if (__put_user (kbuf->atime.tv_sec, &ubuf->st_atime) ||
++			 __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime_nsec))
++			 return -EFAULT;
++	}
++	if (SLITE_MTIME(kbuf->lite_mask)) {
++	    if (__put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime) ||
++			 __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec))
++			 return -EFAULT;
++	}
++	if (SLITE_CTIME(kbuf->lite_mask)) {
++	    if (__put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime) ||
++			 __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec))
++			 return -EFAULT;
++	}
++	if (SLITE_BLKSIZE(kbuf->lite_mask)) {
++	    if (__put_user (kbuf->blksize, &ubuf->st_blksize))
++			 return -EFAULT;
++	}
++	if (SLITE_BLOCKS(kbuf->lite_mask)) {
++	    if (__put_user (kbuf->blocks, &ubuf->st_blocks))
++			 return -EFAULT;
++	}
++	return 0;
++}
++
+ asmlinkage long
+ sys32_truncate64(char __user * filename, unsigned long offset_low, unsigned long offset_high)
+ {
+@@ -150,6 +203,57 @@
+ 	return 0;
+ }
+ 
++static int
++cp_stat64_lite(struct stat64_lite __user *ubuf, struct kstat_lite *stat_lite)
++{
++	typeof(ubuf->st_uid) uid = 0;
++	typeof(ubuf->st_gid) gid = 0;
++	SET_UID(uid, stat_lite->uid);
++	SET_GID(gid, stat_lite->gid);
++	if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64_lite)) ||
++	    __put_user(huge_encode_dev(stat_lite->dev), &ubuf->st_dev) ||
++	    __put_user (stat_lite->ino, &ubuf->__st_ino) ||
++	    __put_user (stat_lite->ino, &ubuf->st_ino) ||
++	    __put_user (stat_lite->mode, &ubuf->st_mode) ||
++	    __put_user (stat_lite->nlink, &ubuf->st_nlink) ||
++	    __put_user (uid, &ubuf->st_uid) ||
++	    __put_user (gid, &ubuf->st_gid) ||
++	    __put_user (huge_encode_dev(stat_lite->rdev), &ubuf->st_rdev))
++		return -EFAULT;
++
++	if (__put_user (stat_lite->lite_mask, &ubuf->st_litemask))
++		return -EFAULT;
++
++	if (SLITE_SIZET(stat_lite->lite_mask)) {
++	    if (__put_user (stat_lite->size, &ubuf->st_size))
++			 return -EFAULT;
++	}
++	if (SLITE_ATIME(stat_lite->lite_mask)) {
++	    if (__put_user (stat_lite->atime.tv_sec, &ubuf->st_atime) ||
++			 __put_user (stat_lite->atime.tv_nsec, &ubuf->st_atime_nsec)) 
++			 return -EFAULT;
++	}
++	if (SLITE_MTIME(stat_lite->lite_mask)) {
++	    if (__put_user (stat->mtime.tv_sec, &ubuf->st_mtime) ||
++			 __put_user (stat->mtime.tv_nsec, &ubuf->st_mtime_nsec))
++			 return -EFAULT;
++	}
++	if (SLITE_CTIME(stat_lite->lite_mask)) {
++	    if (__put_user (stat->ctime.tv_sec, &ubuf->st_ctime) ||
++			 __put_user (stat->ctime.tv_nsec, &ubuf->st_ctime_nsec))
++			 return -EFAULT;
++	}
++	if (SLITE_BLKSIZE(stat_lite->lite_mask)) {
++	    if (__put_user (stat_lite->blksize, &ubuf->st_blksize))
++			 return -EFAULT;
++	}
++	if (SLITE_BLOCKS(stat_lite->lite_mask)) {
++		 if (__put_user (stat->blocks, &ubuf->st_blocks))
++			return -EFAULT;
++	}
++	return 0;
++}
++
+ asmlinkage long
+ sys32_stat64(char __user * filename, struct stat64 __user *statbuf)
+ {
+@@ -161,6 +265,16 @@
+ }
+ 
+ asmlinkage long
++sys32_statlite64(char __user * filename, struct stat64_lite __user *statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int ret = vfs_statlite(filename, &stat_lite);
++	if (!ret)
++		ret = cp_stat64_lite(statlitebuf, &stat_lite);
++	return ret;
++}
++
++asmlinkage long
+ sys32_lstat64(char __user * filename, struct stat64 __user *statbuf)
+ {
+ 	struct kstat stat;
+@@ -171,6 +285,16 @@
+ }
+ 
+ asmlinkage long
++sys32_lstatlite64(char __user * filename, struct stat64_lite __user *statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int ret = vfs_lstatlite(filename, &stat_lite);
++	if (!ret)
++		ret = cp_stat64_lite(statlitebuf, &stat_lite);
++	return ret;
++}
++
++asmlinkage long
+ sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf)
+ {
+ 	struct kstat stat;
+@@ -181,6 +305,16 @@
+ }
+ 
+ asmlinkage long
++sys32_fstatlite64(unsigned int fd, struct stat64_lite __user *statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int ret = vfs_fstatlite(fd, &stat_lite);
++	if (!ret)
++		ret = cp_stat64_lite(statlitebuf, &stat_lite);
++	return ret;
++}
++
++asmlinkage long
+ sys32_fstatat(unsigned int dfd, char __user *filename,
+ 	      struct stat64 __user* statbuf, int flag)
+ {
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/fs/compat.c vanilla-new/fs/compat.c
+--- vanilla/fs/compat.c	2006-05-05 13:59:14.000000000 -0500
++++ vanilla-new/fs/compat.c	2006-05-05 14:16:16.000000000 -0500
+@@ -103,6 +103,17 @@
+ 	return error;
+ }
+ 
++asmlinkage long compat_sys_newstatlite(char __user * filename,
++		struct compat_stat_lite __user *statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int error = vfs_statlite_fd(AT_FDCWD, filename, &stat_lite);
++
++	if (!error)
++		error = cp_compat_statlite(&stat_lite, statlitebuf);
++	return error;
++}
++
+ asmlinkage long compat_sys_newlstat(char __user * filename,
+ 		struct compat_stat __user *statbuf)
+ {
+@@ -114,6 +125,17 @@
+ 	return error;
+ }
+ 
++asmlinkage long compat_sys_newlstatlite(char __user * filename,
++		struct compat_stat_lite __user *statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int error = vfs_lstatlite_fd(AT_FDCWD, filename, &stat_lite);
++
++	if (!error)
++		error = cp_compat_statlite(&stat_lite, statlitebuf);
++	return error;
++}
++
+ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename,
+ 		struct compat_stat __user *statbuf, int flag)
+ {
+@@ -146,6 +168,17 @@
+ 	return error;
+ }
+ 
++asmlinkage long compat_sys_newfstatlite(unsigned int fd,
++		struct compat_stat_lite __user * statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int error = vfs_fstatlite(fd, &stat_lite);
++
++	if (!error)
++		error = cp_compat_statlite(&stat_lite, statlitebuf);
++	return error;
++}
++
+ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
+ {
+ 	
+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-03-19 23:53:29.000000000 -0600
++++ vanilla-new/fs/stat.c	2006-05-05 17:12:15.000000000 -0500
+@@ -38,6 +38,33 @@
+ 
+ EXPORT_SYMBOL(generic_fillattr);
+ 
++void generic_fillattr_lite(struct inode *inode, struct kstat_lite *stat_lite)
++{
++	unsigned long lite_mask = stat_lite->lite_mask;
++
++	stat_lite->dev = inode->i_sb->s_dev;
++	stat_lite->ino = inode->i_ino;
++	stat_lite->mode = inode->i_mode;
++	stat_lite->nlink = inode->i_nlink;
++	stat_lite->uid = inode->i_uid;
++	stat_lite->gid = inode->i_gid;
++	stat_lite->rdev = inode->i_rdev;
++	if (SLITE_ATIME(lite_mask))
++		stat_lite->atime = inode->i_atime;
++	if (SLITE_MTIME(lite_mask))
++		stat_lite->mtime = inode->i_mtime;
++	if (SLITE_CTIME(lite_mask))
++		stat_lite->ctime = inode->i_ctime;
++	if (SLITE_SIZET(lite_mask))
++		stat_lite->size = i_size_read(inode);
++	if (SLITE_BLOCKS(lite_mask))
++		stat_lite->blocks = inode->i_blocks;
++	if (SLITE_BLKSIZE(lite_mask))
++		stat_lite->blksize = inode->i_blksize;
++}
++
++EXPORT_SYMBOL_GPL(generic_fillattr_lite);
++
+ int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+ {
+ 	struct inode *inode = dentry->d_inode;
+@@ -63,6 +90,31 @@
+ 
+ EXPORT_SYMBOL(vfs_getattr);
+ 
++int vfs_getattr_lite(struct vfsmount *mnt, struct dentry *dentry, struct kstat_lite *stat_lite)
++{
++	struct inode *inode = dentry->d_inode;
++	int retval;
++
++	retval = security_inode_getattr(mnt, dentry);
++	if (retval)
++		return retval;
++
++	if (inode->i_op->getattr_lite)
++		return inode->i_op->getattr_lite(mnt, dentry, stat_lite);
++
++	generic_fillattr_lite(inode, stat_lite);
++	if (!stat_lite->blksize) {
++		struct super_block *s = inode->i_sb;
++		unsigned blocks;
++		blocks = (stat_lite->size+s->s_blocksize-1) >> s->s_blocksize_bits;
++		stat_lite->blocks = (s->s_blocksize / 512) * blocks;
++		stat_lite->blksize = s->s_blocksize;
++	}
++	return 0;
++}
++
++EXPORT_SYMBOL_GPL(vfs_getattr_lite);
++
+ int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
+ {
+ 	struct nameidata nd;
+@@ -76,6 +128,19 @@
+ 	return error;
+ }
+ 
++int vfs_statlite_fd(int dfd, char __user *name, struct kstat_lite *stat_lite)
++{
++	struct nameidata nd;
++	int error;
++
++	error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
++	if (!error) {
++		error = vfs_getattr_lite(nd.mnt, nd.dentry, stat_lite);
++		path_release(&nd);
++	}
++	return error;
++}
++
+ int vfs_stat(char __user *name, struct kstat *stat)
+ {
+ 	return vfs_stat_fd(AT_FDCWD, name, stat);
+@@ -83,6 +148,13 @@
+ 
+ EXPORT_SYMBOL(vfs_stat);
+ 
++int vfs_statlite(char __user *name, struct kstat_lite *stat_lite)
++{
++	return vfs_statlite_fd(AT_FDCWD, name, stat_lite);
++}
++
++EXPORT_SYMBOL_GPL(vfs_statlite);
++
+ int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
+ {
+ 	struct nameidata nd;
+@@ -96,6 +168,19 @@
+ 	return error;
+ }
+ 
++int vfs_lstatlite_fd(int dfd, char __user *name, struct kstat_lite *stat_lite)
++{
++	struct nameidata nd;
++	int error;
++
++	error = __user_walk_fd(dfd, name, 0, &nd);
++	if (!error) {
++		error = vfs_getattr_lite(nd.mnt, nd.dentry, stat_lite);
++		path_release(&nd);
++	}
++	return error;
++}
++
+ int vfs_lstat(char __user *name, struct kstat *stat)
+ {
+ 	return vfs_lstat_fd(AT_FDCWD, name, stat);
+@@ -103,6 +188,13 @@
+ 
+ EXPORT_SYMBOL(vfs_lstat);
+ 
++int vfs_lstatlite(char __user *name, struct kstat_lite *stat_lite)
++{
++	return vfs_lstatlite_fd(AT_FDCWD, name, stat_lite);
++}
++
++EXPORT_SYMBOL_GPL(vfs_lstatlite);
++
+ int vfs_fstat(unsigned int fd, struct kstat *stat)
+ {
+ 	struct file *f = fget(fd);
+@@ -117,6 +209,20 @@
+ 
+ EXPORT_SYMBOL(vfs_fstat);
+ 
++int vfs_fstatlite(unsigned int fd, struct kstat_lite *stat_lite)
++{
++	struct file *f = fget(fd);
++	int error = -EBADF;
++
++	if (f) {
++		error = vfs_getattr_lite(f->f_vfsmnt, f->f_dentry, stat_lite);
++		fput(f);
++	}
++	return error;
++}
++
++EXPORT_SYMBOL_GPL(vfs_fstatlite);
++
+ #ifdef __ARCH_WANT_OLD_STAT
+ 
+ /*
+@@ -239,6 +345,81 @@
+ 	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)
++{
++	struct stat_lite tmp;
++
++#if BITS_PER_LONG == 32
++	if (!old_valid_dev(stat_lite->dev) || !old_valid_dev(stat_lite->rdev))
++		return -EOVERFLOW;
++#else
++	if (!new_valid_dev(stat_lite->dev) || !new_valid_dev(stat_lite->rdev))
++		return -EOVERFLOW;
++#endif
++
++	memset(&tmp, 0, sizeof(tmp));
++#if BITS_PER_LONG == 32
++	tmp.st_dev = old_encode_dev(stat_lite->dev);
++#else
++	tmp.st_dev = new_encode_dev(stat_lite->dev);
++#endif
++	tmp.st_ino = stat_lite->ino;
++	tmp.st_mode = stat_lite->mode;
++	tmp.st_nlink = stat_lite->nlink;
++	if (tmp.st_nlink != stat_lite->nlink)
++		return -EOVERFLOW;
++	SET_UID(tmp.st_uid, stat_lite->uid);
++	SET_GID(tmp.st_gid, stat_lite->gid);
++#if BITS_PER_LONG == 32
++	tmp.st_rdev = old_encode_dev(stat_lite->rdev);
++#else
++	tmp.st_rdev = new_encode_dev(stat_lite->rdev);
++#endif
++#if BITS_PER_LONG == 32
++	if (SLITE_SIZET(stat_lite->lite_mask) && stat_lite->size > MAX_NON_LFS)
++		return -EOVERFLOW;
++#endif
++	if (SLITE_SIZET(stat_lite->lite_mask)) {
++		tmp.st_size = stat_lite->size;
++		tmp.st_litemask |= S_SLITE_SIZET;
++	}
++	if (SLITE_ATIME(stat_lite->lite_mask)) {
++		tmp.st_atime = stat_lite->atime.tv_sec;
++		tmp.st_litemask |= S_SLITE_ATIME;
++	}
++	if (SLITE_MTIME(stat_lite->lite_mask)) {
++		tmp.st_mtime = stat_lite->mtime.tv_sec;
++		tmp.st_litemask |= S_SLITE_MTIME;
++	}
++	if (SLITE_CTIME(stat_lite->lite_mask)) {
++		tmp.st_ctime = stat_lite->ctime.tv_sec;
++		tmp.st_litemask |= S_SLITE_CTIME;
++	}
++#ifdef STAT_HAVE_NSEC
++	if (SLITE_ATIME(stat_lite->lite_mask)) {
++		tmp.st_atime_nsec = stat_lite->atime.tv_nsec;
++		tmp.st_litemask |= S_SLITE_ATIME;
++	}
++	if (SLITE_MTIME(stat_lite->lite_mask)) {
++		tmp.st_mtime_nsec = stat_lite->mtime.tv_nsec;
++		tmp.st_litemask |= S_SLITE_MTIME;
++	}
++	if (SLITE_CTIME(stat_lite->lite_mask)) {
++		tmp.st_ctime_nsec = stat_lite->ctime.tv_nsec;
++		tmp.st_litemask |= S_SLITE_CTIME;
++	}
++#endif
++	if (SLITE_BLOCKS(stat_lite->lite_mask)) {
++		tmp.st_blocks = stat_lite->blocks;
++		tmp.st_litemask |= S_SLITE_BLOCKS;
++	}
++	if (SLITE_BLKSIZE(stat_lite->lite_mask)) {
++		tmp.st_blksize = stat_lite->blksize;
++		tmp.st_litemask |= S_SLITE_BLKSIZE;
++	}
++	return copy_to_user(statlitebuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
++}
++
+ asmlinkage long sys_newstat(char __user *filename, struct stat __user *statbuf)
+ {
+ 	struct kstat stat;
+@@ -250,6 +431,17 @@
+ 	return error;
+ }
+ 
++asmlinkage long sys_newstatlite(char __user *filename, struct stat_lite __user *statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int error = vfs_statlite_fd(AT_FDCWD, filename, &stat_lite);
++
++	if (!error)
++		error = cp_new_statlite(&stat_lite, statlitebuf);
++
++	return error;
++}
++
+ asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
+ {
+ 	struct kstat stat;
+@@ -261,6 +453,17 @@
+ 	return error;
+ }
+ 
++asmlinkage long sys_newlstatlite(char __user *filename, struct stat_lite __user *statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int error = vfs_lstatlite_fd(AT_FDCWD, filename, &stat_lite);
++
++	if (!error)
++		error = cp_new_statlite(&stat_lite, statlitebuf);
++
++	return error;
++}
++
+ #ifndef __ARCH_WANT_STAT64
+ asmlinkage long sys_newfstatat(int dfd, char __user *filename,
+ 				struct stat __user *statbuf, int flag)
+@@ -295,6 +498,17 @@
+ 	return error;
+ }
+ 
++asmlinkage long sys_newfstatlite(unsigned int fd, struct stat_lite __user *statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int error = vfs_fstatlite(fd, &stat_lite);
++
++	if (!error)
++		error = cp_new_statlite(&stat_lite, statlitebuf);
++
++	return error;
++}
++
+ asmlinkage long sys_readlinkat(int dfd, const char __user *path,
+ 				char __user *buf, int bufsiz)
+ {
+@@ -366,6 +580,60 @@
+ 	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)
++{
++	struct stat64_lite tmp;
++
++	memset(&tmp, 0, sizeof(struct stat64_lite));
++#ifdef CONFIG_MIPS
++	/* mips has weird padding, so we don't get 64 bits there */
++	if (!new_valid_dev(stat_lite->dev) || !new_valid_dev(stat_lite->rdev))
++		return -EOVERFLOW;
++	tmp.st_dev = new_encode_dev(stat_lite->dev);
++	tmp.st_rdev = new_encode_dev(stat_lite->rdev);
++#else
++	tmp.st_dev = huge_encode_dev(stat_lite->dev);
++	tmp.st_rdev = huge_encode_dev(stat_lite->rdev);
++#endif
++	tmp.st_ino = stat_lite->ino;
++#ifdef STAT64_HAS_BROKEN_ST_INO
++	tmp.__st_ino = stat_lite->ino;
++#endif
++	tmp.st_mode = stat_lite->mode;
++	tmp.st_nlink = stat_lite->nlink;
++	tmp.st_uid = stat_lite->uid;
++	tmp.st_gid = stat_lite->gid;
++
++	if (SLITE_ATIME(stat_lite->lite_mask)) {
++		tmp.st_atime = stat_lite->atime.tv_sec;
++		tmp.st_atime_nsec = stat_lite->atime.tv_nsec;
++		tmp.st_litemask |= S_SLITE_ATIME;
++	}
++	if (SLITE_MTIME(stat_lite->lite_mask)) {
++		tmp.st_mtime = stat_lite->mtime.tv_sec;
++		tmp.st_mtime_nsec = stat_lite->mtime.tv_nsec;
++		tmp.st_litemask |= S_SLITE_MTIME;
++	}
++	if (SLITE_CTIME(stat_lite->lite_mask)) {
++		tmp.st_ctime = stat_lite->ctime.tv_sec;
++		tmp.st_ctime_nsec = stat_lite->ctime.tv_nsec;
++		tmp.st_litemask |= S_SLITE_CTIME;
++	}
++	if (SLITE_SIZET(stat_lite->lite_mask)) {
++		tmp.st_size = stat_lite->size;
++		tmp.st_litemask |= S_SLITE_SIZET;
++	}
++	if (SLITE_BLOCKS(stat_lite->lite_mask)) {
++		tmp.st_blocks = stat_lite->blocks;
++		tmp.st_litemask |= S_SLITE_BLOCKS;
++	}
++	if (SLITE_BLKSIZE(stat_lite->lite_mask)) {
++		tmp.st_blksize = stat_lite->blksize;
++		tmp.st_litemask |= S_SLITE_BLKSIZE;
++	}
++	return copy_to_user(statlitebuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
++}
++
+ asmlinkage long sys_stat64(char __user * filename, struct stat64 __user * statbuf)
+ {
+ 	struct kstat stat;
+@@ -376,6 +644,18 @@
+ 
+ 	return error;
+ }
++
++asmlinkage long sys_statlite64(char __user * filename, struct stat64_lite __user * statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int error = vfs_statlite(filename, &stat_lite);
++
++	if (!error)
++		error = cp_new_stat64_lite(&stat_lite, statlitebuf);
++
++	return error;
++}
++
+ asmlinkage long sys_lstat64(char __user * filename, struct stat64 __user * statbuf)
+ {
+ 	struct kstat stat;
+@@ -386,6 +666,18 @@
+ 
+ 	return error;
+ }
++
++asmlinkage long sys_lstatlite64(char __user * filename, struct stat64_lite __user * statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int error = vfs_lstatlite(filename, &stat_lite);
++
++	if (!error)
++		error = cp_new_stat64_lite(&stat_lite, statlitebuf);
++
++	return error;
++}
++
+ asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user * statbuf)
+ {
+ 	struct kstat stat;
+@@ -397,6 +689,17 @@
+ 	return error;
+ }
+ 
++asmlinkage long sys_fstatlite64(unsigned long fd, struct stat64_lite __user * statlitebuf)
++{
++	struct kstat_lite stat_lite;
++	int error = vfs_fstatlite(fd, &stat_lite);
++
++	if (!error)
++		error = cp_new_stat64_lite(&stat_lite, statlitebuf);
++
++	return error;
++}
++
+ asmlinkage long sys_fstatat64(int dfd, char __user *filename,
+ 			       struct stat64 __user *statbuf, int flag)
+ {
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-i386/stat.h vanilla-new/include/asm-i386/stat.h
+--- vanilla/include/asm-i386/stat.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/asm-i386/stat.h	2006-05-05 16:58:22.000000000 -0500
+@@ -36,6 +36,28 @@
+ 	unsigned long  __unused5;
+ };
+ 
++struct stat_lite {
++	unsigned long  st_dev;
++	unsigned long  st_ino;
++	unsigned short st_mode;
++	unsigned short st_nlink;
++	unsigned short st_uid;
++	unsigned short st_gid;
++	unsigned long  st_rdev;
++	unsigned long  st_litemask;
++	unsigned long  st_size;
++	unsigned long  st_blksize;
++	unsigned long  st_blocks;
++	unsigned long  st_atime;
++	unsigned long  st_atime_nsec;
++	unsigned long  st_mtime;
++	unsigned long  st_mtime_nsec;
++	unsigned long  st_ctime;
++	unsigned long  st_ctime_nsec;
++	unsigned long  __unused4;
++	unsigned long  __unused5;
++};
++
+ /* This matches struct stat64 in glibc2.1, hence the absolutely
+  * insane amounts of padding around dev_t's.
+  */
+@@ -75,4 +97,41 @@
+ 
+ #define STAT_HAVE_NSEC 1
+ 
++struct stat64_lite {
++	unsigned long long	st_dev;
++	unsigned char	__pad0[4];
++
++#define STAT64_HAS_BROKEN_ST_INO	1
++	unsigned long	__st_ino;
++
++	unsigned int	st_mode;
++	unsigned int	st_nlink;
++
++	unsigned long	st_uid;
++	unsigned long	st_gid;
++
++	unsigned long long	st_rdev;
++	unsigned char	__pad3[4];
++
++	unsigned long  st_litemask;
++	unsigned char  __pad5[4];
++
++	long long	st_size;
++	unsigned long	st_blksize;
++
++	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
++	unsigned long	__pad4;		/* future possible st_blocks high bits */
++
++	unsigned long	st_atime;
++	unsigned long	st_atime_nsec;
++
++	unsigned long	st_mtime;
++	unsigned int	st_mtime_nsec;
++
++	unsigned long	st_ctime;
++	unsigned long	st_ctime_nsec;
++
++	unsigned long long	st_ino;
++};
++
+ #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-05 13:59:14.000000000 -0500
++++ vanilla-new/include/asm-i386/unistd.h	2006-05-05 15:22:38.000000000 -0500
+@@ -318,8 +318,14 @@
+ #define __NR_unshare		310
+ #define __NR_openg      311
+ #define __NR_openfh     312
++#define __NR_newstatlite 313
++#define __NR_newlstatlite 314
++#define __NR_newfstatlite 315
++#define __NR_statlite64  316
++#define __NR_lstatlite64 317
++#define __NR_fstatlite64 318
+ 
+-#define NR_syscalls 313
++#define NR_syscalls 319
+ 
+ /*
+  * 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-05 13:59:14.000000000 -0500
++++ vanilla-new/include/asm-ia64/unistd.h	2006-05-05 15:27:03.000000000 -0500
+@@ -287,12 +287,15 @@
+ #define __NR_unshare			1296
+ #define __NR_openg         1297
+ #define __NR_openfh        1298
++#define __NR_statlite      1299
++#define __NR_lstatlite     1300
++#define __NR_fstatlite     1301
+ 
+ #ifdef __KERNEL__
+ 
+ #include <linux/config.h>
+ 
+-#define NR_syscalls			275 /* length of syscall table */
++#define NR_syscalls			278 /* 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/stat.h vanilla-new/include/asm-powerpc/stat.h
+--- vanilla/include/asm-powerpc/stat.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/asm-powerpc/stat.h	2006-05-05 11:48:16.000000000 -0500
+@@ -55,6 +55,37 @@
+ #endif
+ };
+ 
++struct stat_lite {
++	unsigned long	st_dev;
++	ino_t		st_ino;
++#ifdef __powerpc64__
++	nlink_t		st_nlink;
++	mode_t		st_mode;
++#else
++	mode_t		st_mode;
++	nlink_t		st_nlink;
++#endif
++	uid_t		st_uid;
++	gid_t		st_gid;
++	unsigned long	st_rdev;
++	unsigned long  st_litemask;
++	off_t		st_size;
++	unsigned long	st_blksize;
++	unsigned long	st_blocks;
++	unsigned long	st_atime;
++	unsigned long	st_atime_nsec;
++	unsigned long	st_mtime;
++	unsigned long	st_mtime_nsec;
++	unsigned long	st_ctime;
++	unsigned long	st_ctime_nsec;
++	unsigned long	__unused4;
++	unsigned long	__unused5;
++#ifdef __powerpc64__
++	unsigned long	__unused6;
++#endif
++};
++
++
+ /* This matches struct stat64 in glibc2.1. Only used for 32 bit. */
+ struct stat64 {
+ 	unsigned long long st_dev;		/* Device.  */
+@@ -78,4 +109,28 @@
+ 	unsigned int	__unused5;
+ };
+ 
++/* This matches struct stat64_lite in glibc2.1. Only used for 32 bit. */
++struct stat64_lite {
++	unsigned long long st_dev;		/* Device.  */
++	unsigned long long st_ino;		/* File serial number.  */
++	unsigned int	st_mode;	/* File mode.  */
++	unsigned int	st_nlink;	/* Link count.  */
++	unsigned int	st_uid;		/* User ID of the file's owner.  */
++	unsigned int	st_gid;		/* Group ID of the file's group. */
++	unsigned long long st_rdev;	/* Device number, if device.  */
++	unsigned short	__pad2;
++	unsigned long  st_litemask;
++	long long	st_size;	/* Size of file, in bytes.  */
++	int		st_blksize;	/* Optimal block size for I/O.  */
++	long long	st_blocks;	/* Number 512-byte blocks allocated. */
++	int		st_atime;	/* Time of last access.  */
++	unsigned int	st_atime_nsec;
++	int		st_mtime;	/* Time of last modification.  */
++	unsigned int	st_mtime_nsec;
++	int		st_ctime;	/* Time of last status change.  */
++	unsigned int	st_ctime_nsec;
++	unsigned int	__unused4;
++	unsigned int	__unused5;
++};
++
+ #endif /* _ASM_POWERPC_STAT_H */
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-x86_64/compat.h vanilla-new/include/asm-x86_64/compat.h
+--- vanilla/include/asm-x86_64/compat.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/asm-x86_64/compat.h	2006-05-05 13:56:12.000000000 -0500
+@@ -69,6 +69,30 @@
+ 	u32		__unused5;
+ };
+ 
++struct compat_stat_lite {
++	compat_dev_t	st_dev;
++	u16		__pad1;
++	compat_ino_t	st_ino;
++	compat_mode_t	st_mode;
++	compat_nlink_t	st_nlink;
++	__compat_uid_t	st_uid;
++	__compat_gid_t	st_gid;
++	compat_dev_t	st_rdev;
++	u16		__pad2;
++	u32      st_litemask;
++	u32		st_size;
++	u32		st_blksize;
++	u32		st_blocks;
++	u32		st_atime;
++	u32		st_atime_nsec;
++	u32		st_mtime;
++	u32		st_mtime_nsec;
++	u32		st_ctime;
++	u32		st_ctime_nsec;
++	u32		__unused4;
++	u32		__unused5;
++};
++
+ struct compat_flock {
+ 	short		l_type;
+ 	short		l_whence;
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/asm-x86_64/stat.h vanilla-new/include/asm-x86_64/stat.h
+--- vanilla/include/asm-x86_64/stat.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/asm-x86_64/stat.h	2006-05-05 17:05:54.000000000 -0500
+@@ -26,6 +26,30 @@
+   	long		__unused[3];
+ };
+ 
++struct stat_lite {
++	unsigned long	st_dev;
++	unsigned long	st_ino;
++	unsigned long	st_nlink;
++
++	unsigned int	st_mode;
++	unsigned int	st_uid;
++	unsigned int	st_gid;
++	unsigned int	__pad0;
++	unsigned long	st_rdev;
++	unsigned long  st_litemask;
++	long		st_size;
++	long		st_blksize;
++	long		st_blocks;	/* Number 512-byte blocks allocated. */
++
++	unsigned long	st_atime;
++	unsigned long 	st_atime_nsec; 
++	unsigned long	st_mtime;
++	unsigned long	st_mtime_nsec;
++	unsigned long	st_ctime;
++	unsigned long   st_ctime_nsec;
++  	long		__unused[3];
++};
++
+ /* For 32bit emulation */
+ struct __old_kernel_stat {
+ 	unsigned short st_dev;
+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-05 13:59:14.000000000 -0500
++++ vanilla-new/include/asm-x86_64/unistd.h	2006-05-05 15:18:33.000000000 -0500
+@@ -609,8 +609,14 @@
+ __SYSCALL(__NR_openg,   sys_openg)
+ #define __NR_openfh     274
+ __SYSCALL(__NR_openfh,  sys_openfh)
++#define __NR_newstatlite   275
++__SYSCALL(__NR_newstatlite, sys_newstatlite)
++#define __NR_newlstatlite  276
++__SYSCALL(__NR_newlstatlite, sys_newlstatlite)
++#define __NR_newfstatlite  277
++__SYSCALL(__NR_newfstatlite, sys_newfstatlite)
+ 
+-#define __NR_syscall_max __NR_openfh
++#define __NR_syscall_max __NR_newfstatlite
+ 
+ #ifndef __NO_STUBS
+ 
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/linux/compat.h vanilla-new/include/linux/compat.h
+--- vanilla/include/linux/compat.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/linux/compat.h	2006-05-05 16:19:58.000000000 -0500
+@@ -52,6 +52,7 @@
+ } compat_sigset_t;
+ 
+ extern int cp_compat_stat(struct kstat *, struct compat_stat __user *);
++extern int cp_compat_statlite(struct kstat_lite *, struct compat_stat_lite __user *);
+ extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *);
+ extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *);
+ 
+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-05 13:59:14.000000000 -0500
++++ vanilla-new/include/linux/fs.h	2006-05-05 16:55:19.000000000 -0500
+@@ -1065,6 +1065,7 @@
+ 	int (*permission) (struct inode *, int, struct nameidata *);
+ 	int (*setattr) (struct dentry *, struct iattr *);
+ 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
++	int (*getattr_lite) (struct vfsmount *mnt, struct dentry *, struct kstat_lite *);
+ 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+ 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
+ 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
+@@ -1702,7 +1703,9 @@
+ extern struct inode_operations page_symlink_inode_operations;
+ extern int generic_readlink(struct dentry *, char __user *, int);
+ extern void generic_fillattr(struct inode *, struct kstat *);
++extern void generic_fillattr_lite(struct inode *, struct kstat_lite *);
+ extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
++extern int vfs_getattr_lite(struct vfsmount *, struct dentry *, struct kstat_lite *);
+ void inode_add_bytes(struct inode *inode, loff_t bytes);
+ void inode_sub_bytes(struct inode *inode, loff_t bytes);
+ loff_t inode_get_bytes(struct inode *inode);
+@@ -1711,10 +1714,15 @@
+ extern int vfs_readdir(struct file *, filldir_t, void *);
+ 
+ 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 *);
++extern int vfs_lstatlite(char __user *, struct kstat_lite *);
+ extern int vfs_stat_fd(int dfd, char __user *, struct kstat *);
++extern int vfs_statlite_fd(int dfd, char __user *, struct kstat_lite *);
+ extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *);
++extern int vfs_lstatlite_fd(int dfd, char __user *, struct kstat_lite *);
+ extern int vfs_fstat(unsigned int, struct kstat *);
++extern int vfs_fstatlite(unsigned int, struct kstat_lite *);
+ 
+ extern int vfs_ioctl(struct file *, unsigned int, unsigned int, unsigned long);
+ 
+@@ -1728,6 +1736,7 @@
+ extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
+ extern int dcache_readdir(struct file *, void *, filldir_t);
+ extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
++extern int simple_getattr_lite(struct vfsmount *, struct dentry *, struct kstat_lite *);
+ extern int simple_statfs(struct super_block *, struct kstatfs *);
+ extern int simple_link(struct dentry *, struct inode *, struct dentry *);
+ extern int simple_unlink(struct inode *, struct dentry *);
+diff -Naur --exclude-from=/home/vilayann/redhat/BUILD/kernel-2.6.16/exclude vanilla/include/linux/stat.h vanilla-new/include/linux/stat.h
+--- vanilla/include/linux/stat.h	2006-03-19 23:53:29.000000000 -0600
++++ vanilla-new/include/linux/stat.h	2006-05-05 17:00:11.000000000 -0500
+@@ -44,6 +44,22 @@
+ #define S_IWOTH 00002
+ #define S_IXOTH 00001
+ 
++#define S_SLITE_SIZET     0x1
++#define S_SLITE_BLKSIZE   0x2
++#define S_SLITE_BLOCKS    0x4
++#define S_SLITE_ATIME     0x8
++#define S_SLITE_MTIME     0x10
++#define S_SLITE_CTIME     0x20
++#define S_SLITE_ALL       (S_SLITE_SIZET | S_SLITE_BLKSIZE | S_SLITE_BLOCKS \
++									S_SLITE_ATIME | S_SLITE_MTIME   | S_SLITE_CTIME)
++
++#define SLITE_SIZET(m)    ((m) & S_SLITE_SIZET)
++#define SLITE_BLKSIZE(m)  ((m) & S_SLITE_BLKSIZE)
++#define SLITE_BLOCKS(m)   ((m) & S_SLITE_BLOCKS)
++#define SLITE_ATIME(m)    ((m) & S_SLITE_ATIME)
++#define SLITE_MTIME(m)    ((m) & S_SLITE_MTIME)
++#define SLITE_CTIME(m)    ((m) & S_SLITE_CTIME)
++
+ #endif
+ 
+ #ifdef __KERNEL__
+@@ -72,6 +88,24 @@
+ 	unsigned long	blocks;
+ };
+ 
++struct kstat_lite {
++	unsigned long	ino;
++	dev_t		dev;
++	umode_t		mode;
++	unsigned int	nlink;
++	uid_t		uid;
++	gid_t		gid;
++	dev_t		rdev;
++	unsigned long  lite_mask;
++	/* Fields below this are optional */
++	loff_t		size;
++	struct timespec  atime;
++	struct timespec	mtime;
++	struct timespec	ctime;
++	unsigned long	blksize;
++	unsigned long	blocks;
++};
++
+ #endif
+ 
+ #endif
+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-05 13:59:14.000000000 -0500
++++ vanilla-new/include/linux/syscalls.h	2006-05-05 17:12:01.000000000 -0500
+@@ -38,7 +38,9 @@
+ struct shmid_ds;
+ struct sockaddr;
+ struct stat;
++struct stat_lite;
+ struct stat64;
++struct stat64_lite;
+ struct statfs;
+ struct statfs64;
+ struct __sysctl_args;
+@@ -226,16 +228,29 @@
+ 			struct __old_kernel_stat __user *statbuf);
+ asmlinkage long sys_newstat(char __user *filename,
+ 				struct stat __user *statbuf);
++asmlinkage long sys_newstatlite(char __user *filename,
++				struct stat_lite __user *statlitebuf);
+ asmlinkage long sys_newlstat(char __user *filename,
+ 				struct stat __user *statbuf);
++asmlinkage long sys_newlstatlite(char __user *filename,
++				struct stat_lite __user *statlitebuf);
+ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf);
++asmlinkage long sys_newfstatlite(unsigned int fd, 
++				struct stat_lite __user *statlitebuf);
+ asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf);
+ #if BITS_PER_LONG == 32
+ asmlinkage long sys_stat64(char __user *filename,
+ 				struct stat64 __user *statbuf);
+-asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf);
++asmlinkage long sys_statlite64(char __user *filename,
++				struct stat64_lite __user *statlitebuf);
++asmlinkage long sys_fstat64(unsigned long fd, 
++				struct stat64 __user *statbuf);
++asmlinkage long sys_fstatlite64(unsigned long fd,
++				struct stat64_lite __user *statlitebuf);
+ asmlinkage long sys_lstat64(char __user *filename,
+ 				struct stat64 __user *statbuf);
++asmlinkage long sys_lstatlite64(char __user *filename,
++				struct stat64_lite __user *statlitebuf);
+ asmlinkage long sys_truncate64(const char __user *path, loff_t length);
+ asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length);
+ #endif



More information about the Pvfs2-cvs mailing list