diff options
author | Eric Wong <normalperson@yhbt.net> | 2013-06-25 19:46:02 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2013-06-25 19:46:02 +0000 |
commit | 0ad0f16bce2769a599eb718261e0283e79c57639 (patch) | |
tree | 320edb81f1278eac4a774a598b9c9584e0bfba3a | |
parent | 86e5d10649f14fe3b3c8af37fd8ec04cc337fc9e (diff) | |
download | cmogstored-0ad0f16bce2769a599eb718261e0283e79c57639.tar.gz |
st_rdev matching is necessary for cases where the block devices are aliased (not via symlinks), and mountlist returns a different name for the device than what iostat uses. This is the case for my cryptmount(8) setup, where /dev/mapper/FOO and /dev/dm-N refer to the same device (with matching st_dev and st_rdev numbers), but neither is a symlink to the other (nor are they hardlinks). stat() on block devices in /dev should always be fast and non-blocking, as /dev is expected to be non-networked on any reasonable system (at least those serving as a MogileFS storage node).
-rw-r--r-- | mnt.c | 24 |
1 files changed, 24 insertions, 0 deletions
@@ -285,9 +285,12 @@ void mog_mnt_release(const struct mount_entry *me) CHECK(int, 0, pthread_mutex_unlock(&by_dev_lock) ); } +#define MOG_DEV_T_INVAL ((dev_t)-1) + struct mnt_update { const char *prefix; size_t prefixlen; + dev_t st_rdev; char util[MOG_IOUTIL_LEN]; }; @@ -297,6 +300,10 @@ struct mnt_update { */ static bool me_update_match(struct mount_entry *me, struct mnt_update *update) { + if (update->st_rdev != MOG_DEV_T_INVAL + && me->me_dev == update->st_rdev) + return true; + if (strlen(me->me_devname) < update->prefixlen) return false; return memcmp(update->prefix, me->me_devname, update->prefixlen) == 0; @@ -334,10 +341,27 @@ static bool update_util_each(void *ent, void *upd) void mog_mnt_update_util(struct mog_iostat *iostat) { struct mnt_update update; + struct stat st; const char *devsuffix = iostat->dev; update.prefix = xasprintf("/dev/%s", devsuffix); update.prefixlen = strlen(update.prefix); + + /* + * st_rdev matching is necessary for cryptmount(8) on Linux, where + * /dev/mapper/FOO is NOT a symlink to /dev/dm-N, but /dev/dm-N + * and /dev/mapper/FOO both refer to the same device (where + * /dev/mapper/FOO is the mounted device name, mountlist never + * sees /dev/dm-N). + * + * FIXME: parse /proc/partitions under Linux like mogstored does + * may avoid this stat. + */ + if (stat(update.prefix, &st) == 0 && S_ISBLK(st.st_mode)) + update.st_rdev = st.st_rdev; + else + update.st_rdev = MOG_DEV_T_INVAL; + assert(sizeof(update.util) == sizeof(iostat->util)); memcpy(&update.util, iostat->util, sizeof(update.util)); |