summaryrefslogtreecommitdiff
path: root/fs/ceph
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/inode.c38
-rw-r--r--fs/ceph/super.c4
-rw-r--r--fs/ceph/super.h10
3 files changed, 44 insertions, 8 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index d163fa96cb40..823084fff98c 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -14,6 +14,7 @@
#include <linux/random.h>
#include <linux/sort.h>
#include <linux/iversion.h>
+#include <linux/jhash.h>
#include "super.h"
#include "mds_client.h"
@@ -36,14 +37,44 @@ static const struct inode_operations ceph_symlink_iops;
static void ceph_inode_work(struct work_struct *work);
+static u32 ceph_inode_key_hash_fn(const void *data, u32 len, u32 seed)
+{
+ const struct ceph_vino *pvino = data;
+
+ return jhash(pvino, sizeof(*pvino), seed);
+}
+
+static u32 ceph_inode_obj_hash_fn(const void *obj, u32 len, u32 seed)
+{
+ const struct ceph_inode_info *ci = ceph_inode(obj);
+
+ return jhash(&ci->i_vino, sizeof(ci->i_vino), seed);
+}
+
+static int ceph_inode_hash_cmp_fn(struct rhashtable_compare_arg *arg,
+ const void *obj)
+{
+ if (ceph_ino_compare(obj, arg->key))
+ return 0;
+ return 1;
+}
+
+const struct rhashtable_params ceph_inode_table_params = {
+ .head_offset = offsetof(struct inode, i_hash),
+ .hashfn = ceph_inode_key_hash_fn,
+ .obj_hashfn = ceph_inode_obj_hash_fn,
+ .obj_cmpfn = ceph_inode_hash_cmp_fn,
+};
+
/*
* find or create an inode, given the ceph ino number
*/
-static int ceph_set_ino_cb(struct inode *inode, void *data)
+static int ceph_set_ino_cb(struct inode *inode, const void *data)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ const struct ceph_vino *pvino = data;
- ci->i_vino = *(struct ceph_vino *)data;
+ ci->i_vino = *pvino;
inode->i_ino = ceph_vino_to_ino_t(ci->i_vino);
inode_set_iversion_raw(inode, 0);
return 0;
@@ -53,8 +84,7 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
{
struct inode *inode;
- inode = iget5_locked(sb, (unsigned long)vino.ino, ceph_ino_compare,
- ceph_set_ino_cb, &vino);
+ inode = iget5_locked(sb, ceph_set_ino_cb, &vino);
if (!inode)
return ERR_PTR(-ENOMEM);
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 7ec0e6d03d10..5cca520134fa 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -1086,6 +1086,10 @@ static int ceph_get_tree(struct fs_context *fc)
dout("get_sb got existing client %p\n", fsc);
} else {
dout("get_sb using new client %p\n", fsc);
+ err = super_setup_inode_table(sb, &ceph_inode_table_params);
+ if (err < 0)
+ goto out_splat;
+
err = ceph_setup_bdi(sb, fsc);
if (err < 0)
goto out_splat;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index a3995ebe0623..0acd007e734f 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -482,6 +482,8 @@ static inline ino_t ceph_vino_to_ino_t(struct ceph_vino vino)
/* for printf-style formatting */
#define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap
+extern const struct rhashtable_params ceph_inode_table_params;
+
static inline u64 ceph_ino(struct inode *inode)
{
return ceph_inode(inode)->i_vino.ino;
@@ -514,15 +516,15 @@ static inline u64 ceph_present_inode(struct inode *inode)
return ceph_present_ino(inode->i_sb, ceph_ino(inode));
}
-static inline int ceph_ino_compare(struct inode *inode, void *data)
+static inline int ceph_ino_compare(const struct inode *inode,
+ const struct ceph_vino *pvino)
{
- struct ceph_vino *pvino = (struct ceph_vino *)data;
struct ceph_inode_info *ci = ceph_inode(inode);
+
return ci->i_vino.ino == pvino->ino &&
ci->i_vino.snap == pvino->snap;
}
-
static inline struct inode *ceph_find_inode(struct super_block *sb,
struct ceph_vino vino)
{
@@ -531,7 +533,7 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
* anyway, so there is no need to squash the inode number down to
* 32-bits first. Just use low-order bits on arches with 32-bit long.
*/
- return ilookup5(sb, (unsigned long)vino.ino, ceph_ino_compare, &vino);
+ return ilookup5(sb, &vino);
}