From: Andreas Gruenbacher <agruen@suse.de>
To: "Linux-FSDevel" <linux-fsdevel@vger.kernel.org>
Subject: Re: [RFC] POSIX ACL kernel infrastructure
Date: Sun, 4 Aug 2002 16:14:47 +0200 [thread overview]
Message-ID: <200208041614.47152.agruen@suse.de> (raw)
In-Reply-To: <20020804150407.A27593@infradead.org>
On Sunday 04 August 2002 16:04, you wrote:
> On Sun, Aug 04, 2002 at 03:46:35PM +0200, Andreas Gruenbacher wrote:
> > Hello,
> >
> > I want to propose adding some infrastructure to the VFS for POSIX ACL
> > ssupport. There are already implementations for XFS and Ext2/Ext3;
> > ReiserFS is to follow soon.
>
> Could you please resend without mime and gzip?
Well, sorry the patch is rather large uncompressed.
Cheers,
Andreas.
diff -Nur --exclude-from=linux.excl linux-2.5.30/fs/Config.help
linux-2.5.30.patch/fs/Config.help
--- linux-2.5.30/fs/Config.help Thu Aug 1 23:16:33 2002
+++ linux-2.5.30.patch/fs/Config.help Sun Aug 4 13:38:57 2002
@@ -1,3 +1,20 @@
+CONFIG_FS_POSIX_ACL
+ POSIX Access Control Lists (ACLs) support permissions for users and
+ groups beyond the owner/group/world scheme.
+
+ To learn more about Access Control Lists, visit
+ <http://acl.bestbits.at/>.
+
+ You need an additional filesystem patch to get POSIX ACL support
+ on one of the built-in filesystems; such patches are available at
+ http://acl.bestbits.at/ for ext2 and ext3, and at
+ http://oss.sgi.com/projects/xfs/ for XFS.
+
+ The getfacl and setfacl utilities for manipulating POSIX ACLs are also
+ available at these web sites.
+
+ If you don't know what Access Control Lists are, say N.
+
CONFIG_QUOTA
If you say Y here, you will be able to set per user limits for disk
usage (also called disk quotas). Currently, it works for the
diff -Nur --exclude-from=linux.excl linux-2.5.30/fs/Config.in
linux-2.5.30.patch/fs/Config.in
--- linux-2.5.30/fs/Config.in Thu Aug 1 23:16:29 2002
+++ linux-2.5.30.patch/fs/Config.in Sun Aug 4 13:24:12 2002
@@ -4,6 +4,8 @@
mainmenu_option next_comment
comment 'File systems'
+bool 'POSIX Access Control Lists' CONFIG_FS_POSIX_ACL
+
bool 'Quota support' CONFIG_QUOTA
dep_tristate ' Old quota format support' CONFIG_QFMT_V1 $CONFIG_QUOTA
dep_tristate ' Quota format v2 support' CONFIG_QFMT_V2 $CONFIG_QUOTA
diff -Nur --exclude-from=linux.excl linux-2.5.30/fs/Makefile
linux-2.5.30.patch/fs/Makefile
--- linux-2.5.30/fs/Makefile Thu Aug 1 23:16:03 2002
+++ linux-2.5.30.patch/fs/Makefile Sun Aug 4 13:28:38 2002
@@ -7,7 +7,8 @@
O_TARGET := fs.o
-export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o
+export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o \
+ posix_acl.o
obj-y := open.o read_write.o devices.o file_table.o buffer.o \
bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \
@@ -36,6 +37,8 @@
obj-$(CONFIG_QFMT_V2) += quota_v2.o
obj-$(CONFIG_QUOTACTL) += quota.o
+obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
+
obj-$(CONFIG_PROC_FS) += proc/
obj-y += partitions/
obj-y += driverfs/
diff -Nur --exclude-from=linux.excl linux-2.5.30/fs/posix_acl.c
linux-2.5.30.patch/fs/posix_acl.c
--- linux-2.5.30/fs/posix_acl.c Thu Jan 1 01:00:00 1970
+++ linux-2.5.30.patch/fs/posix_acl.c Sun Aug 4 14:52:42 2002
@@ -0,0 +1,496 @@
+/*
+ * linux/fs/posix_acl.c
+ *
+ * Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
+ *
+ * Fixes from William Schumacher incorporated on 15 March 2001.
+ * (Reported by Charles Bertsch, <CBertsch@microtest.com>).
+ */
+
+/*
+ * This file contains generic functions for manipulating
+ * POSIX 1003.1e draft standard 17 ACLs.
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <asm/atomic.h>
+#include <linux/fs.h>
+#include <linux/posix_acl.h>
+#include <linux/module.h>
+
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+
+MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
+MODULE_DESCRIPTION("Generic Posix Access Control List (ACL) Manipulation");
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+MODULE_LICENSE("GPL");
+#endif
+
+EXPORT_SYMBOL(posix_acl_alloc);
+EXPORT_SYMBOL(posix_acl_dup);
+EXPORT_SYMBOL(posix_acl_clone);
+EXPORT_SYMBOL(posix_acl_release);
+EXPORT_SYMBOL(posix_acl_valid);
+EXPORT_SYMBOL(posix_acl_equiv_mode);
+EXPORT_SYMBOL(posix_acl_from_mode);
+EXPORT_SYMBOL(posix_acl_create_masq);
+EXPORT_SYMBOL(posix_acl_chmod_masq);
+EXPORT_SYMBOL(posix_acl_masq_nfs_mode);
+EXPORT_SYMBOL(posix_acl_permission);
+
+EXPORT_SYMBOL(get_posix_acl);
+EXPORT_SYMBOL(set_posix_acl);
+
+/*
+ * Allocate a new ACL with the specified number of entries.
+ */
+posix_acl_t *
+posix_acl_alloc(int count)
+{
+ const size_t size = sizeof(posix_acl_t) +
+ count * sizeof(posix_acl_entry_t);
+ posix_acl_t *acl = kmalloc(size, GFP_KERNEL);
+ if (acl) {
+ atomic_set(&acl->a_refcount, 1);
+ acl->a_count = count;
+ }
+ return acl;
+}
+
+/*
+ * Duplicate an ACL handle.
+ */
+posix_acl_t *
+posix_acl_dup(posix_acl_t *acl)
+{
+ if (acl)
+ atomic_inc(&acl->a_refcount);
+ return acl;
+}
+
+/*
+ * Clone an ACL.
+ */
+posix_acl_t *
+posix_acl_clone(const posix_acl_t *acl)
+{
+ posix_acl_t *clone = NULL;
+
+ if (acl) {
+ int size = sizeof(posix_acl_t) + acl->a_count *
+ sizeof(posix_acl_entry_t);
+ clone = kmalloc(size, GFP_KERNEL);
+ if (clone) {
+ memcpy(clone, acl, size);
+ atomic_set(&clone->a_refcount, 1);
+ }
+ }
+ return clone;
+}
+
+/*
+ * Free an ACL handle.
+ */
+void
+posix_acl_release(posix_acl_t *acl)
+{
+ if (acl && atomic_dec_and_test(&acl->a_refcount))
+ kfree(acl);
+}
+
+/*
+ * Check if an acl is valid. Returns 0 if it is, or -E... otherwise.
+ */
+int
+posix_acl_valid(const posix_acl_t *acl)
+{
+ const posix_acl_entry_t *pa, *pe;
+ int state = ACL_USER_OBJ;
+ unsigned int id = 0; /* keep gcc happy */
+ int needs_mask = 0;
+
+ FOREACH_ACL_ENTRY(pa, acl, pe) {
+ if (pa->e_perm & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
+ return -EINVAL;
+ switch (pa->e_tag) {
+ case ACL_USER_OBJ:
+ if (state == ACL_USER_OBJ) {
+ id = 0;
+ state = ACL_USER;
+ break;
+ }
+ return -EINVAL;
+
+ case ACL_USER:
+ if (state != ACL_USER)
+ return -EINVAL;
+ if (pa->e_id == ACL_UNDEFINED_ID ||
+ pa->e_id < id)
+ return -EINVAL;
+ id = pa->e_id + 1;
+ needs_mask = 1;
+ break;
+
+ case ACL_GROUP_OBJ:
+ if (state == ACL_USER) {
+ id = 0;
+ state = ACL_GROUP;
+ break;
+ }
+ return -EINVAL;
+
+ case ACL_GROUP:
+ if (state != ACL_GROUP)
+ return -EINVAL;
+ if (pa->e_id == ACL_UNDEFINED_ID ||
+ pa->e_id < id)
+ return -EINVAL;
+ id = pa->e_id + 1;
+ needs_mask = 1;
+ break;
+
+ case ACL_MASK:
+ if (state != ACL_GROUP)
+ return -EINVAL;
+ state = ACL_OTHER;
+ break;
+
+ case ACL_OTHER:
+ if (state == ACL_OTHER ||
+ (state == ACL_GROUP && !needs_mask)) {
+ state = 0;
+ break;
+ }
+ return -EINVAL;
+
+ default:
+ return -EINVAL;
+ }
+ }
+ if (state == 0)
+ return 0;
+ return -EINVAL;
+}
+
+/*
+ * Returns 0 if the acl can be exactly represented in the traditional
+ * file mode permission bits, or else 1. Returns -E... on error.
+ */
+int
+posix_acl_equiv_mode(const posix_acl_t *acl, mode_t *mode_p)
+{
+ const posix_acl_entry_t *pa, *pe;
+ mode_t mode = 0;
+ int not_equiv = 0;
+
+ FOREACH_ACL_ENTRY(pa, acl, pe) {
+ switch (pa->e_tag) {
+ case ACL_USER_OBJ:
+ mode |= (pa->e_perm & S_IRWXO) << 6;
+ break;
+ case ACL_GROUP_OBJ:
+ mode |= (pa->e_perm & S_IRWXO) << 3;
+ break;
+ case ACL_OTHER:
+ mode |= pa->e_perm & S_IRWXO;
+ break;
+ case ACL_MASK:
+ mode = (mode & ~S_IRWXG) |
+ ((pa->e_perm & S_IRWXO) << 3);
+ not_equiv = 1;
+ break;
+ case ACL_USER:
+ case ACL_GROUP:
+ not_equiv = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ if (mode_p)
+ *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
+ return not_equiv;
+}
+
+/*
+ * Create an ACL representing the file mode permission bits of an inode.
+ */
+posix_acl_t *
+posix_acl_from_mode(mode_t mode)
+{
+ posix_acl_t *acl = posix_acl_alloc(3);
+ if (!acl)
+ return ERR_PTR(-ENOMEM);
+
+ acl->a_entries[0].e_tag = ACL_USER_OBJ;
+ acl->a_entries[0].e_id = ACL_UNDEFINED_ID;
+ acl->a_entries[0].e_perm = (mode & S_IRWXU) >> 6;
+
+ acl->a_entries[1].e_tag = ACL_GROUP_OBJ;
+ acl->a_entries[1].e_id = ACL_UNDEFINED_ID;
+ acl->a_entries[1].e_perm = (mode & S_IRWXG) >> 3;
+
+ acl->a_entries[2].e_tag = ACL_OTHER;
+ acl->a_entries[2].e_id = ACL_UNDEFINED_ID;
+ acl->a_entries[2].e_perm = (mode & S_IRWXO);
+ return acl;
+}
+
+/*
+ * Return 0 if current is granted want access to the inode
+ * by the acl. Returns -E... otherwise.
+ */
+int
+posix_acl_permission(struct inode *inode, const posix_acl_t *acl, int want)
+{
+ const posix_acl_entry_t *pa, *pe, *mask_obj;
+ int found = 0;
+
+ FOREACH_ACL_ENTRY(pa, acl, pe) {
+ switch(pa->e_tag) {
+ case ACL_USER_OBJ:
+ /* (May have been checked already) */
+ if (inode->i_uid == current->fsuid)
+ goto check_perm;
+ break;
+ case ACL_USER:
+ if (pa->e_id == current->fsuid)
+ goto mask;
+ break;
+ case ACL_GROUP_OBJ:
+ if (in_group_p(inode->i_gid)) {
+ found = 1;
+ if ((pa->e_perm & want) == want)
+ goto mask;
+ }
+ break;
+ case ACL_GROUP:
+ if (in_group_p(pa->e_id)) {
+ found = 1;
+ if ((pa->e_perm & want) == want)
+ goto mask;
+ }
+ break;
+ case ACL_MASK:
+ break;
+ case ACL_OTHER:
+ if (found)
+ return -EACCES;
+ else
+ goto check_perm;
+ default:
+ return -EIO;
+ }
+ }
+ return -EIO;
+
+mask:
+ for (mask_obj = pa+1; mask_obj != pe; mask_obj++) {
+ if (mask_obj->e_tag == ACL_MASK) {
+ if ((pa->e_perm & mask_obj->e_perm & want) == want)
+ return 0;
+ return -EACCES;
+ }
+ }
+
+check_perm:
+ if ((pa->e_perm & want) == want)
+ return 0;
+ return -EACCES;
+}
+
+/*
+ * Modify acl when creating a new inode. The caller must ensure the acl is
+ * only referenced once.
+ *
+ * mode_p initially must contain the mode parameter to the open() / creat()
+ * system calls. All permissions that are not granted by the acl are removed.
+ * The permissions in the acl are changed to reflect the mode_p parameter.
+ */
+int
+posix_acl_create_masq(posix_acl_t *acl, mode_t *mode_p)
+{
+ posix_acl_entry_t *pa, *pe;
+ posix_acl_entry_t *group_obj = NULL, *mask_obj = NULL;
+ mode_t mode = *mode_p;
+ int not_equiv = 0;
+
+ /* assert(atomic_read(acl->a_refcount) == 1); */
+
+ FOREACH_ACL_ENTRY(pa, acl, pe) {
+ switch(pa->e_tag) {
+ case ACL_USER_OBJ:
+ pa->e_perm &= (mode >> 6) | ~S_IRWXO;
+ mode &= (pa->e_perm << 6) | ~S_IRWXU;
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+ not_equiv = 1;
+ break;
+
+ case ACL_GROUP_OBJ:
+ group_obj = pa;
+ break;
+
+ case ACL_OTHER:
+ pa->e_perm &= mode | ~S_IRWXO;
+ mode &= pa->e_perm | ~S_IRWXO;
+ break;
+
+ case ACL_MASK:
+ mask_obj = pa;
+ not_equiv = 1;
+ break;
+
+ default:
+ return -EIO;
+ }
+ }
+
+ if (mask_obj) {
+ mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
+ mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
+ } else {
+ if (!group_obj)
+ return -EIO;
+ group_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
+ mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
+ }
+
+ *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
+ return not_equiv;
+}
+
+/*
+ * Modify the ACL for the chmod syscall.
+ */
+int
+posix_acl_chmod_masq(posix_acl_t *acl, mode_t mode)
+{
+ posix_acl_entry_t *group_obj = NULL, *mask_obj = NULL;
+ posix_acl_entry_t *pa, *pe;
+
+ /* assert(atomic_read(acl->a_refcount) == 1); */
+
+ FOREACH_ACL_ENTRY(pa, acl, pe) {
+ switch(pa->e_tag) {
+ case ACL_USER_OBJ:
+ pa->e_perm = (mode & S_IRWXU) >> 6;
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+ break;
+
+ case ACL_GROUP_OBJ:
+ group_obj = pa;
+ break;
+
+ case ACL_MASK:
+ mask_obj = pa;
+ break;
+
+ case ACL_OTHER:
+ pa->e_perm = (mode & S_IRWXO);
+ break;
+
+ default:
+ return -EIO;
+ }
+ }
+
+ if (mask_obj) {
+ mask_obj->e_perm = (mode & S_IRWXG) >> 3;
+ } else {
+ if (!group_obj)
+ return -EIO;
+ group_obj->e_perm = (mode & S_IRWXG) >> 3;
+ }
+
+ return 0;
+}
+
+/*
+ * Adjust the mode parameter so that NFSv2 grants nobody permissions
+ * that may not be granted by the ACL. This is necessary because NFSv2
+ * may compute access permissions on the client side, and may serve cached
+ * data whenever it assumes access would be granted. Since ACLs may also
+ * be used to deny access to specific users, the minimal permissions
+ * for secure operation over NFSv2 are very restrictive. Permissions
+ * granted to users via Access Control Lists will not be effective over
+ * NFSv2.
+ *
+ * Privilege escalation can only happen for read operations, as writes are
+ * always carried out on the NFS server, where the proper access checks are
+ * implemented.
+ */
+int
+posix_acl_masq_nfs_mode(posix_acl_t *acl, mode_t *mode_p)
+{
+ posix_acl_entry_t *pa, *pe; int min_perm = S_IRWXO;
+
+ FOREACH_ACL_ENTRY(pa, acl, pe) {
+ switch(pa->e_tag) {
+ case ACL_USER_OBJ:
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP_OBJ:
+ case ACL_GROUP:
+ case ACL_MASK:
+ case ACL_OTHER:
+ min_perm &= pa->e_perm;
+ break;
+
+ default:
+ return -EIO;
+ }
+ }
+ *mode_p = (*mode_p & ~(S_IRWXG|S_IRWXO)) | (min_perm << 3) | min_perm;
+
+ return 0;
+}
+
+/*
+ * Get the POSIX ACL of an inode.
+ */
+posix_acl_t *
+get_posix_acl(struct inode *inode, int type)
+{
+ posix_acl_t *acl;
+
+ if (!inode->i_op || !inode->i_op->get_posix_acl)
+ return ERR_PTR(-ENOTSUP);
+
+ down(&inode->i_sem);
+ lock_kernel(); /* goes away in 2.5.x */
+ acl = inode->i_op->get_posix_acl(inode, type);
+ unlock_kernel(); /* goes away in 2.5.x */
+ up(&inode->i_sem);
+
+ return acl;
+}
+
+/*
+ * Set the POSIX ACL of an inode.
+ */
+int
+set_posix_acl(struct inode *inode, int type, posix_acl_t *acl)
+{
+ int error;
+
+ if (!inode->i_op || !inode->i_op->set_posix_acl)
+ return -ENOTSUP;
+
+ down(&inode->i_sem);
+ lock_kernel(); /* goes away in 2.5.x */
+ error = inode->i_op->set_posix_acl(inode, type, acl);
+ unlock_kernel(); /* goes away in 2.5.x */
+ up(&inode->i_sem);
+
+ return error;
+}
diff -Nur --exclude-from=linux.excl linux-2.5.30/include/linux/errno.h
linux-2.5.30.patch/include/linux/errno.h
--- linux-2.5.30/include/linux/errno.h Sun Aug 4 14:59:40 2002
+++ linux-2.5.30.patch/include/linux/errno.h Sun Aug 4 14:59:26 2002
@@ -11,6 +11,8 @@
#define ERESTARTNOHAND 514 /* restart if no handler.. */
#define ENOIOCTLCMD 515 /* No ioctl command */
+#define ENOTSUP -1 /* UNRESOLVED ISSUE -- see other proposal */
+
/* Defined for the NFSv3 protocol */
#define EBADHANDLE 521 /* Illegal NFS file handle */
#define ENOTSYNC 522 /* Update synchronization mismatch */
diff -Nur --exclude-from=linux.excl linux-2.5.30/include/linux/fs.h
linux-2.5.30.patch/include/linux/fs.h
--- linux-2.5.30/include/linux/fs.h Thu Aug 1 23:16:15 2002
+++ linux-2.5.30.patch/include/linux/fs.h Sun Aug 4 13:29:31 2002
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/radix-tree.h>
#include <linux/bitops.h>
+#include <linux/posix_acl.h>
#include <asm/atomic.h>
@@ -787,6 +788,8 @@
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
+ posix_acl_t *(*get_posix_acl) (struct inode *, int);
+ int (*set_posix_acl) (struct inode *, int, posix_acl_t *);
};
struct seq_file;
diff -Nur --exclude-from=linux.excl linux-2.5.30/include/linux/posix_acl.h
linux-2.5.30.patch/include/linux/posix_acl.h
--- linux-2.5.30/include/linux/posix_acl.h Thu Jan 1 01:00:00 1970
+++ linux-2.5.30.patch/include/linux/posix_acl.h Sun Aug 4 13:24:12 2002
@@ -0,0 +1,69 @@
+/*
+ File: linux/posix_acl.h
+
+ (C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
+*/
+
+
+#ifndef __LINUX_POSIX_ACL_H
+#define __LINUX_POSIX_ACL_H
+
+
+#define ACL_UNDEFINED_ID (-1)
+
+/* a_type field in acl_user_posix_entry_t */
+#define ACL_TYPE_ACCESS (0x8000)
+#define ACL_TYPE_DEFAULT (0x4000)
+
+/* e_tag entry in posix_acl_entry_t */
+#define ACL_USER_OBJ (0x01)
+#define ACL_USER (0x02)
+#define ACL_GROUP_OBJ (0x04)
+#define ACL_GROUP (0x08)
+#define ACL_MASK (0x10)
+#define ACL_OTHER (0x20)
+
+/* permissions in the e_perm field */
+#define ACL_READ (0x04)
+#define ACL_WRITE (0x02)
+#define ACL_EXECUTE (0x01)
+//#define ACL_ADD (0x08)
+//#define ACL_DELETE (0x10)
+
+#ifdef __KERNEL__
+
+typedef struct {
+ short e_tag;
+ unsigned short e_perm;
+ unsigned int e_id;
+} posix_acl_entry_t;
+
+typedef struct {
+ atomic_t a_refcount;
+ unsigned int a_count;
+ posix_acl_entry_t a_entries[0];
+} posix_acl_t;
+
+#define FOREACH_ACL_ENTRY(pa, acl, pe) \
+ for(pa=(acl)->a_entries, pe=pa+(acl)->a_count; pa<pe; pa++)
+
+/* pxacl.c */
+
+extern posix_acl_t *posix_acl_alloc(int);
+extern posix_acl_t *posix_acl_dup(posix_acl_t *);
+extern posix_acl_t *posix_acl_clone(const posix_acl_t *);
+extern void posix_acl_release(posix_acl_t *);
+extern int posix_acl_valid(const posix_acl_t *);
+extern int posix_acl_permission(struct inode *, const posix_acl_t *, int);
+extern posix_acl_t *posix_acl_from_mode(mode_t);
+extern int posix_acl_equiv_mode(const posix_acl_t *, mode_t *);
+extern int posix_acl_create_masq(posix_acl_t *, mode_t *);
+extern int posix_acl_chmod_masq(posix_acl_t *, mode_t);
+extern int posix_acl_masq_nfs_mode(posix_acl_t *, mode_t *);
+
+extern posix_acl_t *get_posix_acl(struct inode *, int);
+extern int set_posix_acl(struct inode *, int, posix_acl_t *);
+#endif /* __KERNEL__ */
+
+
+#endif /* __LINUX_POSIX_ACL_H */
next prev parent reply other threads:[~2002-08-04 14:14 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-08-04 13:46 [RFC] POSIX ACL kernel infrastructure Andreas Gruenbacher
2002-08-04 14:04 ` Christoph Hellwig
2002-08-04 14:14 ` Andreas Gruenbacher [this message]
2002-08-04 14:33 ` Christoph Hellwig
2002-08-05 12:11 ` Andreas Gruenbacher
2002-08-05 12:28 ` Christoph Hellwig
2002-08-09 2:02 ` Nathan Scott
2002-08-09 10:53 ` Andreas Gruenbacher
2002-08-09 11:15 ` Christoph Hellwig
2002-08-09 12:22 ` Andreas Gruenbacher
2002-08-09 12:32 ` Christoph Hellwig
2002-08-09 13:17 ` Andreas Gruenbacher
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200208041614.47152.agruen@suse.de \
--to=agruen@suse.de \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox