diff options
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/inode.c | 38 | ||||
-rw-r--r-- | fs/ceph/super.c | 4 | ||||
-rw-r--r-- | fs/ceph/super.h | 10 |
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); } |