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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.