/* * User defined low-level merge driver support. */ static int ll_ext_merge(const struct ll_merge_driver *fn, mmbuffer_t *result, const char *path, mmfile_t *orig, const char *orig_name, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, const struct ll_merge_options *opts, int marker_size) { char temp[4][50]; struct strbuf cmd = STRBUF_INIT; struct strbuf_expand_dict_entry dict[6]; struct strbuf path_sq = STRBUF_INIT; const char *args[] = { NULL, NULL }; int status, fd, i; struct stat st; assert(opts); sq_quote_buf(&path_sq, path); dict[0].placeholder = "O"; dict[0].value = temp[0]; dict[1].placeholder = "A"; dict[1].value = temp[1]; dict[2].placeholder = "B"; dict[2].value = temp[2]; dict[3].placeholder = "L"; dict[3].value = temp[3]; dict[4].placeholder = "P"; dict[4].value = path_sq.buf; dict[5].placeholder = NULL; dict[5].value = NULL; if (fn->cmdline == NULL) die("custom merge driver %s lacks command line.", fn->name); result->ptr = NULL; result->size = 0; create_temp(orig, temp[0], sizeof(temp[0])); create_temp(src1, temp[1], sizeof(temp[1])); create_temp(src2, temp[2], sizeof(temp[2])); xsnprintf(temp[3], sizeof(temp[3]), "%d", marker_size); strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict); args[0] = cmd.buf; status = run_command_v_opt(args, RUN_USING_SHELL); fd = open(temp[1], O_RDONLY); if (fd < 0) goto bad; if (fstat(fd, &st)) goto close_bad; result->size = st.st_size; result->ptr = xmallocz(result->size); if (read_in_full(fd, result->ptr, result->size) != result->size) { FREE_AND_NULL(result->ptr); result->size = 0; } close_bad: close(fd); bad: for (i = 0; i < 3; i++) unlink_or_warn(temp[i]); strbuf_release(&cmd); strbuf_release(&path_sq); return status; }
/* * User defined low-level merge driver support. */ static int ll_ext_merge(const struct ll_merge_driver *fn, mmbuffer_t *result, const char *path, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, int virtual_ancestor) { char temp[3][50]; struct strbuf cmd = STRBUF_INIT; struct strbuf_expand_dict_entry dict[] = { { "O", temp[0] }, { "A", temp[1] }, { "B", temp[2] }, { NULL } }; const char *args[] = { "sh", "-c", NULL, NULL }; int status, fd, i; struct stat st; if (fn->cmdline == NULL) die("custom merge driver %s lacks command line.", fn->name); result->ptr = NULL; result->size = 0; create_temp(orig, temp[0]); create_temp(src1, temp[1]); create_temp(src2, temp[2]); strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict); args[2] = cmd.buf; status = run_command_v_opt(args, 0); if (status < -ERR_RUN_COMMAND_FORK) ; /* failure in run-command */ else status = -status; fd = open(temp[1], O_RDONLY); if (fd < 0) goto bad; if (fstat(fd, &st)) goto close_bad; result->size = st.st_size; result->ptr = xmalloc(result->size + 1); if (read_in_full(fd, result->ptr, result->size) != result->size) { free(result->ptr); result->ptr = NULL; result->size = 0; } close_bad: close(fd); bad: for (i = 0; i < 3; i++) unlink_or_warn(temp[i]); strbuf_release(&cmd); return status; }
/* * User defined low-level merge driver support. */ static int ll_ext_merge(const struct ll_merge_driver *fn, mmbuffer_t *result, const char *path, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, int flag, int marker_size) { char temp[4][50]; struct strbuf cmd = STRBUF_INIT; struct strbuf_expand_dict_entry dict[] = { { "O", temp[0] }, { "A", temp[1] }, { "B", temp[2] }, { "L", temp[3] }, { NULL } }; const char *args[] = { NULL, NULL }; int status, fd, i; struct stat st; if (fn->cmdline == NULL) die("custom merge driver %s lacks command line.", fn->name); result->ptr = NULL; result->size = 0; create_temp(orig, temp[0]); create_temp(src1, temp[1]); create_temp(src2, temp[2]); sprintf(temp[3], "%d", marker_size); strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict); args[0] = cmd.buf; status = run_command_v_opt(args, RUN_USING_SHELL); fd = open(temp[1], O_RDONLY); if (fd < 0) goto bad; if (fstat(fd, &st)) goto close_bad; result->size = st.st_size; result->ptr = xmalloc(result->size + 1); if (read_in_full(fd, result->ptr, result->size) != result->size) { free(result->ptr); result->ptr = NULL; result->size = 0; } close_bad: close(fd); bad: for (i = 0; i < 3; i++) unlink_or_warn(temp[i]); strbuf_release(&cmd); return status; }
/* * User defined low-level merge driver support. */ static int ll_ext_merge(const struct ll_merge_driver *fn, mmbuffer_t *result, const char *path, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, int virtual_ancestor) { char temp[3][50]; char cmdbuf[2048]; struct interp table[] = { { "%O" }, { "%A" }, { "%B" }, }; struct child_process child; const char *args[20]; int status, fd, i; struct stat st; if (fn->cmdline == NULL) die("custom merge driver %s lacks command line.", fn->name); result->ptr = NULL; result->size = 0; create_temp(orig, temp[0]); create_temp(src1, temp[1]); create_temp(src2, temp[2]); interp_set_entry(table, 0, temp[0]); interp_set_entry(table, 1, temp[1]); interp_set_entry(table, 2, temp[2]); interpolate(cmdbuf, sizeof(cmdbuf), fn->cmdline, table, 3); memset(&child, 0, sizeof(child)); child.argv = args; args[0] = "sh"; args[1] = "-c"; args[2] = cmdbuf; args[3] = NULL; status = run_command(&child); if (status < -ERR_RUN_COMMAND_FORK) ; /* failure in run-command */ else status = -status; fd = open(temp[1], O_RDONLY); if (fd < 0) goto bad; if (fstat(fd, &st)) goto close_bad; result->size = st.st_size; result->ptr = xmalloc(result->size + 1); if (read_in_full(fd, result->ptr, result->size) != result->size) { free(result->ptr); result->ptr = NULL; result->size = 0; } close_bad: close(fd); bad: for (i = 0; i < 3; i++) unlink(temp[i]); return status; }
void CreateTemp() { if(create_temp()==-1) err_temp(tempname2); }
int main (int argc, char **argv) { ssize_t ret_size; struct stat st; int ret, flags; int part_request; long long this_time; double part_min, part_max, time_min, time_max; double time_sum, time_sum2, time_mdev, time_avg; double part_sum, part_sum2, part_mdev, part_avg; long long time_now, time_next, period_deadline; setvbuf(stdout, NULL, _IOLBF, 0); parse_options(argc, argv); interval_ts.tv_sec = interval / 1000000; interval_ts.tv_nsec = (interval % 1000000) * 1000; if (!size) size = default_size; if (size <= 0) errx(1, "request size must be greather than zero"); #ifdef MAX_RW_COUNT if (size > MAX_RW_COUNT) warnx("this platform supports requests %u bytes at most", MAX_RW_COUNT); #endif if (wsize) temp_wsize = wsize; else if (size > temp_wsize) temp_wsize = size; flags = O_RDONLY; #if !defined(HAVE_POSIX_FADVICE) && !defined(HAVE_NOCACHE_IO) # if defined(HAVE_DIRECT_IO) direct |= !cached; # else if (!cached && !write_test) { warnx("non-cached read I/O not supported by this platform"); warnx("you can use write I/O to get reliable results"); cached = 1; } # endif #endif if (write_test) { flags = O_RDWR; make_request = do_pwrite; } if (async) aio_setup(); if (direct) #ifdef HAVE_DIRECT_IO flags |= O_DIRECT; #else errx(1, "direct I/O not supported by this platform"); #endif #ifdef __MINGW32__ flags |= O_BINARY; #endif if (stat(path, &st)) err(2, "stat \"%s\" failed", path); if (!S_ISDIR(st.st_mode) && write_test && write_test < 3) errx(2, "think twice, then use -WWW to shred this target"); if (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode)) { if (S_ISDIR(st.st_mode)) st.st_size = offset + temp_wsize; parse_device(st.st_dev); } else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) { fd = open(path, flags); if (fd < 0) err(2, "failed to open \"%s\"", path); if (get_device_size(fd, &st)) { if (!S_ISCHR(st.st_mode)) err(2, "block get size ioctl failed"); st.st_size = offset + temp_wsize; fstype = "character"; device = "device"; } else { device_size = st.st_size; fstype = "block"; device = "device "; } if (!cached && write_test && fdatasync(fd)) { warnx("fdatasync not supported by \"%s\", " "enable cached requests", path); cached = 1; } } else { errx(2, "unsupported destination: \"%s\"", path); } if (wsize > st.st_size || offset > st.st_size - wsize) errx(2, "target is too small for this"); if (!wsize) wsize = st.st_size - offset; if (size > wsize) errx(2, "request size is too big for this target"); ret = posix_memalign(&buf, 0x1000, size); if (ret) errx(2, "buffer allocation failed"); random_memory(buf, size); if (S_ISDIR(st.st_mode)) { fd = create_temp(path, "ioping.tmp"); if (fd < 0) err(2, "failed to create temporary file at \"%s\"", path); if (keep_file) { if (fstat(fd, &st)) err(2, "fstat at \"%s\" failed", path); if (st.st_size >= offset + wsize) #ifndef __MINGW32__ if (st.st_blocks >= (st.st_size + 511) / 512) #endif goto skip_preparation; } for (woffset = 0 ; woffset < wsize ; woffset += ret_size) { ret_size = size; if (woffset + ret_size > wsize) ret_size = wsize - woffset; if (woffset) random_memory(buf, ret_size); ret_size = pwrite(fd, buf, ret_size, offset + woffset); if (ret_size <= 0) err(2, "preparation write failed"); } skip_preparation: if (fsync(fd)) err(2, "fsync failed"); } else if (S_ISREG(st.st_mode)) { fd = open(path, flags); if (fd < 0) err(2, "failed to open \"%s\"", path); } if (!cached) { #ifdef HAVE_POSIX_FADVICE ret = posix_fadvise(fd, offset, wsize, POSIX_FADV_RANDOM); if (ret) err(2, "fadvise failed"); #endif #ifdef HAVE_NOCACHE_IO ret = fcntl(fd, F_NOCACHE, 1); if (ret) err(2, "fcntl nocache failed"); #endif } srandom(now()); if (deadline) deadline += now(); set_signal(); request = 0; woffset = 0; part_request = 0; part_min = time_min = LLONG_MAX; part_max = time_max = LLONG_MIN; part_sum = time_sum = 0; part_sum2 = time_sum2 = 0; time_now = now(); period_deadline = time_now + period_time; while (!exiting) { request++; part_request++; if (randomize) woffset = random() % (wsize / size) * size; #ifdef HAVE_POSIX_FADVICE if (!cached) { ret = posix_fadvise(fd, offset + woffset, size, POSIX_FADV_DONTNEED); if (ret) err(3, "fadvise failed"); } #endif if (write_test) shake_memory(buf, size); this_time = now(); ret_size = make_request(fd, buf, size, offset + woffset); if (ret_size < 0) { if (errno != EINTR) err(3, "request failed"); } else if (ret_size < size) warnx("request returned less than expected: %zu", ret_size); else if (ret_size > size) errx(3, "request returned more than expected: %zu", ret_size); time_now = now(); this_time = time_now - this_time; time_next = time_now + interval; part_sum += this_time; part_sum2 += this_time * this_time; if (this_time < part_min) part_min = this_time; if (this_time > part_max) part_max = this_time; if (!quiet) { print_size(ret_size); printf(" %s %s (%s %s", write_test ? "to" : "from", path, fstype, device); if (device_size) print_size(device_size); printf("): request=%d time=", request); print_time(this_time); printf("\n"); } if ((period_request && (part_request >= period_request)) || (period_time && (time_next >= period_deadline))) { part_avg = part_sum / part_request; part_mdev = sqrt(part_sum2 / part_request - part_avg * part_avg); printf("%d %.0f %.0f %.0f %.0f %.0f %.0f %.0f\n", part_request, part_sum, 1000000. * part_request / part_sum, 1000000. * part_request * size / part_sum, part_min, part_avg, part_max, part_mdev); time_sum += part_sum; time_sum2 += part_sum2; if (part_min < time_min) time_min = part_min; if (part_max > time_max) time_max = part_max; part_min = LLONG_MAX; part_max = LLONG_MIN; part_sum = part_sum2 = 0; part_request = 0; period_deadline = time_now + period_time; } if (!randomize) { woffset += size; if (woffset + size > wsize) woffset = 0; } if (exiting) break; if (stop_at_request && request >= stop_at_request) break; if (deadline && time_next >= deadline) break; if (interval) nanosleep(&interval_ts, NULL); } time_sum += part_sum; time_sum2 += part_sum2; if (part_min < time_min) time_min = part_min; if (part_max > time_max) time_max = part_max; time_avg = time_sum / request; time_mdev = sqrt(time_sum2 / request - time_avg * time_avg); if (batch_mode) { printf("%d %.0f %.0f %.0f %.0f %.0f %.0f %.0f\n", request, time_sum, 1000000. * request / time_sum, 1000000. * request * size / time_sum, time_min, time_avg, time_max, time_mdev); } else if (!quiet || (!period_time && !period_request)) { printf("\n--- %s (%s %s", path, fstype, device); if (device_size) print_size(device_size); printf(") ioping statistics ---\n"); print_int(request); printf(" requests completed in "); print_time(time_sum); printf(", "); print_size((long long)request * size); printf(" %s, ", write_test ? "written" : "read"); print_int(1000000. * request / time_sum); printf(" iops, "); print_size(1000000. * request * size / time_sum); printf("/s\n"); printf("min/avg/max/mdev = "); print_time(time_min); printf(" / "); print_time(time_avg); printf(" / "); print_time(time_max); printf(" / "); print_time(time_mdev); printf("\n"); } return 0; }