Пример #1
0
static int
set_extsize(const char *path, int fd, long extsz)
{
	struct fsxattr	fsx;
	struct stat64	stat;

	if (fstat64(fd, &stat) < 0) {
		perror("fstat64");
		return 0;
	}
	if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
		printf("%s: XFS_IOC_FSGETXATTR %s: %s\n",
			progname, path, strerror(errno));
		return 0;
	}

	if (S_ISREG(stat.st_mode)) {
		fsx.fsx_xflags |= XFS_XFLAG_EXTSIZE;
	} else if (S_ISDIR(stat.st_mode)) {
		fsx.fsx_xflags |= XFS_XFLAG_EXTSZINHERIT;
	} else {
		printf(_("invalid target file type - file %s\n"), path);
		return 0;
	}
	fsx.fsx_extsize = extsz;

	if ((xfsctl(path, fd, XFS_IOC_FSSETXATTR, &fsx)) < 0) {
		printf("%s: XFS_IOC_FSSETXATTR %s: %s\n",
			progname, path, strerror(errno));
		return 0;
	}

	return 0;
}
Пример #2
0
static int
chattr_callback(
	const char		*path,
	const struct stat	*stat,
	int			status,
	struct FTW		*data)
{
	struct fsxattr		attr;
	int			fd;

	if (recurse_dir && !S_ISDIR(stat->st_mode))
		return 0;

	if ((fd = open(path, O_RDONLY)) == -1) {
		fprintf(stderr, _("%s: cannot open %s: %s\n"),
			progname, path, strerror(errno));
	} else if (xfsctl(path, fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
		fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
			progname, path, strerror(errno));
	} else {
		attr.fsx_xflags |= orflags;
		attr.fsx_xflags &= ~andflags;
		if (xfsctl(path, fd, XFS_IOC_FSSETXATTR, &attr) < 0)
			fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
				progname, path, strerror(errno));
	}

	if (fd != -1)
		close(fd);
	return 0;
}
Пример #3
0
static int
statfs_f(
	int			argc,
	char			**argv)
{
	struct xfs_fsop_counts	fscounts;
	struct xfs_fsop_geom	fsgeo;
	struct statfs		st;

	printf(_("fd.path = \"%s\"\n"), file->name);
	if (platform_fstatfs(file->fd, &st) < 0) {
		perror("fstatfs");
	} else {
		printf(_("statfs.f_bsize = %lld\n"), (long long) st.f_bsize);
		printf(_("statfs.f_blocks = %lld\n"), (long long) st.f_blocks);
#if defined(__sgi__)
		printf(_("statfs.f_frsize = %lld\n"), (long long) st.f_frsize);
#else
		printf(_("statfs.f_bavail = %lld\n"), (long long) st.f_bavail);
#endif
		printf(_("statfs.f_files = %lld\n"), (long long) st.f_files);
		printf(_("statfs.f_ffree = %lld\n"), (long long) st.f_ffree);
	}
	if (file->flags & IO_FOREIGN)
		return 0;
	if ((xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) {
		perror("XFS_IOC_FSGEOMETRY_V1");
	} else {
		printf(_("geom.bsize = %u\n"), fsgeo.blocksize);
		printf(_("geom.agcount = %u\n"), fsgeo.agcount);
		printf(_("geom.agblocks = %u\n"), fsgeo.agblocks);
		printf(_("geom.datablocks = %llu\n"),
			(unsigned long long) fsgeo.datablocks);
		printf(_("geom.rtblocks = %llu\n"),
			(unsigned long long) fsgeo.rtblocks);
		printf(_("geom.rtextents = %llu\n"),
			(unsigned long long) fsgeo.rtextents);
		printf(_("geom.rtextsize = %u\n"), fsgeo.rtextsize);
		printf(_("geom.sunit = %u\n"), fsgeo.sunit);
		printf(_("geom.swidth = %u\n"), fsgeo.swidth);
	}
	if ((xfsctl(file->name, file->fd, XFS_IOC_FSCOUNTS, &fscounts)) < 0) {
		perror("XFS_IOC_FSCOUNTS");
	} else {
		printf(_("counts.freedata = %llu\n"),
			(unsigned long long) fscounts.freedata);
		printf(_("counts.freertx = %llu\n"),
			(unsigned long long) fscounts.freertx);
		printf(_("counts.freeino = %llu\n"),
			(unsigned long long) fscounts.freeino);
		printf(_("counts.allocino = %llu\n"),
			(unsigned long long) fscounts.allocino);
	}
	return 0;
}
Пример #4
0
static int
stat_f(
	int		argc,
	char		**argv)
{
	struct dioattr	dio;
	struct fsxattr	fsx, fsxa;
	struct stat64	st;
	int		verbose = (argc == 2 && !strcmp(argv[1], "-v"));

	printf(_("fd.path = \"%s\"\n"), file->name);
	printf(_("fd.flags = %s,%s,%s%s%s%s%s\n"),
		file->flags & IO_OSYNC ? _("sync") : _("non-sync"),
		file->flags & IO_DIRECT ? _("direct") : _("non-direct"),
		file->flags & IO_READONLY ? _("read-only") : _("read-write"),
		file->flags & IO_REALTIME ? _(",real-time") : "",
		file->flags & IO_APPEND ? _(",append-only") : "",
		file->flags & IO_NONBLOCK ? _(",non-block") : "",
		file->flags & IO_TMPFILE ? _(",tmpfile") : "");
	if (fstat64(file->fd, &st) < 0) {
		perror("fstat64");
	} else {
		printf(_("stat.ino = %lld\n"), (long long)st.st_ino);
		printf(_("stat.type = %s\n"), filetype(st.st_mode));
		printf(_("stat.size = %lld\n"), (long long)st.st_size);
		printf(_("stat.blocks = %lld\n"), (long long)st.st_blocks);
		if (verbose) {
			printf(_("stat.atime = %s"), ctime(&st.st_atime));
			printf(_("stat.mtime = %s"), ctime(&st.st_mtime));
			printf(_("stat.ctime = %s"), ctime(&st.st_ctime));
		}
	}
	if (file->flags & IO_FOREIGN)
		return 0;
	if ((xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTR, &fsx)) < 0 ||
	    (xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTRA, &fsxa)) < 0) {
		perror("XFS_IOC_FSGETXATTR");
	} else {
		printf(_("fsxattr.xflags = 0x%x "), fsx.fsx_xflags);
		printxattr(fsx.fsx_xflags, verbose, 0, file->name, 1, 1);
		printf(_("fsxattr.projid = %u\n"), fsx.fsx_projid);
		printf(_("fsxattr.extsize = %u\n"), fsx.fsx_extsize);
		printf(_("fsxattr.nextents = %u\n"), fsx.fsx_nextents);
		printf(_("fsxattr.naextents = %u\n"), fsxa.fsx_nextents);
	}
	if ((xfsctl(file->name, file->fd, XFS_IOC_DIOINFO, &dio)) < 0) {
		perror("XFS_IOC_DIOINFO");
	} else {
		printf(_("dioattr.mem = 0x%x\n"), dio.d_mem);
		printf(_("dioattr.miniosz = %u\n"), dio.d_miniosz);
		printf(_("dioattr.maxiosz = %u\n"), dio.d_maxiosz);
	}
	return 0;
}
Пример #5
0
static int
lsattr_callback(
	const char		*path,
	const struct stat	*stat,
	int			status,
	struct FTW		*data)
{
	struct fsxattr		fsx;
	int			fd;

	if (recurse_dir && !S_ISDIR(stat->st_mode))
		return 0;

	if ((fd = open(path, O_RDONLY)) == -1)
		fprintf(stderr, _("%s: cannot open %s: %s\n"),
			progname, path, strerror(errno));
	else if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0)
		fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
			progname, path, strerror(errno));
	else
		printxattr(fsx.fsx_xflags, 0, 1, path, 0, 1);

	if (fd != -1)
		close(fd);
	return 0;
}
Пример #6
0
int main(int argc, char **argv)
{
   int fd, i;

   int64_t x[131072];

   for (i = 0; i < 131072; i++) {
      x[i] = -1;
   }
   fd = open(argv[1], O_RDWR | O_CREAT, 0644);

#ifdef WRITE
   f.l_whence = 0;
   f.l_start = 0;
   f.l_len = 1048576;
   xfsctl (argv[1], fd, XFS_IOC_RESVSP, &f);
   for (i = 0; i < 131072; i++) {
      x[i] = i;
   }
   write(fd, &x, 1048576);
#endif

#ifdef READ
   read(fd, &x, 1048576);
   for (i = 0; i < 131072; i++) {
      if (x[i] != i) {
         printf("error: %d %d %lld\n", i ,8 * i, (long long)x[i]);
	 exit(1);
      }
   }
#endif

   close(fd);
   exit(0);
}
Пример #7
0
static int
setup_project(
	const char		*path,
	const struct stat	*stat,
	int			flag,
	struct FTW		*data)
{
	struct fsxattr		fsx;
	int			fd;

	if (recurse_depth >= 0 && data->level > recurse_depth)
		return -1;

	if (flag == FTW_NS ){
		exitcode = 1;
		fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
		return 0;
	}
	if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
		fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
		return 0;
	}

	if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
		exitcode = 1;
		fprintf(stderr, _("%s: cannot open %s: %s\n"),
			progname, path, strerror(errno));
		return 0;
	} else if (xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx) < 0) {
		exitcode = 1;
		fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
			progname, path, strerror(errno));
		close(fd);
		return 0;
	}

	fsx.fsx_projid = prid;
	fsx.fsx_xflags |= XFS_XFLAG_PROJINHERIT;
	if (xfsctl(path, fd, XFS_IOC_FSSETXATTR, &fsx) < 0) {
		exitcode = 1;
		fprintf(stderr, _("%s: cannot set project on %s: %s\n"),
			progname, path, strerror(errno));
	}
	close(fd);
	return 0;
}
Пример #8
0
static int
get_extsize(const char *path, int fd)
{
	struct fsxattr	fsx;

	if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
		printf("%s: XFS_IOC_FSGETXATTR %s: %s\n",
			progname, path, strerror(errno));
		return 0;
	}
	printf("[%u] %s\n", fsx.fsx_extsize, path);
	return 0;
}
Пример #9
0
	bool XfsPreallocate(int fd, Uint64 size)
	{
		if( ! platform_test_xfs_fd(fd) )
		{
			return false;
		}

		xfs_flock64_t allocopt;
		allocopt.l_whence = 0;
		allocopt.l_start = 0;
		allocopt.l_len  = size;

		return (! static_cast<bool>(xfsctl(0, fd, XFS_IOC_RESVSP64, &allocopt)) );

	}
