Re: [PATCH] s390: getdents patch for 32 -> 64 converter

2005-02-02 Thread Martin Schwidefsky
Hi Sripathi,

> This patch solves a problem with working of getdents while using 32 bit 
> binaries on 64 bit Linux/390. glibc expects d_type to be passed if we 
> have a kernel version after 2.6.4, so we have to also handle it in the 
> 32bit syscall converter. Similar patch was given for PPC by Marcus 
> Meissner 
> (http://ozlabs.org/pipermail/linuxppc64-dev/2004-March/001359.html) and 
> was integrated into 2.6.5.

thanks for bringing this to my attention. This is indeed broken,
but I prefer a different solution: remove the s390 specific compat
functions and use the generic ones. 

Andrew, would you please add this to your patch collection?

blue skies,
  Martin.

---

[patch] s390: compat_sys_old_readdir and compat_sys_getdents.

From: Sripathi Kodi <[EMAIL PROTECTED]>
From: Martin Schwidefsky <[EMAIL PROTECTED]>

s390 should use the generic compat functions for compat_sys_old_readdir
and compat_sys_getdents. The s390 specific ones are buggy and superflous.

Signed-off-by: Martin Schwidefsky <[EMAIL PROTECTED]>

diffstat:
 arch/s390/kernel/compat_linux.c   |  130 --
 arch/s390/kernel/compat_wrapper.S |4 -
 2 files changed, 2 insertions(+), 132 deletions(-)

diff -urN linux-2.6/arch/s390/kernel/compat_linux.c 
linux-2.6-patched/arch/s390/kernel/compat_linux.c
--- linux-2.6/arch/s390/kernel/compat_linux.c   2005-02-02 13:47:25.0 
+0100
+++ linux-2.6-patched/arch/s390/kernel/compat_linux.c   2005-02-02 
13:50:32.0 +0100
@@ -355,136 +355,6 @@
return sys_ftruncate(fd, (high << 32) | low);
 }
 
