Re: [PATCH 3/7] revoke: core code

2007-03-11 Thread Pekka Enberg
On Fri, 2007-03-09 at 10:15 +0200, Pekka J Enberg wrote:
> > +  again:
> > +   restart_addr = zap_page_range(vma, start_addr, end_addr - start_addr,
> > + details);
> > +
> > +   need_break = need_resched() || need_lockbreak(details->i_mmap_lock);
> > +   if (need_break)
> > +   goto out_need_break;
> > +
> > +   if (restart_addr < end_addr) {
> > +   start_addr = restart_addr;
> > +   goto again;
> > +   }
> > +   return 0;
> > +
> > +  out_need_break:
> > +   spin_unlock(details->i_mmap_lock);
> > +   cond_resched();
> > +   spin_lock(details->i_mmap_lock);
> > +   return -EINTR;

On Fri, 2007-03-09 at 13:30 +0100, Peter Zijlstra wrote:
> I'm not sure this scheme works, given a sufficiently loaded machine,
> this might never complete.

Hmm, so what's the alternative? It's better to fail revoke than lock up
the box.

On Fri, 2007-03-09 at 13:30 +0100, Peter Zijlstra wrote:
> I'm never sure of operator precedence and prefer:
> 
>  (vma->vm_flags & VM_SHARED) && ...
> 
> which leaves no room for error.

Thanks, fixed.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/7] revoke: core code

2007-03-11 Thread Pekka Enberg
On Fri, 2007-03-09 at 10:15 +0200, Pekka J Enberg wrote:
  +  again:
  +   restart_addr = zap_page_range(vma, start_addr, end_addr - start_addr,
  + details);
  +
  +   need_break = need_resched() || need_lockbreak(details-i_mmap_lock);
  +   if (need_break)
  +   goto out_need_break;
  +
  +   if (restart_addr  end_addr) {
  +   start_addr = restart_addr;
  +   goto again;
  +   }
  +   return 0;
  +
  +  out_need_break:
  +   spin_unlock(details-i_mmap_lock);
  +   cond_resched();
  +   spin_lock(details-i_mmap_lock);
  +   return -EINTR;

On Fri, 2007-03-09 at 13:30 +0100, Peter Zijlstra wrote:
 I'm not sure this scheme works, given a sufficiently loaded machine,
 this might never complete.

Hmm, so what's the alternative? It's better to fail revoke than lock up
the box.

On Fri, 2007-03-09 at 13:30 +0100, Peter Zijlstra wrote:
 I'm never sure of operator precedence and prefer:
 
  (vma-vm_flags  VM_SHARED)  ...
 
 which leaves no room for error.

Thanks, fixed.

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/7] revoke: core code

2007-03-09 Thread Peter Zijlstra
On Fri, 2007-03-09 at 10:15 +0200, Pekka J Enberg wrote:

> +static int revoke_vma(struct vm_area_struct *vma, struct zap_details 
> *details)
> +{
> + unsigned long restart_addr, start_addr, end_addr;
> + int need_break;
> +
> + start_addr = vma->vm_start;
> + end_addr = vma->vm_end;
> +
> + /*
> +  * Not holding ->mmap_sem here.
> +  */
> + vma->vm_flags |= VM_REVOKED;
> + smp_mb();

Hmm, i_mmap_lock pins the vma and excludes modifications, but doesn't
exclude concurrent faults.

I guess its save.

> +  again:
> + restart_addr = zap_page_range(vma, start_addr, end_addr - start_addr,
> +   details);
> +
> + need_break = need_resched() || need_lockbreak(details->i_mmap_lock);
> + if (need_break)
> + goto out_need_break;
> +
> + if (restart_addr < end_addr) {
> + start_addr = restart_addr;
> + goto again;
> + }
> + return 0;
> +
> +  out_need_break:
> + spin_unlock(details->i_mmap_lock);
> + cond_resched();
> + spin_lock(details->i_mmap_lock);
> + return -EINTR;

I'm not sure this scheme works, given a sufficiently loaded machine,
this might never complete.

> +}
> +
> +static int revoke_mapping(struct address_space *mapping, struct file 
> *to_exclude)
> +{
> + struct vm_area_struct *vma;
> + struct prio_tree_iter iter;
> + struct zap_details details;
> + int err = 0;
> +
> + details.i_mmap_lock = >i_mmap_lock;
> +
> + spin_lock(>i_mmap_lock);
> + vma_prio_tree_foreach(vma, , >i_mmap, 0, ULONG_MAX) {
> + if (vma->vm_flags & VM_SHARED && vma->vm_file != to_exclude) {

I'm never sure of operator precedence and prefer:

 (vma->vm_flags & VM_SHARED) && ...

which leaves no room for error.

> + err = revoke_vma(vma, );
> + if (err)
> + goto out;
> + }
> + }
> +
> + list_for_each_entry(vma, >i_mmap_nonlinear, 
> shared.vm_set.list) {
> + if (vma->vm_flags & VM_SHARED && vma->vm_file != to_exclude) {

Idem.

> + err = revoke_vma(vma, );
> + if (err)
> + goto out;
> + }
> + }
> +  out:
> + spin_unlock(>i_mmap_lock);
> + return err;
> +}


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/7] revoke: core code