Пример #10
0
void fscounts(char *fname, int fsfd)
{
    xfs_fsop_counts_t   counts;
    int                 ret;
    
    ret=xfsctl(fname, fsfd, XFS_IOC_FSCOUNTS, &counts);
    if (ret) {
        perror("xfsctl(XFS_IOC_FSCOUNTS)");
        exit(1);
    }

    printf("XFS_IOC_FSCOUNTS-\n    freedata: %lld freertx: %lld freeino: %lld allocino: %lld\n",
            (long long)counts.freedata, (long long)counts.freertx,
	   (long long)counts.freeino, (long long)counts.allocino);
}
Пример #11
0
static int
lsattr_f(
	int		argc,
	char		**argv)
{
	struct fsxattr	fsx;
	char		*name = file->name;
	int		c, aflag = 0, vflag = 0;

	recurse_all = recurse_dir = 0;
	while ((c = getopt(argc, argv, "DRav")) != EOF) {
		switch (c) {
		case 'D':
			recurse_all = 0;
			recurse_dir = 1;
			break;
		case 'R':
			recurse_all = 1;
			recurse_dir = 0;
			break;
		case 'a':
			aflag = 1;
			vflag = 0;
			break;
		case 'v':
			aflag = 0;
			vflag = 1;
			break;
		default:
			return command_usage(&lsattr_cmd);
		}
	}

	if (recurse_all || recurse_dir) {
		nftw(name, lsattr_callback,
			100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
	} else if ((xfsctl(name, file->fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
		fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
			progname, name, strerror(errno));
	} else {
		printxattr(fsx.fsx_xflags, vflag, !aflag, name, vflag, !aflag);
		if (aflag) {
			fputs("/", stdout);
			printxattr(-1, 0, 1, name, 0, 1);
		}
	}
	return 0;
}
Пример #12
0
int
thaw_f(
	int		argc,
	char		**argv)
{
	int		level = 1;

	if (xfsctl(file->name, file->fd, XFS_IOC_THAW, &level) < 0) {
		fprintf(stderr,
			_("%s: cannot unfreeze filesystem mounted at %s: %s\n"),
			progname, file->name, strerror(errno));
		exitcode = 1;
		return 0;
	}
	return 0;
}
Пример #13
0
static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors)
{
    struct xfs_flock64 fl;

    memset(&fl, 0, sizeof(fl));
    fl.l_whence = SEEK_SET;
    fl.l_start = sector_num << 9;
    fl.l_len = (int64_t)nb_sectors << 9;

    if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
        DEBUG_BLOCK_PRINT("cannot punch hole (%s)\n", strerror(errno));
        return -errno;
    }

    return 0;
}
Пример #14
0
static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes)
{
    struct xfs_flock64 fl;

    memset(&fl, 0, sizeof(fl));
    fl.l_whence = SEEK_SET;
    fl.l_start = offset;
    fl.l_len = bytes;

    if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
        DEBUG_BLOCK_PRINT("cannot punch hole (%s)\n", strerror(errno));
        return -errno;
    }

    return 0;
}
Пример #15
0
__u64 getresblks(char *fname, int fsfd)
{
    xfs_fsop_resblks_t  res;
    int                 ret;
    
    ret=xfsctl(fname, fsfd, XFS_IOC_GET_RESBLKS, &res);
    if (ret) {
        perror("xfsctl(XFS_IOC_GET_RESBLKS)");
        exit(1);
    }
    
    printf("XFS_IOC_GET_RESBLKS-\n    resblks: %lld blksavail: %lld\n",
            (long long)res.resblks, (long long)res.resblks_avail);
    
    return res.resblks;
}
Пример #16
0
static int
check_project(
	const char		*path,
	const struct stat	*stat,
	int			flag,
	struct FTW		*data)
{
	struct fsxattr		fsx;
	int			fd;

	if (recurse_depth >= 0 && data->level > recurse_depth)
		return -1;

	if (flag == FTW_NS ){
		exitcode = 1;
		fprintf(stderr, _("%s: cannot stat file %s\n"), progname, path);
		return 0;
	}
	if (EXCLUDED_FILE_TYPES(stat->st_mode)) {
		fprintf(stderr, _("%s: skipping special file %s\n"), progname, path);
		return 0;
	}

	if ((fd = open(path, O_RDONLY|O_NOCTTY)) == -1) {
		exitcode = 1;
		fprintf(stderr, _("%s: cannot open %s: %s\n"),
			progname, path, strerror(errno));
	} else if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
		exitcode = 1;
		fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
			progname, path, strerror(errno));
	} else {
		if (fsx.fsx_projid != prid)
			printf(_("%s - project identifier is not set"
				 " (inode=%u, tree=%u)\n"),
				path, fsx.fsx_projid, (unsigned int)prid);
		if (!(fsx.fsx_xflags & XFS_XFLAG_PROJINHERIT))
			printf(_("%s - project inheritance flag is not set\n"),
				path);
	}
	if (fd != -1)
		close(fd);
	return 0;
}
Пример #17
0
static int preallocate_xfs(int fd, lock_type * fl)
{
	/* IMPORTANT: We use RESVSP because we want the extents to be
	 * allocated, but we don't want the allocation to show up in
	 * st_size or persist after the close(2).
	 */

#if defined(XFS_IOC_RESVSP64)
	/* On Linux this comes in via libxfs.h. */
	return xfsctl(NULL, fd, XFS_IOC_RESVSP64, &fl);
#elif defined(F_RESVSP64)
	/* On IRIX, this comes from fcntl.h. */
	return fcntl(fd, F_RESVSP64, &fl);
#else
	errno = ENOTSUP;
	return -1;
#endif

}
Пример #18
0
static int preallocate_space(int fd, SMB_OFF_T size)
{
	int err;
#ifndef HAVE_GPFS
	lock_type fl = {0};

	if (size <= 0) {
		return 0;
	}

	fl.l_whence = SEEK_SET;
	fl.l_start = 0;
	fl.l_len = size;

	/* IMPORTANT: We use RESVSP because we want the extents to be
	 * allocated, but we don't want the allocation to show up in
	 * st_size or persist after the close(2).
	 */

#if defined(XFS_IOC_RESVSP64)
	/* On Linux this comes in via libxfs.h. */
	err = xfsctl(NULL, fd, XFS_IOC_RESVSP64, &fl);
#elif defined(F_RESVSP64)
	/* On IRIX, this comes from fcntl.h. */
	err = fcntl(fd, F_RESVSP64, &fl);
#else
	err = -1;
	errno = ENOSYS;
#endif
#else /* GPFS uses completely different interface */
       err = gpfs_prealloc(fd, (gpfs_off64_t)0, (gpfs_off64_t)size);
#endif

	if (err) {
		DEBUG(module_debug,
			("%s: preallocate failed on fd=%d size=%lld: %s\n",
			MODULE, fd, (long long)size, strerror(errno)));
	}

	return err;
}
Пример #19
0
/*
 * Determine the realtime extent size of the XFS file system
 */
