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

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