-/* readdir & getdents */
-
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
-#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
-
-struct old_linux_dirent32 {
-   u32 d_ino;
-   u32 d_offset;
-   unsigned short  d_namlen;
-   chard_name[1];
-};
-
-struct readdir_callback32 {
-   struct old_linux_dirent32 * dirent;
-   int count;
-};
-
-static int fillonedir(void * __buf, const char * name, int namlen,
- loff_t offset, ino_t ino, unsigned int d_type)
-{
-   struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
-   struct old_linux_dirent32 * dirent;
-
-   if (buf->count)
-   return -EINVAL;
-   buf->count++;
-   dirent = buf->dirent;
-   put_user(ino, >d_ino);
-   put_user(offset, >d_offset);
-   put_user(namlen, >d_namlen);
-   copy_to_user(dirent->d_name, name, namlen);
-   put_user(0, dirent->d_name + namlen);
-   return 0;
-}
-
-asmlinkage long old32_readdir(unsigned int fd, struct old_linux_dirent32 
*dirent, unsigned int count)
-{
-   int error = -EBADF;
-   struct file * file;
-   struct readdir_callback32 buf;
-
-   file = fget(fd);
-   if (!file)
-   goto out;
-
-   buf.count = 0;
-   buf.dirent = dirent;
-
-   error = vfs_readdir(file, fillonedir, );
-   if (error < 0)
-   goto out_putf;
-   error = buf.count;
-
-out_putf:
-   fput(file);
-out:
-   return error;
-}
-
-struct linux_dirent32 {
-   u32 d_ino;
-   u32 d_off;
-   unsigned short  d_reclen;
-   chard_name[1];
-};
-
-struct getdents_callback32 {
-   struct linux_dirent32 * current_dir;
-   struct linux_dirent32 * previous;
-   int count;
-   int error;
-};
-
-static int filldir(void * __buf, const char * name, int namlen, loff_t offset, 
ino_t ino,
-  unsigned int d_type)
-{
-   struct linux_dirent32 * dirent;
-   struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
-   int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
-
-   buf->error = -EINVAL;   /* only used if we fail.. */
-   if (reclen > buf->count)
-   return -EINVAL;
-   dirent = buf->previous;
-   if (dirent)
-   put_user(offset, >d_off);
-   dirent = buf->current_dir;
-   buf->previous = dirent;
-   put_user(ino, >d_ino);
-   put_user(reclen, >d_reclen);
-   copy_to_user(dirent->d_name, name, namlen);
-   put_user(0, dirent->d_name + namlen);
-   buf->current_dir = ((void *)dirent) + reclen;
-   buf->count -= reclen;
-   return 0;
-}
-
-asmlinkage long sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, 
unsigned int count)
-{
-   struct file * file;
-   struct linux_dirent32 * lastdirent;
-   struct getdents_callback32 buf;
-   int error = -EBADF;
-
-   file = fget(fd);
-   if (!file)
-   goto out;
-
-   buf.current_dir = dirent;
-   buf.previous = NULL;
-   buf.count = count;
-   buf.error = 0;
-
-   error = vfs_readdir(file, filldir, );
-   if (error < 0)
-   goto out_putf;
-   lastdirent = buf.previous;
-   error = buf.error;
-   if(lastdirent) {
-   

Re: [PATCH] s390: getdents patch for 32 - 64 converter

2005-02-02 Thread Martin Schwidefsky
Hi Sripathi,

 This patch solves a problem with working of getdents while using 32 bit 
 binaries on 64 bit Linux/390. glibc expects d_type to be passed if we 
 have a kernel version after 2.6.4, so we have to also handle it in the 
 32bit syscall converter. Similar patch was given for PPC by Marcus 
 Meissner 
 (http://ozlabs.org/pipermail/linuxppc64-dev/2004-March/001359.html) and 
 was integrated into 2.6.5.

thanks for bringing this to my attention. This is indeed broken,
but I prefer a different solution: remove the s390 specific compat
functions and use the generic ones. 

Andrew, would you please add this to your patch collection?

blue skies,
  Martin.

---

[patch] s390: compat_sys_old_readdir and compat_sys_getdents.

From: Sripathi Kodi [EMAIL PROTECTED]
From: Martin Schwidefsky [EMAIL PROTECTED]

s390 should use the generic compat functions for compat_sys_old_readdir
and compat_sys_getdents. The s390 specific ones are buggy and superflous.

Signed-off-by: Martin Schwidefsky [EMAIL PROTECTED]

diffstat:
 arch/s390/kernel/compat_linux.c   |  130 --
 arch/s390/kernel/compat_wrapper.S |4 -
 2 files changed, 2 insertions(+), 132 deletions(-)

diff -urN linux-2.6/arch/s390/kernel/compat_linux.c 
linux-2.6-patched/arch/s390/kernel/compat_linux.c
--- linux-2.6/arch/s390/kernel/compat_linux.c   2005-02-02 13:47:25.0 
+0100
+++ linux-2.6-patched/arch/s390/kernel/compat_linux.c   2005-02-02 
13:50:32.0 +0100
@@ -355,136 +355,6 @@
return sys_ftruncate(fd, (high  32) | low);
 }
 
-/* readdir  getdents */
-
-#define NAME_OFFSET(de) ((int) ((de)-d_name - (char *) (de)))
-#define ROUND_UP(x) (((x)+sizeof(u32)-1)  ~(sizeof(u32)-1))
-
-struct old_linux_dirent32 {
-   u32 d_ino;
-   u32 d_offset;
-   unsigned short  d_namlen;
-   chard_name[1];
-};
-
-struct readdir_callback32 {
-   struct old_linux_dirent32 * dirent;
-   int count;
-};
-
-static int fillonedir(void * __buf, const char * name, int namlen,
- loff_t offset, ino_t ino, unsigned int d_type)
-{
-   struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
-   struct old_linux_dirent32 * dirent;
-
-   if (buf-count)
-   return -EINVAL;
-   buf-count++;
-   dirent = buf-dirent;
-   put_user(ino, dirent-d_ino);
-   put_user(offset, dirent-d_offset);
-   put_user(namlen, dirent-d_namlen);
-   copy_to_user(dirent-d_name, name, namlen);
-   put_user(0, dirent-d_name + namlen);
-   return 0;
-}
-
-asmlinkage long old32_readdir(unsigned int fd, struct old_linux_dirent32 
*dirent, unsigned int count)
-{
-   int error = -EBADF;
-   struct file * file;
-   struct readdir_callback32 buf;
-
-   file = fget(fd);
-   if (!file)
-   goto out;
-
-   buf.count = 0;
-   buf.dirent = dirent;
-
-   error = vfs_readdir(file, fillonedir, buf);
-   if (error  0)
-   goto out_putf;
-   error = buf.count;
-
-out_putf:
-   fput(file);
-out:
-   return error;
-}
-
-struct linux_dirent32 {
-   u32 d_ino;
-   u32 d_off;
-   unsigned short  d_reclen;
-   chard_name[1];
-};
-
-struct getdents_callback32 {
-   struct linux_dirent32 * current_dir;
-   struct linux_dirent32 * previous;
-   int count;
-   int error;
-};
-
-static int filldir(void * __buf, const char * name, int namlen, loff_t offset, 
ino_t ino,
-  unsigned int d_type)
-{
-   struct linux_dirent32 * dirent;
-   struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
-   int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
-
-   buf-error = -EINVAL;   /* only used if we fail.. */
-   if (reclen  buf-count)
-   return -EINVAL;
-   dirent = buf-previous;
-   if (dirent)
-   put_user(offset, dirent-d_off);
-   dirent = buf-current_dir;
-   buf-previous = dirent;
-   put_user(ino, dirent-d_ino);
-   put_user(reclen, dirent-d_reclen);
-   copy_to_user(dirent-d_name, name, namlen);
-   put_user(0, dirent-d_name + namlen);
-   buf-current_dir = ((void *)dirent) + reclen;
-   buf-count -= reclen;
-   return 0;
-}
-
-asmlinkage long sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, 
unsigned int count)
-{
-   struct file * file;
-   struct linux_dirent32 * lastdirent;
-   struct getdents_callback32 buf;
-   int error = -EBADF;
-
-   file = fget(fd);
-   if (!file)
-   goto out;
-
-   buf.current_dir = dirent;
-   buf.previous = NULL;
-   buf.count = count;
-   buf.error = 0;
-
-   error = vfs_readdir(file, filldir, buf);
-   if (error  0)
-   goto out_putf;
-   lastdirent = buf.previous;
-   error = buf.error;
-   if(lastdirent) {
-   

[PATCH] s390: getdents patch for 32 -> 64 converter

2005-02-01 Thread Sripathi Kodi
Hi,
This patch solves a problem with working of getdents while using 32 bit 
binaries on 64 bit Linux/390. glibc expects d_type to be passed if we 
have a kernel version after 2.6.4, so we have to also handle it in the 
32bit syscall converter. Similar patch was given for PPC by Marcus 
Meissner 
(http://ozlabs.org/pipermail/linuxppc64-dev/2004-March/001359.html) and 
was integrated into 2.6.5.

Thanks,
Sripathi.
Signed-off-by: Sripathi Kodi <[EMAIL PROTECTED]>
--- linux-2.6.10/arch/s390/kernel/compat_linux.c2004-12-25 
03:05:24.0 +0530
+++ /home/sripathi/12795/mainline/compat_linux.c2005-02-01 
14:06:33.0 +0530
@@ -433,7 +433,7 @@ static int filldir(void * __buf, const c
 {
struct linux_dirent32 * dirent;
struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
-   int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+   int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
 
buf->error = -EINVAL;   /* only used if we fail.. */
if (reclen > buf->count)
@@ -447,6 +447,7 @@ static int filldir(void * __buf, const c
put_user(reclen, >d_reclen);
copy_to_user(dirent->d_name, name, namlen);
put_user(0, dirent->d_name + namlen);
+   put_user(d_type, (char *) dirent + reclen - 1);
buf->current_dir = ((void *)dirent) + reclen;
buf->count -= reclen;
return 0;


[PATCH] s390: getdents patch for 32 - 64 converter

2005-02-01 Thread Sripathi Kodi
Hi,
This patch solves a problem with working of getdents while using 32 bit 
binaries on 64 bit Linux/390. glibc expects d_type to be passed if we 
have a kernel version after 2.6.4, so we have to also handle it in the 
32bit syscall converter. Similar patch was given for PPC by Marcus 
Meissner 
(http://ozlabs.org/pipermail/linuxppc64-dev/2004-March/001359.html) and 
was integrated into 2.6.5.

Thanks,
Sripathi.
Signed-off-by: Sripathi Kodi [EMAIL PROTECTED]
--- linux-2.6.10/arch/s390/kernel/compat_linux.c2004-12-25 
03:05:24.0 +0530
+++ /home/sripathi/12795/mainline/compat_linux.c2005-02-01 
14:06:33.0 +0530
@@ -433,7 +433,7 @@ static int filldir(void * __buf, const c
 {
struct linux_dirent32 * dirent;
struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
-   int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+   int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
 
buf-error = -EINVAL;   /* only used if we fail.. */
if (reclen  buf-count)
@@ -447,6 +447,7 @@ static int filldir(void * __buf, const c
put_user(reclen, dirent-d_reclen);
copy_to_user(dirent-d_name, name, namlen);
put_user(0, dirent-d_name + namlen);
+   put_user(d_type, (char *) dirent + reclen - 1);
buf-current_dir = ((void *)dirent) + reclen;
buf-count -= reclen;
return 0;