From: Christoph Hellwig <hch@infradead.org>
To: Carlos Maiolino <cmaiolino@redhat.com>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH] xfs_fsr: Get the last mount on a specific mount point
Date: Mon, 13 Feb 2012 12:42:40 -0500 [thread overview]
Message-ID: <20120213174240.GA3474@infradead.org> (raw)
In-Reply-To: <1328640076-12645-1-git-send-email-cmaiolino@redhat.com>
Thanks for taking care of this, but this just seems to make the already
horribly ugly code even worse.
What do you think about the version below?
---
From: Christoph Hellwig <hch@lst.de>
Subject: fsr: fix /proc/mounts parsing
Make sure we do not reject an XFS root mount just because /dev/root is also
listed in /proc/mounts. The root cause for this was the awkward getmntany
function, which is replaced with a broader reach find_mountpoint function
which replace getmntany and the surrounding code from the main routine in
a structured way. This changes the flow from finding a mounted filesystem
matching the argument and checking that it's XFS to find a mounted XFS
filesystem and thus fixes the bug.
Based on analysis and an earlier patch from
Carlos Maiolino <cmaiolino@redhat.com>.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fsr/xfs_fsr.c | 142 +++++++++++++++++++++++++++++-----------------------------
1 file changed, 72 insertions(+), 70 deletions(-)
Index: xfsprogs-dev/fsr/xfs_fsr.c
===================================================================
--- xfsprogs-dev.orig/fsr/xfs_fsr.c 2012-02-12 16:30:07.286766766 -0800
+++ xfsprogs-dev/fsr/xfs_fsr.c 2012-02-12 16:42:39.293447376 -0800
@@ -109,7 +109,6 @@ static void tmp_init(char *mnt);
static char * tmp_next(char *mnt);
static void tmp_close(char *mnt);
int xfs_getgeom(int , xfs_fsop_geom_v1_t * );
-static int getmntany(FILE *, struct mntent *, struct mntent *, struct stat64 *);
xfs_fsop_geom_v1_t fsgeom; /* geometry of active mounted system */
@@ -178,18 +177,73 @@ aborter(int unused)
exit(1);
}
+/*
+ * Check if the argument is either the device name or mountpoint of an XFS
+ * filesystem. Note that we do not care about bind mounted regular files
+ * here - the code that handles defragmentation of invidual files takes care
+ * of that.
+ */
+static char *
+find_mountpoint(char *mtab, char *argname, struct stat64 *sb)
+{
+ struct mntent *t;
+ struct stat64 ms;
+ FILE *mtabp;
+ char *mntp = NULL;
+
+ mtabp = setmntent(mtab, "r");
+ if (!mtabp) {
+ fprintf(stderr, _("%s: cannot read %s\n"),
+ progname, mtab);
+ exit(1);
+ }
+
+ while ((t = getmntent(mtabp))) {
+ if (S_ISDIR(sb->st_mode)) {
+ if (stat64(t->mnt_dir, &ms) < 0)
+ continue;
+ if (sb->st_ino != ms.st_ino)
+ continue;
+ if (sb->st_dev != ms.st_dev)
+ continue;
+ } else {
+ if (stat64(t->mnt_fsname, &ms) < 0)
+ continue;
+ if (sb->st_rdev != ms.st_rdev)
+ continue;
+ }
+
+ if (strcmp(t->mnt_type, MNTTYPE_XFS) != 0)
+ continue;
+
+ /*
+ * If we found an entry based on the device name make sure we
+ * stat the mountpoint that the mtab gave actually is accessible
+ * before using it.
+ */
+ if (S_ISBLK(sb->st_mode)) {
+ struct stat64 sb2;
+
+ if (stat64(t->mnt_dir, &sb2) < 0)
+ continue;
+ }
+
+ mntp = t->mnt_dir;
+ break;
+ }
+
+ endmntent(mtabp);
+ return mntp;
+}
+
int
main(int argc, char **argv)
{
- struct stat64 sb, sb2;
+ struct stat64 sb;
char *argname;
- char *cp;
int c;
- struct mntent mntpref;
- register struct mntent *mntp;
- struct mntent ment;
+ char *mntp;
char *mtab = NULL;
- register FILE *mtabp;
setlinebuf(stdout);
progname = basename(argv[0]);
@@ -281,49 +335,26 @@ main(int argc, char **argv)
if (optind < argc) {
for (; optind < argc; optind++) {
argname = argv[optind];
- mntp = NULL;
+
if (lstat64(argname, &sb) < 0) {
fprintf(stderr,
_("%s: could not stat: %s: %s\n"),
progname, argname, strerror(errno));
continue;
}
- if (S_ISLNK(sb.st_mode) && stat64(argname, &sb2) == 0 &&
- (S_ISBLK(sb2.st_mode) || S_ISCHR(sb2.st_mode)))
- sb = sb2;
- if (S_ISBLK(sb.st_mode) || (S_ISDIR(sb.st_mode))) {
- if ((mtabp = setmntent(mtab, "r")) == NULL) {
- fprintf(stderr,
- _("%s: cannot read %s\n"),
- progname, mtab);
- exit(1);
- }
- bzero(&mntpref, sizeof(mntpref));
- if (S_ISDIR(sb.st_mode))
- mntpref.mnt_dir = argname;
- else
- mntpref.mnt_fsname = argname;
- if (getmntany(mtabp, &ment, &mntpref, &sb) &&
- strcmp(ment.mnt_type, MNTTYPE_XFS) == 0) {
- mntp = &ment;
- if (S_ISBLK(sb.st_mode)) {
- cp = mntp->mnt_dir;
- if (cp == NULL ||
- stat64(cp, &sb2) < 0) {
- fprintf(stderr, _(
- "%s: could not stat: %s: %s\n"),
- progname, argname,
- strerror(errno));
- continue;
- }
- sb = sb2;
- argname = cp;
- }
- }
+ if (S_ISLNK(sb.st_mode)) {
+ struct stat64 sb2;
+
+ if (stat64(argname, &sb2) == 0 &&
+ (S_ISBLK(sb2.st_mode) ||
+ S_ISCHR(sb2.st_mode)))
+ sb = sb2;
}
+
+ mntp = find_mountpoint(mtab, argname, &sb);
if (mntp != NULL) {
- fsrfs(mntp->mnt_dir, 0, 100);
+ fsrfs(mntp, 0, 100);
} else if (S_ISCHR(sb.st_mode)) {
fprintf(stderr, _(
"%s: char special not supported: %s\n"),
@@ -1639,35 +1670,6 @@ fsrprintf(const char *fmt, ...)
}
/*
- * emulate getmntany
- */
-static int
-getmntany(FILE *fp, struct mntent *mp, struct mntent *mpref, struct stat64 *s)
-{
- struct mntent *t;
- struct stat64 ms;
-
- while ((t = getmntent(fp))) {
- if (mpref->mnt_fsname) { /* device */
- if (stat64(t->mnt_fsname, &ms) < 0)
- continue;
- if (s->st_rdev != ms.st_rdev)
- continue;
- }
- if (mpref->mnt_dir) { /* mount point */
- if (stat64(t->mnt_dir, &ms) < 0)
- continue;
- if (s->st_ino != ms.st_ino || s->st_dev != ms.st_dev)
- continue;
- }
- *mp = *t;
- break;
- }
- return (t != NULL);
-}
-
-
-/*
* Initialize a directory for tmp file use. This is used
* by the full filesystem defragmentation when we're walking
* the inodes and do not know the path for the individual
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2012-02-13 17:42 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-07 18:41 [PATCH] xfs_fsr: Get the last mount on a specific mount point Carlos Maiolino
2012-02-13 17:42 ` Christoph Hellwig [this message]
2012-02-15 12:31 ` Carlos Maiolino
2012-02-17 17:26 ` Christoph Hellwig
2012-02-17 23:36 ` Eric Sandeen
2012-04-24 20:14 ` Carlos Maiolino
2012-04-24 20:57 ` Mark Tinguely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120213174240.GA3474@infradead.org \
--to=hch@infradead.org \
--cc=cmaiolino@redhat.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox