From e068391c87de10f0fc75710c7059988d73554769 Mon Sep 17 00:00:00 2001 From: YuQing <384681@qq.com> Date: Wed, 2 Jun 2021 11:07:28 +0800 Subject: [PATCH] add function get_path_block_size and get_device_block_size --- HISTORY | 3 +- src/system_info.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++ src/system_info.h | 5 ++ 3 files changed, 129 insertions(+), 1 deletion(-) diff --git a/HISTORY b/HISTORY index 643a404..36d1750 100644 --- a/HISTORY +++ b/HISTORY @@ -1,7 +1,8 @@ -Version 1.52 2021-06-01 +Version 1.52 2021-06-02 * process_stop more gracefully (kill -9 on timeout) * add function fc_queue_pop_to_queue_ex + * add function get_path_block_size and get_device_block_size Version 1.51 2021-05-27 * fast_mblock.[hc]: support batch alloc and batch free diff --git a/src/system_info.c b/src/system_info.c index d77b493..9be2b03 100644 --- a/src/system_info.c +++ b/src/system_info.c @@ -36,6 +36,7 @@ #ifdef OS_LINUX #include #include +#include #else #ifdef OS_FREEBSD #include @@ -835,3 +836,124 @@ int get_kernel_version(Version *version) version->patch = numbers[1]; return 0; } + +#ifdef OS_LINUX +int get_device_block_size(const char *device, int *block_size) +{ + int result; + int fd; + size_t bs; + + if ((fd=open(device, O_RDONLY)) < 0) { + result = errno != 0 ? errno : ENOENT; + logError("file: "__FILE__", line: %d, " + "open device %s fail, errno: %d, error info: %s", + __LINE__, device, result, strerror(result)); + return result; + } + + if (ioctl(fd, BLKSSZGET, &bs) == 0) { + *block_size = bs; + result = 0; + } else { + result = errno != 0 ? errno : EPERM; + logError("file: "__FILE__", line: %d, " + "ioctl device %s fail, errno: %d, error info: %s", + __LINE__, device, result, strerror(result)); + } + + close(fd); + return result; +} + +static int get_block_size_by_write(const char *path, int *block_size) +{ +#define MAX_BLK_SIZE (128 * 1024) + char tmp_filename[PATH_MAX]; + char *buff; + int result; + int fd; + + if ((result=posix_memalign((void **)&buff, + MAX_BLK_SIZE, MAX_BLK_SIZE)) != 0) + { + logError("file: "__FILE__", line: %d, " + "posix_memalign %d bytes fail, " + "errno: %d, error info: %s", __LINE__, + MAX_BLK_SIZE, result, STRERROR(result)); + return result; + } + + snprintf(tmp_filename, sizeof(tmp_filename), + "%s/.blksize-test.tmp", path); + if ((fd=open(tmp_filename, O_WRONLY | O_CREAT | O_DIRECT)) < 0) { + result = errno != 0 ? errno : ENOENT; + logError("file: "__FILE__", line: %d, " + "open file %s fail, errno: %d, error info: %s", + __LINE__, tmp_filename, result, strerror(result)); + free(buff); + return result; + } + + result = EINVAL; + *block_size = 512; + while (*block_size <= MAX_BLK_SIZE) { + if (write(fd, buff, *block_size) == *block_size) { + result = 0; + break; + } + result = errno != 0 ? errno : EINTR; + if (result == EINTR) { + continue; + } + + if (result != EINVAL) { + logError("file: "__FILE__", line: %d, " + "write to file %s fail, errno: %d, error info: %s", + __LINE__, tmp_filename, result, strerror(result)); + break; + } + + *block_size *= 2; + } + + free(buff); + close(fd); + unlink(tmp_filename); + return result; +} + +int get_path_block_size(const char *path, int *block_size) +{ + char dev_path[64]; + struct stat statbuf; + int result; + + if (stat(path, &statbuf) != 0) { + result = errno != 0 ? errno : EPERM; + logError("file: "__FILE__", line: %d, " + "stat %s fail, errno: %d, error info: %s", + __LINE__, path, result, strerror(result)); + return result; + } + + if (S_ISBLK(statbuf.st_mode)) { + return get_device_block_size(path, block_size); + } + if (!S_ISDIR(statbuf.st_mode)) { + logError("file: "__FILE__", line: %d, " + "%s is NOT a directory!", __LINE__, path); + return ENOTDIR; + } + + sprintf(dev_path, "/dev/block/%d:%d", (int)major(statbuf.st_dev), + (int)minor(statbuf.st_dev)); + if (access(dev_path, R_OK) == 0) { + if ((result=get_device_block_size(dev_path, block_size)) == 0) { + return 0; + } + } + + return get_block_size_by_write(path, block_size); +} +#endif diff --git a/src/system_info.h b/src/system_info.h index df60e0c..8aa73ce 100644 --- a/src/system_info.h +++ b/src/system_info.h @@ -164,6 +164,11 @@ int get_sysinfo(struct fast_sysinfo *info); int get_kernel_version(Version *version); +#ifdef OS_LINUX +int get_device_block_size(const char *device, int *block_size); +int get_path_block_size(const char *path, int *block_size); +#endif + #endif #ifdef __cplusplus