int
xfsrtextsize( char *path)
{
	int fd, rval, rtextsize;
	xfs_fsop_geom_v1_t geo;

	fd = open( path, O_RDONLY );
	if ( fd < 0 ) {
		fprintf(stderr, _("%s: could not open %s: %s\n"),
			progname, path, strerror(errno));
		return -1;
	}
	rval = xfsctl( path, fd, XFS_IOC_FSGEOMETRY_V1, &geo );
	close(fd);
	if ( rval < 0 )
		return -1;

	rtextsize = geo.rtextsize * geo.blocksize;

	return rtextsize;
}
Пример #20
0
int
imap_f(int argc, char **argv)
{
	int		count;
	int		nent;
	int		i;
	__u64		last = 0;
	xfs_inogrp_t	*t;
	xfs_fsop_bulkreq_t bulkreq;

	if (argc != 2)
		nent = 1;
	else
		nent = atoi(argv[1]);

	t = malloc(nent * sizeof(*t));

	bulkreq.lastip  = &last;
	bulkreq.icount  = nent;
	bulkreq.ubuffer = (void *)t;
	bulkreq.ocount  = &count;

	while (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS, &bulkreq) == 0) {
		if (count == 0)
			return 0;
		for (i = 0; i < count; i++) {
			printf(_("ino %10llu count %2d mask %016llx\n"),
				(unsigned long long)t[i].xi_startino,
				t[i].xi_alloccount,
				(unsigned long long)t[i].xi_allocmask);
		}
	}
	perror("xfsctl(XFS_IOC_FSINUMBERS)");
	exitcode = 1;
	return 0;
}
Пример #21
0
int
main(int argc, char **argv)
{
	int		i, j;
	int		howfar = 0;
	int		open_flags;
	xfs_off_t	pos, end_pos;
	size_t		length;
	int		c, first_residue, tmp_residue;
	__uint64_t	size, sizeb;
	__uint64_t	numblocks = 0;
	int		wblocks = 0;
	int		num_threads = 0;
	struct dioattr	d;
	int		wbuf_size;
	int		wbuf_align;
	int		wbuf_miniosize;
	int		source_is_file = 0;
	int		buffered_output = 0;
	int		duplicate = 0;
	uint		btree_levels, current_level;
	ag_header_t	ag_hdr;
	xfs_mount_t	*mp;
	xfs_mount_t	mbuf;
	xfs_buf_t	*sbp;
	xfs_sb_t	*sb;
	xfs_agnumber_t	num_ags, agno;
	xfs_agblock_t	bno;
	xfs_daddr_t	begin, next_begin, ag_begin, new_begin, ag_end;
	struct xfs_btree_block *block;
	xfs_alloc_ptr_t	*ptr;
	xfs_alloc_rec_t	*rec_ptr;
	extern char	*optarg;
	extern int	optind;
	libxfs_init_t	xargs;
	thread_args	*tcarg;
	struct stat64	statbuf;

	progname = basename(argv[0]);

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	while ((c = getopt(argc, argv, "bdL:V")) != EOF)  {
		switch (c) {
		case 'b':
			buffered_output = 1;
			break;
		case 'd':
			duplicate = 1;
			break;
		case 'L':
			logfile_name = optarg;
			break;
		case 'V':
			printf(_("%s version %s\n"), progname, VERSION);
			exit(0);
		case '?':
			usage();
		}
	}

	if (argc - optind < 2)
		usage();

	if (logfile_name)  {
		logfd = open(logfile_name, O_CREAT|O_WRONLY|O_EXCL, 0600);
	} else  {
		logfile_name = LOGFILE_NAME;
		logfd = mkstemp(logfile_name);
	}

	if (logfd < 0)  {
		fprintf(stderr, _("%s: couldn't open log file \"%s\"\n"),
			progname, logfile_name);
		perror(_("Aborting XFS copy - reason"));
		exit(1);
	}

	if ((logerr = fdopen(logfd, "w")) == NULL)  {
		fprintf(stderr, _("%s: couldn't set up logfile stream\n"),
			progname);
		perror(_("Aborting XFS copy - reason"));
		exit(1);
	}

	source_name = argv[optind];
	source_fd = -1;
	optind++;

	num_targets = argc - optind;
	if ((target = malloc(sizeof(target_control) * num_targets)) == NULL)  {
		do_log(_("Couldn't allocate target array\n"));
		die_perror();
	}
	for (i = 0; optind < argc; i++, optind++)  {
		target[i].name = argv[optind];
		target[i].fd = -1;
		target[i].position = -1;
		target[i].state = INACTIVE;
		target[i].error = 0;
		target[i].err_type = 0;
	}

	parent_pid = getpid();

	if (atexit(killall))  {
		do_log(_("%s: couldn't register atexit function.\n"), progname);
		die_perror();
	}

	/* open up source -- is it a file? */

	open_flags = O_RDONLY;

	if ((source_fd = open(source_name, open_flags)) < 0)  {
		do_log(_("%s:  couldn't open source \"%s\"\n"),
			progname, source_name);
		die_perror();
	}

	if (fstat64(source_fd, &statbuf) < 0)  {
		do_log(_("%s:  couldn't stat source \"%s\"\n"),
			progname, source_name);
		die_perror();
	}

	if (S_ISREG(statbuf.st_mode))
		source_is_file = 1;

	if (source_is_file && platform_test_xfs_fd(source_fd))  {
		if (fcntl(source_fd, F_SETFL, open_flags | O_DIRECT) < 0)  {
			do_log(_("%s: Cannot set direct I/O flag on \"%s\".\n"),
				progname, source_name);
			die_perror();
		}
		if (xfsctl(source_name, source_fd, XFS_IOC_DIOINFO, &d) < 0)  {
			do_log(_("%s: xfsctl on file \"%s\" failed.\n"),
				progname, source_name);
			die_perror();
		}

		wbuf_align = d.d_mem;
		wbuf_size = MIN(d.d_maxiosz, 1 * 1024 * 1024);
		wbuf_miniosize = d.d_miniosz;
	} else  {
		/* set arbitrary I/O params, miniosize at least 1 disk block */

		wbuf_align = getpagesize();
		wbuf_size = 1 * 1024 * 1024;
		wbuf_miniosize = -1;	/* set after mounting source fs */
	}

	if (!source_is_file)  {
		/*
		 * check to make sure a filesystem isn't mounted
		 * on the device
		 */
		if (platform_check_ismounted(source_name, NULL, &statbuf, 0))  {
			do_log(
	_("%s:  Warning -- a filesystem is mounted on the source device.\n"),
				progname);
			do_log(
	_("\t\tGenerated copies may be corrupt unless the source is\n"));
			do_log(
	_("\t\tunmounted or mounted read-only.  Copy proceeding...\n"));
		}
	}

	/* prepare the libxfs_init structure */

	memset(&xargs, 0, sizeof(xargs));
	xargs.isdirect = LIBXFS_DIRECT;
	xargs.isreadonly = LIBXFS_ISREADONLY;

	if (source_is_file)  {
		xargs.dname = source_name;
		xargs.disfile = 1;
	} else
		xargs.volname = source_name;

	if (!libxfs_init(&xargs))  {
		do_log(_("%s: couldn't initialize XFS library\n"
			"%s: Aborting.\n"), progname, progname);
		exit(1);
	}

	/* prepare the mount structure */

	sbp = libxfs_readbuf(xargs.ddev, XFS_SB_DADDR, 1, 0);
	memset(&mbuf, 0, sizeof(xfs_mount_t));
	sb = &mbuf.m_sb;
	libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbp));

	mp = libxfs_mount(&mbuf, sb, xargs.ddev, xargs.logdev, xargs.rtdev, 1);
	if (mp == NULL) {
		do_log(_("%s: %s filesystem failed to initialize\n"
			"%s: Aborting.\n"), progname, source_name, progname);
		exit(1);
	} else if (mp->m_sb.sb_inprogress)  {
		do_log(_("%s %s filesystem failed to initialize\n"
			"%s: Aborting.\n"), progname, source_name, progname);
		exit(1);
	} else if (mp->m_sb.sb_logstart == 0)  {
		do_log(_("%s: %s has an external log.\n%s: Aborting.\n"),
			progname, source_name, progname);
		exit(1);
	} else if (mp->m_sb.sb_rextents != 0)  {
		do_log(_("%s: %s has a real-time section.\n"
			"%s: Aborting.\n"), progname, source_name, progname);
		exit(1);
	}

	source_blocksize = mp->m_sb.sb_blocksize;
	source_sectorsize = mp->m_sb.sb_sectsize;

	if (wbuf_miniosize == -1)
		wbuf_miniosize = source_sectorsize;

	ASSERT(source_blocksize % source_sectorsize == 0);
	ASSERT(source_sectorsize % BBSIZE == 0);

	if (source_blocksize > source_sectorsize)  {
		/* get number of leftover sectors in last block of ag header */

		tmp_residue = ((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize)
					% source_blocksize;
		first_residue = (tmp_residue == 0) ? 0 :
			source_blocksize - tmp_residue;
		ASSERT(first_residue % source_sectorsize == 0);
	} else if (source_blocksize == source_sectorsize)  {
		first_residue = 0;
	} else  {
		do_log(_("Error:  filesystem block size is smaller than the"
			" disk sectorsize.\nAborting XFS copy now.\n"));
		exit(1);
	}

	first_agbno = (((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize)
				+ first_residue) / source_blocksize;
	ASSERT(first_agbno != 0);
	ASSERT( ((((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize)
				+ first_residue) % source_blocksize) == 0);

	/* now open targets */

	open_flags = O_RDWR;

	for (i = 0; i < num_targets; i++)  {
		int	write_last_block = 0;

		if (stat64(target[i].name, &statbuf) < 0)  {
			/* ok, assume it's a file and create it */

			do_out(_("Creating file %s\n"), target[i].name);

			open_flags |= O_CREAT;
			if (!buffered_output)
				open_flags |= O_DIRECT;
			write_last_block = 1;
		} else if (S_ISREG(statbuf.st_mode))  {
			open_flags |= O_TRUNC;
			if (!buffered_output)
				open_flags |= O_DIRECT;
			write_last_block = 1;
		} else  {
			/*
			 * check to make sure a filesystem isn't mounted
			 * on the device
			 */
			if (platform_check_ismounted(target[i].name,
							NULL, &statbuf, 0))  {
				do_log(_("%s:  a filesystem is mounted "
					"on target device \"%s\".\n"
					"%s cannot copy to mounted filesystems."
					"  Aborting\n"),
					progname, target[i].name, progname);
				exit(1);
			}
		}

		target[i].fd = open(target[i].name, open_flags, 0644);
		if (target[i].fd < 0)  {
			do_log(_("%s:  couldn't open target \"%s\"\n"),
				progname, target[i].name);
			die_perror();
		}

		if (write_last_block)  {
			/* ensure regular files are correctly sized */

			if (ftruncate64(target[i].fd, mp->m_sb.sb_dblocks *
						source_blocksize))  {
				do_log(_("%s:  cannot grow data section.\n"),
					progname);
				die_perror();
			}
			if (platform_test_xfs_fd(target[i].fd))  {
				if (xfsctl(target[i].name, target[i].fd,
						XFS_IOC_DIOINFO, &d) < 0)  {
					do_log(
				_("%s:  xfsctl on \"%s\" failed.\n"),
						progname, target[i].name);
					die_perror();
				} else {
					wbuf_align = MAX(wbuf_align, d.d_mem);
					wbuf_size = MIN(d.d_maxiosz, wbuf_size);
					wbuf_miniosize = MAX(d.d_miniosz,
								wbuf_miniosize);
				}
			}
		} else  {
			char	*lb[XFS_MAX_SECTORSIZE] = { NULL };
			off64_t	off;

			/* ensure device files are sufficiently large */

			off = mp->m_sb.sb_dblocks * source_blocksize;
			off -= sizeof(lb);
			if (pwrite64(target[i].fd, lb, sizeof(lb), off) < 0)  {
				do_log(_("%s:  failed to write last block\n"),
					progname);
				do_log(_("\tIs target \"%s\" too small?\n"),
					target[i].name);
				die_perror();
			}
		}
	}

	/* initialize locks and bufs */

	if (pthread_mutex_init(&glob_masks.mutex, NULL) != 0)  {
		do_log(_("Couldn't initialize global thread mask\n"));
		die_perror();
	}
	glob_masks.num_working = 0;

	if (wbuf_init(&w_buf, wbuf_size, wbuf_align,
					wbuf_miniosize, 0) == NULL)  {
		do_log(_("Error initializing wbuf 0\n"));
		die_perror();
	}

	wblocks = wbuf_size / BBSIZE;

	if (wbuf_init(&btree_buf, MAX(source_blocksize, wbuf_miniosize),
				wbuf_align, wbuf_miniosize, 1) == NULL)  {
		do_log(_("Error initializing btree buf 1\n"));
		die_perror();
	}

	if (pthread_mutex_init(&mainwait,NULL) != 0)  {
		do_log(_("Error creating first semaphore.\n"));
		die_perror();
		exit(1);
	}
	/* need to start out blocking */
	pthread_mutex_lock(&mainwait);

	/* set up sigchild signal handler */

	signal(SIGCHLD, handler);
	signal_maskfunc(SIGCHLD, SIG_BLOCK);

	/* make children */

	if ((targ = malloc(num_targets * sizeof(thread_args))) == NULL)  {
		do_log(_("Couldn't malloc space for thread args\n"));
		die_perror();
		exit(1);
	}

	for (i = 0, tcarg = targ; i < num_targets; i++, tcarg++)  {
		if (!duplicate)
			platform_uuid_generate(&tcarg->uuid);
		else
			platform_uuid_copy(&tcarg->uuid, &mp->m_sb.sb_uuid);

		if (pthread_mutex_init(&tcarg->wait, NULL) != 0)  {
			do_log(_("Error creating thread mutex %d\n"), i);
			die_perror();
			exit(1);
		}
		/* need to start out blocking */
		pthread_mutex_lock(&tcarg->wait);
	}

	for (i = 0, tcarg = targ; i < num_targets; i++, tcarg++)  {
		tcarg->id = i;
		tcarg->fd = target[i].fd;

		target[i].state = ACTIVE;
		num_threads++;

		if (pthread_create(&target[i].pid, NULL,
					begin_reader, (void *)tcarg))  {
			do_log(_("Error creating thread for target %d\n"), i);
			die_perror();
		}
	}

	ASSERT(num_targets == num_threads);

	/* set up statistics */

	num_ags = mp->m_sb.sb_agcount;

	init_bar(mp->m_sb.sb_blocksize / BBSIZE
			* ((__uint64_t)mp->m_sb.sb_dblocks
			    - (__uint64_t)mp->m_sb.sb_fdblocks + 10 * num_ags));

	kids = num_targets;
	block = (struct xfs_btree_block *) btree_buf.data;

	for (agno = 0; agno < num_ags && kids > 0; agno++)  {
		/* read in first blocks of the ag */

		read_ag_header(source_fd, agno, &w_buf, &ag_hdr, mp,
			source_blocksize, source_sectorsize);

		/* set the in_progress bit for the first AG */

		if (agno == 0)
			ag_hdr.xfs_sb->sb_inprogress = 1;

		/* save what we need (agf) in the btree buffer */

		memmove(btree_buf.data, ag_hdr.xfs_agf, source_sectorsize);
		ag_hdr.xfs_agf = (xfs_agf_t *) btree_buf.data;
		btree_buf.length = source_blocksize;

		/* write the ag header out */

		write_wbuf();

		/* traverse btree until we get to the leftmost leaf node */

		bno = be32_to_cpu(ag_hdr.xfs_agf->agf_roots[XFS_BTNUM_BNOi]);
		current_level = 0;
		btree_levels = be32_to_cpu(ag_hdr.xfs_agf->
						agf_levels[XFS_BTNUM_BNOi]);

		ag_end = XFS_AGB_TO_DADDR(mp, agno,
				be32_to_cpu(ag_hdr.xfs_agf->agf_length) - 1)
				+ source_blocksize / BBSIZE;

		for (;;) {
			/* none of this touches the w_buf buffer */

			ASSERT(current_level < btree_levels);

			current_level++;

			btree_buf.position = pos = (xfs_off_t)
				XFS_AGB_TO_DADDR(mp,agno,bno) << BBSHIFT;
			btree_buf.length = source_blocksize;

			read_wbuf(source_fd, &btree_buf, mp);
			block = (struct xfs_btree_block *)
				 ((char *)btree_buf.data +
				  pos - btree_buf.position);

			ASSERT(be32_to_cpu(block->bb_magic) == XFS_ABTB_MAGIC);

			if (be16_to_cpu(block->bb_level) == 0)
				break;

			ptr = XFS_ALLOC_PTR_ADDR(mp, block, 1,
							mp->m_alloc_mxr[1]);
			bno = be32_to_cpu(ptr[0]);
		}

		/* align first data copy but don't overwrite ag header */

		pos = w_buf.position >> BBSHIFT;
		length = w_buf.length >> BBSHIFT;
		next_begin = pos + length;
		ag_begin = next_begin;

		ASSERT(w_buf.position % source_sectorsize == 0);

		/* handle the rest of the ag */

		for (;;) {
			if (be16_to_cpu(block->bb_level) != 0)  {
				do_log(
			_("WARNING:  source filesystem inconsistent.\n"));
				do_log(
			_("  A leaf btree rec isn't a leaf.  Aborting now.\n"));
				exit(1);
			}

			rec_ptr = XFS_ALLOC_REC_ADDR(mp, block, 1);
			for (i = 0; i < be16_to_cpu(block->bb_numrecs);
							i++, rec_ptr++)  {
				/* calculate in daddr's */

				begin = next_begin;

				/*
				 * protect against pathological case of a
				 * hole right after the ag header in a
				 * mis-aligned case
				 */

				if (begin < ag_begin)
					begin = ag_begin;

				/*
				 * round size up to ensure we copy a
				 * range bigger than required
				 */

				sizeb = XFS_AGB_TO_DADDR(mp, agno, 
					be32_to_cpu(rec_ptr->ar_startblock)) - 
						begin;
				size = roundup(sizeb <<BBSHIFT, wbuf_miniosize);
				if (size > 0)  {
					/* copy extent */

					w_buf.position = (xfs_off_t)
						begin << BBSHIFT;

					while (size > 0)  {
						/*
						 * let lower layer do alignment
						 */
						if (size > w_buf.size)  {
							w_buf.length = w_buf.size;
							size -= w_buf.size;
							sizeb -= wblocks;
							numblocks += wblocks;
						} else  {
							w_buf.length = size;
							numblocks += sizeb;
							size = 0;
						}

						read_wbuf(source_fd, &w_buf, mp);
						write_wbuf();

						w_buf.position += w_buf.length;

						howfar = bump_bar(
							howfar, numblocks);
					}
				}

				/* round next starting point down */

				new_begin = XFS_AGB_TO_DADDR(mp, agno,
						be32_to_cpu(rec_ptr->ar_startblock) +
					 	be32_to_cpu(rec_ptr->ar_blockcount));
				next_begin = rounddown(new_begin,
						w_buf.min_io_size >> BBSHIFT);
			}

			if (be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK)
				break;

			/* read in next btree record block */

			btree_buf.position = pos = (xfs_off_t)
				XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(
						block->bb_u.s.bb_rightsib)) << BBSHIFT;
			btree_buf.length = source_blocksize;

			/* let read_wbuf handle alignment */

			read_wbuf(source_fd, &btree_buf, mp);

			block = (struct xfs_btree_block *)
				 ((char *) btree_buf.data +
				  pos - btree_buf.position);

			ASSERT(be32_to_cpu(block->bb_magic) == XFS_ABTB_MAGIC);
		}

		/*
		 * write out range of used blocks after last range
		 * of free blocks in AG
		 */
		if (next_begin < ag_end)  {
			begin = next_begin;

			sizeb = ag_end - begin;
			size = roundup(sizeb << BBSHIFT, wbuf_miniosize);

			if (size > 0)  {
				/* copy extent */

				w_buf.position = (xfs_off_t) begin << BBSHIFT;

				while (size > 0)  {
					/*
					 * let lower layer do alignment
					 */
					if (size > w_buf.size)  {
						w_buf.length = w_buf.size;
						size -= w_buf.size;
						sizeb -= wblocks;
						numblocks += wblocks;
					} else  {
						w_buf.length = size;
						numblocks += sizeb;
						size = 0;
					}

					read_wbuf(source_fd, &w_buf, mp);
					write_wbuf();

					w_buf.position += w_buf.length;

					howfar = bump_bar(howfar, numblocks);
				}
			}
		}
	}

	if (kids > 0)  {
		if (!duplicate)  {

			/* write a clean log using the specified UUID */
			for (j = 0, tcarg = targ; j < num_targets; j++)  {
				w_buf.owner = tcarg;
				w_buf.length = rounddown(w_buf.size,
							 w_buf.min_io_size);
				pos = write_log_header(
							source_fd, &w_buf, mp);
				end_pos = write_log_trailer(
							source_fd, &w_buf, mp);
				w_buf.position = pos;
				memset(w_buf.data, 0, w_buf.length);

				while (w_buf.position < end_pos)  {
					do_write(tcarg);
					w_buf.position += w_buf.length;
				}
				tcarg++;
			}
		} else {
			num_ags = 1;
		}

		/* reread and rewrite superblocks (UUID and in-progress) */
		/* [backwards, so inprogress bit only updated when done] */

		for (i = num_ags - 1; i >= 0; i--)  {
			read_ag_header(source_fd, i, &w_buf, &ag_hdr, mp,
				source_blocksize, source_sectorsize);
			if (i == 0)
				ag_hdr.xfs_sb->sb_inprogress = 0;

			/* do each thread in turn, each has its own UUID */

			for (j = 0, tcarg = targ; j < num_targets; j++)  {
				platform_uuid_copy(&ag_hdr.xfs_sb->sb_uuid,
							&tcarg->uuid);
				do_write(tcarg);
				tcarg++;
			}
		}

		bump_bar(100, 0);
	}

	check_errors();
	killall();
	pthread_exit(NULL);
	/*NOTREACHED*/
	return 0;
}
Пример #22
0
static int
do_bulkstat(parent_t *parentbuf, size_t *parentbuf_size, xfs_bstat_t *bstatbuf,
	    int fsfd, jdm_fshandle_t *fshandlep)
{
	__s32 buflenout;
	__u64 lastino = 0;
	xfs_bstat_t *p;
	xfs_bstat_t *endp;
	xfs_fsop_bulkreq_t bulkreq;
	struct stat mntstat;

	if (stat(mntpt, &mntstat)) {
		fprintf(stderr, _("can't stat mount point \"%s\": %s\n"),
			mntpt, strerror(errno));
		return 1;
	}

	bulkreq.lastip  = &lastino;
	bulkreq.icount  = BSTATBUF_SZ;
	bulkreq.ubuffer = (void *)bstatbuf;
	bulkreq.ocount  = &buflenout;

	while (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq) == 0) {
		if (*(bulkreq.ocount) == 0) {
			return 0;
		}
		for (p = bstatbuf, endp = bstatbuf + *bulkreq.ocount; p < endp; p++) {

			/* inode being modified, get synced data with iget */
			if ( (!p->bs_nlink || !p->bs_mode) && p->bs_ino != 0 ) {

				if (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq) < 0) {
				    fprintf(stderr,
					  _("failed to get bulkstat information for inode %llu\n"),
					 (unsigned long long) p->bs_ino);
				    continue;
				}
				if (!p->bs_nlink || !p->bs_mode || !p->bs_ino) {
				    fprintf(stderr,
					  _("failed to get valid bulkstat information for inode %llu\n"),
					 (unsigned long long) p->bs_ino);
				    continue;
				}
			}

			/* skip root */
			if (p->bs_ino == mntstat.st_ino) {
				continue;
			}

			if (verbose_flag > 1) {
			       printf(_("checking inode %llu\n"),
				       (unsigned long long) p->bs_ino);
			}

			/* print dotted progress */
			if ((inodes_checked % 100) == 0 && verbose_flag == 1) {
				printf("."); fflush(stdout);
			}
			inodes_checked++;

			check_parents(parentbuf, parentbuf_size, fshandlep, p);
		}

	}/*while*/

	fprintf(stderr, _("syssgi bulkstat failed: %s\n"), strerror(errno));
	return 1;
}
Пример #23
0
static bool
preallocate_file_full (const char * filename, uint64_t length)
{
    bool success = 0;

#ifdef WIN32

    HANDLE hFile = CreateFile (filename, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        LARGE_INTEGER li;
        li.QuadPart = length;
        success = SetFilePointerEx (hFile, li, NULL, FILE_BEGIN) && SetEndOfFile (hFile);
        CloseHandle (hFile);
    }

#else

    int flags = O_RDWR | O_CREAT | O_LARGEFILE;
    int fd = open (filename, flags, 0666);
    if (fd >= 0)
    {
# ifdef HAVE_FALLOCATE64
       if (!success)
       {
           success = !fallocate64 (fd, 0, 0, length);
       }
# endif
# ifdef HAVE_XFS_XFS_H
        if (!success && platform_test_xfs_fd (fd))
        {
            xfs_flock64_t fl;
            fl.l_whence = 0;
            fl.l_start = 0;
            fl.l_len = length;
            success = !xfsctl (NULL, fd, XFS_IOC_RESVSP64, &fl);
        }
# endif
# ifdef SYS_DARWIN
        if (!success)
        {
            fstore_t fst;
            fst.fst_flags = F_ALLOCATECONTIG;
            fst.fst_posmode = F_PEOFPOSMODE;
            fst.fst_offset = 0;
            fst.fst_length = length;
            fst.fst_bytesalloc = 0;
            success = !fcntl (fd, F_PREALLOCATE, &fst);
        }
# endif
#undef HAVE_POSIX_FALLOCATE
# ifdef HAVE_POSIX_FALLOCATE
        if (!success)
        {
            success = !posix_fallocate (fd, 0, length);
        }
# endif

#define MINSLEEP 3
#define MAXSLEEP 40000
#define INCRFACT 1.9
#define DECRFACT 3
#define BLCKSIZE 32768
#define TSTEVERYBYTES 524288
#define TSTEVERYBLKS TSTEVERYBYTES/BLCKSIZE
        if (!success) /* if nothing else works, do it the old-fashioned way */
        {
	  struct timeval lastTime, thisTime;
	  // Set up buffer with 0s.
	  unsigned int block_size = BLCKSIZE;
	  uint8_t buf[ block_size ];
	  memset (buf, 0, sizeof (buf));

	  // Set up speed test counters.
	  unsigned int testEveryBytes = TSTEVERYBYTES;
	  unsigned int testEveryIters = TSTEVERYBLKS;
	  unsigned int itersUntilTest = testEveryIters;
	  long         lastTook = 0;
	  long         currentTook = 0;
	  gettimeofday(&lastTime, NULL);
	  unsigned int sleep = MINSLEEP;
	  unsigned int lastSlept = 0;
	  unsigned int size=length;

	  success = true;
	  while (success && (length > 0))
	  {
	      if (itersUntilTest == 0) {
		gettimeofday(&thisTime, NULL);
		currentTook = thisTime.tv_sec*1000000 + thisTime.tv_usec - lastTime.tv_sec*1000000 - lastTime.tv_usec - lastSlept;
		if (currentTook > lastTook) {
		  sleep = MIN(sleep * INCRFACT, MAXSLEEP);
		} else if (currentTook < lastTook) {
		  sleep = MAX(sleep / DECRFACT, MINSLEEP);
		}
		lastSlept = 0;
		lastTook = currentTook;
		lastTime = thisTime;
		itersUntilTest = testEveryIters;
		fprintf (stderr, "{\"TR_PREALLOC\":%d,\"filename\":\"%s\"}\n", (int)(100.f*(float)(size - length)/(float)size), filename);
		//fprintf (stderr, "Will sleep %d usec on every write.\n", sleep);
	      }

	      const int thisPass = MIN (length, sizeof (buf));
	      success = write (fd, buf, thisPass) == thisPass;
	      length -= thisPass;

	      --itersUntilTest;
	      usleep(sleep);
	      lastSlept = lastSlept + sleep;
	    }
        }

/*
        if (!success) // if nothing else works, do it the old-fashioned way 
        {
            uint8_t buf[ 32768 ];
            memset (buf, 0, sizeof (buf));
            success = true;
            while (success && (length > 0))
            {
                const int thisPass = MIN (length, sizeof (buf));
                success = write (fd, buf, thisPass) == thisPass;
                length -= thisPass;
		usleep(9000);
            }
        }
*/



        close (fd);
    }

#endif

    return success;
}
int
main(int argc, char *argv[])
{
    int e;
    int fd = 0;
    int i;
    int j;
    int k;
    int nfiles;
    int stride;
    struct stat sbuf;
    ino_t *inodelist;
    __u32 *genlist;
    xfs_fsop_bulkreq_t a;
    xfs_bstat_t *ret;
    int iterations;
    char fname[MAXPATHLEN];
    char *dirname;

    if (argc != 5) {
    	fprintf(stderr, "Usage: %s iterations nfiles stride dir\n", argv[0]);
    	fprintf(stderr, "Create dir with nfiles, unlink each stride'th file, sync, bulkstat\n");
	exit(1);
    }

    iterations = atoi(argv[1]);
    nfiles = atoi(argv[2]);
    stride = atoi(argv[3]);
    dirname = argv[4];
    if (!nfiles || !iterations) {
	fprintf(stderr, "Iterations and nfiles showld be non zero.\n");
    	exit(1);
    }

    inodelist = (ino_t *)malloc(nfiles * sizeof(ino_t));
    genlist = (__u32 *)malloc(nfiles * sizeof(__u32));
    ret = (xfs_bstat_t *)malloc(nfiles * sizeof(xfs_bstat_t));

    for (k=0; k < iterations; k++) {
	xfs_ino_t last_inode = 0;
	int count = 0;
	int testFiles = 0;

	printf("Iteration %d ... \n", k);

	memset(inodelist, 0, nfiles * sizeof(ino_t));
	memset(genlist, 0, nfiles * sizeof(__u32));
	memset(ret, 0, nfiles * sizeof(xfs_bstat_t));
	memset(&a, 0, sizeof(xfs_fsop_bulkreq_t));
	a.lastip = (__u64 *)&last_inode;
	a.icount = nfiles;
	a.ubuffer = ret;
	a.ocount = &count;

	if (mkdir(dirname, 0755) < 0) {
	    perror(dirname);
	    exit(1);
	}

	/* create nfiles and store their inode numbers in inodelist */
	for (i=0; i < nfiles; i++) {
	    sprintf(fname, "%s/file%06d", dirname, i);
	    if ((fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
		perror(fname);
		exit(1);
	    }
	    write(fd, fname, sizeof(fname));
	    if (fstat(fd, &sbuf) < 0) {
		perror(fname);
		exit(1);
	    }
	    inodelist[i] = sbuf.st_ino;
	    close(fd);
	}
	
	sync();
	
	/* collect bs_gen for the nfiles files */
	if ((fd = open(dirname, O_RDONLY)) < 0) {
	    perror(dirname);
	    exit(1);
	}

	testFiles = 0;
	for (;;) {
	    if ((e = xfsctl(dirname, fd, XFS_IOC_FSBULKSTAT, &a)) < 0) {
		perror("XFS_IOC_FSBULKSTAT1:");
		exit(1);
	    }

	    if (count == 0)
		break;

	    for (i=0; i < count; i++) {
		for (j=0; j < nfiles; j += stride) {
		    if (ret[i].bs_ino == inodelist[j]) {
			genlist[j] = ret[i].bs_gen;
			testFiles++;
		    }
		}
	    }
	}
	close(fd);
	
	printf("testFiles %d ... \n", testFiles);

	/* remove some of the first set of files */
	for (i=0; i < nfiles; i += stride) {
	    sprintf(fname, "%s/file%06d", dirname, i);
	    if (unlink(fname) < 0) {
	    	perror(fname);
		exit(1);
	    }
	}

	/* create a new set of files (replacing the unlinked ones) */
	for (i=0; i < nfiles; i += stride) {
	    sprintf(fname, "%s/file%06d", dirname, i);
	    if ((fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
		perror(fname);
		exit(1);
	    }
	    write(fd, fname, sizeof(fname));
	    close(fd);
	}

	sync();
	last_inode = 0; count = 0;

	if ((fd = open(dirname, O_RDONLY)) < 0) {
	    perror(dirname);
	    exit(1);
	}

	for (;;) {
	    if ((e = xfsctl(dirname, fd, XFS_IOC_FSBULKSTAT, &a)) < 0) {
		perror("XFS_IOC_FSBULKSTAT:");
		exit(1);
	    }

	    if (count == 0)
		    break;

	    for (i=0; i < count; i++) {
		for (j=0; j < nfiles; j += stride) {
		    if ((ret[i].bs_ino == inodelist[j]) &&
			(ret[i].bs_gen == genlist[j])) {
			/* oops, the same inode with old gen number */
			printf("Unlinked inode %llu with generation %d "
			       "returned by bulkstat\n",
				(unsigned long long)inodelist[j],
				 genlist[j]);
			exit(1);
		    }
		    if (ret[i].bs_ino == inodelist[j] &&
			ret[i].bs_gen != genlist[j] + 1) {
			/* oops, the new gen number is not 1 bigger than the old */
			printf("Inode with old generation %d, new generation %d\n",
			genlist[j], ret[i].bs_gen);
			exit(1);
		    }
		}
	    }
	}

	close(fd);

	sprintf(fname, "rm -rf %s\n", dirname);
	system(fname);

	sync();
	sleep(2);
	printf("passed\n");
    }

    exit(0);
}
static bool
preallocate_file_full( const char * filename, uint64_t length )
{
    bool success = 0;

#ifdef WIN32

    HANDLE hFile = CreateFile( filename, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0 );
    if( hFile != INVALID_HANDLE_VALUE )
    {
        LARGE_INTEGER li;
        li.QuadPart = length;
        success = SetFilePointerEx( hFile, li, NULL, FILE_BEGIN ) && SetEndOfFile( hFile );
        CloseHandle( hFile );
    }

#else

    int flags = O_RDWR | O_CREAT | O_LARGEFILE;
    int fd = open( filename, flags, 0666 );
    if( fd >= 0 )
    {
# ifdef HAVE_FALLOCATE64
       if( !success )
       {
           success = !fallocate64( fd, 0, 0, length );
       }
# endif
# ifdef HAVE_XFS_XFS_H
        if( !success && platform_test_xfs_fd( fd ) )
        {
            xfs_flock64_t fl;
            fl.l_whence = 0;
            fl.l_start = 0;
            fl.l_len = length;
            success = !xfsctl( NULL, fd, XFS_IOC_RESVSP64, &fl );
        }
# endif
# ifdef SYS_DARWIN
        if( !success )
        {
            fstore_t fst;
            fst.fst_flags = F_ALLOCATECONTIG;
            fst.fst_posmode = F_PEOFPOSMODE;
            fst.fst_offset = 0;
            fst.fst_length = length;
            fst.fst_bytesalloc = 0;
            success = !fcntl( fd, F_PREALLOCATE, &fst );
        }
# endif
# ifdef HAVE_POSIX_FALLOCATE
        if( !success )
        {
            success = !posix_fallocate( fd, 0, length );
        }
# endif

        if( !success ) /* if nothing else works, do it the old-fashioned way */
        {
            uint8_t buf[ 4096 ];
            memset( buf, 0, sizeof( buf ) );
            success = true;
            while ( success && ( length > 0 ) )
            {
                const int thisPass = MIN( length, sizeof( buf ) );
                success = write( fd, buf, thisPass ) == thisPass;
                length -= thisPass;
            }
        }

        close( fd );
    }

#endif

    return success;
}
Пример #26
0
int
main(int argc, char *argv[])
{
	int e;
	int i;
	int j;
	int k;
	int nfiles;
	int stride;

	int c;

	struct stat sbuf;
	ino_t *inodelist;
	xfs_fsop_bulkreq_t a;
	xfs_bstat_t *ret;
	int iterations;
	char fname[MAXPATHLEN];
	char *dirname;
	int chknb = 0;

	while ((c = getopt(argc, argv, "r")) != -1) {
		switch(c) {
		case 'r':
			chknb = 1;
			break;
		default:
			break;
		}
	}

	if ((argc - optind) != 4) {
		fprintf(stderr, "Usage: %s iterations nfiles stride dir [options]\n", argv[0]);
		fprintf(stderr, "Create dir with nfiles, unlink each stride'th file, sync, bulkstat\n");
		exit(1);
	}


	iterations = atoi(argv[optind++]);
	nfiles     = atoi(argv[optind++]);
	stride     = atoi(argv[optind++]);

	dirname = argv[optind++];

	if (chknb)
		printf("Runing extended checks.\n");

	inodelist = (ino_t *)malloc(nfiles * sizeof(ino_t));
	ret = (xfs_bstat_t *)malloc(nfiles * sizeof(xfs_bstat_t));

	for (k=0; k < iterations; k++) {
		int fd[nfiles + 1];
		xfs_ino_t last_inode = 0;
		int count = 0, scount = -1;

		printf("Iteration %d ... (%d files)", k, nfiles);

		memset(&a, 0, sizeof(xfs_fsop_bulkreq_t));
		a.lastip = (__u64 *)&last_inode;
		a.icount = nfiles;
		a.ubuffer = ret;
		a.ocount = &count;

		if (mkdir(dirname, 0755) < 0) {
			printf("Warning (%s,%d), mkdir(%s) failed.\n", __FILE__, __LINE__, dirname);
			perror(dirname);
			exit(1);
		}

		if ((fd[nfiles] = open(dirname, O_RDONLY)) < 0) {
			printf("Warning (%s,%d), open(%s) failed.\n", __FILE__, __LINE__, dirname);
			perror(dirname);
			exit(1);
		}

		if (chknb) { /* Get the original number of inodes (lazy) */
			sync();
			if (xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a) != 0) {
				printf("Warning (%s:%d), xfsctl(XFS_IOC_FSBULKSTAT) FAILED.\n", __FILE__, __LINE__);
			}

			scount = count;
		}

		for (i=0; i < nfiles; i++) { /* Open the files */
			sprintf(fname, "%s/file%06d", dirname, i);
			if ((fd[i] = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
				printf("Warning (%s,%d), open(%s) failed.\n", __FILE__, __LINE__, fname);
				perror(fname);
				exit(1);
			}
			write(fd[i], fname, sizeof(fname));
			if (fstat(fd[i], &sbuf) < 0) {
				printf("Warning (%s,%d), fstat failed.\n", __FILE__, __LINE__);
				perror(fname);
				exit(1);
			}
			inodelist[i] = sbuf.st_ino;
			unlink(fname);
		}

		if (chknb) {
			/*
			 *The files are still opened (but unlink()ed) ,
			 * we should have more inodes than before
			 */
			sync();
			last_inode = 0;
			if (xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a) != 0) {
				printf("Warning (%s:%d), xfsctl(XFS_IOC_FSBULKSTAT) FAILED.\n", __FILE__, __LINE__);
			}
			if (count < scount) {
				printf("ERROR, count(%d) < scount(%d).\n", count, scount);
				return -1;
			}
		}

		/* Close all the files */
		for (i = 0; i < nfiles; i++) {
			close(fd[i]);
		}

		if (chknb) {
			/*
			 * The files are now closed, we should be back to our,
			 * previous inode count
			 */
			sync();
			last_inode = 0;
			if (xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a) != 0) {
				printf("Warning (%s:%d), xfsctl(XFS_IOC_FSBULKSTAT) FAILED.\n", __FILE__, __LINE__);
			}
			if (count != scount) {
				printf("ERROR, count(%d) != scount(%d).\n", count, scount);
				return -1;
			}
		}

		sync();
		last_inode = 0;
		for (;;) {
			if ((e = xfsctl(dirname, fd[nfiles], XFS_IOC_FSBULKSTAT, &a)) < 0) {
				printf("Warning (%s,%d), xfsctl failed.\n", __FILE__, __LINE__);
				perror("XFS_IOC_FSBULKSTAT:");
				exit(1);
			}

			if (count == 0)
				break;

			for (i=0; i < count; i++) {
				for (j=0; j < nfiles; j += stride) {
					if (ret[i].bs_ino == inodelist[j]) {
						/* oops ... */
						printf("failed. Unlinked inode %llu returned by bulkstat\n", (unsigned long long)inodelist[j]);
						exit(1);
					}
				}
			}
		}

		close(fd[nfiles]);
		sprintf(fname, "rm -rf %s\n", dirname);
		system(fname);

		sync();
		sleep(2);
		printf("passed\n");
	}

	exit(0);
}
Пример #27
0
void AsyncFile::openReq(Request* request)
{  
  m_auto_sync_freq = 0;
  m_write_wo_sync = 0;
  m_open_flags = request->par.open.flags;

  // for open.flags, see signal FSOPENREQ
#ifdef NDB_WIN32
  DWORD dwCreationDisposition;
  DWORD dwDesiredAccess = 0;
  DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_NO_BUFFERING;
  Uint32 flags = request->par.open.flags;
    
    // Convert file open flags from Solaris to Windows
  if ((flags & FsOpenReq::OM_CREATE) && (flags & FsOpenReq::OM_TRUNCATE)){
    dwCreationDisposition = CREATE_ALWAYS;
  } else if (flags & FsOpenReq::OM_TRUNCATE){
    dwCreationDisposition = TRUNCATE_EXISTING;
  } else if (flags & FsOpenReq::OM_CREATE){
    dwCreationDisposition = CREATE_NEW;
  } else {
    dwCreationDisposition = OPEN_EXISTING;
  }
  
  switch(flags & 3){
  case FsOpenReq::OM_READONLY:
    dwDesiredAccess = GENERIC_READ;
    break;
  case FsOpenReq::OM_WRITEONLY:
    dwDesiredAccess = GENERIC_WRITE;
    break;
  case FsOpenReq::OM_READWRITE:
    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
    break;
  default:
    request->error = 1000;
    break;
    return;
  }

  hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode, 
                     0, dwCreationDisposition, dwFlagsAndAttributes, 0);
    
  if(INVALID_HANDLE_VALUE == hFile) {
    request->error = GetLastError();
    if(((ERROR_PATH_NOT_FOUND == request->error) || (ERROR_INVALID_NAME == request->error))
       && (flags & FsOpenReq::OM_CREATE)) {
      createDirectories();
      hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode, 
                         0, dwCreationDisposition, dwFlagsAndAttributes, 0);
            
      if(INVALID_HANDLE_VALUE == hFile)
        request->error = GetLastError();
      else
        request->error = 0;
            
      return;
    }
  } 
  else {
    request->error = 0;
    return;
  }