2007-03-09 Thread Pekka J Enberg
On Fri, 9 Mar 2007 10:15:15 +0200 (EET)
Pekka J Enberg <[EMAIL PROTECTED]> wrote:
> > +static ssize_t revoked_file_aio_read(struct kiocb *iocb,
> > +const struct iovec *iov,
> > +unsigned long nr_segs, loff_t pos)
> > +{
> > +   return -EBADF;
> > +}
 
On Fri, 9 Mar 2007, Alan Cox wrote:
> Do we need both -EBADF and -EXNIO versions. It is hard to tell from
> existing OS's as they don't support revoke of files just special files ?

No, we don't. We should always do EBADF except for close(2) which is zero 
always and make read(2) zero for special files.

On Fri, 9 Mar 2007 10:15:15 +0200 (EET)
Pekka J Enberg <[EMAIL PROTECTED]> wrote:
> > +static ssize_t revoked_special_file_read(struct file *filp, char __user * 
> > buf,
> > +size_t size, loff_t * ppos)
> > +{
> > +   return -ENXIO;
> > +}

On Fri, 9 Mar 2007, Alan Cox wrote:
> Bezerkly Unix returns 0 for the special file read case

Aah, I'll fix that up. Thanks.

Pekka
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/7] revoke: core code

2007-03-09 Thread Alan Cox
On Fri, 9 Mar 2007 10:15:15 +0200 (EET)
Pekka J Enberg <[EMAIL PROTECTED]> wrote:

> From: Pekka Enberg <[EMAIL PROTECTED]>
> 
> The revokeat(2) and frevoke(2) system calls invalidate open file
> descriptors and shared mappings of an inode. After an successful
> revocation, operations on file descriptors fail with the EBADF or
> ENXIO error code for regular and device files,
> respectively. Attempting to read from or write to a revoked mapping
> causes SIGBUS.

Acked-by: Alan Cox <[EMAIL PROTECTED]>


> +static ssize_t revoked_file_aio_read(struct kiocb *iocb,
> +  const struct iovec *iov,
> +  unsigned long nr_segs, loff_t pos)
> +{
> + return -EBADF;
> +}

Do we need both -EBADF and -EXNIO versions. It is hard to tell from
existing OS's as they don't support revoke of files just special files ?

> +static ssize_t revoked_special_file_read(struct file *filp, char __user * 
> buf,
> +  size_t size, loff_t * ppos)
> +{
> + return -ENXIO;
> +}

Bezerkly Unix returns 0 for the special file read case


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/7] revoke: core code

2007-03-09 Thread Pekka J Enberg
From: Pekka Enberg <[EMAIL PROTECTED]>

The revokeat(2) and frevoke(2) system calls invalidate open file
descriptors and shared mappings of an inode. After an successful
revocation, operations on file descriptors fail with the EBADF or
ENXIO error code for regular and device files,
respectively. Attempting to read from or write to a revoked mapping
causes SIGBUS.

The actual operation is done in two passes:

 1. Revoke all file descriptors that point to the given inode. We do
this under tasklist_lock so that after this pass, we don't need
to worry about racing with close(2) or dup(2).
   
 2. Take down shared memory mappings of the inode and close all file
pointers.

The file descriptors and memory mapping ranges are preserved until the
owning task does close(2) and munmap(2), respectively.

Signed-off-by: Pekka Enberg <[EMAIL PROTECTED]>
---
 fs/Makefile  |2 
 fs/revoke.c  |  633 
 fs/revoked_inode.c   |  668 +++
 include/linux/fs.h   |4 
 include/linux/syscalls.h |3 
 5 files changed, 1309 insertions(+), 1 deletion(-)

