return 0;
}
+int buffer::list::write_fd(int fd, uint64_t offset) const
+{
+ // use writev!
+ iovec iov[IOV_MAX];
+ int iovlen = 0;
+ ssize_t bytes = 0;
+
+ std::list<ptr>::const_iterator p = _buffers.begin();
+ while (p != _buffers.end()) {
+ if (p->length() > 0) {
+ iov[iovlen].iov_base = (void *)p->c_str();
+ iov[iovlen].iov_len = p->length();
+ bytes += p->length();
+ iovlen++;
+ }
+ ++p;
+
+ if (iovlen == IOV_MAX-1 ||
+ p == _buffers.end()) {
+ iovec *start = iov;
+ int num = iovlen;
+ ssize_t wrote;
+ retry:
+ wrote = ::pwritev(fd, start, num, offset);
+ if (wrote < 0) {
+ int err = errno;
+ if (err == EINTR)
+ goto retry;
+ return -err;
+ }
+ offset += wrote;
+ if (wrote < bytes) {
+ // partial write, recover!
+ while ((size_t)wrote >= start[0].iov_len) {
+ wrote -= start[0].iov_len;
+ bytes -= start[0].iov_len;
+ start++;
+ num--;
+ }
+ if (wrote > 0) {
+ start[0].iov_len -= wrote;
+ start[0].iov_base = (char *)start[0].iov_base + wrote;
+ bytes -= wrote;
+ }
+ goto retry;
+ }
+ iovlen = 0;
+ bytes = 0;
+ }
+ }
+ return 0;
+}
+
void buffer::list::prepare_iov(std::vector<iovec> *piov) const
{
piov->resize(_buffers.size());
int read_fd_zero_copy(int fd, size_t len);
int write_file(const char *fn, int mode=0644);
int write_fd(int fd) const;
+ int write_fd(int fd, uint64_t offset) const;
int write_fd_zero_copy(int fd) const;
void prepare_iov(std::vector<iovec> *piov) const;
uint32_t crc32c(uint32_t crc) const;
dout(15) << "write " << cid << "/" << oid << " " << offset << "~" << len << dendl;
int r;
- int64_t actual;
-
FDRef fd;
r = lfn_open(cid, oid, true, &fd);
if (r < 0) {
goto out;
}
- // seek
- actual = ::lseek64(**fd, offset, SEEK_SET);
- if (actual < 0) {
- r = -errno;
- dout(0) << "write lseek64 to " << offset << " failed: " << cpp_strerror(r) << dendl;
- lfn_close(fd);
- goto out;
- }
- if (actual != (int64_t)offset) {
- dout(0) << "write lseek64 to " << offset << " gave bad offset " << actual << dendl;
- r = -EIO;
- lfn_close(fd);
- goto out;
- }
-
// write
- r = bl.write_fd(**fd);
+ r = bl.write_fd(**fd, offset);
if (r == 0)
r = bl.length();
::unlink(FILENAME);
}
+TEST(BufferList, write_fd_offset) {
+ ::unlink(FILENAME);
+ int fd = ::open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600);
+ bufferlist bl;
+ for (unsigned i = 0; i < IOV_MAX * 2; i++) {
+ bufferptr ptr("A", 1);
+ bl.push_back(ptr);
+ }
+ uint64_t offset = 200;
+ EXPECT_EQ(0, bl.write_fd(fd, offset));
+ ::close(fd);
+ struct stat st;
+ memset(&st, 0, sizeof(st));
+ ::stat(FILENAME, &st);
+ EXPECT_EQ(IOV_MAX * 2 + offset, st.st_size);
+ ::unlink(FILENAME);
+}
+
TEST(BufferList, crc32c) {
bufferlist bl;
__u32 crc = 0;