#else
  Uint32 flags = request->par.open.flags;
  int new_flags = 0;

  // Convert file open flags from Solaris to Liux
  if (flags & FsOpenReq::OM_CREATE)
  {
    new_flags |= O_CREAT;
  }
  
  if (flags & FsOpenReq::OM_TRUNCATE){
#if 0
    if(Global_unlinkO_CREAT){
      unlink(theFileName.c_str());
    } else 
#endif
      new_flags |= O_TRUNC;
  }  

  if (flags & FsOpenReq::OM_AUTOSYNC)
  {
    m_auto_sync_freq = request->par.open.auto_sync_size;
  }

  if (flags & FsOpenReq::OM_APPEND){
    new_flags |= O_APPEND;
  }

  if (flags & FsOpenReq::OM_DIRECT) 
#ifdef O_DIRECT
  {
    new_flags |= O_DIRECT;
  }
#endif
  
  if ((flags & FsOpenReq::OM_SYNC) && ! (flags & FsOpenReq::OM_INIT))
  {
#ifdef O_SYNC
    new_flags |= O_SYNC;
#endif
  }

  const char * rw = "";
  switch(flags & 0x3){
  case FsOpenReq::OM_READONLY:
    rw = "r";
    new_flags |= O_RDONLY;
    break;
  case FsOpenReq::OM_WRITEONLY:
    rw = "w";
    new_flags |= O_WRONLY;
    break;
  case FsOpenReq::OM_READWRITE:
    rw = "rw";
    new_flags |= O_RDWR;
    break;
  default:
    request->error = 1000;
    break;
    return;
  }

  // allow for user to choose any permissionsa with umask
  const int mode = S_IRUSR | S_IWUSR |
	           S_IRGRP | S_IWGRP |
		   S_IROTH | S_IWOTH;
  if (flags & FsOpenReq::OM_CREATE_IF_NONE)
  {
    Uint32 tmp_flags = new_flags;
#ifdef O_DIRECT
    tmp_flags &= ~O_DIRECT;
#endif
    if ((theFd = ::open(theFileName.c_str(), tmp_flags, mode)) != -1) 
    {
      close(theFd);
      request->error = FsRef::fsErrFileExists;      
      return;
    }
    new_flags |= O_CREAT;
  }

