aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2011-07-11 12:40:59 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2011-07-23 10:32:48 -0400
commitfd2421f54423f307ecd31bdebdca6bc317e0c492 (patch)
tree6e681349c6111a6bca9a562090bdedfd5b2ed29c /fs/9p
parent5034990e28efb2d232ee82443a9edd62defd17ba (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.c20
-rw-r--r--fs/9p/cache.h9
-rw-r--r--fs/9p/v9fs.c2
-rw-r--r--fs/9p/v9fs.h2
-rw-r--r--fs/9p/vfs_inode.c36
-rw-r--r--fs/9p/vfs_inode_dotl.c41
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
118static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, 117static 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
139static enum 137static 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
96static 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
105static inline void v9fs_fscache_wait_on_page_write(struct inode *inode, 96static 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
435static 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
457static 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
436static struct inode *v9fs_qid_iget(struct super_block *sb, 466static 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
89static 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
111static 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
89static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, 121static 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.