+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc.
* 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
*/
#include "libxfs.h"
#include "jdm.h"
#include "xfs_bmap_btree.h"
#include "xfs_attr_sf.h"
+#include "path.h"
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/statvfs.h>
#include <sys/xattr.h>
-
-#ifdef HAVE_MNTENT
-# include <mntent.h>
-#endif
-
-#ifndef XFS_XFLAG_NODEFRAG
-#define XFS_XFLAG_NODEFRAG 0x00002000 /* src dependancy, remove later */
-#endif
+#include <paths.h>
#define _PATH_FSRLAST "/var/tmp/.fsrlast_xfs"
#define _PATH_PROC_MOUNTS "/proc/mounts"
char *progname;
-int vflag;
-int gflag;
+static int vflag;
+static int gflag;
static int Mflag;
/* static int nflag; */
-int dflag = 0;
+static int dflag = 0;
/* static int sflag; */
-int argv_blksz_dio;
+static int argv_blksz_dio;
extern int max_ext_size;
static int npasses = 10;
static int startpass = 0;
-struct getbmap *outmap = NULL;
-int outmap_size = 0;
-int RealUid;
-int tmp_agi;
-static __int64_t minimumfree = 2048;
+static struct getbmap *outmap = NULL;
+static int outmap_size = 0;
+static int RealUid;
+static int tmp_agi;
+static int64_t minimumfree = 2048;
#define MNTTYPE_XFS "xfs"
#define NULLFD -1
#define GRABSZ 64
#define TARGETRANGE 10
-#define V_NONE 0
-#define V_OVERVIEW 1
-#define V_ALL 2
-#define BUFFER_SIZE (1<<16)
#define BUFFER_MAX (1<<24)
static time_t howlong = 7200; /* default seconds of reorganizing */
static void fsrall_cleanup(int timeout);
static int getnextents(int);
int xfsrtextsize(int fd);
-int xfs_getrt(int fd, struct statvfs64 *sfbp);
+int xfs_getrt(int fd, struct statvfs *sfbp);
char * gettmpname(char *fname);
char * getparent(char *fname);
int fsrprintf(const char *fmt, ...);
static void tmp_close(char *mnt);
int xfs_getgeom(int , xfs_fsop_geom_v1_t * );
-xfs_fsop_geom_v1_t fsgeom; /* geometry of active mounted system */
+static xfs_fsop_geom_v1_t fsgeom; /* geometry of active mounted system */
#define NMOUNT 64
static int numfs;
int npass;
} fsdesc_t;
-fsdesc_t *fs, *fsbase, *fsend;
-int fsbufsize = 10; /* A starting value */
-int nfrags = 0; /* Debug option: Coerse into specific number
+static fsdesc_t *fs, *fsbase, *fsend;
+static int fsbufsize = 10; /* A starting value */
+static int nfrags = 0; /* Debug option: Coerse into specific number
* of extents */
-int openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;
+static int openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;
-int
+static int
xfs_fsgeometry(int fd, xfs_fsop_geom_v1_t *geom)
{
return ioctl(fd, XFS_IOC_FSGEOMETRY_V1, geom);
}
-int
+static int
xfs_bulkstat_single(int fd, xfs_ino_t *lastip, xfs_bstat_t *ubuffer)
{
xfs_fsop_bulkreq_t bulkreq;
return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
}
-int
+static int
xfs_bulkstat(int fd, xfs_ino_t *lastip, int icount,
xfs_bstat_t *ubuffer, __s32 *ocount)
{
return ioctl(fd, XFS_IOC_FSBULKSTAT, &bulkreq);
}
-int
+static int
xfs_swapext(int fd, xfs_swapext_t *sx)
{
return ioctl(fd, XFS_IOC_SWAPEXT, sx);
}
-int
+static int
xfs_fscounts(int fd, xfs_fsop_counts_t *counts)
{
return ioctl(fd, XFS_IOC_FSCOUNTS, counts);
}
-void
+static void
aborter(int unused)
{
fsrall_cleanup(1);
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)) { /* mount point */
- if (stat64(t->mnt_dir, &ms) < 0)
- continue;
- if (sb->st_ino != ms.st_ino)
- continue;
- if (sb->st_dev != ms.st_dev)
- continue;
- if (strcmp(t->mnt_type, MNTTYPE_XFS) != 0)
- continue;
- } else { /* device */
- struct stat64 sb2;
-
- 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;
-
- /*
- * Make sure the mountpoint given by mtab is accessible
- * before using it.
- */
- 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;
+ struct stat sb;
char *argname;
int c;
- char *mntp;
+ struct fs_path *fsp;
char *mtab = NULL;
setlinebuf(stdout);
if (vflag)
setbuf(stdout, NULL);
- starttime = time(0);
+ starttime = time(NULL);
/* Save the caller's real uid */
RealUid = getuid();
pagesize = getpagesize();
-
+ fs_table_initialise(0, NULL, 0, NULL);
if (optind < argc) {
for (; optind < argc; optind++) {
argname = argv[optind];
- if (lstat64(argname, &sb) < 0) {
+ if (lstat(argname, &sb) < 0) {
fprintf(stderr,
_("%s: could not stat: %s: %s\n"),
progname, argname, strerror(errno));
}
if (S_ISLNK(sb.st_mode)) {
- struct stat64 sb2;
+ struct stat sb2;
- if (stat64(argname, &sb2) == 0 &&
+ if (stat(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, 0, 100);
+ fsp = fs_table_lookup_mount(argname);
+ if (!fsp)
+ fsp = fs_table_lookup_blkdev(argname);
+ if (fsp != NULL) {
+ fsrfs(fsp->fs_dir, 0, 100);
} else if (S_ISCHR(sb.st_mode)) {
fprintf(stderr, _(
"%s: char special not supported: %s\n"),
static void
initallfs(char *mtab)
{
- FILE *fp;
- struct mntent *mp;
+ struct mntent_cursor cursor;
+ struct mntent *mnt= NULL;
int mi;
char *cp;
- struct stat64 sb;
-
- fp = setmntent(mtab, "r");
- if (fp == NULL) {
- fsrprintf(_("could not open mtab file: %s\n"), mtab);
- exit(1);
- }
+ struct stat sb;
/* malloc a number of descriptors, increased later if needed */
if (!(fsbase = (fsdesc_t *)malloc(fsbufsize * sizeof(fsdesc_t)))) {
/* find all rw xfs file systems */
mi = 0;
fs = fsbase;
- while ((mp = getmntent(fp))) {
+
+ if (platform_mntent_open(&cursor, mtab) != 0){
+ fprintf(stderr, "Error: can't get mntent entries.\n");
+ exit(1);
+ }
+
+ while ((mnt = platform_mntent_next(&cursor)) != NULL) {
int rw = 0;
- if (strcmp(mp->mnt_type, MNTTYPE_XFS ) != 0 ||
- stat64(mp->mnt_fsname, &sb) == -1 ||
+ if (strcmp(mnt->mnt_type, MNTTYPE_XFS ) != 0 ||
+ stat(mnt->mnt_fsname, &sb) == -1 ||
!S_ISBLK(sb.st_mode))
continue;
- cp = strtok(mp->mnt_opts,",");
+ cp = strtok(mnt->mnt_opts,",");
do {
if (strcmp("rw", cp) == 0)
rw++;
if (rw == 0) {
if (dflag)
fsrprintf(_("Skipping %s: not mounted rw\n"),
- mp->mnt_fsname);
+ mnt->mnt_fsname);
continue;
}
fs = (fsbase + mi); /* Needed ? */
}
- fs->dev = strdup(mp->mnt_fsname);
- fs->mnt = strdup(mp->mnt_dir);
+ fs->dev = strdup(mnt->mnt_fsname);
+ fs->mnt = strdup(mnt->mnt_dir);
if (fs->dev == NULL) {
- fsrprintf(_("strdup(%s) failed\n"), mp->mnt_fsname);
+ fsrprintf(_("strdup(%s) failed\n"), mnt->mnt_fsname);
exit(1);
}
if (fs->mnt == NULL) {
- fsrprintf(_("strdup(%s) failed\n"), mp->mnt_dir);
+ fsrprintf(_("strdup(%s) failed\n"), mnt->mnt_dir);
exit(1);
}
mi++;
fs++;
}
+ platform_mntent_close(&cursor);
+
numfs = mi;
fsend = (fsbase + numfs);
- endmntent(fp);
if (numfs == 0) {
fsrprintf(_("no rw xfs file systems in mtab: %s\n"), mtab);
exit(0);
char *ptr;
xfs_ino_t startino = 0;
fsdesc_t *fsp;
- struct stat64 sb, sb2;
+ struct stat sb, sb2;
fsrprintf("xfs_fsr -m %s -t %d -f %s ...\n", mtab, howlong, leftofffile);
fs = fsbase;
/* where'd we leave off last time? */
- if (lstat64(leftofffile, &sb) == 0) {
+ if (lstat(leftofffile, &sb) == 0) {
if ( (fd = open(leftofffile, O_RDONLY)) == -1 ) {
fsrprintf(_("%s: open failed\n"), leftofffile);
}
- else if ( fstat64(fd, &sb2) == 0) {
+ else if ( fstat(fd, &sb2) == 0) {
/*
* Verify that lstat & fstat point to the
* same regular file (no links/no quick spoofs)
signal(SIGTERM, aborter);
/* reorg for 'howlong' -- checked in 'fsrfs' */
- while (endtime > time(0)) {
+ while (endtime > time(NULL)) {
pid_t pid;
- if (fs == fsend)
- fs = fsbase;
- if (fs->npass == npasses) {
- fsrprintf(_("Completed all %d passes\n"), npasses);
- break;
- }
+
if (npasses > 1 && !fs->npass)
Mflag = 1;
else
startino = 0; /* reset after the first time through */
fs->npass++;
fs++;
+ if (fs == fsend)
+ fs = fsbase;
+ if (fs->npass == npasses) {
+ fsrprintf(_("Completed all %d passes\n"), npasses);
+ break;
+ }
}
- fsrall_cleanup(endtime <= time(0));
+ fsrall_cleanup(endtime <= time(NULL));
}
/*
if (timeout) {
fsrprintf(_("%s startpass %d, endpass %d, time %d seconds\n"),
progname, startpass, fs->npass,
- time(0) - endtime + howlong);
+ time(NULL) - endtime + howlong);
/* record where we left off */
fd = open(leftofffile, O_WRONLY|O_CREAT|O_EXCL, 0644);
break;
}
}
- if (endtime && endtime < time(0)) {
+ if (endtime && endtime < time(NULL)) {
tmp_close(mntdir);
close(fsfd);
fsrall_cleanup(1);
xfs_bstat_t *statp)
{
int error;
- struct statvfs64 vfss;
+ struct statvfs vfss;
struct fsxattr fsx;
unsigned long bsize;
* Note that xfs_bstat.bs_blksize returns the filesystem blocksize,
* not the optimal I/O size as struct stat.
*/
- if (statvfs64(fsname ? fsname : fname, &vfss) < 0) {
+ if (statvfs(fsname ? fsname : fname, &vfss) < 0) {
fsrprintf(_("unable to get fs stat on %s: %s\n"),
fname, strerror(errno));
return -1;
return 1;
}
- if ((ioctl(fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
+ if ((ioctl(fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
fsrprintf(_("failed to get inode attrs: %s\n"), fname);
return(-1);
}
- if (fsx.fsx_xflags & (XFS_XFLAG_IMMUTABLE|XFS_XFLAG_APPEND)) {
+ if (fsx.fsx_xflags & (FS_XFLAG_IMMUTABLE|FS_XFLAG_APPEND)) {
if (vflag)
fsrprintf(_("%s: immutable/append, ignoring\n"), fname);
return(0);
}
- if (fsx.fsx_xflags & XFS_XFLAG_NODEFRAG) {
+ if (fsx.fsx_xflags & FS_XFLAG_NODEFRAG) {
if (vflag)
fsrprintf(_("%s: marked as don't defrag, ignoring\n"),
fname);
return(0);
}
- if (fsx.fsx_xflags & XFS_XFLAG_REALTIME) {
+ if (fsx.fsx_xflags & FS_XFLAG_REALTIME) {
if (xfs_getrt(fd, &vfss) < 0) {
fsrprintf(_("cannot get realtime geometry for: %s\n"),
fname);
xfs_bstat_t *bstatp)
{
#ifdef HAVE_FSETXATTR
- struct stat64 tstatbuf;
+ struct stat tstatbuf;
int i;
int diff = 0;
int last_forkoff = 0;
int no_change_cnt = 0;
int ret;
- if (!(bstatp->bs_xflags & XFS_XFLAG_HASATTR))
+ if (!(bstatp->bs_xflags & FS_XFLAG_HASATTR))
return 0;
/*
/* attr2 w/ fork offsets */
- if (fstat64(tfd, &tstatbuf) < 0) {
+ if (fstat(tfd, &tstatbuf) < 0) {
fsrprintf(_("unable to stat temp file: %s\n"),
strerror(errno));
return -1;
}
continue;
} else if (i == 0) {
- struct fsxattr fsx;
/*
* First pass, and temp file already has an inline
* xattr, probably due to selinux.
*
* It's *possible* that the temp file attr area
- * is larger than the target file's, if the
- * target file's attrs are not inline:
+ * is larger than the target file's:
*
* Target Temp
* +-------+ 0 +-------+ 0
* | | v-------v forkoff
* | | | |
* v-------v forkoff | Attr | local
- * | Attr | ext/btree | |
+ * | Attr | | |
* +-------+ +-------+
- *
- * FSGETXATTRA will tell us nr of attr extents in
- * target, if any. If none, it's local:
*/
- memset(&fsx, 0, sizeof(fsx));
- if (ioctl(fd, XFS_IOC_FSGETXATTRA, &fsx)) {
- fsrprintf(_("FSGETXATTRA failed on target\n"));
- return -1;
- }
-
/*
- * If target attr area is less than the temp's (diff < 0)
- * and the target is not local, write a big attr to
- * the temp file to knock the attr out of local format,
- * to match the target. (This should actually *increase*
- * the temp file's forkoffset when the attr moves out
- * of the inode)
+ * If target attr area is less than the temp's
+ * (diff < 0) write a big attr to the temp file to knock
+ * the attr out of local format.
+ * (This should actually *increase* the temp file's
+ * forkoffset when the attr moves out of the inode)
*/
- if (diff < 0 && fsx.fsx_nextents > 0) {
+ if (diff < 0) {
char val[2048];
memset(val, 'X', 2048);
if (fsetxattr(tfd, name, val, 2048, 0)) {
/* Setup extended inode flags, project identifier, etc */
if (fsxp->fsx_xflags || fsxp->fsx_projid) {
- if (ioctl(tfd, XFS_IOC_FSSETXATTR, fsxp) < 0) {
+ if (ioctl(tfd, FS_IOC_FSSETXATTR, fsxp) < 0) {
fsrprintf(_("could not set inode attrs on tmp: %s\n"),
tname);
goto out;
fsrprintf(_("could not trunc tmp %s\n"),
tname);
}
- if (lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
+ if (lseek(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
fsrprintf(_("could not lseek in tmpfile: %s : %s\n"),
tname, strerror(errno));
goto out;
" %s\n"), tname);
goto out;
}
- if (lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
+ if (lseek(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
fsrprintf(_("could not lseek in tmpfile: %s : %s\n"),
tname, strerror(errno));
goto out;
}
} /* end of space allocation loop */
- if (lseek64(tfd, 0, SEEK_SET)) {
+ if (lseek(tfd, 0, SEEK_SET)) {
fsrprintf(_("Couldn't rewind on temporary file\n"));
goto out;
}
for (extent = 0; extent < nextents; extent++) {
pos = outmap[extent].bmv_offset;
if (outmap[extent].bmv_block == -1) {
- if (lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
+ if (lseek(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
fsrprintf(_("could not lseek in tmpfile: %s : %s\n"),
tname, strerror(errno));
goto out;
}
- if (lseek64(fd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
+ if (lseek(fd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
fsrprintf(_("could not lseek in file: %s : %s\n"),
fname, strerror(errno));
goto out;
}
}
}
- if (ftruncate64(tfd, statp->bs_size) < 0) {
+ if (ftruncate(tfd, statp->bs_size) < 0) {
fsrprintf(_("could not truncate tmpfile: %s : %s\n"),
fname, strerror(errno));
goto out;
/*
* Read the block map and return the number of extents.
*/
-int
+static int
getnextents(int fd)
{
int nextents;
* Get xfs realtime space information
*/
int
-xfs_getrt(int fd, struct statvfs64 *sfbp)
+xfs_getrt(int fd, struct statvfs *sfbp)
{
unsigned long bsize;
unsigned long factor;