diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2011-07-11 12:40:59 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2011-07-23 10:32:48 -0400 |
commit | fd2421f54423f307ecd31bdebdca6bc317e0c492 (patch) | |
tree | 6e681349c6111a6bca9a562090bdedfd5b2ed29c /fs/9p | |
parent | 5034990e28efb2d232ee82443a9edd62defd17ba (diff) |
fs/9p: When doing inode lookup compare qid details and inode mode bits.
This make sure we don't use wrong inode from the inode hash. The inode number
of the file deleted is reused by the next file system object created
and if we only use inode number for inode hash lookup we could end up
with wrong struct inode.
Also compare inode generation number. Not all Linux file system provide
st_gen in userspace. So it could be 0;
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'fs/9p')
-rw-r--r-- | fs/9p/cache.c | 20 | ||||
-rw-r--r-- | fs/9p/cache.h | 9 | ||||
-rw-r--r-- | fs/9p/v9fs.c | 2 | ||||
-rw-r--r-- | fs/9p/v9fs.h | 2 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 36 | ||||
-rw-r--r-- | fs/9p/vfs_inode_dotl.c | 41 |
6 files changed, 81 insertions, 29 deletions
diff --git a/fs/9p/cache.c b/fs/9p/cache.c index 5b335c5086a1..945aa5f02f9b 100644 --- a/fs/9p/cache.c +++ b/fs/9p/cache.c | |||
@@ -108,11 +108,10 @@ static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data, | |||
108 | void *buffer, uint16_t bufmax) | 108 | void *buffer, uint16_t bufmax) |
109 | { | 109 | { |
110 | const struct v9fs_inode *v9inode = cookie_netfs_data; | 110 | const struct v9fs_inode *v9inode = cookie_netfs_data; |
111 | memcpy(buffer, &v9inode->fscache_key->path, | 111 | memcpy(buffer, &v9inode->qid.path, sizeof(v9inode->qid.path)); |
112 | sizeof(v9inode->fscache_key->path)); | ||
113 | P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &v9inode->vfs_inode, | 112 | P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &v9inode->vfs_inode, |
114 | v9inode->fscache_key->path); | 113 | v9inode->qid.path); |
115 | return sizeof(v9inode->fscache_key->path); | 114 | return sizeof(v9inode->qid.path); |
116 | } | 115 | } |
117 | 116 | ||
118 | static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, | 117 | static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, |
@@ -129,11 +128,10 @@ static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data, | |||
129 | void *buffer, uint16_t buflen) | 128 | void *buffer, uint16_t buflen) |
130 | { | 129 | { |
131 | const struct v9fs_inode *v9inode = cookie_netfs_data; | 130 | const struct v9fs_inode *v9inode = cookie_netfs_data; |
132 | memcpy(buffer, &v9inode->fscache_key->version, | 131 | memcpy(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version)); |
133 | sizeof(v9inode->fscache_key->version)); | ||
134 | P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &v9inode->vfs_inode, | 132 | P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &v9inode->vfs_inode, |
135 | v9inode->fscache_key->version); | 133 | v9inode->qid.version); |
136 | return sizeof(v9inode->fscache_key->version); | 134 | return sizeof(v9inode->qid.version); |
137 | } | 135 | } |
138 | 136 | ||
139 | static enum | 137 | static enum |
@@ -143,11 +141,11 @@ fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data, | |||
143 | { | 141 | { |
144 | const struct v9fs_inode *v9inode = cookie_netfs_data; | 142 | const struct v9fs_inode *v9inode = cookie_netfs_data; |
145 | 143 | ||
146 | if (buflen != sizeof(v9inode->fscache_key->version)) | 144 | if (buflen != sizeof(v9inode->qid.version)) |
147 | return FSCACHE_CHECKAUX_OBSOLETE; | 145 | return FSCACHE_CHECKAUX_OBSOLETE; |
148 | 146 | ||
149 | if (memcmp(buffer, &v9inode->fscache_key->version, | 147 | if (memcmp(buffer, &v9inode->qid.version, |
150 | sizeof(v9inode->fscache_key->version))) | 148 | sizeof(v9inode->qid.version))) |
151 | return FSCACHE_CHECKAUX_OBSOLETE; | 149 | return FSCACHE_CHECKAUX_OBSOLETE; |
152 | 150 | ||
153 | return FSCACHE_CHECKAUX_OKAY; | 151 | return FSCACHE_CHECKAUX_OKAY; |
diff --git a/fs/9p/cache.h b/fs/9p/cache.h index 049507a5b01c..40cc54ced5d9 100644 --- a/fs/9p/cache.h +++ b/fs/9p/cache.h | |||
@@ -93,15 +93,6 @@ static inline void v9fs_uncache_page(struct inode *inode, struct page *page) | |||
93 | BUG_ON(PageFsCache(page)); | 93 | BUG_ON(PageFsCache(page)); |
94 | } | 94 | } |
95 | 95 | ||
96 | static inline void v9fs_fscache_set_key(struct inode *inode, | ||
97 | struct p9_qid *qid) | ||
98 | { | ||
99 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
100 | spin_lock(&v9inode->fscache_lock); | ||
101 | v9inode->fscache_key = qid; | ||
102 | spin_unlock(&v9inode->fscache_lock); | ||
103 | } | ||
104 | |||
105 | static inline void v9fs_fscache_wait_on_page_write(struct inode *inode, | 96 | static inline void v9fs_fscache_wait_on_page_write(struct inode *inode, |
106 | struct page *page) | 97 | struct page *page) |
107 | { | 98 | { |
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index c82b017f51f3..8b7c6be2450b 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -487,8 +487,8 @@ static void v9fs_inode_init_once(void *foo) | |||
487 | struct v9fs_inode *v9inode = (struct v9fs_inode *)foo; | 487 | struct v9fs_inode *v9inode = (struct v9fs_inode *)foo; |
488 | #ifdef CONFIG_9P_FSCACHE | 488 | #ifdef CONFIG_9P_FSCACHE |
489 | v9inode->fscache = NULL; | 489 | v9inode->fscache = NULL; |
490 | v9inode->fscache_key = NULL; | ||
491 | #endif | 490 | #endif |
491 | memset(&v9inode->qid, 0, sizeof(v9inode->qid)); | ||
492 | inode_init_once(&v9inode->vfs_inode); | 492 | inode_init_once(&v9inode->vfs_inode); |
493 | } | 493 | } |
494 | 494 | ||
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index e5ebedfc5ed8..5d7392ead24b 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h | |||
@@ -125,8 +125,8 @@ struct v9fs_inode { | |||
125 | #ifdef CONFIG_9P_FSCACHE | 125 | #ifdef CONFIG_9P_FSCACHE |
126 | spinlock_t fscache_lock; | 126 | spinlock_t fscache_lock; |
127 | struct fscache_cookie *fscache; | 127 | struct fscache_cookie *fscache; |
128 | struct p9_qid *fscache_key; | ||
129 | #endif | 128 | #endif |
129 | struct p9_qid qid; | ||
130 | unsigned int cache_validity; | 130 | unsigned int cache_validity; |
131 | struct p9_fid *writeback_fid; | 131 | struct p9_fid *writeback_fid; |
132 | struct mutex v_mutex; | 132 | struct mutex v_mutex; |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index a5a95372cd68..3d8a18ee78e6 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -216,7 +216,6 @@ struct inode *v9fs_alloc_inode(struct super_block *sb) | |||
216 | return NULL; | 216 | return NULL; |
217 | #ifdef CONFIG_9P_FSCACHE | 217 | #ifdef CONFIG_9P_FSCACHE |
218 | v9inode->fscache = NULL; | 218 | v9inode->fscache = NULL; |
219 | v9inode->fscache_key = NULL; | ||
220 | spin_lock_init(&v9inode->fscache_lock); | 219 | spin_lock_init(&v9inode->fscache_lock); |
221 | #endif | 220 | #endif |
222 | v9inode->writeback_fid = NULL; | 221 | v9inode->writeback_fid = NULL; |
@@ -433,6 +432,37 @@ void v9fs_evict_inode(struct inode *inode) | |||
433 | } | 432 | } |
434 | } | 433 | } |
435 | 434 | ||
435 | static int v9fs_test_inode(struct inode *inode, void *data) | ||
436 | { | ||
437 | int umode; | ||
438 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
439 | struct p9_wstat *st = (struct p9_wstat *)data; | ||
440 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | ||
441 | |||
442 | umode = p9mode2unixmode(v9ses, st->mode); | ||
443 | /* don't match inode of different type */ | ||
444 | if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) | ||
445 | return 0; | ||
446 | |||
447 | /* compare qid details */ | ||
448 | if (memcmp(&v9inode->qid.version, | ||
449 | &st->qid.version, sizeof(v9inode->qid.version))) | ||
450 | return 0; | ||
451 | |||
452 | if (v9inode->qid.type != st->qid.type) | ||
453 | return 0; | ||
454 | return 1; | ||
455 | } | ||
456 | |||
457 | static int v9fs_set_inode(struct inode *inode, void *data) | ||
458 | { | ||
459 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
460 | struct p9_wstat *st = (struct p9_wstat *)data; | ||
461 | |||
462 | memcpy(&v9inode->qid, &st->qid, sizeof(st->qid)); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
436 | static struct inode *v9fs_qid_iget(struct super_block *sb, | 466 | static struct inode *v9fs_qid_iget(struct super_block *sb, |
437 | struct p9_qid *qid, | 467 | struct p9_qid *qid, |
438 | struct p9_wstat *st) | 468 | struct p9_wstat *st) |
@@ -443,7 +473,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, | |||
443 | struct v9fs_session_info *v9ses = sb->s_fs_info; | 473 | struct v9fs_session_info *v9ses = sb->s_fs_info; |
444 | 474 | ||
445 | i_ino = v9fs_qid2ino(qid); | 475 | i_ino = v9fs_qid2ino(qid); |
446 | inode = iget_locked(sb, i_ino); | 476 | inode = iget5_locked(sb, i_ino, v9fs_test_inode, v9fs_set_inode, st); |
447 | if (!inode) | 477 | if (!inode) |
448 | return ERR_PTR(-ENOMEM); | 478 | return ERR_PTR(-ENOMEM); |
449 | if (!(inode->i_state & I_NEW)) | 479 | if (!(inode->i_state & I_NEW)) |
@@ -453,6 +483,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, | |||
453 | * FIXME!! we may need support for stale inodes | 483 | * FIXME!! we may need support for stale inodes |
454 | * later. | 484 | * later. |
455 | */ | 485 | */ |
486 | inode->i_ino = i_ino; | ||
456 | umode = p9mode2unixmode(v9ses, st->mode); | 487 | umode = p9mode2unixmode(v9ses, st->mode); |
457 | retval = v9fs_init_inode(v9ses, inode, umode); | 488 | retval = v9fs_init_inode(v9ses, inode, umode); |
458 | if (retval) | 489 | if (retval) |
@@ -460,7 +491,6 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, | |||
460 | 491 | ||
461 | v9fs_stat2inode(st, inode, sb); | 492 | v9fs_stat2inode(st, inode, sb); |
462 | #ifdef CONFIG_9P_FSCACHE | 493 | #ifdef CONFIG_9P_FSCACHE |
463 | v9fs_fscache_set_key(inode, &st->qid); | ||
464 | v9fs_cache_inode_get_cookie(inode); | 494 | v9fs_cache_inode_get_cookie(inode); |
465 | #endif | 495 | #endif |
466 | unlock_new_inode(inode); | 496 | unlock_new_inode(inode); |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 32bbbe5aa689..dc9e7de38202 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
@@ -86,6 +86,38 @@ static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode) | |||
86 | return dentry; | 86 | return dentry; |
87 | } | 87 | } |
88 | 88 | ||
89 | static int v9fs_test_inode_dotl(struct inode *inode, void *data) | ||
90 | { | ||
91 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
92 | struct p9_stat_dotl *st = (struct p9_stat_dotl *)data; | ||
93 | |||
94 | /* don't match inode of different type */ | ||
95 | if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) | ||
96 | return 0; | ||
97 | |||
98 | if (inode->i_generation != st->st_gen) | ||
99 | return 0; | ||
100 | |||
101 | /* compare qid details */ | ||
102 | if (memcmp(&v9inode->qid.version, | ||
103 | &st->qid.version, sizeof(v9inode->qid.version))) | ||
104 | return 0; | ||
105 | |||
106 | if (v9inode->qid.type != st->qid.type) | ||
107 | return 0; | ||
108 | return 1; | ||
109 | } | ||
110 | |||
111 | static int v9fs_set_inode_dotl(struct inode *inode, void *data) | ||
112 | { | ||
113 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
114 | struct p9_stat_dotl *st = (struct p9_stat_dotl *)data; | ||
115 | |||
116 | memcpy(&v9inode->qid, &st->qid, sizeof(st->qid)); | ||
117 | inode->i_generation = st->st_gen; | ||
118 | return 0; | ||
119 | } | ||
120 | |||
89 | static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, | 121 | static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, |
90 | struct p9_qid *qid, | 122 | struct p9_qid *qid, |
91 | struct p9_fid *fid, | 123 | struct p9_fid *fid, |
@@ -97,7 +129,8 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, | |||
97 | struct v9fs_session_info *v9ses = sb->s_fs_info; | 129 | struct v9fs_session_info *v9ses = sb->s_fs_info; |
98 | 130 | ||
99 | i_ino = v9fs_qid2ino(qid); | 131 | i_ino = v9fs_qid2ino(qid); |
100 | inode = iget_locked(sb, i_ino); | 132 | inode = iget5_locked(sb, i_ino, v9fs_test_inode_dotl, |
133 | v9fs_set_inode_dotl, st); | ||
101 | if (!inode) | 134 | if (!inode) |
102 | return ERR_PTR(-ENOMEM); | 135 | return ERR_PTR(-ENOMEM); |
103 | if (!(inode->i_state & I_NEW)) | 136 | if (!(inode->i_state & I_NEW)) |
@@ -107,13 +140,13 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, | |||
107 | * FIXME!! we may need support for stale inodes | 140 | * FIXME!! we may need support for stale inodes |
108 | * later. | 141 | * later. |
109 | */ | 142 | */ |
143 | inode->i_ino = i_ino; | ||
110 | retval = v9fs_init_inode(v9ses, inode, st->st_mode); | 144 | retval = v9fs_init_inode(v9ses, inode, st->st_mode); |
111 | if (retval) | 145 | if (retval) |
112 | goto error; | 146 | goto error; |
113 | 147 | ||
114 | v9fs_stat2inode_dotl(st, inode); | 148 | v9fs_stat2inode_dotl(st, inode); |
115 | #ifdef CONFIG_9P_FSCACHE | 149 | #ifdef CONFIG_9P_FSCACHE |
116 | v9fs_fscache_set_key(inode, &st->qid); | ||
117 | v9fs_cache_inode_get_cookie(inode); | 150 | v9fs_cache_inode_get_cookie(inode); |
118 | #endif | 151 | #endif |
119 | retval = v9fs_get_acl(inode, fid); | 152 | retval = v9fs_get_acl(inode, fid); |
@@ -136,7 +169,7 @@ v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, | |||
136 | struct p9_stat_dotl *st; | 169 | struct p9_stat_dotl *st; |
137 | struct inode *inode = NULL; | 170 | struct inode *inode = NULL; |
138 | 171 | ||
139 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | 172 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN); |
140 | if (IS_ERR(st)) | 173 | if (IS_ERR(st)) |
141 | return ERR_CAST(st); | 174 | return ERR_CAST(st); |
142 | 175 | ||
@@ -547,7 +580,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) | |||
547 | inode->i_blocks = stat->st_blocks; | 580 | inode->i_blocks = stat->st_blocks; |
548 | } | 581 | } |
549 | if (stat->st_result_mask & P9_STATS_GEN) | 582 | if (stat->st_result_mask & P9_STATS_GEN) |
550 | inode->i_generation = stat->st_gen; | 583 | inode->i_generation = stat->st_gen; |
551 | 584 | ||
552 | /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION | 585 | /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION |
553 | * because the inode structure does not have fields for them. | 586 | * because the inode structure does not have fields for them. |