#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
#include "include/int_types.h"
#ifdef __linux__
return ret;
}
+bool block_device_support_discard(const char *devname)
+{
+ bool can_trim = false;
+ char *p = strstr((char *)devname, "sd");
+ char name[32] = {0};
+
+ strcpy(name, p);
+ for (unsigned int i = 0; i < strlen(name); i++) {
+ if(isdigit(name[i])) {
+ name[i] = 0;
+ break;
+ }
+ }
+
+ char filename[100] = {0};
+ sprintf(filename, "/sys/block/%s/queue/discard_granularity", name);
+
+ FILE *fp = fopen(filename, "r");
+ if (fp == NULL) {
+ can_trim = false;
+ } else {
+ char buff[256] = {0};
+ if (fgets(buff, sizeof(buff) - 1, fp)) {
+ if (strcmp(buff, "0"))
+ can_trim = false;
+ else
+ can_trim = true;
+ } else
+ can_trim = false;
+ fclose(fp);
+ }
+ return can_trim;
+}
+
+int block_device_discard(int fd, int64_t offset, int64_t len)
+{
+ uint64_t range[2] = {(uint64_t)offset, (uint64_t)len};
+ return ioctl(fd, BLKDISCARD, range);
+}
+
#elif defined(__APPLE__)
#include <sys/disk.h>
return ret;
}
+bool block_device_support_discard(const char *devname)
+{
+ return false;
+}
+
+int block_device_discard(int fd, int64_t offset, int64_t len)
+{
+ return -EOPNOTSUPP;
+}
#elif defined(__FreeBSD__)
#include <sys/disk.h>
return ret;
}
+bool block_device_support_discard(const char *devname)
+{
+ return false;
+}
+
+int block_device_discard(int fd, int64_t offset, int64_t len)
+{
+ return -EOPNOTSUPP;
+}
#else
# error "Unable to query block device size: unsupported platform, please report."
#endif
#define __CEPH_COMMON_BLKDEV_H
extern int get_block_device_size(int fd, int64_t *psize);
-
+extern bool block_device_support_discard(const char *devname);
+extern int block_device_discard(int fd, int64_t offset, int64_t len);
#endif
/* block devices have to write in blocks of CEPH_PAGE_SIZE */
block_size = CEPH_PAGE_SIZE;
+ discard = block_device_support_discard(fn.c_str());
+ dout(10) << fn << " support discard: " << (int)discard << dendl;
_check_disk_write_cache();
return 0;
}
}
}
+/*
+ *send discard command to joural block deivce
+ */
+void FileJournal::do_discard(int64_t offset, int64_t end)
+{
+ dout(10) << __func__ << "trim(" << offset << ", " << end << dendl;
+
+ offset = ROUND_UP_TO(offset, block_size);
+ if (offset >= end)
+ return;
+ end = ROUND_UP_TO(end - block_size, block_size);
+ assert(end >= offset);
+ if (offset < end)
+ if (block_device_discard(fd, offset, end - offset) < 0)
+ dout(1) << __func__ << "ioctl(BLKDISCARD) error:" << cpp_strerror(errno) << dendl;
+}
+
void FileJournal::committed_thru(uint64_t seq)
{
Mutex::Locker locker(write_lock);
while (!journalq.empty() && journalq.front().first <= seq) {
journalq.pop_front();
}
+
+ int64_t old_start = header.start;
if (!journalq.empty()) {
header.start = journalq.front().second;
header.start_seq = journalq.front().first;
header.start = write_pos;
header.start_seq = seq + 1;
}
+
+ if (discard) {
+ dout(10) << __func__ << " will trim (" << old_start << ", " << header.start << ")" << dendl;
+ if (old_start < header.start)
+ do_discard(old_start, header.start - 1);
+ else {
+ do_discard(old_start, header.max_size - 1);
+ do_discard(get_top(), header.start - 1);
+ }
+ }
+
must_write_header = true;
print_header();
bool directio, aio, force_aio;
bool must_write_header;
off64_t write_pos; // byte where the next entry to be written will go
- off64_t read_pos; //
+ off64_t read_pos; //
+ bool discard; //for block journal whether support discard
#ifdef HAVE_LIBAIO
/// state associated with an in-flight aio request
off64_t *out_pos ///< [out] next position to read, will be wrapped
);
+ void do_discard(int64_t offset, int64_t end);
+
class Writer : public Thread {
FileJournal *journal;
public:
directio(dio), aio(ai), force_aio(faio),
must_write_header(false),
write_pos(0), read_pos(0),
+ discard(false),
#ifdef HAVE_LIBAIO
aio_lock("FileJournal::aio_lock"),
aio_ctx(0),