no_odirect:
  if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) 
  {
    PRINT_ERRORANDFLAGS(new_flags);
    if ((errno == ENOENT) && (new_flags & O_CREAT)) 
    {
      createDirectories();
      if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) 
      {
#ifdef O_DIRECT
	if (new_flags & O_DIRECT)
	{
	  new_flags &= ~O_DIRECT;
	  goto no_odirect;
	}
#endif
        PRINT_ERRORANDFLAGS(new_flags);
        request->error = errno;
	return;
      }
    }
#ifdef O_DIRECT
    else if (new_flags & O_DIRECT)
    {
      new_flags &= ~O_DIRECT;
      goto no_odirect;
    }
#endif
    else
    {
      request->error = errno;
      return;
    }
  }
  
  if (flags & FsOpenReq::OM_CHECK_SIZE)
  {
    struct stat buf;
    if ((fstat(theFd, &buf) == -1))
    {
      request->error = errno;
    } 
    else if((Uint64)buf.st_size != request->par.open.file_size)
    {
      request->error = FsRef::fsErrInvalidFileSize;
    }
    if (request->error)
      return;
  }
  
  if (flags & FsOpenReq::OM_INIT)
  {
    off_t off = 0;
    const off_t sz = request->par.open.file_size;
    Uint32 tmp[sizeof(SignalHeader)+25];
    Signal * signal = (Signal*)(&tmp[0]);
    FsReadWriteReq* req = (FsReadWriteReq*)signal->getDataPtrSend();

    Uint32 index = 0;
    Uint32 block = refToBlock(request->theUserReference);

#ifdef HAVE_XFS_XFS_H
    if(platform_test_xfs_fd(theFd))
    {
      ndbout_c("Using xfsctl(XFS_IOC_RESVSP64) to allocate disk space");
      xfs_flock64_t fl;
      fl.l_whence= 0;
      fl.l_start= 0;
      fl.l_len= (off64_t)sz;
      if(xfsctl(NULL, theFd, XFS_IOC_RESVSP64, &fl) < 0)
        ndbout_c("failed to optimally allocate disk space");
    }
#endif
#ifdef HAVE_POSIX_FALLOCATE
    posix_fallocate(theFd, 0, sz);
#endif

    while(off < sz)
    {
      req->filePointer = 0;          // DATA 0
      req->userPointer = request->theUserPointer;          // DATA 2
      req->numberOfPages = 1;        // DATA 5  
      req->varIndex = index++;
      req->data.pageData[0] = m_page_ptr.i;

      m_fs.EXECUTE_DIRECT(block, GSN_FSWRITEREQ, signal, 
			  FsReadWriteReq::FixedLength + 1);
  retry:
      Uint32 size = request->par.open.page_size;
      char* buf = (char*)m_page_ptr.p;
      while(size > 0){
	const int n = write(theFd, buf, size);
	if(n == -1 && errno == EINTR)
	{
	  continue;
	}
	if(n == -1 || n == 0)
	{
	  break;
	}
	size -= n;
	buf += n;
      }
      if(size != 0)
      {
	int err = errno;
#ifdef O_DIRECT
	if ((new_flags & O_DIRECT) && off == 0)
	{
	  ndbout_c("error on first write(%d), disable O_DIRECT", err);
	  new_flags &= ~O_DIRECT;
	  close(theFd);
	  theFd = ::open(theFileName.c_str(), new_flags, mode);
	  if (theFd != -1)
	    goto retry;
	}
#endif
	close(theFd);
	unlink(theFileName.c_str());
	request->error = err;
	return;
      }
      off += request->par.open.page_size;
    }
    if(lseek(theFd, 0, SEEK_SET) != 0)
      request->error = errno;
  }
  else if (flags & FsOpenReq::OM_DIRECT)
  {
#ifdef O_DIRECT
    if (flags & (FsOpenReq::OM_TRUNCATE | FsOpenReq::OM_CREATE))
    {
      request->error = check_odirect_write(flags, new_flags, mode);
    }
    else
    {
      request->error = check_odirect_read(flags, new_flags, mode);
    }
    
    if (request->error)
      return;
#endif
  }
