bug-hurd
[Top][All Lists]
Advanced

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

Re: [Linux 2.6 PATCH] support for Hurd ext2 format extensions


From: Roland McGrath
Subject: Re: [Linux 2.6 PATCH] support for Hurd ext2 format extensions
Date: Mon, 1 Mar 2004 17:32:39 -0800

Emacs: freely redistributable; void where prohibited by law.
--text follows this line--
I had a straightforward bug that only affected newly-created nodes, which I
probably didn't really test the first time.  Note that the nature of the
bug could possibly have caused your buggy kernel to clobber any random
block on that disk partition.  So even if e2fsck is happy, it's not out of
the question that some random data blocks are bad now.  I hope that was a
test filesystem like mine was!

Here is a new version of the patch.  Please let me know how it works for you.


Thanks,
Roland


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/ialloc.c
===================================================================
RCS file: /home/roland/redhat/bkcvs/linux-2.5/fs/ext2/ialloc.c,v
retrieving revision 1.39
diff -b -p -u -r1.39 ialloc.c
--- fs/ext2/ialloc.c    20 Jan 2004 05:07:51 -0000      1.39
+++ fs/ext2/ialloc.c    28 Feb 2004 23:10:27 -0000
@@ -590,6 +590,10 @@ got:
        ei->i_frag_size = 0;
        ei->i_file_acl = 0;
        ei->i_dir_acl = 0;
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       ei->i_hurd_translator = 0;
+       ei->i_hurd_author = 0;
+#endif
        ei->i_dtime = 0;
        ei->i_block_group = group;
        ei->i_next_alloc_block = 0;
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     28 Feb 2004 23:12:16 -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     28 Feb 2004 23:22:53 -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,14 @@ ext2_xattr_delete_inode(struct inode *in
 
 cleanup:
        brelse(bh);
+#ifdef CONFIG_EXT2_FS_XATTR_HURD
+       printk("dropping inode %ld translator %u\n",
+              inode->i_ino, EXT2_I(inode)->i_hurd_translator);
+       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 +1165,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 +1206,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-28 15:11:57.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]