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

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