#ifdef VM_TRACE
  if (flags & FsOpenReq::OM_DIRECT)
  {
#ifdef O_DIRECT
    ndbout_c("%s %s O_DIRECT: %d",
             theFileName.c_str(), rw,
             !!(new_flags & O_DIRECT));
#else
    ndbout_c("%s %s O_DIRECT: 0",
             theFileName.c_str(), rw);
#endif
  }
#endif  
  if ((flags & FsOpenReq::OM_SYNC) && (flags & FsOpenReq::OM_INIT))
  {
#ifdef O_SYNC
    /**
     * reopen file with O_SYNC
     */
    close(theFd);
    new_flags &= ~(O_CREAT | O_TRUNC);
    new_flags |= O_SYNC;
    theFd = ::open(theFileName.c_str(), new_flags, mode);
    if (theFd == -1)
    {
      request->error = errno;
    }
#endif
  }
#endif
}
Пример #28
0
int
openfile(
	char		*path,
	xfs_fsop_geom_t	*geom,
	int		flags,
	mode_t		mode)
{
	int		fd;
	int		oflags;

	oflags = flags & IO_READONLY ? O_RDONLY : O_RDWR;
	if (flags & IO_APPEND)
		oflags |= O_APPEND;
	if (flags & IO_CREAT)
		oflags |= O_CREAT;
	if (flags & IO_DIRECT)
		oflags |= O_DIRECT;
	if (flags & IO_OSYNC)
		oflags |= O_SYNC;
	if (flags & IO_TRUNC)
		oflags |= O_TRUNC;
	if (flags & IO_NONBLOCK)
		oflags |= O_NONBLOCK;
	if (flags & IO_TMPFILE)
		oflags |= O_TMPFILE;

	fd = open(path, oflags, mode);
	if (fd < 0) {
		if (errno == EISDIR &&
		    ((oflags & (O_RDWR|O_TMPFILE)) == O_RDWR)) {
			/* make it as if we asked for O_RDONLY & try again */
			oflags &= ~O_RDWR;
			oflags |= O_RDONLY;
			flags |= IO_READONLY;
			fd = open(path, oflags, mode);
			if (fd < 0) {
				perror(path);
				return -1;
			}
		} else {
			perror(path);
			return -1;
		}
	}

	if (!geom || !platform_test_xfs_fd(fd))
		return fd;

	if (xfsctl(path, fd, XFS_IOC_FSGEOMETRY, geom) < 0) {
		perror("XFS_IOC_FSGEOMETRY");
		close(fd);
		return -1;
	}

	if (!(flags & IO_READONLY) && (flags & IO_REALTIME)) {
		struct fsxattr	attr;

		if (xfsctl(path, fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
			perror("XFS_IOC_FSGETXATTR");
			close(fd);
			return -1;
		}
		if (!(attr.fsx_xflags & XFS_XFLAG_REALTIME)) {
			attr.fsx_xflags |= XFS_XFLAG_REALTIME;
			if (xfsctl(path, fd, XFS_IOC_FSSETXATTR, &attr) < 0) {
				perror("XFS_IOC_FSSETXATTR");
				close(fd);
				return -1;
			}
		}
	}
	return fd;
}
Пример #29
0
int
bmap_f(
	int			argc,
	char			**argv)
{
	struct fsxattr		fsx;
	struct getbmapx		*map;
	struct xfs_fsop_geom	fsgeo;
	int			map_size;
	int			loop = 0;
	int			flg = 0;
	int			aflag = 0;
	int			lflag = 0;
	int			nflag = 0;
	int			pflag = 0;
	int			vflag = 0;
	int			is_rt = 0;
	int			bmv_iflags = 0;	/* flags for XFS_IOC_GETBMAPX */
	int			i = 0;
	int			c;
	int			egcnt;

	while ((c = getopt(argc, argv, "adln:pv")) != EOF) {
		switch (c) {
		case 'a':	/* Attribute fork. */
			bmv_iflags |= BMV_IF_ATTRFORK;
			aflag = 1;
			break;
		case 'l':	/* list number of blocks with each extent */
			lflag = 1;
			break;
		case 'n':	/* number of extents specified */
			nflag = atoi(optarg);
			break;
		case 'd':
		/* do not recall possibly offline DMAPI files */
			bmv_iflags |= BMV_IF_NO_DMAPI_READ;
			break;
		case 'p':
		/* report unwritten preallocated blocks */
			pflag = 1;
			bmv_iflags |= BMV_IF_PREALLOC;
			break;
		case 'v':	/* Verbose output */
			vflag++;
			break;
		default:
			return command_usage(&bmap_cmd);
		}
	}
	if (aflag)
		bmv_iflags &= ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ);

	if (vflag) {
		c = xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo);
		if (c < 0) {
			fprintf(stderr,
				_("%s: can't get geometry [\"%s\"]: %s\n"),
				progname, file->name, strerror(errno));
			exitcode = 1;
			return 0;
		}
		c = xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTR, &fsx);
		if (c < 0) {
			fprintf(stderr,
				_("%s: cannot read attrs on \"%s\": %s\n"),
				progname, file->name, strerror(errno));
			exitcode = 1;
			return 0;
		}

		if (fsx.fsx_xflags == XFS_XFLAG_REALTIME) {
			/*
			 * ag info not applicable to rt, continue
			 * without ag output.
			 */
			is_rt = 1;
		}
	}

	map_size = nflag ? nflag+2 : 32;	/* initial guess - 32 */
	map = malloc(map_size*sizeof(*map));
	if (map == NULL) {
		fprintf(stderr, _("%s: malloc of %d bytes failed.\n"),
			progname, (int)(map_size * sizeof(*map)));
		exitcode = 1;
		return 0;
	}