Index: uml-2.6/fs/Makefile
===
--- uml-2.6.orig/fs/Makefile2007-03-08 10:24:23.0 +0200
+++ uml-2.6/fs/Makefile 2007-03-08 10:24:32.0 +0200
@@ -11,7 +11,7 @@
attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
seq_file.o xattr.o libfs.o fs-writeback.o \
pnode.o drop_caches.o splice.o sync.o utimes.o \
-   stack.o
+   stack.o revoke.o revoked_inode.o
 
 ifeq ($(CONFIG_BLOCK),y)
 obj-y +=   buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
Index: uml-2.6/include/linux/syscalls.h
===
--- uml-2.6.orig/include/linux/syscalls.h   2007-03-08 10:24:24.0 
+0200
+++ uml-2.6/include/linux/syscalls.h2007-03-08 10:24:32.0 +0200
@@ -605,4 +605,7 @@
 
 int kernel_execve(const char *filename, char *const argv[], char *const 
envp[]);
 
+asmlinkage int sys_revokeat(int dfd, const char __user *filename);
+asmlinkage int sys_frevoke(unsigned int fd);
+
 #endif
Index: uml-2.6/include/linux/fs.h
===
--- uml-2.6.orig/include/linux/fs.h 2007-03-08 10:24:31.0 +0200
+++ uml-2.6/include/linux/fs.h  2007-03-08 10:24:32.0 +0200
@@ -1102,6 +1102,7 @@
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t 
*, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info 
*, size_t, unsigned int);
+   int (*revoke)(struct file *);
 };
 
 struct inode_operations {
@@ -1741,6 +1742,9 @@
 extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
size_t len, unsigned int flags);
 
+/* fs/revoke.c */
+extern int generic_file_revoke(struct file *);
+
 extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
Index: uml-2.6/fs/revoke.c
===
--- /dev/null   1970-01-01 00:00:00.0 +
+++ uml-2.6/fs/revoke.c 2007-03-08 10:24:32.0 +0200
@@ -0,0 +1,633 @@
+/*
+ * fs/revoke.c - Invalidate all current open file descriptors of an inode.
+ *
+ * Copyright (C) 2006-2007  Pekka Enberg
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * This is used for pre-allocating an array of file pointers so that we don't
+ * have to do memory allocation under tasklist_lock.
+ */
+struct revoke_table {
+   struct file **files;
+   unsigned long size;
+   unsigned long end;
+   unsigned long restore_start;
+};
+
+struct kmem_cache *revokefs_inode_cache;
+
+/*
+ * Revoked file descriptors point to inodes in the revokefs filesystem.
+ */
+static struct vfsmount *revokefs_mnt;
+
+struct revokefs_inode_info {
+   struct task_struct *owner;
+   struct file *file;
+   unsigned int fd;
+   struct inode vfs_inode;
+};
+
+static inline struct revokefs_inode_info *revokefs_i(struct inode *inode)
+{
+   return container_of(inode, struct revokefs_inode_info, vfs_inode);
+}
+
+extern void make_revoked_inode(struct inode *, int);
+
+static struct file *get_revoked_file(void)
+{
+   struct dentry *dentry;
+   struct inode *inode;
+   struct file *filp;
+   struct qstr name;
+
+   filp = get_empty_filp();
+   if (!filp)
+   goto err;
+
+   inode = new_inode(revokefs_mnt->mnt_sb);
+   if (!inode)
+   goto err_inode;
+
+   name.name = "revoked_file";

[PATCH 3/7] revoke: core code

2007-03-09 Thread Pekka J Enberg
From: Pekka Enberg [EMAIL PROTECTED]

The revokeat(2) and frevoke(2) system calls invalidate open file
descriptors and shared mappings of an inode. After an successful
revocation, operations on file descriptors fail with the EBADF or
ENXIO error code for regular and device files,
respectively. Attempting to read from or write to a revoked mapping
causes SIGBUS.

The actual operation is done in two passes:

 1. Revoke all file descriptors that point to the given inode. We do
this under tasklist_lock so that after this pass, we don't need
to worry about racing with close(2) or dup(2).
   
 2. Take down shared memory mappings of the inode and close all file
pointers.

The file descriptors and memory mapping ranges are preserved until the
owning task does close(2) and munmap(2), respectively.

Signed-off-by: Pekka Enberg [EMAIL PROTECTED]
---
 fs/Makefile  |2 
 fs/revoke.c  |  633 
 fs/revoked_inode.c   |  668 +++
 include/linux/fs.h   |4 
 include/linux/syscalls.h |3 
 5 files changed, 1309 insertions(+), 1 deletion(-)

Index: uml-2.6/fs/Makefile
===
--- uml-2.6.orig/fs/Makefile2007-03-08 10:24:23.0 +0200
+++ uml-2.6/fs/Makefile 2007-03-08 10:24:32.0 +0200
@@ -11,7 +11,7 @@
attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
seq_file.o xattr.o libfs.o fs-writeback.o \
pnode.o drop_caches.o splice.o sync.o utimes.o \
-   stack.o
+   stack.o revoke.o revoked_inode.o
 
 ifeq ($(CONFIG_BLOCK),y)
 obj-y +=   buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
Index: uml-2.6/include/linux/syscalls.h
===
--- uml-2.6.orig/include/linux/syscalls.h   2007-03-08 10:24:24.0 
+0200
+++ uml-2.6/include/linux/syscalls.h2007-03-08 10:24:32.0 +0200
@@ -605,4 +605,7 @@
 
 int kernel_execve(const char *filename, char *const argv[], char *const 
envp[]);
 
+asmlinkage int sys_revokeat(int dfd, const char __user *filename);
+asmlinkage int sys_frevoke(unsigned int fd);
+
 #endif
Index: uml-2.6/include/linux/fs.h
===
--- uml-2.6.orig/include/linux/fs.h 2007-03-08 10:24:31.0 +0200
+++ uml-2.6/include/linux/fs.h  2007-03-08 10:24:32.0 +0200
@@ -1102,6 +1102,7 @@
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t 
*, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info 
*, size_t, unsigned int);
+   int (*revoke)(struct file *);
 };
 
 struct inode_operations {
@@ -1741,6 +1742,9 @@
 extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
size_t len, unsigned int flags);
 
