/* preallocate the whole object */ int prealloc(int fd, uint64_t size) { int ret = xfallocate(fd, 0, 0, size); if (ret < 0) { if (errno != ENOSYS && errno != EOPNOTSUPP) { return ret; } return xftruncate(fd, size); } return 0; }
/* Preallocate the whole object to get a better filesystem layout. */ int prealloc(int fd, uint32_t size) { int ret = xfallocate(fd, 0, 0, size); if (ret < 0) { if (errno != ENOSYS && errno != EOPNOTSUPP) { sd_err("failed to preallocate space, %m"); return ret; } return xftruncate(fd, size); } return 0; }
static int migrate_from_v0_to_v1(void) { int ret, fd; struct sheepdog_config_v1 config; fd = open(config_path, O_RDWR); if (fd < 0) { sd_err("failed to open config file, %m"); return -1; } memset(&config, 0, sizeof(config)); ret = xread(fd, &config, sizeof(config)); if (ret < 0) { sd_err("failed to read config file, %m"); close(fd); return ret; } config.version = 1; ret = xpwrite(fd, &config, sizeof(config), 0); if (ret != sizeof(config)) { sd_err("failed to write config data, %m"); close(fd); return -1; } /* 0.5.1 could wrongly extend the config file, so truncate it here */ ret = xftruncate(fd, sizeof(config)); if (ret != 0) { sd_err("failed to truncate config data, %m"); close(fd); return -1; } close(fd); /* * If the config file contains a space field, the store layout * is compatible with v1. In this case, what we need to do is * only adding version number to the config file. */ if (config.space > 0) return 0; /* upgrade epoch log */ for_each_epoch(update_epoch_from_v0_to_v1); return ret; }
static void shm_queue_init(void) { int ret; shmfd = open(shmfile, O_CREAT | O_RDWR, 0644); if (shmfd < 0) panic("cannot open shared file, %s", shmfile); shm_queue_lock(); ret = xftruncate(shmfd, sizeof(*shm_queue)); if (ret != 0) panic("failed to truncate shmfile, %m"); shm_queue = mmap(NULL, sizeof(*shm_queue), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0); if (shm_queue == MAP_FAILED) panic("mmap error, %m"); if (is_shm_queue_valid()) { block_event_pos = shm_queue->block_event_pos; nonblock_event_pos = shm_queue->nonblock_event_pos; } else { /* initialize shared memory */ block_event_pos = 0; nonblock_event_pos = 0; ret = xftruncate(shmfd, 0); if (ret != 0) panic("failed to truncate shmfile, %m"); ret = xftruncate(shmfd, sizeof(*shm_queue)); if (ret != 0) panic("failed to truncate shmfile, %m"); } shm_queue_unlock(); }
int default_create_and_write(uint64_t oid, const struct siocb *iocb) { char path[PATH_MAX], tmp_path[PATH_MAX]; int flags = prepare_iocb(oid, iocb, true); int ret, fd; uint32_t len = iocb->length; size_t obj_size; uint64_t offset = iocb->offset; sd_debug("%"PRIx64, oid); get_store_path(oid, iocb->ec_index, path); get_store_tmp_path(oid, iocb->ec_index, tmp_path); if (uatomic_is_true(&sys->use_journal) && journal_write_store(oid, iocb->buf, iocb->length, iocb->offset, true) != SD_RES_SUCCESS) { sd_err("turn off journaling"); uatomic_set_false(&sys->use_journal); flags |= O_DSYNC; sync(); } fd = open(tmp_path, flags, sd_def_fmode); if (fd < 0) { if (errno == EEXIST) { /* * This happens if node membership changes during object * creation; while gateway retries a CREATE request, * recovery process could also recover the object at the * same time. They should try to write the same date, * so it is okay to simply return success here. */ sd_debug("%s exists", tmp_path); return SD_RES_SUCCESS; } sd_err("failed to open %s: %m", tmp_path); return err_to_sderr(path, oid, errno); } obj_size = get_store_objsize(oid); trim_zero_blocks(iocb->buf, &offset, &len); if (offset != 0 || len != get_objsize(oid)) { if (is_sparse_object(oid)) ret = xftruncate(fd, obj_size); else ret = prealloc(fd, obj_size); if (ret < 0) { ret = err_to_sderr(path, oid, errno); goto out; } } ret = xpwrite(fd, iocb->buf, len, offset); if (ret != len) { sd_err("failed to write object. %m"); ret = err_to_sderr(path, oid, errno); goto out; } ret = rename(tmp_path, path); if (ret < 0) { sd_err("failed to rename %s to %s: %m", tmp_path, path); ret = err_to_sderr(path, oid, errno); goto out; } ret = SD_RES_SUCCESS; objlist_cache_insert(oid); out: if (ret != SD_RES_SUCCESS) unlink(tmp_path); close(fd); return ret; }
static void do_xfer_recv(const struct xfer_opts xfer_opts, const char* filename, const char* desired_basename, int from_peer) { struct xfer_msg statm = recv_xfer_msg(from_peer); if (statm.type != XFER_MSG_STAT) die(ECOMM, "expected stat msg"); struct cleanup* error_cl = cleanup_allocate(); struct stat st; const char* parent_directory = NULL; const char* rename_to = NULL; const char* write_mode = NULL; int dest_fd; if (stat(filename, &st) == 0) { if (S_ISDIR(st.st_mode)) { if (desired_basename == NULL) die(EISDIR, "\"%s\" is a directory", filename); parent_directory = filename; filename = xaprintf("%s/%s", parent_directory, desired_basename); } else if (S_ISREG(st.st_mode)) { if (st.st_nlink > 1) write_mode = "inplace"; } else { write_mode = "inplace"; } } if (parent_directory == NULL) parent_directory = xdirname(filename); if (write_mode == NULL) write_mode = xfer_opts.write_mode; bool atomic; bool automatic_mode = false; if (write_mode == NULL) { automatic_mode = true; atomic = true; } else if (strcmp(write_mode, "atomic") == 0) { atomic = true; } else if (strcmp(write_mode, "inplace") == 0) { atomic = false; } else { die(EINVAL, "unknown write mode \"%s\"", write_mode); } bool regular_file = true; bool preallocated = false; bool chmod_explicit = false; mode_t chmod_explicit_modes = 0; if (xfer_opts.preserve) { chmod_explicit = true; chmod_explicit_modes = statm.u.stat.ugo_bits; } if (xfer_opts.mode) { char* endptr = NULL; errno = 0; unsigned long omode = strtoul(xfer_opts.mode, &endptr, 8); if (errno != 0 || *endptr != '\0' || (omode &~ 0777) != 0) die(EINVAL, "invalid mode bits: %s", xfer_opts.mode); chmod_explicit = true; chmod_explicit_modes = (mode_t) omode; } mode_t creat_mode = (chmod_explicit_modes ? 0200 : 0666); if (atomic) { rename_to = filename; filename = xaprintf("%s.fb-adb-%s", filename, gen_hex_random(ENOUGH_ENTROPY)); dest_fd = try_xopen( filename, O_CREAT | O_WRONLY | O_EXCL, creat_mode); if (dest_fd == -1) { if (errno == EACCES && automatic_mode) { atomic = false; filename = rename_to; rename_to = NULL; } else { die_errno("open(\"%s\")", filename); } } } if (!atomic) { dest_fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, creat_mode); if (!S_ISREG(xfstat(dest_fd).st_mode)) regular_file = false; } if (regular_file) cleanup_commit(error_cl, unlink_cleanup, filename); if (regular_file && statm.u.stat.size > 0) preallocated = fallocate_if_supported( dest_fd, statm.u.stat.size); uint64_t total_written = copy_loop_posix_recv(from_peer, dest_fd); if (preallocated && total_written < statm.u.stat.size) xftruncate(dest_fd, total_written); if (xfer_opts.preserve) { struct timeval times[2] = { { statm.u.stat.atime, statm.u.stat.atime_ns / 1000 }, { statm.u.stat.mtime, statm.u.stat.mtime_ns / 1000 }, }; #ifdef HAVE_FUTIMES if (futimes(dest_fd, times) == -1) die_errno("futimes"); #else if (utimes(filename, times) == -1) die_errno("times"); #endif } if (chmod_explicit) if (fchmod(dest_fd, chmod_explicit_modes) == -1) die_errno("fchmod"); if (xfer_opts.sync) xfsync(dest_fd); if (rename_to) xrename(filename, rename_to); if (xfer_opts.sync) xfsync(xopen(parent_directory, O_DIRECTORY|O_RDONLY, 0)); cleanup_forget(error_cl); }