bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Linux 2.6 PATCH] support for Hurd ext2 format extensions


From: Roland McGrath
Subject: [Linux 2.6 PATCH] support for Hurd ext2 format extensions
Date: Fri, 20 Feb 2004 14:46:36 -0800

This is a cleaned-up and polished version of the Linux 2.6 patch to support
Hurd ext2 format extensions via the xattr interfaces.  This is against
2.6.3 or thereabouts.  After applying the patch, you must turn on
CONFIG_EXT2_FS_XATTR (not on by default) and then you can turn on the new
option CONFIG_EXT2_FS_XATTR_HURD to enable the new code.  Please test this
out and report any problems to me.  I am not going to submit this to Linus
et al until I've gotten positive reports that people are actually using it
in practice and successfully.


Thanks,
Roland



Index: fs/Kconfig
===================================================================
RCS file: /home/roland/redhat/bkcvs/linux-2.5/fs/Kconfig,v
retrieving revision 1.38
diff -b -p -u -r1.38 Kconfig
--- fs/Kconfig  19 Feb 2004 04:49:14 -0000      1.38
+++ fs/Kconfig  19 Feb 2004 22:07:15 -0000
@@ -59,6 +59,14 @@ config EXT2_FS_XATTR
 
          If unsure, say N.
 
+config EXT2_FS_XATTR_HURD
+       bool "Ext2 GNU/Hurd special attribute support"
+       depends on EXT2_FS_XATTR
+       default y
+       help
+         Enable access to gnu.* extended attribute names on ext2 filesystems
+         created for use with the GNU/Hurd operating system.
+
 config EXT2_FS_POSIX_ACL
        bool "Ext2 POSIX Access Control Lists"
        depends on EXT2_FS_XATTR
Index: fs/ext2/Makefile
===================================================================
RCS file: /home/roland/redhat/bkcvs/linux-2.5/fs/ext2/Makefile,v
retrieving revision 1.10
diff -b -p -u -r1.10 Makefile
--- fs/ext2/Makefile    25 Jul 2003 23:00:05 -0000      1.10
+++ fs/ext2/Makefile    18 Feb 2004 00:52:48 -0000
@@ -10,3 +10,4 @@ ext2-y := balloc.o bitmap.o dir.o file.o
 ext2-$(CONFIG_EXT2_FS_XATTR)    += xattr.o xattr_user.o xattr_trusted.o
 ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o
 ext2-$(CONFIG_EXT2_FS_SECURITY)         += xattr_security.o
+ext2-$(CONFIG_EXT2_FS_XATTR_HURD)+= xattr_hurd.o
Index: fs/ext2/ext2.h
===================================================================
RCS file: /home/roland/redhat/bkcvs/linux-2.5/fs/ext2/ext2.h,v
retrieving revision 1.13
diff -b -p -u -r1.13 ext2.h
--- fs/ext2/ext2.h      7 Jul 2003 02:41:12 -0000       1.13
+++ fs/ext2/ext2.h      18 Feb 2004 01:01:19 -0000
@@ -55,6 +55,10 @@ struct ext2_inode_info {
        struct posix_acl        *i_acl;
        struct posix_acl        *i_default_acl;
 #endif
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       __u32   i_hurd_translator;
+       __u32   i_hurd_author;
+#endif
        rwlock_t i_meta_lock;
        struct inode    vfs_inode;
 };
