Add interfaces in libcephfs to enable users to read/write data via iovec structure.
Signed-off-by: Jevon Qiao <qiaojianfeng@unitedstack.com>
#include <sys/param.h>
#include <fcntl.h>
#include <sys/utsname.h>
+#include <sys/uio.h>
#if defined(__linux__)
#include <linux/falloc.h>
delete logger;
}
-
-
-
-
-
void Client::tear_down_cache()
{
// fd's
return r;
}
+int Client::preadv(int fd, const struct iovec *iov, int iovcnt, loff_t offset)
+{
+ return _preadv_pwritev(fd, iov, iovcnt, offset, false);
+}
+
int Client::_read(Fh *f, int64_t offset, uint64_t size, bufferlist *bl)
{
const md_config_t *conf = cct->_conf;
if (fh->flags & O_PATH)
return -EBADF;
#endif
- int r = _write(fh, offset, size, buf);
+ int r = _write(fh, offset, size, buf, NULL, 0);
ldout(cct, 3) << "write(" << fd << ", \"...\", " << size << ", " << offset << ") = " << r << dendl;
return r;
}
+int Client::pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset)
+{
+ return _preadv_pwritev(fd, iov, iovcnt, offset, true);
+}
+
+int Client::_preadv_pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset, bool write)
+{
+ Mutex::Locker lock(client_lock);
+ tout(cct) << fd << std::endl;
+ tout(cct) << offset << std::endl;
+
+ Fh *fh = get_filehandle(fd);
+ if (!fh)
+ return -EBADF;
+#if defined(__linux__) && defined(O_PATH)
+ if (fh->flags & O_PATH)
+ return -EBADF;
+#endif
+ loff_t totallen = 0;
+ for (int i = 0; i < iovcnt; i++) {
+ totallen += iov[i].iov_len;
+ }
+ if (write) {
+ int w = _write(fh, offset, totallen, NULL, iov, iovcnt);
+ ldout(cct, 3) << "write(" << fd << ", \"...\", " << totallen << ", " << offset << ") = " << w << dendl;
+ return w;
+ } else {
+ bufferlist bl;
+ int r = _read(fh, offset, totallen, &bl);
+ ldout(cct, 3) << "read(" << fd << ", " << offset << ") = " << r << dendl;
+ int bufoff = 0;
+ uint32_t rlen = 0;
+ for (int j = 0, tmplen = r; j < iovcnt && tmplen > 0; j++) {
+ /*
+ * This piece of code aims to handle the case that bufferlist does no have enough data
+ * to fill in the iov
+ */
+ if (tmplen < iov[j].iov_len) {
+ bl.copy(bufoff, tmplen, (char *)iov[j].iov_base);
+ break;
+ } else {
+ bl.copy(bufoff, iov[j].iov_len, (char *)iov[j].iov_base);
+ }
+ tmplen -= iov[j].iov_len;
+ bufoff += iov[j].iov_len;
+ }
+ return r;
+ }
+}
-int Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf)
+int Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf,
+ const struct iovec *iov, int iovcnt)
{
if ((uint64_t)(offset+size) > mdsmap->get_max_filesize()) //too large!
return -EFBIG;
}
// copy into fresh buffer (since our write may be resub, async)
- bufferptr bp;
- if (size > 0) bp = buffer::copy(buf, size);
bufferlist bl;
- bl.push_back( bp );
+ bufferptr *bparr;
+ if (buf) {
+ bufferptr bp;
+ if (size > 0) bp = buffer::copy(buf, size);
+ bl.push_back( bp );
+ } else if (iov){
+ //iov case
+ bparr = new bufferptr[iovcnt];
+ for (int i = 0; i < iovcnt; i++) {
+ if (iov[i].iov_len > 0) bparr[i] = buffer::copy((char*)iov[i].iov_base, iov[i].iov_len);
+ bl.push_back( bparr[i] );
+ }
+ }
utime_t lat;
uint64_t totalwritten;
}
put_cap_ref(in, CEPH_CAP_FILE_WR);
+ if (buf == NULL && iov != NULL) {
+ delete[] bparr;
+ }
return r;
}
tout(cct) << off << std::endl;
tout(cct) << len << std::endl;
- int r = _write(fh, off, len, data);
+ int r = _write(fh, off, len, data, NULL, 0);
ldout(cct, 3) << "ll_write " << fh << " " << off << "~" << len << " = " << r
<< dendl;
return r;
bool *created = NULL, int uid=-1, int gid=-1);
loff_t _lseek(Fh *fh, loff_t offset, int whence);
int _read(Fh *fh, int64_t offset, uint64_t size, bufferlist *bl);
- int _write(Fh *fh, int64_t offset, uint64_t size, const char *buf);
+ int _write(Fh *fh, int64_t offset, uint64_t size, const char *buf,
+ const struct iovec *iov, int iovcnt);
+ int _preadv_pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset, bool write);
int _flush(Fh *fh);
int _fsync(Fh *fh, bool syncdataonly);
int _sync_fs();
int close(int fd);
loff_t lseek(int fd, loff_t offset, int whence);
int read(int fd, char *buf, loff_t size, loff_t offset=-1);
+ int preadv(int fd, const struct iovec *iov, int iovcnt, loff_t offset=-1);
int write(int fd, const char *buf, loff_t size, loff_t offset=-1);
+ int pwritev(int fd, const struct iovec *iov, int iovcnt, loff_t offset=-1);
int fake_write_size(int fd, loff_t size);
int ftruncate(int fd, loff_t size);
int fsync(int fd, bool syncdataonly);
*/
int ceph_read(struct ceph_mount_info *cmount, int fd, char *buf, int64_t size, int64_t offset);
+/**
+ * Read data from the file.
+ * @param cmount the ceph mount handle to use for performing the read.
+ * @param fd the file descriptor of the open file to read from.
+ * @param iov the iov structure to read data into
+ * @param iovcnt the number of items that iov includes
+ * @param offset the offset in the file to read from. If this value is negative, the
+ * function reads from the current offset of the file descriptor.
+ * @returns the number of bytes read into buf, or a negative error code on failure.
+ */
+int ceph_preadv(struct ceph_mount_info *cmount, int fd, const struct iovec *iov, int iovcnt,
+ int64_t offset);
+
/**
* Write data to a file.
*
int ceph_write(struct ceph_mount_info *cmount, int fd, const char *buf, int64_t size,
int64_t offset);
+/**
+ * Write data to a file.
+ *
+ * @param cmount the ceph mount handle to use for performing the write.
+ * @param fd the file descriptor of the open file to write to
+ * @param iov the iov structure to read data into
+ * @param iovcnt the number of items that iov includes
+ * @param offset the offset of the file write into. If this value is negative, the
+ * function writes to the current offset of the file descriptor.
+ * @returns the number of bytes written, or a negative error code
+ */
+int ceph_pwritev(struct ceph_mount_info *cmount, int fd, const struct iovec *iov, int iovcnt,
+ int64_t offset);
+
/**
* Truncate a file to the given size.
*
return cmount->get_client()->read(fd, buf, size, offset);
}
+extern "C" int ceph_preadv(struct ceph_mount_info *cmount, int fd,
+ const struct iovec *iov, int iovcnt, int64_t offset)
+{
+ if (!cmount->is_mounted())
+ return -ENOTCONN;
+ return cmount->get_client()->preadv(fd, iov, iovcnt, offset);
+}
+
extern "C" int ceph_write(struct ceph_mount_info *cmount, int fd, const char *buf,
int64_t size, int64_t offset)
{
return cmount->get_client()->write(fd, buf, size, offset);
}
+extern "C" int ceph_pwritev(struct ceph_mount_info *cmount, int fd,
+ const struct iovec *iov, int iovcnt, int64_t offset)
+{
+ if (!cmount->is_mounted())
+ return -ENOTCONN;
+ return cmount->get_client()->pwritev(fd, iov, iovcnt, offset);
+}
+
extern "C" int ceph_ftruncate(struct ceph_mount_info *cmount, int fd, int64_t size)
{
if (!cmount->is_mounted())