Hi! 

        I'm Christian Brunello, the co-maintainer of GNU fdisk package.

As described in some bug reports (both in [email protected] and
[email protected]) libparted does not support second extended file
system very well so I'm working to make it support most important s
features like ext_attr, resize_inode and dir_index.  

With this mail there is a patch to make libparted support user extended
attributes on ext2 and ext3 file system. 

To apply this patch people need to download the parted-1.8.8 package and
the file `parted-1.8.8_ext2_ext_attr_support.patch'. When ready simple
type those commands:

        u...@host:~$ ls
        parted-1.8.8.tar.bz2    parted-1.8.8_ext2_ext_attr_support.patch
        u...@host:~$ tar -xf parted-1.8.8.tar.bz2
        u...@host:~$ patch -p0 < parted-1.8.8_ext2_ext_attr_support.patch
        patching file parted-1.8.8/libparted/fs/ext2/ext2_block_relocator.c
        patching file parted-1.8.8/libparted/fs/ext2/ext2.c
        patching file parted-1.8.8/libparted/fs/ext2/ext2_fs.h
        patching file parted-1.8.8/libparted/fs/ext2/ext2.h
        patching file parted-1.8.8/tests/t3100-resize-ext2-partion.sh
        u...@host:~$ cd parted-1.8.8

Now we can configure, compile, test and install parted.

My patch also modify `tests/t3100-resize-ext2-partition.sh' because
before ext_attr support there is a test expected to fail. 

