Blame SOURCES/0002-xfsdump-intercept-bind-mount-targets.patch

f39c93
From 0717c1cdfeaedc98df8af97b5ab110830e176a5b Mon Sep 17 00:00:00 2001
f39c93
From: Gao Xiang <hsiangkao@redhat.com>
f39c93
Date: Thu, 3 Feb 2022 12:42:30 -0500
f39c93
Subject: [PATCH 2/2] xfsdump: intercept bind mount targets
f39c93
f39c93
It's a bit strange pointing at some non-root bind mount target and
f39c93
then actually dumping from the actual root dir instead.
f39c93
f39c93
Therefore, instead of searching for the root dir of the filesystem,
f39c93
just intercept all bind mount targets by checking whose ino # of
f39c93
".." is itself with getdents.
f39c93
f39c93
Fixes: 25195ebf107d ("xfsdump: handle bind mount targets")
f39c93
Cc: Eric Sandeen <sandeen@redhat.com>
f39c93
Signed-off-by: Gao Xiang <hsiangkao@redhat.com>
f39c93
[sandeen: add explanatory comment to new function]
f39c93
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
f39c93
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
f39c93
---
f39c93
f39c93
Index: xfsdump-3.1.8/dump/content.c
f39c93
===================================================================
f39c93
--- xfsdump-3.1.8.orig/dump/content.c
f39c93
+++ xfsdump-3.1.8/dump/content.c
f39c93
@@ -511,6 +511,60 @@ static bool_t create_inv_session(
f39c93
 		ix_t subtreecnt,
f39c93
 		size_t strmix);
f39c93
 
f39c93
+/*
f39c93
+ * Verify that we are asked to dump from the root of the filesystem;
f39c93
+ * test this by checking whether the inode number we've been given matches
f39c93
+ * the inode number for this directory's ".."
f39c93
+ */
f39c93
+static bool_t
f39c93
+check_rootdir(int fd,
f39c93
+	      xfs_ino_t ino)
f39c93
+{
f39c93
+	struct dirent	*gdp;
f39c93
+	size_t		gdsz;
f39c93
+	bool_t		found = BOOL_FALSE;
f39c93
+
f39c93
+	gdsz = sizeof(struct dirent) + NAME_MAX + 1;
f39c93
+	if (gdsz < GETDENTSBUF_SZ_MIN)
f39c93
+		gdsz = GETDENTSBUF_SZ_MIN;
f39c93
+	gdp = (struct dirent *)calloc(1, gdsz);
f39c93
+	assert(gdp);
f39c93
+
f39c93
+	while (1) {
f39c93
+		struct dirent *p;
f39c93
+		int nread;
f39c93
+
f39c93
+		nread = getdents_wrap(fd, (char *)gdp, gdsz);
f39c93
+		/*
f39c93
+		 * negative count indicates something very bad happened;
f39c93
+		 * try to gracefully end this dir.
f39c93
+		 */
f39c93
+		if (nread < 0) {
f39c93
+			mlog(MLOG_NORMAL | MLOG_WARNING,
f39c93
+_("unable to read dirents for directory ino %llu: %s\n"),
f39c93
+			      ino, strerror(errno));
f39c93
+			break;
f39c93
+		}
f39c93
+
f39c93
+		/* no more directory entries: break; */
f39c93
+		if (!nread)
f39c93
+			break;
f39c93
+
f39c93
+		for (p = gdp; nread > 0;
f39c93
+		     nread -= (int)p->d_reclen,
f39c93
+		     assert(nread >= 0),
f39c93
+		     p = (struct dirent *)((char *)p + p->d_reclen)) {
f39c93
+			if (!strcmp(p->d_name, "..")) {
f39c93
+				if (p->d_ino == ino)
f39c93
+					found = BOOL_TRUE;
f39c93
+				break;
f39c93
+			}
f39c93
+		}
f39c93
+	}
f39c93
+	free(gdp);
f39c93
+	return found;
f39c93
+}
f39c93
+
f39c93
 bool_t
f39c93
 content_init( int argc,
f39c93
 	      char *argv[ ],
f39c93
@@ -1394,6 +1448,14 @@ baseuuidbypass:
f39c93
 			      mntpnt );
f39c93
 			return BOOL_FALSE;
f39c93
 		}
f39c93
+
f39c93
+		if (!check_rootdir(sc_fsfd, rootstat.st_ino)) {
f39c93
+			mlog(MLOG_ERROR,
f39c93
+_("%s is not the root of the filesystem (bind mount?) - use primary mountpoint\n"),
f39c93
+			     mntpnt);
f39c93
+			return BOOL_FALSE;
f39c93
+		}
f39c93
+
f39c93
 		sc_rootxfsstatp =
f39c93
 			( xfs_bstat_t * )calloc( 1, sizeof( xfs_bstat_t ));
f39c93
 		assert( sc_rootxfsstatp );