From: Greg Farnum Date: Thu, 26 Feb 2015 23:12:47 +0000 (-0800) Subject: Client: support using dentry invalidation callbacks on older kernels X-Git-Tag: v0.93~1^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=694529ae7d0407c5d2f19d8fce8d1a5567bd8042;p=ceph.git Client: support using dentry invalidation callbacks on older kernels This brings back a few small code chunks that were removed in 0827bb79ea5127e6763f6e904dfa1a3266046ffb. We check the kernel version, and if it is less than 3.18 we use these dentry invalidation callbacks instead of the remount callback. This should resolve a number of issues with racing against remount, including #10916, and lets older unprivileged users on older kernels run even if they can't apply options on mount (#10542). Signed-off-by: Greg Farnum --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 837b90cfe6de..4548ca9f1a83 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -164,6 +164,7 @@ Client::Client(Messenger *m, MonClient *mc) ino_invalidate_cb(NULL), dentry_invalidate_cb(NULL), getgroups_cb(NULL), + can_invalidate_dentries(false), require_remount(false), async_ino_invalidator(m->cct), async_dentry_invalidator(m->cct), @@ -3459,10 +3460,18 @@ public: void Client::_invalidate_kernel_dcache() { - // Hacky: - // when remounting a file system, linux kernel trims all unused dentries in the file system - if (remount_cb) + if (can_invalidate_dentries && dentry_invalidate_cb && root->dir) { + for (ceph::unordered_map::iterator p = root->dir->dentries.begin(); + p != root->dir->dentries.end(); + ++p) { + if (p->second->inode) + _schedule_invalidate_dentry_callback(p->second, false); + } + } else if (remount_cb) { + // Hacky: + // when remounting a file system, linux kernel trims all unused dentries in the fs remount_finisher.queue(new C_Client_Remount(this)); + } } void Client::trim_caps(MetaSession *s, int max) @@ -3494,6 +3503,13 @@ void Client::trim_caps(MetaSession *s, int max) while (q != in->dn_set.end()) { Dentry *dn = *q++; if (dn->lru_is_expireable()) { + if (can_invalidate_dentries && + dn->dir->parent_inode->ino == MDS_INO_ROOT) { + // Only issue one of these per DN for inodes in root: handle + // others more efficiently by calling for root-child DNs at + // the end of this function. + _schedule_invalidate_dentry_callback(dn, true); + } trim_dentry(dn); } else { ldout(cct, 20) << " not expirable: " << dn->name << dendl; @@ -7995,11 +8011,17 @@ void Client::ll_register_callbacks(struct client_callback_args *args) getgroups_cb = args->getgroups_cb; } -int Client::test_remount() +int Client::test_dentry_handling(bool can_invalidate) { int r = 0; - if (remount_cb) { + can_invalidate_dentries = can_invalidate; + + if (can_invalidate_dentries) { + assert(dentry_invalidate_cb); + ldout(cct, 1) << "using dentry_invalidate_cb" << dendl; + } else if (remount_cb) { + ldout(cct, 1) << "using remount_cb" << dendl; int s = remount_cb(callback_handle); if (s) { lderr(cct) << "Failed to invoke remount, needed to ensure kernel dcache consistency" @@ -8009,6 +8031,10 @@ int Client::test_remount() require_remount = true; r = s; } + } else { + lderr(cct) << "no method to invalidate kernel dentry cache; expect issues!" << dendl; + if (cct->_conf->client_die_on_failed_remount) + assert(0); } return r; } diff --git a/src/client/Client.h b/src/client/Client.h index 121d178df80c..fda445798920 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -242,6 +242,7 @@ class Client : public Dispatcher { client_ino_callback_t ino_invalidate_cb; client_dentry_callback_t dentry_invalidate_cb; client_getgroups_callback_t getgroups_cb; + bool can_invalidate_dentries; bool require_remount; Finisher async_ino_invalidator; @@ -955,7 +956,7 @@ public: int ll_osdaddr(int osd, char* buf, size_t size); void ll_register_callbacks(struct client_callback_args *args); - int test_remount(); + int test_dentry_handling(bool can_invalidate); }; #endif diff --git a/src/common/config_opts.h b/src/common/config_opts.h index 38416ae1691e..d9380ed06b41 100644 --- a/src/common/config_opts.h +++ b/src/common/config_opts.h @@ -326,6 +326,7 @@ OPTION(fuse_big_writes, OPT_BOOL, true) OPTION(fuse_atomic_o_trunc, OPT_BOOL, true) OPTION(fuse_debug, OPT_BOOL, false) OPTION(fuse_multithreaded, OPT_BOOL, true) +OPTION(client_try_dentry_invalidate, OPT_BOOL, true) // the client should try to use dentry invaldation instead of remounting, on kernels it believes that will work for OPTION(client_die_on_failed_remount, OPT_BOOL, true) OPTION(crush_location, OPT_STR, "") // whitespace-separated list of key=value pairs describing crush location