/* * Sets up the defragmentation of a file based on the * filepath. It collects the bstat information, does * an open on the file and passes this all to fsrfile_common. */ static int fsrfile(char *fname, xfs_ino_t ino) { xfs_bstat_t statbuf; jdm_fshandle_t *fshandlep; int fd, fsfd; int error = 0; char *tname; fshandlep = jdm_getfshandle(getparent (fname) ); if (! fshandlep) { fsrprintf( "unable to construct sys handle for %s: %s\n", fname, strerror(errno)); return -1; } /* * Need to open something on the same filesystem as the * file. Open the parent. */ fsfd = open(getparent(fname), O_RDONLY); if (fsfd < 0) { fsrprintf( "unable to open sys handle for %s: %s\n", fname, strerror(errno)); return -1; } if ((xfs_bulkstat_single(fsfd, &ino, &statbuf)) < 0) { fsrprintf( "unable to get bstat on %s: %s\n", fname, strerror(errno)); close(fsfd); return -1; } fd = jdm_open( fshandlep, &statbuf, O_RDWR); if (fd < 0) { fsrprintf( "unable to open handle %s: %s\n", fname, strerror(errno)); close(fsfd); return -1; } /* Get the fs geometry */ if (xfs_getgeom(fsfd, &fsgeom) < 0 ) { fsrprintf("Unable to get geom on fs for: %s\n", fname); close(fsfd); return -1; } close(fsfd); tname = gettmpname(fname); if (tname) error = fsrfile_common(fname, tname, NULL, fd, &statbuf); close(fd); return error; }
static off64_t quantity2offset( jdm_fshandle_t *fshandlep, xfs_bstat_t *statp, off64_t qty ) { intgen_t fd; getbmapx_t bmap[ BMAP_LEN ]; off64_t offset; off64_t offset_next; off64_t qty_accum; /* If GETOPT_DUMPASOFFLINE was specified and the HSM provided an * estimate, then use it. */ if (hsm_fs_ctxtp) { if (HsmEstimateFileOffset(hsm_fs_ctxtp, statp, qty, &offset)) return offset; } offset = 0; offset_next = 0; qty_accum = 0; bmap[ 0 ].bmv_offset = 0; bmap[ 0 ].bmv_length = -1; bmap[ 0 ].bmv_count = BMAP_LEN; bmap[ 0 ].bmv_iflags = BMV_IF_NO_DMAPI_READ; bmap[ 0 ].bmv_entries = -1; fd = jdm_open( fshandlep, statp, O_RDONLY ); if ( fd < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_INOMAP, _( "could not open ino %llu to read extent map: %s\n"), statp->bs_ino, strerror( errno )); return 0; } for ( ; ; ) { intgen_t eix; intgen_t rval; rval = ioctl( fd, XFS_IOC_GETBMAPX, bmap ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_INOMAP, _( "could not read extent map for ino %llu: %s\n"), statp->bs_ino, strerror( errno )); ( void )close( fd ); return 0; } if ( bmap[ 0 ].bmv_entries <= 0 ) { ASSERT( bmap[ 0 ].bmv_entries == 0 ); ( void )close( fd ); return offset_next; } for ( eix = 1 ; eix <= bmap[ 0 ].bmv_entries ; eix++ ) { getbmapx_t *bmapp = &bmap[ eix ]; off64_t qty_new; if ( bmapp->bmv_block == -1 ) { continue; /* hole */ } offset = bmapp->bmv_offset * BBSIZE; qty_new = qty_accum + bmapp->bmv_length * BBSIZE; if ( qty_new >= qty ) { ( void )close( fd ); return offset + ( qty - qty_accum ); } offset_next = offset + bmapp->bmv_length * BBSIZE; qty_accum = qty_new; } } /* NOTREACHED */ }
/* * fsrfs -- reorganize a file system */ static int fsrfs(char *mntdir, xfs_ino_t startino, int targetrange) { int fsfd, fd; int count = 0; int ret; size_t buflenout; xfs_bstat_t buf[GRABSZ]; char fname[64]; char *tname; jdm_fshandle_t *fshandlep; xfs_ino_t lastino = startino; fsrprintf("%s startino=%llu\n", mntdir, (unsigned long long)startino); fshandlep = jdm_getfshandle( mntdir ); if ( ! fshandlep ) { fsrprintf("unable to get handle: %s: %s\n", mntdir, strerror( errno )); return -1; } if ((fsfd = open(mntdir, O_RDONLY)) < 0) { fsrprintf("unable to open: %s: %s\n", mntdir, strerror( errno )); return -1; } if (xfs_getgeom(fsfd, &fsgeom) < 0 ) { fsrprintf("Skipping %s: could not get XFS geom\n", mntdir); return -1; } tmp_init(mntdir); sync(); while (! xfs_bulkstat(fsfd, &lastino, GRABSZ, &buf[0], &buflenout)) { xfs_bstat_t *p; xfs_bstat_t *endp; if (buflenout == 0 ) goto out0; /* Each loop through, defrag targetrange percent of the files */ count = (buflenout * targetrange) / 100; qsort((char *)buf, buflenout, sizeof(struct xfs_bstat), cmp); for ( p = buf, endp = (buf + buflenout); p < endp ; p++ ) { /* Do some obvious checks now */ if (((p->bs_mode & S_IFMT) != S_IFREG) || (p->bs_extents < 2)) continue; if((fd = jdm_open(fshandlep, p, O_RDWR)) < 0) { /* This probably means the file was * removed while in progress of handling * it. Just quietly ignore this file. */ if (dflag) fsrprintf("could not open: ino %llu\n", p->bs_ino); continue; } /* Don't know the pathname, so make up something */ sprintf(fname, "ino=%llu", (unsigned long long)p->bs_ino); /* Get a tmp file name */ tname = tmp_next(mntdir); ret = fsrfile_common(fname, tname, mntdir, fd, p); leftoffino = p->bs_ino; close(fd); if (ret == 0) { if (--count <= 0) break; } } if (endtime && endtime < time(0)) { tmp_close(mntdir); close(fsfd); fsrall_cleanup(1); exit(1); } } out0: tmp_close(mntdir); close(fsfd); return 0; }