Writing zeroes into the last sector of an object is not going to preallocate it, but just allocates the last sector. This leads to fairly nasty fragmentation. Use fallocate on the whole object instead. On my test setup with XFS this speeds up writes to an unallocate volume from ~73MB/s to ~80MB/s. If the filesystem does not support fallocate we fall back to the old code. Signed-off-by: Christoph Hellwig <hch at lst.de> Index: sheepdog/sheep/store.c =================================================================== --- sheepdog.orig/sheep/store.c 2011-11-11 13:36:16.000000000 +0100 +++ sheepdog/sheep/store.c 2011-11-11 13:40:03.600023318 +0100 @@ -723,14 +723,37 @@ out: return ret; } +static int store_write_last_sector(int fd) +{ + const int size = SECTOR_SIZE; + char *buf = NULL; + int ret; + + buf = valloc(size); + if (!buf) { + eprintf("failed to allocate memory\n"); + return SD_RES_NO_MEM; + } + + memset(buf, 0, size); + ret = pwrite64(fd, buf, size, SD_DATA_OBJ_SIZE - size); + free(buf); + + if (ret != size) { + if (errno == ENOSPC) + return SD_RES_NO_SPACE; + eprintf("%m\n"); + return SD_RES_EIO; + } + + return SD_RES_SUCCESS; +} static int store_create_and_write_obj(struct request *req, uint32_t epoch) { struct sd_obj_req *hdr = (struct sd_obj_req *)&req->rq; - const int size = SECTOR_SIZE; int ret = SD_RES_SUCCESS; int fd = -1; - char *buf = NULL; if (!hdr->copies) { eprintf("the number of copies cannot be zero\n"); @@ -741,24 +764,17 @@ static int store_create_and_write_obj(st if (fd < 0) return ret; - buf = valloc(size); - if (!buf) { - eprintf("failed to allocate memory\n"); - ret = SD_RES_NO_MEM; - goto out; - } - memset(buf, 0, size); - ret = pwrite64(fd, buf, size, SD_DATA_OBJ_SIZE - size); - free(buf); - - if (ret != size) { - if (errno == ENOSPC) - ret = SD_RES_NO_SPACE; - else { - eprintf("%m\n"); + /* + * Preallocate the whole object to get a better filesystem layout. + */ + ret = fallocate(fd, 0, 0, SD_DATA_OBJ_SIZE); + if (ret < 0) { + if (errno != ENOSYS && errno != EOPNOTSUPP) { ret = SD_RES_EIO; + goto out; } - goto out; + + ret = store_write_last_sector(fd); } ret = store_write_obj_fd(fd, req, epoch); |