static int raw_open_common(BlockDriverState *bs, QDict *options, int bdrv_flags, int open_flags) { BDRVRawState *s = bs->opaque; QemuOpts *opts; Error *local_err = NULL; const char *filename; int fd, ret; opts = qemu_opts_create_nofail(&raw_runtime_opts); qemu_opts_absorb_qdict(opts, options, &local_err); if (error_is_set(&local_err)) { qerror_report_err(local_err); error_free(local_err); ret = -EINVAL; goto fail; } filename = qemu_opt_get(opts, "filename"); ret = raw_normalize_devicepath(&filename); if (ret != 0) { goto fail; } s->open_flags = open_flags; raw_parse_flags(bdrv_flags, &s->open_flags); s->fd = -1; fd = qemu_open(filename, s->open_flags, 0644); if (fd < 0) { ret = -errno; if (ret == -EROFS) { ret = -EACCES; } goto fail; } s->fd = fd; #ifdef CONFIG_LINUX_AIO if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) { qemu_close(fd); ret = -errno; goto fail; } #endif s->has_discard = 1; #ifdef CONFIG_XFS if (platform_test_xfs_fd(s->fd)) { s->is_xfs = 1; } #endif ret = 0; fail: qemu_opts_del(opts); return ret; }
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)) ); }
static int raw_open_common(BlockDriverState *bs, const char *filename, int bdrv_flags, int open_flags) { BDRVRawState *s = bs->opaque; int fd, ret; ret = raw_normalize_devicepath(&filename); if (ret != 0) { return ret; } s->open_flags = open_flags; raw_parse_flags(bdrv_flags, &s->open_flags); s->fd = -1; fd = qemu_open(filename, s->open_flags, 0644); if (fd < 0) { ret = -errno; if (ret == -EROFS) ret = -EACCES; return ret; } s->fd = fd; #ifdef CONFIG_LINUX_AIO if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) { qemu_close(fd); return -errno; } #endif s->has_discard = 1; #ifdef CONFIG_XFS if (platform_test_xfs_fd(s->fd)) { s->is_xfs = 1; } #endif return 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 }
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; }
void init( int argc, char **argv) { int c, flags = 0; char *sp; mode_t mode = 0600; xfs_fsop_geom_t geometry = { 0 }; progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); pagesize = getpagesize(); gettimeofday(&stopwatch, NULL); while ((c = getopt(argc, argv, "ac:dFfmp:nrRstVx")) != EOF) { switch (c) { case 'a': flags |= IO_APPEND; break; case 'c': add_user_command(optarg); break; case 'd': flags |= IO_DIRECT; break; case 'F': /* Ignored / deprecated now, handled automatically */ break; case 'f': flags |= IO_CREAT; break; case 'm': mode = strtoul(optarg, &sp, 0); if (!sp || sp == optarg) { fprintf(stderr, _("non-numeric mode -- %s\n"), optarg); exit(1); } break; case 'n': flags |= IO_NONBLOCK; break; case 'p': progname = optarg; break; case 'r': flags |= IO_READONLY; break; case 's': flags |= IO_OSYNC; break; case 't': flags |= IO_TRUNC; break; case 'R': flags |= IO_REALTIME; break; case 'x': expert = 1; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); default: usage(); } } while (optind < argc) { if ((c = openfile(argv[optind], &geometry, flags, mode)) < 0) exit(1); if (!platform_test_xfs_fd(c)) flags |= IO_FOREIGN; if (addfile(argv[optind], c, &geometry, flags) < 0) exit(1); optind++; } init_commands(); add_args_command(init_args_command); add_check_command(init_check_command); }
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; }
static int raw_open_common(BlockDriverState *bs, const char *filename, int bdrv_flags, int open_flags) { BDRVRawState *s = bs->opaque; int fd, ret; ret = raw_normalize_devicepath(&filename); if (ret != 0) { return ret; } s->open_flags = open_flags | O_BINARY; s->open_flags &= ~O_ACCMODE; if (bdrv_flags & BDRV_O_RDWR) { s->open_flags |= O_RDWR; } else { s->open_flags |= O_RDONLY; } /* Use O_DSYNC for write-through caching, no flags for write-back caching, * and O_DIRECT for no caching. */ if ((bdrv_flags & BDRV_O_NOCACHE)) s->open_flags |= O_DIRECT; if (!(bdrv_flags & BDRV_O_CACHE_WB)) s->open_flags |= O_DSYNC; s->fd = -1; fd = qemu_open(filename, s->open_flags, 0644); if (fd < 0) { ret = -errno; if (ret == -EROFS) ret = -EACCES; return ret; } s->fd = fd; s->aligned_buf = NULL; if ((bdrv_flags & BDRV_O_NOCACHE)) { /* * Allocate a buffer for read/modify/write cycles. Chose the size * pessimistically as we don't know the block size yet. */ s->aligned_buf_size = 32 * MAX_BLOCKSIZE; s->aligned_buf = qemu_memalign(MAX_BLOCKSIZE, s->aligned_buf_size); if (s->aligned_buf == NULL) { goto out_close; } } #ifdef CONFIG_LINUX_AIO if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) == (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) { /* We're falling back to POSIX AIO in some cases */ paio_init(); s->aio_ctx = laio_init(); if (!s->aio_ctx) { goto out_free_buf; } s->use_aio = 1; } else #endif { if (paio_init() < 0) { goto out_free_buf; } #ifdef CONFIG_LINUX_AIO s->use_aio = 0; #endif } #ifdef CONFIG_XFS if (platform_test_xfs_fd(s->fd)) { s->is_xfs = 1; } #endif return 0; out_free_buf: qemu_vfree(s->aligned_buf); out_close: close(fd); return -errno; }
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; }
static int open_f( int argc, char **argv) { int c, fd, flags = 0; char *sp; mode_t mode = 0600; xfs_fsop_geom_t geometry = { 0 }; if (argc == 1) { if (file) return stat_f(argc, argv); fprintf(stderr, _("no files are open, try 'help open'\n")); return 0; } while ((c = getopt(argc, argv, "FRTacdfm:nrstx")) != EOF) { switch (c) { case 'F': /* Ignored / deprecated now, handled automatically */ break; case 'a': flags |= IO_APPEND; break; case 'c': case 'f': flags |= IO_CREAT; break; case 'd': flags |= IO_DIRECT; break; case 'm': mode = strtoul(optarg, &sp, 0); if (!sp || sp == optarg) { printf(_("non-numeric mode -- %s\n"), optarg); return 0; } break; case 'n': flags |= IO_NONBLOCK; break; case 'r': flags |= IO_READONLY; break; case 's': flags |= IO_OSYNC; break; case 't': flags |= IO_TRUNC; break; case 'R': case 'x': /* backwards compatibility */ flags |= IO_REALTIME; break; case 'T': flags |= IO_TMPFILE; break; default: return command_usage(&open_cmd); } } if (optind != argc - 1) return command_usage(&open_cmd); if ((flags & (IO_READONLY|IO_TMPFILE)) == (IO_READONLY|IO_TMPFILE)) { fprintf(stderr, _("-T and -r options are incompatible\n")); return -1; } fd = openfile(argv[optind], &geometry, flags, mode); if (fd < 0) return 0; if (!platform_test_xfs_fd(fd)) flags |= IO_FOREIGN; addfile(argv[optind], fd, &geometry, flags); return 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; }