Skip to contentSkip to conversation

xfsdump: save & restore 32-bit projids

PATCH In review Eric Sandeen 4 participants 4 messages Aug 27, 2012 – Sep 18, 2012

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 xfsdump: save & restore 32-bit projids

Current xfsdump/xfsrestore only recognize the lower 16 bits of the projid. With this patch, the full 32 bits are dumped & restored.

---

This also adds a definition for bs_forkoff, but I don't think that is something which should get saved & restored, correct?

TBH I've done very little hacking on xfsdump. I think this requires a new version, but not sure. This seems to work but may need sanity checks & fixups. And, of course, an xfstest.

Thanks,
-Eric

common/arch_xlate.c +2 -1
index c156313..e42abd5 100644
@@ -376,7 +376,8 @@ xlate_bstat(bstat_t *bs1, bstat_t *bs2, int dir)
 	IXLATE(bs1, bs2, bs_extsize);
 	IXLATE(bs1, bs2, bs_extents);
 	IXLATE(bs1, bs2, bs_gen);
-	IXLATE(bs1, bs2, bs_projid);
+	IXLATE(bs1, bs2, bs_projid_lo);
+	IXLATE(bs1, bs2, bs_projid_hi);
 	IXLATE(bs1, bs2, bs_dmevmask);
 	IXLATE(bs1, bs2, bs_dmstate);
 