/*	Try the xfsctl(XFS_IOC_GETBMAPX) for the number of extents specified
 *	by nflag, or the initial guess number of extents (32).
 *
 *	If there are more extents than we guessed, use xfsctl
 *	(XFS_IOC_FSGETXATTR[A]) to get the extent count, realloc some more
 *	space based on this count, and try again.
 *
 *	If the initial FGETBMAPX attempt returns EINVAL, this may mean
 *	that we tried the FGETBMAPX on a zero length file.  If we get
 *	EINVAL, check the length with fstat() and return "no extents"
 *	if the length == 0.
 *
 *	Why not do the xfsctl(XFS_IOC_FSGETXATTR[A]) first?  Two reasons:
 *	(1)	The extent count may be wrong for a file with delayed
 *		allocation blocks.  The XFS_IOC_GETBMAPX forces the real
 *		allocation and fixes up the extent count.
 *	(2)	For XFS_IOC_GETBMAP[X] on a DMAPI file that has been moved
 *		offline by a DMAPI application (e.g., DMF) the
 *		XFS_IOC_FSGETXATTR only reflects the extents actually online.
 *		Doing XFS_IOC_GETBMAPX call first forces that data blocks online
 *		and then everything proceeds normally (see PV #545725).
 *
 *		If you don't want this behavior on a DMAPI offline file,
 *		try the "-d" option which sets the BMV_IF_NO_DMAPI_READ
 *		iflag for XFS_IOC_GETBMAPX.
 */

	do {	/* loop a miximum of two times */

		memset(map, 0, sizeof(*map));	/* zero header */

		map->bmv_length = -1;
		map->bmv_count = map_size;
		map->bmv_iflags = bmv_iflags;

		i = xfsctl(file->name, file->fd, XFS_IOC_GETBMAPX, map);
		if (i < 0) {
			if (   errno == EINVAL
			    && !aflag && filesize() == 0) {
				break;
			} else	{
				fprintf(stderr, _("%s: xfsctl(XFS_IOC_GETBMAPX)"
					" iflags=0x%x [\"%s\"]: %s\n"),
					progname, map->bmv_iflags, file->name,
					strerror(errno));
				free(map);
				exitcode = 1;
				return 0;
			}
		}
		if (nflag)
			break;
		if (map->bmv_entries < map->bmv_count-1)
			break;
		/* Get number of extents from xfsctl XFS_IOC_FSGETXATTR[A]
		 * syscall.
		 */
		i = xfsctl(file->name, file->fd, aflag ?
				XFS_IOC_FSGETXATTRA : XFS_IOC_FSGETXATTR, &fsx);
		if (i < 0) {
			fprintf(stderr, "%s: xfsctl(XFS_IOC_FSGETXATTR%s) "
				"[\"%s\"]: %s\n", progname, aflag ? "A" : "",
				file->name, strerror(errno));
			free(map);
			exitcode = 1;
			return 0;
		}
		if (2 * fsx.fsx_nextents > map_size) {
			map_size = 2 * fsx.fsx_nextents + 1;
			map = realloc(map, map_size*sizeof(*map));
			if (map == NULL) {
				fprintf(stderr,
					_("%s: cannot realloc %d bytes\n"),
					progname, (int)(map_size*sizeof(*map)));
				exitcode = 1;
				return 0;
			}
		}
	} while (++loop < 2);
	if (!nflag) {
		if (map->bmv_entries <= 0) {
			printf(_("%s: no extents\n"), file->name);
			free(map);
			return 0;
		}
	}
	egcnt = nflag ? min(nflag, map->bmv_entries) : map->bmv_entries;
	printf("%s:\n", file->name);
	if (!vflag) {
		for (i = 0; i < egcnt; i++) {
			printf("\t%d: [%lld..%lld]: ", i,
				(long long) map[i + 1].bmv_offset,
				(long long)(map[i + 1].bmv_offset +
				map[i + 1].bmv_length - 1LL));
			if (map[i + 1].bmv_block == -1)
				printf(_("hole"));
			else {
				printf("%lld..%lld",
					(long long) map[i + 1].bmv_block,
					(long long)(map[i + 1].bmv_block +
						map[i + 1].bmv_length - 1LL));

			}
			if (lflag)
				printf(_(" %lld blocks\n"),
					(long long)map[i+1].bmv_length);
			else
				printf("\n");
		}
	} else {
		/*
		 * Verbose mode displays:
		 *   extent: [startoffset..endoffset]: startblock..endblock \
		 *	ag# (agoffset..agendoffset) totalbbs
		 */
#define MINRANGE_WIDTH	16
#define MINAG_WIDTH	2
#define MINTOT_WIDTH	5
#define NFLG		5	/* count of flags */
#define	FLG_NULL	000000	/* Null flag */
#define	FLG_PRE		010000	/* Unwritten extent */
#define	FLG_BSU		001000	/* Not on begin of stripe unit  */
#define	FLG_ESU		000100	/* Not on end   of stripe unit  */
#define	FLG_BSW		000010	/* Not on begin of stripe width */
#define	FLG_ESW		000001	/* Not on end   of stripe width */
		int	agno;
		off64_t agoff, bbperag;
		int	foff_w, boff_w, aoff_w, tot_w, agno_w;
		char	rbuf[32], bbuf[32], abuf[32];
		int	sunit, swidth;

		foff_w = boff_w = aoff_w = MINRANGE_WIDTH;
		tot_w = MINTOT_WIDTH;
		if (is_rt)
			sunit = swidth = bbperag = 0;
		else {
			bbperag = (off64_t)fsgeo.agblocks *
				  (off64_t)fsgeo.blocksize / BBSIZE;
			sunit = (fsgeo.sunit * fsgeo.blocksize) / BBSIZE;
			swidth = (fsgeo.swidth * fsgeo.blocksize) / BBSIZE;
		}
		flg = sunit | pflag;

		/*
		 * Go through the extents and figure out the width
		 * needed for all columns.
		 */
		for (i = 0; i < egcnt; i++) {
			snprintf(rbuf, sizeof(rbuf), "[%lld..%lld]:",
				(long long) map[i + 1].bmv_offset,
				(long long)(map[i + 1].bmv_offset +
				map[i + 1].bmv_length - 1LL));
			if (map[i + 1].bmv_oflags & BMV_OF_PREALLOC)
				flg = 1;
			if (map[i + 1].bmv_block == -1) {
				foff_w = max(foff_w, strlen(rbuf));
				tot_w = max(tot_w,
					numlen(map[i+1].bmv_length));
			} else {
				snprintf(bbuf, sizeof(bbuf), "%lld..%lld",
					(long long) map[i + 1].bmv_block,
					(long long)(map[i + 1].bmv_block +
						map[i + 1].bmv_length - 1LL));
				boff_w = max(boff_w, strlen(bbuf));
				if (!is_rt) {
					agno = map[i + 1].bmv_block / bbperag;
					agoff = map[i + 1].bmv_block -
							(agno * bbperag);
					snprintf(abuf, sizeof(abuf),
						"(%lld..%lld)",
						(long long)agoff,
						(long long)(agoff +
						 map[i + 1].bmv_length - 1LL));
					aoff_w = max(aoff_w, strlen(abuf));
				} else
					aoff_w = 0;
				foff_w = max(foff_w, strlen(rbuf));
				tot_w = max(tot_w,
					numlen(map[i+1].bmv_length));
			}
		}
		agno_w = is_rt ? 0 : max(MINAG_WIDTH, numlen(fsgeo.agcount));
		printf("%4s: %-*s %-*s %*s %-*s %*s%s\n",
			_("EXT"),
			foff_w, _("FILE-OFFSET"),
			boff_w, is_rt ? _("RT-BLOCK-RANGE") : _("BLOCK-RANGE"),
			agno_w, is_rt ? "" : _("AG"),
			aoff_w, is_rt ? "" : _("AG-OFFSET"),
			tot_w, _("TOTAL"),
			flg ? _(" FLAGS") : "");
		for (i = 0; i < egcnt; i++) {
			flg = FLG_NULL;
			if (map[i + 1].bmv_oflags & BMV_OF_PREALLOC) {
				flg |= FLG_PRE;
			}
			/*
			 * If striping enabled, determine if extent starts/ends
			 * on a stripe unit boundary.
			 */
			if (sunit) {
				if (map[i + 1].bmv_block  % sunit != 0) {
					flg |= FLG_BSU;
				}
				if (((map[i + 1].bmv_block +
				      map[i + 1].bmv_length ) % sunit ) != 0) {
					flg |= FLG_ESU;
				}
				if (map[i + 1].bmv_block % swidth != 0) {
					flg |= FLG_BSW;
				}
				if (((map[i + 1].bmv_block +
				      map[i + 1].bmv_length ) % swidth ) != 0) {
					flg |= FLG_ESW;
				}
			}
			snprintf(rbuf, sizeof(rbuf), "[%lld..%lld]:",
				(long long) map[i + 1].bmv_offset,
				(long long)(map[i + 1].bmv_offset +
				map[i + 1].bmv_length - 1LL));
			if (map[i + 1].bmv_block == -1) {
				printf("%4d: %-*s %-*s %*s %-*s %*lld\n",
					i,
					foff_w, rbuf,
					boff_w, _("hole"),
					agno_w, "",
					aoff_w, "",
					tot_w, (long long)map[i+1].bmv_length);
			} else {
				snprintf(bbuf, sizeof(bbuf), "%lld..%lld",
					(long long) map[i + 1].bmv_block,
					(long long)(map[i + 1].bmv_block +
						map[i + 1].bmv_length - 1LL));
				printf("%4d: %-*s %-*s", i, foff_w, rbuf,
					boff_w, bbuf);
				if (!is_rt) {
					agno = map[i + 1].bmv_block / bbperag;
					agoff = map[i + 1].bmv_block -
							(agno * bbperag);
					snprintf(abuf, sizeof(abuf),
						"(%lld..%lld)",
						(long long)agoff,
						(long long)(agoff +
						 map[i + 1].bmv_length - 1LL));
					printf(" %*d %-*s", agno_w, agno,
						aoff_w, abuf);
				} else
					printf("  ");
				printf(" %*lld", tot_w,
					(long long)map[i+1].bmv_length);
				if (flg == FLG_NULL && !pflag) {
					printf("\n");
				} else {
					printf(" %-*.*o\n", NFLG, NFLG, flg);
				}
			}
		}
		if ((flg || pflag) && vflag > 1) {
			printf(_(" FLAG Values:\n"));
			printf(_("    %*.*o Unwritten preallocated extent\n"),
				NFLG+1, NFLG+1, FLG_PRE);
			printf(_("    %*.*o Doesn't begin on stripe unit\n"),
				NFLG+1, NFLG+1, FLG_BSU);
			printf(_("    %*.*o Doesn't end   on stripe unit\n"),
				NFLG+1, NFLG+1, FLG_ESU);
			printf(_("    %*.*o Doesn't begin on stripe width\n"),
				NFLG+1, NFLG+1, FLG_BSW);
			printf(_("    %*.*o Doesn't end   on stripe width\n"),
				NFLG+1, NFLG+1, FLG_ESW);
		}
	}
	free(map);
	return 0;
}
Пример #30
0
void handle(char *fname, int fsfd, char *path)
{
    xfs_fsop_handlereq_t    handle;
    char                    buffer[1024];
    char                    link[1024];
    int                     ret;
    __u32                   len;
    __u32                   linklen;
    int                     fd;
    
    handle.path=path;
    handle.ohandle=buffer;
    handle.ohandlen=&len;
    ret=xfsctl(fname, fsfd, XFS_IOC_PATH_TO_FSHANDLE, &handle);
    if (ret) {
        perror("xfsctl(XFS_IOC_PATH_TO_FSHANDLE)");
        exit(1);
    }
    printf("XFS_IOC_PATH_TO_FSHANDLE-\n    handle: ");
    handle_print(handle.ohandle, *handle.ohandlen);
    printf("\n");
    
    fd=open(path,O_RDONLY);
    if (fd<0) {
        perror("open");
        exit(1);
    }
    handle.path=NULL;
    handle.fd=fd;
    handle.ohandle=buffer;
    handle.ohandlen=&len;
    ret=xfsctl(fname, fsfd, XFS_IOC_FD_TO_HANDLE, &handle);
    if (ret) {
        perror("ioctl(XFS_IOC_FD_TO_HANDLE)");
        exit(1);
    }
    
    printf("XFS_IOC_FD_TO_HANDLE-\n    path: %s\n    handle: ", path);
    handle_print(handle.ohandle, *handle.ohandlen);
    printf("\n");
    
    close(fd);
    
    handle.path=NULL;
    handle.fd=-1;
    handle.ihandle=buffer;
    handle.ihandlen=len;
    handle.ohandle=NULL;
    handle.ohandlen=NULL;
    ret=xfsctl(fname, fsfd, XFS_IOC_OPEN_BY_HANDLE, &handle);
    if (ret<0) {
        perror("xfsctl(XFS_IOC_OPEN_BY_HANDLE)");
        exit(1);
    }
    printf("XFS_IOC_OPEN_BY_HANDLE-\n    handle: ");
    handle_print(handle.ihandle, handle.ihandlen);
    printf("\n    fd: %d\n    stat- ", ret);
    stat_print(ret);
    close(ret);
    
    handle.path=path;
    handle.ohandle=buffer;
    handle.ohandlen=&len;
    ret=xfsctl(fname, fsfd, XFS_IOC_PATH_TO_HANDLE, &handle);
    if (ret) {
        perror("xfsctl(XFS_IOC_PATH_TO_HANDLE)");
        exit(1);
    }
    printf("XFS_IOC_PATH_TO_HANDLE-\n    path: %s\n    handle: ", path);
    handle_print(handle.ohandle, *handle.ohandlen);
    printf("\n");

    handle.path=NULL;
    handle.fd=-1;
    handle.ihandle=buffer;
    handle.ihandlen=len;
    handle.ohandle=link;
    linklen=sizeof(link);
    handle.ohandlen=&linklen;
    ret=xfsctl(fname, fsfd, XFS_IOC_READLINK_BY_HANDLE, &handle);
    if (ret<0) {
        perror("xfsctl(XFS_IOC_READLINK_BY_HANDLE)");
        fprintf(stderr,"ERROR IGNORED\n");
    } else {
        printf("XFS_IOC_READLINK_BY_HANDLE-\n    handle: ");
        handle_print(handle.ihandle, handle.ihandlen);
        printf("\n    link=\"%*.*s\"\n", 
                ret, ret, (char*)handle.ohandle);
    }
}