+/* fs/revoke.c */
+extern int generic_file_revoke(struct file *);
+
 extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
Index: uml-2.6/fs/revoke.c
===
--- /dev/null   1970-01-01 00:00:00.0 +
+++ uml-2.6/fs/revoke.c 2007-03-08 10:24:32.0 +0200
@@ -0,0 +1,633 @@
+/*
+ * fs/revoke.c - Invalidate all current open file descriptors of an inode.
+ *
+ * Copyright (C) 2006-2007  Pekka Enberg
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include linux/file.h
+#include linux/fs.h
+#include linux/namei.h
+#include linux/mm.h
+#include linux/mman.h
+#include linux/module.h
+#include linux/mount.h
+#include linux/sched.h
+
+/*
+ * This is used for pre-allocating an array of file pointers so that we don't
+ * have to do memory allocation under tasklist_lock.
+ */
+struct revoke_table {
+   struct file **files;
+   unsigned long size;
+   unsigned long end;
+   unsigned long restore_start;
+};
+
+struct kmem_cache *revokefs_inode_cache;
+
+/*
+ * Revoked file descriptors point to inodes in the revokefs filesystem.
+ */
+static struct vfsmount *revokefs_mnt;
+
+struct revokefs_inode_info {
+   struct task_struct *owner;
+   struct file *file;
+   unsigned int fd;
+   struct inode vfs_inode;
+};
+
+static inline struct revokefs_inode_info *revokefs_i(struct inode *inode)
+{
+   return container_of(inode, struct revokefs_inode_info, vfs_inode);
+}
+
+extern void make_revoked_inode(struct inode *, int);
+
+static struct file *get_revoked_file(void)
+{
+   struct dentry *dentry;
+   struct inode *inode;
+   struct file *filp;
+   struct qstr name;
+
+   filp = get_empty_filp();
+   if (!filp)
+   goto err;
+
+   inode = 

Re: [PATCH 3/7] revoke: core code

2007-03-09 Thread Alan Cox
On Fri, 9 Mar 2007 10:15:15 +0200 (EET)
Pekka J Enberg [EMAIL PROTECTED] wrote:

 From: Pekka Enberg [EMAIL PROTECTED]
 
 The revokeat(2) and frevoke(2) system calls invalidate open file
 descriptors and shared mappings of an inode. After an successful
 revocation, operations on file descriptors fail with the EBADF or
 ENXIO error code for regular and device files,
 respectively. Attempting to read from or write to a revoked mapping
 causes SIGBUS.

Acked-by: Alan Cox [EMAIL PROTECTED]


 +static ssize_t revoked_file_aio_read(struct kiocb *iocb,
 +  const struct iovec *iov,
 +  unsigned long nr_segs, loff_t pos)
 +{
 + return -EBADF;
 +}

Do we need both -EBADF and -EXNIO versions. It is hard to tell from
existing OS's as they don't support revoke of files just special files ?

 +static ssize_t revoked_special_file_read(struct file *filp, char __user * 
 buf,
 +  size_t size, loff_t * ppos)
 +{
 + return -ENXIO;
 +}

Bezerkly Unix returns 0 for the special file read case


-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/7] revoke: core code