common/content_inode.h +16 -2
index a25b66e..8f0390c 100644
@@ -173,8 +173,10 @@ struct bstat {				/*		     bytes accum */
 	int32_t		bs_extsize;	/* extent size		 4    50 */
 	int32_t		bs_extents;	/* number of extents	 4    54 */
 	u_int32_t	bs_gen;		/* generation count	 4    58 */
-	u_int16_t	bs_projid;	/* project id		 2    5a */
-	char		bs_pad[ 14 ];	/* for expansion	 e    68 */
+	u_int16_t	bs_projid_lo;	/* low 16 of project id	 2    5a */
+	u_int16_t	bs_forkoff;	/* inode fork offset	 2    5c */
+	u_int16_t	bs_projid_hi;	/* hi 16 of project id	 2    5e */
+	char		bs_pad[ 10 ];	/* for expansion	 e    68 */
 	u_int32_t	bs_dmevmask;	/* DMI event mask        4    6c */
 	u_int16_t	bs_dmstate;	/* DMI state info        2    6e */
 	char		bs_pad1[ 18 ];	/* for expansion        12    80 */
@@ -184,6 +186,18 @@ struct bstat {				/*		     bytes accum */
 
 typedef struct bstat bstat_t;
 
+/*
+ * Project quota id helpers (previously projid was 16bit only
+ * and using two 16bit values to hold new 32bit projid was choosen
+ * to retain compatibility with "old" filesystems).
+ */
+static inline __uint32_t
+bstat_projid(struct bstat *bs)
+{
+        return (__uint32_t)bs->bs_projid_hi << 16 | bs->bs_projid_lo;
+}
+
+
 /* extended inode flags that can only be set after all data
  * has been restored to a file.
  */
common/global.c +1 -0
index 8e49d8b..1793ff4 100644
@@ -281,6 +281,7 @@ global_version_check( u_int32_t version )
 		case GLOBAL_HDR_VERSION_1:
 		case GLOBAL_HDR_VERSION_2:
 		case GLOBAL_HDR_VERSION_3:
+		case GLOBAL_HDR_VERSION_4:
 			return BOOL_TRUE;
 		default:
 			return BOOL_FALSE;
common/global.h +4 -2
index 6556a68..5138ed8 100644
@@ -28,13 +28,15 @@
 #define GLOBAL_HDR_VERSION_1	1
 #define GLOBAL_HDR_VERSION_2	2
 #define GLOBAL_HDR_VERSION_3	3
-	/* version 3 uses the full 32-bit inode generation number in direnthdr_t.
+#define GLOBAL_HDR_VERSION_4	4
+	/* version 4 adds 32-bit projid (projid_hi)
+	 * version 3 uses the full 32-bit inode generation number in direnthdr_t.
 	 * version 2 adds encoding of holes and a change to on-tape inventory format.
 	 * version 1 adds extended file attribute dumping.
 	 * version 0 xfsrestore can't handle media produced
 	 * by version 1 xfsdump. 
 	 */
-#define GLOBAL_HDR_VERSION	GLOBAL_HDR_VERSION_3
+#define GLOBAL_HDR_VERSION	GLOBAL_HDR_VERSION_4
 
 #define GLOBAL_HDR_STRING_SZ	0x100
 #define GLOBAL_HDR_TIME_SZ	4
dump/content.c +2 -1
index 481297a..ec5e954 100644
@@ -4927,7 +4927,8 @@ copy_xfs_bstat(bstat_t *dst, xfs_bstat_t *src)
 	dst->bs_extsize = src->bs_extsize;
 	dst->bs_extents = src->bs_extents;
 	dst->bs_gen = src->bs_gen;
-	dst->bs_projid = src->bs_projid;
+	dst->bs_projid_lo = src->bs_projid_lo;
+	dst->bs_projid_hi = src->bs_projid_hi;
 	dst->bs_dmevmask = src->bs_dmevmask;
 	dst->bs_dmstate = src->bs_dmstate;
 }
restore/content.c +2 -2
index 3110cdf..edd00ed 100644
@@ -7451,7 +7451,7 @@ restore_reg( drive_t *drivep,
 		memset((void *)&fsxattr, 0, sizeof( fsxattr ));
 		fsxattr.fsx_xflags = bstatp->bs_xflags & ~POST_DATA_XFLAGS;
 		fsxattr.fsx_extsize = (u_int32_t) bstatp->bs_extsize;
-		fsxattr.fsx_projid = bstatp->bs_projid;
+		fsxattr.fsx_projid = bstat_projid(bstatp);
 
 		rval = ioctl( *fdp, XFS_IOC_FSSETXATTR, (void *)&fsxattr);
 		if ( rval < 0 ) {
@@ -7702,7 +7702,7 @@ restore_complete_reg(stream_context_t *strcxtp)
 		memset((void *)&fsxattr, 0, sizeof( fsxattr ));
 		fsxattr.fsx_xflags = bstatp->bs_xflags;
 		fsxattr.fsx_extsize = (u_int32_t)bstatp->bs_extsize;
-		fsxattr.fsx_projid = bstatp->bs_projid;
+		fsxattr.fsx_projid = bstat_projid(bstatp);
 
 		rval = ioctl( fd, XFS_IOC_FSSETXATTR, (void *)&fsxattr );
 		if ( rval < 0 ) {
restore/dirattr.c +2 -2
index 68d1b49..8a1fb06 100644
@@ -434,7 +434,7 @@ dirattr_add( filehdr_t *fhdrp )
 	dirattr.d_ctime = ( time32_t )fhdrp->fh_stat.bs_ctime.tv_sec;
 	dirattr.d_xflags = fhdrp->fh_stat.bs_xflags;
 	dirattr.d_extsize = ( u_int32_t )fhdrp->fh_stat.bs_extsize;
-	dirattr.d_projid = fhdrp->fh_stat.bs_projid;
+	dirattr.d_projid = bstat_projid(&(fhdrp->fh_stat));
 	dirattr.d_dmevmask = fhdrp->fh_stat.bs_dmevmask;
 	dirattr.d_dmstate = ( u_int32_t )fhdrp->fh_stat.bs_dmstate;
 #ifdef DIRATTRCHK
@@ -812,7 +812,7 @@ dirattr_update( dah_t dah, filehdr_t *fhdrp )
 	dirattr.d_ctime = ( time32_t )fhdrp->fh_stat.bs_ctime.tv_sec;
 	dirattr.d_xflags = fhdrp->fh_stat.bs_xflags;
 	dirattr.d_extsize = ( u_int32_t )fhdrp->fh_stat.bs_extsize;
-	dirattr.d_projid = fhdrp->fh_stat.bs_projid;
+	dirattr.d_projid = bstat_projid(&(fhdrp->fh_stat));
 	dirattr.d_dmevmask = fhdrp->fh_stat.bs_dmevmask;
 	dirattr.d_dmstate = ( u_int32_t )fhdrp->fh_stat.bs_dmstate;
 	dirattr.d_extattroff = DIRATTR_EXTATTROFFNULL;

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#1 lore raw
Quoted 10 lines · Eric Sandeen

Current xfsdump/xfsrestore only recognize the lower 16 bits of the projid. With this patch, the full 32 bits are dumped & restored.

---

This also adds a definition for bs_forkoff, but I don't think that is something which should get saved & restored, correct?

Right - it's a kernel controlled field, only exported as a hint to help xfs_fsr build similarly formatted inodes.

Quoted 3 lines

TBH I've done very little hacking on xfsdump. I think this requires a new version, but not sure. This seems to work but may need sanity checks & fixups. And, of course, an xfstest.

Looks ok, but I'm in the same boat as you on xfsdump. A QA test would be good to go along with this. ;)

Cheers,

Dave.

Signature · 7 lines
Dave Chinner
[email protected]

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
#2 lore raw

PATCH 1/1 xfstests: test dump/restore of 32-bit projids

In reply to Eric Sandeen

Test that xfsdump/xfsrestore properly restores more than the bottom 16 bits of a 32-bit projid.

---

285 new file +81 -0
new file mode 100755
index 0000000..2804e5d
@@ -0,0 +1,81 @@
+#! /bin/bash
+# FS QA Test No. 285
+#
+# Test projid32: persist 32 bit projids thorugh dump/restore
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2012 Eric Sandeen.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+# creator
[email protected]
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    cd /
+    rm -f $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.dump
+. ./common.quota
+
+_require_scratch
+_require_xfs_quota
+
+# real QA test starts here
+
+_supported_fs xfs
+_supported_os IRIX Linux
+
+_scratch_mkfs_xfs -i projid32bit=1 >> $seq.full || _fail "mkfs failed"
+
+export MOUNT_OPTIONS="-opquota"
+_qmount
+_require_prjquota $SCRATCH_DEV
+
+# > 16 bit project ID
+PROJID=2123456789
+
+# Put a project quota on a dir
+mkdir $SCRATCH_MNT/dir
+xfs_quota -x -c "project -s -p $SCRATCH_MNT/dir $PROJID" $SCRATCH_MNT >> $seq.full || _fail "dir pquota failed"
+
+# Dump it then restore it to a fresh fs, and check the projid
+rm -f $tmp.dumpfile
+xfsdump -L label -M media -f $tmp.dumpfile $SCRATCH_MNT >> $seq.full || _fail "dump failed"
+umount $SCRATCH_DEV
+
+_scratch_mkfs_xfs -i projid32bit=1 >> $seq.full || _fail "re-mkfs failed"
+_qmount
+xfsrestore -f $tmp.dumpfile $SCRATCH_MNT >> $seq.full || _fail "restore failed"
+
+# check (-c) that we got the correct project ID back post-restore
+xfs_quota -x -c "project -s -c -p $SCRATCH_MNT/dir $PROJID" $SCRATCH_MNT
+
+# success, all done
+status=0
+exit
285.out new file +3 -0
new file mode 100644
index 0000000..daf4e4c
@@ -0,0 +1,3 @@
+QA output created by 285
+Checking project 2123456790 (path /mnt/scratch/dir)...
+Processed 1 (/etc/projects and cmdline) paths for project 2123456790 with recursion depth infinite (-1).
group +1 -0
index 104ed35..bbc74fe 100644
@@ -403,3 +403,4 @@ deprecated
 282 dump ioctl auto quick
 283 dump ioctl auto quick
 284 auto
+285 auto dump quota

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

Reviewed-by on v1 1/1
#3 lore raw
In reply to Eric Sandeen

Hey Eric,

Quoted 6 lines · Eric Sandeen

Current xfsdump/xfsrestore only recognize the lower 16 bits of the projid. With this patch, the full 32 bits are dumped & restored.

Quoted 8 lines

---

This also adds a definition for bs_forkoff, but I don't think that is something which should get saved & restored, correct?

TBH I've done very little hacking on xfsdump. I think this requires a new version, but not sure. This seems to work but may need sanity checks & fixups. And, of course, an xfstest.

I have two versioned dump files ~/dump-v3 and ~/dump-v4. v3 is prior to your patch and v4 was with this patch.

Here is a version 3 xfsrestore of a version 4 dump:

~/xfsdump # xfsrestore -f ~/dump-v4 /mnt/scratch
xfsrestore: using file dump (drive_simple) strategy
xfsrestore: version 3.1.0 (dump format 3.0) - type ^C for status and control

			   ^^^^^^^^^^^^^^^ version 3

xfsrestore: searching media for dump
xfsrestore: ERROR: unrecognized media file header version (4)
xfsrestore: restore complete: 0 seconds elapsed
xfsrestore: Restore Summary:
xfsrestore: stream 0 /root/dump-v4 OK (success)
xfsrestore: Restore Status: SUCCESS <---- FAIL?

We should consider whether failure is the correct thing to do when trying to restore from an incompatible dump file. That is not a problem with this patch.

Now a version 4 xfsrestore with a version 3 dump:

~/xfsdump # xfsrestore -f ~/dump-v3 /mnt/scratch
xfsrestore: using file dump (drive_simple) strategy
xfsrestore: version 3.1.0 (dump format 4.0) - type ^C for status and control

			   ^^^^^^^^^^^^^^^ version 4, looks good

xfsrestore: searching media for dump
xfsrestore: examining media file 0
xfsrestore: dump description:
xfsrestore: hostname: foo
xfsrestore: mount point: /mnt/scratch
xfsrestore: volume: /dev/sdb1
xfsrestore: session time: Tue Sep 18 14:45:36 2012
xfsrestore: level: 0
xfsrestore: session label: "k"
xfsrestore: media label: "k"
xfsrestore: file system id: 983f85f2-9a11-460d-a276-9aec42fbd8f7
xfsrestore: session id: 4fbfbd3d-6f4a-4ad5-909b-bdf4742e849d
xfsrestore: media id: 41f8e77c-7b93-49c5-a9ed-c66a391778e7
xfsrestore: using online session inventory
xfsrestore: searching media for directory dump
xfsrestore: reading directories
xfsrestore: 4 directories and 9 entries processed
xfsrestore: directory post-processing
xfsrestore: restoring non-directory files
xfsrestore: restore complete: 0 seconds elapsed
xfsrestore: Restore Summary:
xfsrestore: stream 0 /root/dump-v3 OK (success)
xfsrestore: Restore Status: SUCCESS

So the behavior with respect to versioning is: You can restore from dumps that have a smaller or equal dump version than your xfsrestore, but not from dumps with versions greater than your xfsrestore. Now I'd like to see the behavior with some project ids set and a version 3 dump with version 4 xfsrestore.

A version 4 xfsrestore with a version 3 dump:

~/xfsdump # xfsrestore -f ~/dump-v3-3 /mnt/scratch/restore/
xfsrestore: using file dump (drive_simple) strategy
xfsrestore: version 3.1.0 (dump format 4.0) - type ^C for status and control
xfsrestore: searching media for dump
xfsrestore: examining media file 0
xfsrestore: dump description:
xfsrestore: hostname: foo
xfsrestore: mount point: /mnt/scratch
xfsrestore: volume: /dev/sdb1
xfsrestore: session time: Tue Sep 18 15:18:16 2012
xfsrestore: level: 0
xfsrestore: session label: "l"
xfsrestore: media label: "l"
xfsrestore: file system id: 983f85f2-9a11-460d-a276-9aec42fbd8f7
xfsrestore: session id: 9ad2909c-3542-428b-9f73-0bf207b77888
xfsrestore: media id: 529e47bc-b6fa-427c-a0f5-dcd4c9707adc
xfsrestore: using online session inventory
xfsrestore: searching media for directory dump
xfsrestore: reading directories
xfsrestore: 4 directories and 8 entries processed
xfsrestore: directory post-processing
xfsrestore: restoring non-directory files
xfsrestore: project quota information written to '/mnt/scratch/restore//xfsdump_quotas_proj'
xfsrestore: use 'xfs_quota' to restore quotas
xfsrestore: restore complete: 0 seconds elapsed
xfsrestore: Restore Summary:
xfsrestore: stream 0 /root/dump-v3-3 OK (success)
xfsrestore: Restore Status: SUCCESS

And a version 4 xfsrestore with a version 4 dump:

~/xfsdump # xfsrestore -f ~/dump-v4-3 /mnt/scratch/restore2
xfsrestore: using file dump (drive_simple) strategy
xfsrestore: version 3.1.0 (dump format 4.0) - type ^C for status and control
xfsrestore: searching media for dump
xfsrestore: examining media file 0
xfsrestore: dump description:
xfsrestore: hostname: foo
xfsrestore: mount point: /mnt/scratch
xfsrestore: volume: /dev/sdb1
xfsrestore: session time: Tue Sep 18 15:20:18 2012
xfsrestore: level: 0
xfsrestore: session label: "l"
xfsrestore: media label: "l"
xfsrestore: file system id: 983f85f2-9a11-460d-a276-9aec42fbd8f7
xfsrestore: session id: e5d07daf-3bfc-4ab8-b13c-ad48db813807
xfsrestore: media id: 9d043994-9abb-4fd0-8cc9-eda68c62641c
xfsrestore: using online session inventory
xfsrestore: searching media for directory dump
xfsrestore: reading directories
xfsrestore: 4 directories and 8 entries processed
xfsrestore: directory post-processing
xfsrestore: restoring non-directory files
xfsrestore: project quota information written to '/mnt/scratch/restore2/xfsdump_quotas_proj'
xfsrestore: use 'xfs_quota' to restore quotas
xfsrestore: restore complete: 0 seconds elapsed
xfsrestore: Restore Summary:
xfsrestore: stream 0 /root/dump-v4-3 OK (success)
xfsrestore: Restore Status: SUCCESS

Here are the files with project quotas:

originals:
~/xfsdump # xfs_io -r -c "lsproj" /mnt/scratch/dumpme/16bit projid = 1234
~/xfsdump # xfs_io -r -c "lsproj" /mnt/scratch/dumpme/32bit projid = 2123456789

from the v3 dump:
~/xfsdump # xfs_io -r -c "lsproj" /mnt/scratch/restore/dumpme/16bit projid = 1234
~/xfsdump # xfs_io -r -c "lsproj" /mnt/scratch/restore/dumpme/32bit
projid = 24853 <--- note that it is munged just as in test 287

from the v4 dump:
~/xfsdump # xfs_io -r -c "lsproj" /mnt/scratch/restore2/dumpme/16bit projid = 1234
~/xfsdump # xfs_io -r -c "lsproj" /mnt/scratch/restore2/dumpme/32bit projid = 2123456789

The code looks good, the xfstest 287 looks good, and the above shows that we have the desired behavior with respect to dump versioning.

Committed to git://oss.sgi.com/xfs/cmds/xfsdump.git, master branch.

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs