diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp index 0ff8ed5..db3e1ae 100644 --- a/src/freebsd/btop_collect.cpp +++ b/src/freebsd/btop_collect.cpp @@ -16,6 +16,9 @@ indent = tab tab-size = 4 */ #include +#include +#include +#include #include #include #include @@ -25,6 +28,7 @@ tab-size = 4 #include #include #include +#include #include #include #include @@ -41,12 +45,8 @@ tab-size = 4 #include #include #include -#include -#include -#include -#include -#include +#include #include #include #include @@ -55,6 +55,10 @@ tab-size = 4 #include #include +#include +#include +#include + using std::clamp, std::string_literals::operator""s, std::cmp_equal, std::cmp_less, std::cmp_greater; using std::ifstream, std::numeric_limits, std::streamsize, std::round, std::max, std::min; namespace fs = std::filesystem; @@ -468,25 +472,68 @@ namespace Mem { return Shared::totalMem; } + class dataset { + public: + uint64_t nread; + uint64_t nwritten; + string name; + }; + void collect_disk(unordered_flat_map &disks, unordered_flat_map &mapping) { - static struct statinfo cur, last; - long double etime = 0; - u_int64_t total_bytes_read; - u_int64_t total_bytes_write; - - static std::unique_ptr curDevInfo (reinterpret_cast(std::calloc(1, sizeof(struct devinfo))), std::free); - static std::unique_ptr lastDevInfo (reinterpret_cast(std::calloc(1, sizeof(struct devinfo))), std::free); - cur.dinfo = curDevInfo.get(); - last.dinfo = lastDevInfo.get(); - - if (devstat_getdevs(NULL, &cur) != -1) { - for (int i = 0; i < cur.dinfo->numdevs; i++) { - auto d = cur.dinfo->devices[i]; - devstat_compute_statistics(&d, NULL, etime, DSM_TOTAL_BYTES_READ, &total_bytes_read, DSM_TOTAL_BYTES_WRITE, &total_bytes_write, DSM_NONE); - Logger::debug("dev " + string(d.device_name) + std::to_string(d.unit_number) + " read=" + std::to_string(total_bytes_read) + " write=" + std::to_string(total_bytes_write)); + FILE *f = popen("sysctl kstat.zfs.zroot.dataset", "r"); + unordered_flat_map datasets; + if (f) { + size_t len = 512; + char buf[len]; + while (not std::feof(f)) { + uint64_t nread, nwritten; + string datasetname; + if (fgets(buf, len, f)) { + char *name = std::strtok(buf, ": \n"); + char *value = std::strtok(NULL, ": \n"); + if (string(name).find("dataset_name") != string::npos) { + datasetname = string(value); + dataset d{nread, nwritten, datasetname}; + datasets[datasetname] = d; + Logger::debug("created " + d.name + "(" + std::to_string(d.nread) + "," + std::to_string(d.nwritten) + ")"); + } else if (string(name).find("nread") != string::npos) { + nread = atoll(value); + } else if (string(name).find("nwritten") != string::npos) { + nwritten = atoll(value); + } + } } - Logger::debug(""); + std::fclose(f); } + + for (auto &[mountpoint, disk] : disks) { + if (datasets.contains(disk.dev)) { + Logger::debug("checking dev " + string(disk.dev)); + int64_t readBytes = datasets[disk.dev].nread; + if (disk.io_read.empty()) + disk.io_read.push_back(0); + else + disk.io_read.push_back(max((int64_t)0, (readBytes - disk.old_io.at(0)))); + disk.old_io.at(0) = readBytes; + while (cmp_greater(disk.io_read.size(), width * 2)) disk.io_read.pop_front(); + + int64_t writeBytes = datasets[disk.dev].nwritten; + if (disk.io_write.empty()) + disk.io_write.push_back(0); + else + disk.io_write.push_back(max((int64_t)0, (writeBytes - disk.old_io.at(1)))); + disk.old_io.at(1) = writeBytes; + while (cmp_greater(disk.io_write.size(), width * 2)) disk.io_write.pop_front(); + + // no io times + if (disk.io_activity.empty()) + disk.io_activity.push_back(0); + else + disk.io_activity.push_back(clamp((long)round((double)(disk.io_write.back() + disk.io_read.back()) / (1 << 20)), 0l, 100l)); + while (cmp_greater(disk.io_activity.size(), width * 2)) disk.io_activity.pop_front(); + } + } + } auto collect(const bool no_update) -> mem_info & { @@ -565,15 +612,17 @@ namespace Mem { vector found; found.reserve(last_found.size()); for (int i = 0; i < count; i++) { + auto fstype = string(stfs[i].f_fstypename); + if (fstype == "autofs" || fstype == "devfs" || fstype == "linprocfs" || fstype == "procfs" || fstype == "tmpfs" || fstype == "linsysfs") { + // in memory filesystems -> not useful to show + continue; + } + std::error_code ec; string mountpoint = stfs[i].f_mntonname; string dev = stfs[i].f_mntfromname; mapping[dev] = mountpoint; - if (string(stfs[i].f_fstypename) == "autofs") { - continue; - } - //? Match filter if not empty if (not filter.empty()) { bool match = v_contains(filter, mountpoint);