By the way, I think that this script is not enough to make sure
libparted resize a second extended filesystem in a right way, without
lost data or info. To make sure my ext_attr code work well I had write
some simple functions that make some tests on a ext2 resized file
system. The behaviour of this test is:

      * Create an image from /dev/zero, with a size decided from user;
      * Create a second extended file system with ext_attr feature
        enabled;
      * Mount the file system and create files on it. Files have random
        size, random data (from /dev/urandom), random number of extended
        attributes, random extended attributes names (but all on `user'
        namespace) and random extended attributes values. 
        
        Files are created in different steps, for each of those steps
        the script create files until the file system is full and delete
        random number of random entryes.
        
      * Umount the filesystem and make a backup of the image.
      * Resize the filesystem with parted (the size is random).
      * Mount the resized file system in a directory and the backup in
        another directory.
      * Compare files in the backup with those in the resized file
        system,  using md5sum for data and a simple string compare for
        the user extended attributes.
      * If the test exit successfully try to resize a file system more
        than once, and compare images using diff.
      * repeat all this stuff 3 times, with different (random) size for
        each run.

The following output is a summary of a test with 250000 byte of data:


        ####
        # TESTING WITH IMAGE OF 250000 BYTES (total 750000 bytes)
        ####
        
        
        # CREATED DIRECTORY: EXT2_FS/D86SFORcB4bsAkLHK
        attribute user.KJCsppRal set to nc1oIELigHEgdI6LB for 
EXT2_FS/D86SFORcB4bsAkLHK
        attribute user.jNqnR9bWF set to w0C3FIRgHO1NWC3T2 for 
EXT2_FS/D86SFORcB4bsAkLHK
        attribute user.WwzOmm1ft set to 4IJtaOGzvhCoTHjzd for 
EXT2_FS/D86SFORcB4bsAkLHK
        attribute user.NeiZnDoTA set to 3osDcd77JaAT8WUrj for 
EXT2_FS/D86SFORcB4bsAkLHK
        attribute user.Z2UCkHuR9 set to 2JuNaGIINBb72DGgk for 
EXT2_FS/D86SFORcB4bsAkLHK
        
        # CREATED FILE: EXT2_FS/D86SFORcB4bsAkLHK/sD44OWjb0O6Z80FeH (1862)
        
        # CREATED FILE: EXT2_FS/D86SFORcB4bsAkLHK/bndSDAbi1Nkuro9fM (713)
        attribute user.5BmSsL2et set to jLFzhlHwEnW2l4T9a for 
EXT2_FS/D86SFORcB4bsAkLHK/bndSDAbi1Nkuro9fM
        attribute user.en1EpP7c4 set to h7BJfOc3IOzdfJMWb for 
EXT2_FS/D86SFORcB4bsAkLHK/bndSDAbi1Nkuro9fM
        
        # CREATED FILE: EXT2_FS/D86SFORcB4bsAkLHK/kITHojBG8TkGhHf5e (1080)
        attribute user.OLPaNGJoc set to UW2OBgwBl32esiMzp for 
EXT2_FS/D86SFORcB4bsAkLHK/kITHojBG8TkGhHf5e
        attribute user.0qkMKKOmK set to 6CurwdEAManLdcJIP for 
EXT2_FS/D86SFORcB4bsAkLHK/kITHojBG8TkGhHf5e
        attribute user.tbrffQEGA set to 5igBAB5e14liwrlJW for 
EXT2_FS/D86SFORcB4bsAkLHK/kITHojBG8TkGhHf5e
        attribute user.WB87KtQvT set to A3t45PRwOtZRuvDn9 for 
EXT2_FS/D86SFORcB4bsAkLHK/kITHojBG8TkGhHf5e
        attribute user.uEO2djhc7 set to JI1G2M0ugDjpfqAvz for 
EXT2_FS/D86SFORcB4bsAkLHK/kITHojBG8TkGhHf5e
        
        # CREATED FILE: EXT2_FS/D86SFORcB4bsAkLHK/C1JccMLMb2lwqaZcl (32)
        attribute user.F7HbH7IFb set to LhRPCAp0kFfE1v2fH for 
EXT2_FS/D86SFORcB4bsAkLHK/C1JccMLMb2lwqaZcl
        attribute user.ebo6hO2rt set to klBK6oOEEWIANOmep for 
EXT2_FS/D86SFORcB4bsAkLHK/C1JccMLMb2lwqaZcl
        
        # CREATED FILE: EXT2_FS/D86SFORcB4bsAkLHK/nP3IeS7p4au4PLWlC (1773)
        attribute user.igv6ARusM set to vrHKnrdMWFSA5t7NK for 
EXT2_FS/D86SFORcB4bsAkLHK/nP3IeS7p4au4PLWlC
        
        # CREATED FILE: EXT2_FS/D86SFORcB4bsAkLHK/rW2IvWCqlRG47qzUN (235)
        attribute user.fgOMgquNb set to lq1k52j9jIk7gIwU5 for 
EXT2_FS/D86SFORcB4bsAkLHK/rW2IvWCqlRG47qzUN
        attribute user.lIJPfT8if set to 0b8Lz92qaa5zlNOAg for 
EXT2_FS/D86SFORcB4bsAkLHK/rW2IvWCqlRG47qzUN
        attribute user.TFqKOCp6z set to 2PCoDd7oIip76HLIF for 
EXT2_FS/D86SFORcB4bsAkLHK/rW2IvWCqlRG47qzUN
        attribute user.5s5nLHu48 set to bvf4AhdmapMEHCI16 for 
EXT2_FS/D86SFORcB4bsAkLHK/rW2IvWCqlRG47qzUN
        
        ...
        ...
        ...
        
        ###
        # CREATED 1 directory, 20 files
        
        removed `EXT2_FS/D86SFORcB4bsAkLHK/rdMjBjokdcujIdifl'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/FtZpqmmhckz7Djs6B'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/bndSDAbi1Nkuro9fM'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/b0fhLDzTMM1Qigknu'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/PcntzA6QFalj9NgnZ'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/rWKUj4Spip7t0oz96'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/stRbJGItdRCGj0UTC'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/BpuuWZgreRDsHfeK7'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/sD44OWjb0O6Z80FeH'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/CIiRiJGpodpeoOROG'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/rUKssJfZWdN5qv0A2'
        removed `EXT2_FS/D86SFORcB4bsAkLHK/IEkMTpkktZo8QL96D'
        
        # CREATED DIRECTORY: EXT2_FS/1Kh9ZWapmo3vif9FQ
        attribute user.PP7GtKQIR set to sitCN0RQMCcrdTGfv for 
EXT2_FS/1Kh9ZWapmo3vif9FQ
        attribute user.sre901F2I set to AEoGLrmlQTME7Bz4p for 
EXT2_FS/1Kh9ZWapmo3vif9FQ
        attribute user.ugPL4WL1h set to Jj2qPvsji4acQtudZ for 
EXT2_FS/1Kh9ZWapmo3vif9FQ
        attribute user.FUlo12QZI set to L7v5MBGhQbuJBoklm for 
EXT2_FS/1Kh9ZWapmo3vif9FQ
        
        ...
        ...
        ...
        
        # TEST_IMAGE RESIZED TO 19%
        
        # CHECKING MD5SUM OF FILES
        
        ./1Kh9ZWapmo3vif9FQ/TTmsnCzd1EIUPzklh: OK
        ./1Kh9ZWapmo3vif9FQ/JmCw18P94zKRIutBI: OK
        ./aUbFiuLBUwbrRCrpJ/4NaCHBcwQfUkssoSc: OK
        ./aUbFiuLBUwbrRCrpJ/KuDsOERnrNWmHkwND: OK
        ./O84R1MiNJBZRa7q5Q/ni7g7rivE4vrsQjrv: OK
        
        # CHECKING EXTENDED ATTRIBUTES OF FILES
        
        Comparing EXT2_FS_BACKUP/./D86SFORcB4bsAkLHK
            user.KJCsppRal OK
            user.NeiZnDoTA OK
            user.WwzOmm1ft OK
            user.Z2UCkHuR9 OK
            user.jNqnR9bWF OK
        Comparing EXT2_FS_BACKUP/./1Kh9ZWapmo3vif9FQ
            user.FUlo12QZI OK
            user.PP7GtKQIR OK
            user.sre901F2I OK
            user.ugPL4WL1h OK
        Comparing EXT2_FS_BACKUP/./1Kh9ZWapmo3vif9FQ/TTmsnCzd1EIUPzklh
            user.r26imn2lj OK
        Comparing EXT2_FS_BACKUP/./1Kh9ZWapmo3vif9FQ/JmCw18P94zKRIutBI
            user.10MP91D2i OK
            user.tfFuELNHr OK
        Comparing EXT2_FS_BACKUP/./Ob1a21FoPgc3SIAZa
            user.DfjhmOQoQ OK
            user.MTOTqSWmp OK
            user.iE5mU8LFf OK
        Comparing EXT2_FS_BACKUP/./aUbFiuLBUwbrRCrpJ/4NaCHBcwQfUkssoSc
            user.UShu2zdcC OK
        Comparing EXT2_FS_BACKUP/./O84R1MiNJBZRa7q5Q
            user.R1eK1uqEJ OK
        # TEST_IMAGE RESIZED TO 19%
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 1 [ OK ]
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 2 [ OK ]
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 3 [ OK ]
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 4 [ OK ]
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 5 [ OK ]
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 6 [ OK ]
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 7 [ OK ]
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 8 [ OK ]
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 9 [ OK ]
        # TEST_IMAGE-BACKUP RESIZED TO 19%
        IMAGE COPY TEST 10 [ OK ]
        
        ###
        # ALL TEST PASSED

I think this test is more safe ,so please, can anyone integrate it on
parted package? All scripts are in the attached tarball.


Many thanks!

Christian


--- /home/christian/packages/parted-1.8.8/libparted/fs/ext2/ext2_block_relocator.c	2007-07-31 19:36:57.000000000 +0200
+++ parted-1.8.8/libparted/fs/ext2/ext2_block_relocator.c	2009-04-06 22:02:48.000000000 +0200
@@ -308,7 +308,87 @@
 	struct ext2_inode buf;
 
 	if (!ext2_read_inode(fs, inode, &buf))
-		return 0;
+	  return 0;
+
+	/* Christian Brunello ([email protected])
+  	 *
+  	 * Check for extended attributes block for this inode
+  	 * and mark the block if it was found 
+  	 */
+	if(buf.i_file_acl || buf.i_dir_acl)
+	{
+		/* We have extended attribute block */
+
+		uint32_t acl_block = buf.i_file_acl ? 
+			PED_LE32_TO_CPU(buf.i_file_acl) :
+			PED_LE32_TO_CPU(buf.i_dir_acl);
+	
+	    	if(fs->opt_debug)
+			fprintf(stderr, "inode %d have extended attributes block (%s=%d)\n", inode,
+				buf.i_file_acl ? "i_file_acl" : "i_dir_acl", acl_block);
+		
+		void *ext_attr_block = ped_malloc(1024 << EXT2_SUPER_LOG_BLOCK_SIZE(fs->sb));
+	    	if(ext_attr_block == NULL)
+	    		ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 
+				_("dynamic memory allocation failure"));
+		    	    
+
+	    	/* Do read extended attribute block header */
+	    	if(ext2_read_blocks(fs, ext_attr_block, acl_block , 1))
+	      	{
+			struct ext2_ext_attr_header *ext_attr_block_header;
+			off_t offset;
+			blk_t inodeblock;
+
+			ext_attr_block_header = (struct ext2_ext_attr_header*)ext_attr_block;
+		
+			/* Do check h_magic field */
+			if(PED_LE32_TO_CPU(ext_attr_block_header->h_magic) & ~(EXT2_EXT_ATTR_MAGIC))
+			{
+				ped_free(ext_attr_block);
+				ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 
+					_("bad magic number in extended attributes block"));
+			}
+		
+			else if(PED_LE32_TO_CPU(ext_attr_block_header->h_blocks) > 1)
+			{
+				ped_free(ext_attr_block);
+				/* We have more than 1 block for key and values */
+				ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
+					_("extended attributes on multiple blocks are not supported"));
+			}
+
+			/* Do mark block */
+			offset = ext2_get_inode_offset(fs, inode, &inodeblock);
+
+			if(buf.i_file_acl)
+			{
+				if(!doblock(fs, state, acl_block, inodeblock, 
+					offset + offsetof(struct ext2_inode, i_file_acl), 0))
+				{
+					ped_free(ext_attr_block);
+					return 0;
+				}		
+			}
+			else
+			{
+				if(!doblock(fs, state, acl_block, inodeblock, 
+					offset + offsetof(struct ext2_inode, i_dir_acl), 0))
+				{
+					ped_free(ext_attr_block);
+					return 0;
+				}		
+			}
+			ped_free(ext_attr_block);
+	      	}
+		else
+	    	{
+			/* error read block */
+			ped_free(ext_attr_block);
+			ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
+				_("error reading extended attributes block"));
+		}
+	}
 
 	if (EXT2_INODE_BLOCKS(buf))
 	{
--- /home/christian/packages/parted-1.8.8/libparted/fs/ext2/ext2.c	2007-07-23 19:58:31.000000000 +0200
+++ parted-1.8.8/libparted/fs/ext2/ext2.c	2009-04-06 22:55:00.000000000 +0200
@@ -305,6 +305,7 @@
 		return 0;
 
 	memcpy(data, bh->data + off, sizeof(struct ext2_inode));
+
 	ext2_brelse(bh, 0);
 	return 1;
 }
@@ -688,7 +689,7 @@
 	}
 
 
-	fs->opt_debug = 1;
+	fs->opt_debug = 0;
 	fs->opt_safe = 1;
 	fs->opt_verbose = 0;
 
@@ -716,9 +717,8 @@
 
 	fs->dynamic_version = EXT2_SUPER_REV_LEVEL (fs->sb) > 0;
 
-	if ((EXT2_SUPER_FEATURE_COMPAT(fs->sb)
-	                & ~(EXT3_FEATURE_COMPAT_HAS_JOURNAL |
-			    EXT2_FEATURE_COMPAT_HAS_DIR_INDEX)) ||
+
+	if ((EXT2_SUPER_FEATURE_COMPAT(fs->sb) & ~(LIBPARTED_SUPPORTED_EXT2_FEATURE_COMPAT)) ||
 	    (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb)
 	    		& ~(EXT2_FEATURE_INCOMPAT_FILETYPE |
 			    EXT3_FEATURE_INCOMPAT_RECOVER)) ||
--- /home/christian/packages/parted-1.8.8/libparted/fs/ext2/ext2_fs.h	2007-05-14 17:24:17.000000000 +0200
+++ parted-1.8.8/libparted/fs/ext2/ext2_fs.h	2009-04-06 22:02:48.000000000 +0200
@@ -51,9 +51,25 @@
 /*
  * Feature set definitions
  */
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC	0x0001
+#define EXT2_FEATURE_COMPAT_IMAGIC_INODES	0x0002
 #define EXT3_FEATURE_COMPAT_HAS_JOURNAL		0x0004
+#define EXT2_FEATURE_COMPAT_EXT_ATTR		0x0008
+#define EXT2_FEATURE_COMPAT_RESIZE_INO		0x0010
 #define EXT2_FEATURE_COMPAT_HAS_DIR_INDEX	0x0020
 
+
+/* Libparted supported features */
+#define LIBPARTED_SUPPORTED_EXT2_FEATURE_COMPAT		\
+  EXT3_FEATURE_COMPAT_HAS_JOURNAL |			\
+  EXT2_FEATURE_COMPAT_EXT_ATTR
+
+#if 0
+/* We support following features in the future */			
+  EXT2_FEATURE_COMPAT_RESIZE_INO |			\
+  EXT2_FEATURE_COMPAT_HAS_DIR_INDEX
+#endif
+  
 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001
 #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE	0x0002
 
--- /home/christian/packages/parted-1.8.8/libparted/fs/ext2/ext2.h	2007-07-23 19:58:31.000000000 +0200
+++ parted-1.8.8/libparted/fs/ext2/ext2.h	2009-04-06 22:02:48.000000000 +0200
@@ -241,4 +241,78 @@
 	return 1;
 }
 
+
+/* Extended attributes stuff: 
+ *
+ * Code grabbed from Linux kernel source
+ *
+ * -- Christian Brunello <[email protected]>
+ */
+
+/* Magic value in attribute blocks */
+#define EXT2_EXT_ATTR_MAGIC_v1		0xEA010000
+#define EXT2_EXT_ATTR_MAGIC		0xEA020000
+
+/* Maximum number of references to one attribute block */
+#define EXT2_EXT_ATTR_REFCOUNT_MAX	1024
+
+/* Header of an extended attribute block */
+struct ext2_ext_attr_header {
+  uint32_t h_magic;	  /* magic number for identification */
+  uint32_t h_refcount;	  /* reference count */
+  uint32_t h_blocks;	  /* number of disk blocks used */
+  uint32_t h_hash;	  /* hash value of all attributes */
+  uint32_t h_reserved[4]; /* zero right now */
+};
+
+/* Structure to hold information about an extended attribute entry */
+struct ext2_ext_attr_entry {
+  uint8_t e_name_len;	/* length of name */
+  uint8_t e_name_index;	/* attribute name index */
+  uint16_t e_value_offs;	/* offset in disk block of value */
+  uint32_t e_value_block;	/* disk block attribute is stored on (n/i) */
+  uint32_t e_value_size;	/* size of attribute value */
+  uint32_t e_hash;		/* hash value of name and value */
+#if 0
+  char	e_name[0];	/* attribute name */
 #endif
+};
+
+#define EXT2_EXT_ATTR_PAD_BITS		2
+#define EXT2_EXT_ATTR_PAD		((unsigned) 1<<EXT2_EXT_ATTR_PAD_BITS)
+#define EXT2_EXT_ATTR_ROUND		(EXT2_EXT_ATTR_PAD-1)
+
+#define EXT2_EXT_ATTR_LEN(name_len) \
+	(((name_len) + EXT2_EXT_ATTR_ROUND + \
+	sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
+#define EXT2_EXT_ATTR_NEXT(entry) \
+	( (struct ext2_ext_attr_entry *)( \
+	  (char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
+#define EXT2_EXT_ATTR_SIZE(size) \
+	(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
+#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((uint32_t *)(entry)) == 0UL)
+#define EXT2_EXT_ATTR_NAME(entry) \
+	(((char *) (entry)) + sizeof(struct ext2_ext_attr_entry))
+#define EXT2_XATTR_LEN(name_len) \
+	(((name_len) + EXT2_EXT_ATTR_ROUND + \
+	sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND)
+#define EXT2_XATTR_SIZE(size) \
+	(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
+
+#ifdef __KERNEL__
+# ifdef CONFIG_EXT2_FS_EXT_ATTR
+extern int ext2_get_ext_attr(struct inode *, const char *, char *, size_t, int);
+extern int ext2_set_ext_attr(struct inode *, const char *, char *, size_t, int);
+extern void ext2_ext_attr_free_inode(struct inode *inode);
+extern void ext2_ext_attr_put_super(struct super_block *sb);
+extern int ext2_ext_attr_init(void);
+extern void ext2_ext_attr_done(void);
+# else
+#  define ext2_get_ext_attr NULL
+#  define ext2_set_ext_attr NULL
+# endif
+#endif  /* __KERNEL__ */
+
+/* end of extended attributes stuff */
+
+#endif /* _EXT2_H */
--- /home/christian/packages/parted-1.8.8/libparted/fs/ext2/../../../tests/t3100-resize-ext2-partion.sh	2007-08-09 20:47:57.000000000 +0200
+++ parted-1.8.8/tests/t3100-resize-ext2-partion.sh	2009-04-06 23:17:59.000000000 +0200
@@ -48,9 +48,9 @@
 # relocator should have relocated 64".
 # Eventually, when this bug is fixed, change each of the following
 # expected failures to "test_expect_success".
-test_expect_failure \
+test_expect_success \
     'resize ext2 primary partition' \
     'parted -s $dev resize 1 0 $NEW_SIZE > out 2>&1'
-test_expect_failure 'check for empty output' '$compare out /dev/null'
+test_expect_success 'check for empty output' '$compare out /dev/null'
 
 test_done

Attachment: scripts.tar.bz2
Description: application/bzip-compressed-tar

_______________________________________________
parted-devel mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/parted-devel

Reply via email to