2007-03-09 Thread Pekka J Enberg
On Fri, 9 Mar 2007 10:15:15 +0200 (EET)
Pekka J Enberg [EMAIL PROTECTED] wrote:
  +static ssize_t revoked_file_aio_read(struct kiocb *iocb,
  +const struct iovec *iov,
  +unsigned long nr_segs, loff_t pos)
  +{
  +   return -EBADF;
  +}
 
On Fri, 9 Mar 2007, Alan Cox wrote:
 Do we need both -EBADF and -EXNIO versions. It is hard to tell from
 existing OS's as they don't support revoke of files just special files ?

No, we don't. We should always do EBADF except for close(2) which is zero 
always and make read(2) zero for special files.

On Fri, 9 Mar 2007 10:15:15 +0200 (EET)
Pekka J Enberg [EMAIL PROTECTED] wrote:
  +static ssize_t revoked_special_file_read(struct file *filp, char __user * 
  buf,
  +size_t size, loff_t * ppos)
  +{
  +   return -ENXIO;
  +}

On Fri, 9 Mar 2007, Alan Cox wrote:
 Bezerkly Unix returns 0 for the special file read case

Aah, I'll fix that up. Thanks.

Pekka
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/7] revoke: core code

2007-03-09 Thread Peter Zijlstra
On Fri, 2007-03-09 at 10:15 +0200, Pekka J Enberg wrote:

 +static int revoke_vma(struct vm_area_struct *vma, struct zap_details 
 *details)
 +{
 + unsigned long restart_addr, start_addr, end_addr;
 + int need_break;
 +
 + start_addr = vma-vm_start;
 + end_addr = vma-vm_end;
 +
 + /*
 +  * Not holding -mmap_sem here.
 +  */
 + vma-vm_flags |= VM_REVOKED;
 + smp_mb();

Hmm, i_mmap_lock pins the vma and excludes modifications, but doesn't
exclude concurrent faults.

I guess its save.

 +  again:
 + restart_addr = zap_page_range(vma, start_addr, end_addr - start_addr,
 +   details);
 +
 + need_break = need_resched() || need_lockbreak(details-i_mmap_lock);
 + if (need_break)
 + goto out_need_break;
 +
 + if (restart_addr  end_addr) {
 + start_addr = restart_addr;
 + goto again;
 + }
 + return 0;
 +
 +  out_need_break:
 + spin_unlock(details-i_mmap_lock);
 + cond_resched();
 + spin_lock(details-i_mmap_lock);
 + return -EINTR;

I'm not sure this scheme works, given a sufficiently loaded machine,
this might never complete.

 +}
 +
 +static int revoke_mapping(struct address_space *mapping, struct file 
 *to_exclude)
 +{
 + struct vm_area_struct *vma;
 + struct prio_tree_iter iter;
 + struct zap_details details;
 + int err = 0;
 +
 + details.i_mmap_lock = mapping-i_mmap_lock;
 +
 + spin_lock(mapping-i_mmap_lock);
 + vma_prio_tree_foreach(vma, iter, mapping-i_mmap, 0, ULONG_MAX) {
 + if (vma-vm_flags  VM_SHARED  vma-vm_file != to_exclude) {

I'm never sure of operator precedence and prefer:

 (vma-vm_flags  VM_SHARED)  ...

which leaves no room for error.

 + err = revoke_vma(vma, details);
 + if (err)
 + goto out;
 + }
 + }
 +
 + list_for_each_entry(vma, mapping-i_mmap_nonlinear, 
 shared.vm_set.list) {
 + if (vma-vm_flags  VM_SHARED  vma-vm_file != to_exclude) {

Idem.

 + err = revoke_vma(vma, details);
 + if (err)
 + goto out;
 + }
 + }
 +  out:
 + spin_unlock(mapping-i_mmap_lock);
 + return err;
 +}


-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/