Index: fs/ext2/inode.c
===================================================================
RCS file: /home/roland/redhat/bkcvs/linux-2.5/fs/ext2/inode.c,v
retrieving revision 1.71
diff -b -p -u -r1.71 inode.c
--- fs/ext2/inode.c     19 Jan 2004 18:06:27 -0000      1.71
+++ fs/ext2/inode.c     18 Feb 2004 03:06:43 -0000
@@ -1092,6 +1092,16 @@ void ext2_read_inode (struct inode * ino
        ei->i_prealloc_count = 0;
        ei->i_block_group = (ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
        ei->i_dir_start_lookup = 0;
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       if (EXT2_SB(inode->i_sb)->s_es->s_creator_os == 
cpu_to_le32(EXT2_OS_HURD)) {
+               ei->i_hurd_translator = 
le32_to_cpu(raw_inode->osd1.hurd1.h_i_translator);
+               ei->i_hurd_author = 
le32_to_cpu(raw_inode->osd2.hurd2.h_i_author);
+       }
+       else {
+               ei->i_hurd_translator = 0;
+               ei->i_hurd_author = inode->i_uid;
+       }
+#endif
 
        /*
         * NOTE! The in-memory inode i_data array is in little-endian order
@@ -1218,6 +1228,13 @@ static int ext2_update_inode(struct inod
                }
        }
        
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       if (EXT2_SB(inode->i_sb)->s_es->s_creator_os == 
cpu_to_le32(EXT2_OS_HURD)) {
+               raw_inode->osd1.hurd1.h_i_translator = 
cpu_to_le32(ei->i_hurd_translator);
+               raw_inode->osd2.hurd2.h_i_author = 
cpu_to_le32(ei->i_hurd_author);
+       }
+#endif
+
        raw_inode->i_generation = cpu_to_le32(inode->i_generation);
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
                if (old_valid_dev(inode->i_rdev)) {
@@ -1275,4 +1292,3 @@ int ext2_setattr(struct dentry *dentry, 
                error = ext2_acl_chmod(inode);
        return error;
 }
-
Index: fs/ext2/xattr.c
===================================================================
RCS file: /home/roland/redhat/bkcvs/linux-2.5/fs/ext2/xattr.c,v
retrieving revision 1.20
diff -b -p -u -r1.20 xattr.c
--- fs/ext2/xattr.c     6 Feb 2004 16:50:15 -0000       1.20
+++ fs/ext2/xattr.c     18 Feb 2004 03:08:03 -0000
@@ -434,6 +434,38 @@ bad_block: ext2_error(inode->i_sb, "ext2
        error = size;
 
 cleanup:
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       if (error >= 0) {
+               struct ext2_inode_info *ei = EXT2_I(inode);
+               buf = buffer + size;
+               if (ei->i_hurd_author != inode->i_uid) {
+                       size += sizeof "gnu.author";
+                       if (buffer) {
+                               if (size > buffer_size)
+                                       error = -ERANGE;
+                               else {
+                                       memcpy(buf, "gnu.author",
+                                              sizeof "gnu.author");
+                                       buf += sizeof "gnu.author";
+                               }
+                       }
+               }
+               if (ei->i_hurd_translator != 0) {
+                       size += sizeof "gnu.translator";
+                       if (buffer) {
+                               if (size > buffer_size)
+                                       error = -ERANGE;
+                               else {
+                                       memcpy(buf, "gnu.translator",
+                                              sizeof "gnu.translator");
+                                       buf += sizeof "gnu.translator";
+                               }
+                       }
+               }
+               if (error >= 0)
+                       error = size;
+       }
+#endif
        brelse(bh);
        up_read(&EXT2_I(inode)->xattr_sem);
 
@@ -892,6 +924,12 @@ ext2_xattr_delete_inode(struct inode *in
 
 cleanup:
        brelse(bh);
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       if (EXT2_I(inode)->i_hurd_translator != 0) {
+               ext2_free_blocks(inode, EXT2_I(inode)->i_hurd_translator, 1);
+               EXT2_I(inode)->i_hurd_translator = 0;
+       }
+#endif
        up_write(&EXT2_I(inode)->xattr_sem);
 }
 
@@ -1125,10 +1163,16 @@ init_ext2_xattr(void)
                                  &ext2_xattr_user_handler);
        if (err)
                return err;
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       err = ext2_xattr_register(EXT2_XATTR_INDEX_HURD,
+                                 &ext2_xattr_hurd_handler);
+       if (err)
+               goto out;
+#endif
        err = ext2_xattr_register(EXT2_XATTR_INDEX_TRUSTED,
                                  &ext2_xattr_trusted_handler);
        if (err)
-               goto out;
+               goto out0;
 #ifdef CONFIG_EXT2_FS_SECURITY
        err = ext2_xattr_register(EXT2_XATTR_INDEX_SECURITY,
                                  &ext2_xattr_security_handler);
@@ -1160,7 +1204,12 @@ out1:
 #endif
        ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
                              &ext2_xattr_trusted_handler);
+out0:
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       ext2_xattr_unregister(EXT2_XATTR_INDEX_HURD,
+                             &ext2_xattr_hurd_handler);
 out:
+#endif
        ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
                              &ext2_xattr_user_handler);
        return err;
Index: fs/ext2/xattr.h
===================================================================
RCS file: /home/roland/redhat/bkcvs/linux-2.5/fs/ext2/xattr.h,v
retrieving revision 1.8
diff -b -p -u -r1.8 xattr.h
--- fs/ext2/xattr.h     13 May 2003 06:12:52 -0000      1.8
+++ fs/ext2/xattr.h     13 Feb 2004 03:22:36 -0000
@@ -24,6 +24,7 @@
 #define EXT2_XATTR_INDEX_TRUSTED               4
 #define        EXT2_XATTR_INDEX_LUSTRE                 5
 #define EXT2_XATTR_INDEX_SECURITY              6
+#define EXT2_XATTR_INDEX_HURD                  7
 
 struct ext2_xattr_header {
        __u32   h_magic;        /* magic number for identification */
@@ -135,6 +136,6 @@ exit_ext2_xattr(void)
 # endif  /* CONFIG_EXT2_FS_XATTR */
 
 extern struct ext2_xattr_handler ext2_xattr_user_handler;
+extern struct ext2_xattr_handler ext2_xattr_hurd_handler;
 extern struct ext2_xattr_handler ext2_xattr_trusted_handler;
 extern struct ext2_xattr_handler ext2_xattr_security_handler;
-

--- /dev/null   2003-06-05 09:19:08.000000000 -0700
+++ fs/ext2/xattr_hurd.c        2004-02-17 19:03:00.000000000 -0800
@@ -0,0 +1,260 @@
+/*
+ * linux/fs/ext2/xattr_hurd.c
+ * Handler for Hurd-specific attributes.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/buffer_head.h>
+#include "ext2.h"
+#include "xattr.h"
+
+#define XATTR_HURD_PREFIX "gnu."
+
+static size_t
+ext2_xattr_hurd_list(char *list, struct inode *inode,
+                    const char *name, int name_len)
+{
+       const int prefix_len = sizeof(XATTR_HURD_PREFIX)-1;
+
+       if (!test_opt(inode->i_sb, XATTR_USER))
+               return 0;
+
+       if (list) {
+               memcpy(list, XATTR_HURD_PREFIX, prefix_len);
+               memcpy(list+prefix_len, name, name_len);
+               list[prefix_len + name_len] = '\0';
+       }
+       return prefix_len + name_len + 1;
+}
+
+static inline int
+IS_HURD_COMPAT(struct super_block *sb)
+{
+       return (EXT2_SB(sb)->s_es->s_creator_os == cpu_to_le32(EXT2_OS_HURD));
+}
+
+
+/*
+ * Report the "gnu.translator" and "gnu.author" attribute values
+ * from an inode in EXT2_OS_HURD format.
+ */
+static int
+hurd_compat_get(struct inode *inode, const char *name,
+               void *buffer, size_t size)
+{
+       int error = -EOPNOTSUPP;
+       struct ext2_inode_info *ei = EXT2_I(inode);
+
+       /*
+        * Compatibility mode.
+        */
+       if (!strcmp(name, "translator")) {
+               struct buffer_head *bh;
+               u16 len;
+               if (ei->i_hurd_translator == 0)
+                       /* No translator set, empty.  */
+                       return 0;
+               error = -EIO;
+               bh = sb_bread(inode->i_sb, ei->i_hurd_translator);
+               if (bh) {
+                       len = le16_to_cpup(bh->b_data);
+                       if (len > bh->b_size - 2)
+                               error = -EFBIG; /* ? */
+                       else if (buffer == NULL)
+                               /* Just return the total.  */
+                               error = len;
+                       else if (len > size)
+                               error = -ERANGE;
+                       else {
+                               memcpy(buffer, bh->b_data + 2, len);
+                               error = len;
+                       }
+                       brelse(bh);
+               }
+       }
+       else if (!strcmp(name, "author")) {
+               if (ei->i_hurd_author == inode->i_uid)
+                       error = 0;
+               else {
+                       if (buffer && size < sizeof ei->i_hurd_author)
+                               error = -ERANGE;
+                       else if (buffer)
+                               memcpy(buffer, &ei->i_hurd_author,
+                                      sizeof ei->i_hurd_author);
+                       error = sizeof ei->i_hurd_author;
+               }
+       }
+
+       return error;
+}
+
+/*
+ * Store the "gnu.translator" and "gnu.author" attribute values
+ * in an inode in EXT2_OS_HURD format.
+ */
+static int
+compat_hurd_set(struct inode *inode, const char *name,
+               const void *value, size_t size, int flags)
+{
+       int error;
+       struct ext2_inode_info *ei = EXT2_I(inode);
+
+       /*
+        * Compatibility mode.  We actually have to re-read the
+        * raw inode because ext2_read_inode does not cache this field.
+        */
+       if (!strcmp(name, "translator")) {
+               u32 bno;
+               u16 len;
+               struct buffer_head *bh;
+
+               error = permission(inode, MAY_WRITE, NULL);
+               if (error)
+                       return error;
+               if (ei->i_hurd_translator == 0) {
+                       /* No existing translator.  */
+                       if (flags & XATTR_REPLACE)
+                               return -ENODATA;
+                       if (size == 0) { /* Nothing really to do.  */
+                               inode->i_ctime = CURRENT_TIME;
+                               mark_inode_dirty(inode);
+                               return 0;
+                       }
+               }
+               else if (flags & XATTR_CREATE)
+                       return -EEXIST;
+
+               if (size == 0) { /* Removing translator.  */
+                       bno = ei->i_hurd_translator;
+                       ei->i_hurd_translator = 0;
+                       ext2_free_blocks(inode, bno, 1);
+                       unmap_underlying_metadata(inode->i_sb->s_bdev,
+                                                 bno);
+                       inode->i_ctime = CURRENT_TIME;
+                       mark_inode_dirty(inode);
+                       return 0;
+               }
+
+               if (size > inode->i_sb->s_blocksize - 2)
+                       return -ERANGE;
+
+               bno = ei->i_hurd_translator;
+               if (bno == 0) {
+                       /*
+                        * Need to allocate a new block.
+                        */
+                       struct super_block *sb = inode->i_sb;
+                       u32 goal = le32_to_cpu(EXT2_SB(sb)->s_es->
+                                              s_first_data_block) +
+                               EXT2_I(inode)->i_block_group *
+                               EXT2_BLOCKS_PER_GROUP(sb);
+                       bno = ext2_new_block(inode, goal, 0, 0,
+                                            &error);
+                       if (error)
+                               return error;
+               }
+
+               bh = sb_getblk(inode->i_sb, bno);
+               lock_buffer(bh);
+               len = cpu_to_le16(size);
+               memcpy(bh->b_data, &len, sizeof len);
+               memcpy(bh->b_data + 2, value, size);
+               set_buffer_uptodate(bh);
+               unlock_buffer(bh);
+               mark_buffer_dirty(bh);
+               brelse(bh);
+
+               ei->i_hurd_translator = bno;
+               inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
+               return 0;
+       }
+
+       if (!strcmp(name, "author")) {
+               error = permission(inode, MAY_WRITE, NULL);
+               if (error)
+                       return error;
+               switch (size) {
+               default:
+                       return -EINVAL;
+               case 0:
+                       ei->i_hurd_author = inode->i_uid;
+                       break;
+               case sizeof ei->i_hurd_author:
+                       memcpy(&ei->i_hurd_author,
+                              value, sizeof ei->i_hurd_author);
+                       break;
+               }
+               inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
+               return 0;
+       }
+
+       return -EOPNOTSUPP;
+}
+
+static int
+ext2_xattr_hurd_get(struct inode *inode, const char *name,
+                   void *buffer, size_t size)
+{
+       int error;
+
+       if (IS_HURD_COMPAT(inode->i_sb)) {
+               down_read(&EXT2_I(inode)->xattr_sem);
+               error = hurd_compat_get(inode, name, buffer, size);
+               up_read(&EXT2_I(inode)->xattr_sem);
+               if (error != -EOPNOTSUPP)
+                       return error;
+       }
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       if (!test_opt(inode->i_sb, XATTR_USER)) /* XXX ? */
+               return -EOPNOTSUPP;
+       error = permission(inode, MAY_READ, NULL);
+       if (error)
+               return error;
+
+       return ext2_xattr_get(inode, EXT2_XATTR_INDEX_HURD, name,
+                             buffer, size);
+}
+
+static int
+ext2_xattr_hurd_set(struct inode *inode, const char *name,
+                   const void *value, size_t size, int flags)
+{
+       int error;
+
+       if (value == NULL)
+               size = 0;
+
+       if (IS_HURD_COMPAT(inode->i_sb)) {
+               down_write(&EXT2_I(inode)->xattr_sem);
+               error = compat_hurd_set(inode, name, value, size, flags);
+               up_write(&EXT2_I(inode)->xattr_sem);
+               if (error != -EOPNOTSUPP)
+                       return error;
+       }
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       if (!test_opt(inode->i_sb, XATTR_USER)) /* XXX ? */
+               return -EOPNOTSUPP;
+       error = permission(inode, MAY_WRITE, NULL);
+       if (error)
+               return error;
+
+       return ext2_xattr_set(inode, EXT2_XATTR_INDEX_HURD, name,
+                             value, size, flags);
+}
+
+struct ext2_xattr_handler ext2_xattr_hurd_handler = {
+       .prefix = XATTR_HURD_PREFIX,
+       .list   = ext2_xattr_hurd_list,
+       .get    = ext2_xattr_hurd_get,
+       .set    = ext2_xattr_hurd_set,
+};




reply via email to

[Prev in Thread] Current Thread [Next in Thread]