summaryrefslogtreecommitdiff
path: root/fs/9p/vfs_inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r--fs/9p/vfs_inode.c99
1 files changed, 51 insertions, 48 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index ae0c38ad1fcb..4e9094d77139 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -14,6 +14,7 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/file.h>
+#include <linux/jhash.h>
#include <linux/pagemap.h>
#include <linux/stat.h>
#include <linux/string.h>
@@ -81,7 +82,7 @@ static u32 unixmode2p9mode(struct v9fs_session_info *v9ses, umode_t mode)
*
*/
static int p9mode2perm(struct v9fs_session_info *v9ses,
- struct p9_wstat *stat)
+ const struct p9_wstat *stat)
{
int res;
int mode = stat->mode;
@@ -108,7 +109,7 @@ static int p9mode2perm(struct v9fs_session_info *v9ses,
*
*/
static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses,
- struct p9_wstat *stat, dev_t *rdev)
+ const struct p9_wstat *stat, dev_t *rdev)
{
int res;
u32 mode = stat->mode;
@@ -216,6 +217,48 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
wstat->extension = NULL;
}
+static u32 v9fs_inode_key_hash_fn(const void *data, u32 len, u32 seed)
+{
+ const struct p9_qid *qid = data;
+ u64 hashv = qid->type ^ qid->version ^ qid->path;
+
+ return jhash(&hashv, sizeof(hashv), seed);
+}
+
+static u32 v9fs_inode_obj_hash_fn(const void *obj, u32 len, u32 seed)
+{
+ const struct p9_qid *qid = &V9FS_I(obj)->qid;
+ u64 hashv = qid->type ^ qid->version ^ qid->path;
+
+ return jhash(&hashv, sizeof(hashv), seed);
+}
+
+static int v9fs_inode_hash_cmp_fn(struct rhashtable_compare_arg *arg,
+ const void *obj)
+{
+ const struct inode *inode = obj;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ struct v9fs_inode *v9inode = V9FS_I(inode);
+ const struct p9_wstat *st = arg->key;
+ dev_t rdev;
+ int umode = p9mode2unixmode(v9ses, st, &rdev);
+
+ /* compare qid details */
+ if ((inode->i_mode & S_IFMT) == (umode & S_IFMT) &&
+ v9inode->qid.type == st->qid.type &&
+ v9inode->qid.version == st->qid.version &&
+ v9inode->qid.path == st->qid.path)
+ return 0;
+ return 1;
+}
+
+const struct rhashtable_params v9fs_inode_table_params = {
+ .head_offset = offsetof(struct inode, i_hash),
+ .hashfn = v9fs_inode_key_hash_fn,
+ .obj_hashfn = v9fs_inode_obj_hash_fn,
+ .obj_cmpfn = v9fs_inode_hash_cmp_fn,
+};
+
/**
* v9fs_alloc_inode - helper function to allocate an inode
*
@@ -388,66 +431,26 @@ void v9fs_evict_inode(struct inode *inode)
}
}
-static int v9fs_test_inode(struct inode *inode, void *data)
+static int v9fs_set_inode(struct inode *inode, const void *data)
{
- int umode;
- dev_t rdev;
struct v9fs_inode *v9inode = V9FS_I(inode);
- struct p9_wstat *st = (struct p9_wstat *)data;
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ const struct p9_qid *qid = data;
- umode = p9mode2unixmode(v9ses, st, &rdev);
- /* don't match inode of different type */
- if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
- return 0;
-
- /* compare qid details */
- if (memcmp(&v9inode->qid.version,
- &st->qid.version, sizeof(v9inode->qid.version)))
- return 0;
-
- if (v9inode->qid.type != st->qid.type)
- return 0;
-
- if (v9inode->qid.path != st->qid.path)
- return 0;
- return 1;
-}
-
-static int v9fs_test_new_inode(struct inode *inode, void *data)
-{
- return 0;
-}
-
-static int v9fs_set_inode(struct inode *inode, void *data)
-{
- struct v9fs_inode *v9inode = V9FS_I(inode);
- struct p9_wstat *st = (struct p9_wstat *)data;
-
- memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
+ v9inode->qid = *qid;
return 0;
}
static struct inode *v9fs_qid_iget(struct super_block *sb,
- struct p9_qid *qid,
struct p9_wstat *st,
int new)
{
dev_t rdev;
int retval;
umode_t umode;
- unsigned long i_ino;
struct inode *inode;
struct v9fs_session_info *v9ses = sb->s_fs_info;
- int (*test)(struct inode *, void *);
-
- if (new)
- test = v9fs_test_new_inode;
- else
- test = v9fs_test_inode;
- i_ino = v9fs_qid2ino(qid);
- inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st);
+ inode = iget5_locked(sb, v9fs_set_inode, &st->qid);
if (!inode)
return ERR_PTR(-ENOMEM);
if (!(inode->i_state & I_NEW))
@@ -457,7 +460,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
* FIXME!! we may need support for stale inodes
* later.
*/
- inode->i_ino = i_ino;
+ inode->i_ino = v9fs_qid2ino(&st->qid);
umode = p9mode2unixmode(v9ses, st, &rdev);
retval = v9fs_init_inode(v9ses, inode, umode, rdev);
if (retval)
@@ -484,7 +487,7 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
if (IS_ERR(st))
return ERR_CAST(st);
- inode = v9fs_qid_iget(sb, &st->qid, st, new);
+ inode = v9fs_qid_iget(sb, st, new);
p9stat_free(st);
kfree(st);
return inode;