Skip to content

Commit 27a3ee3

Browse files
committed
afs: Use the vnode ID uniquifier in the cache key not the aux data
AFS vnodes (files) are referenced by a triplet of { volume ID, vnode ID, uniquifier }. Currently, kafs is only using the vnode ID as the file key in the volume fscache index and checking the uniquifier on cookie acquisition against the contents of the auxiliary data stored in the cache. Unfortunately, this is subject to a race in which an FS.RemoveFile or FS.RemoveDir op is issued against the server but the local afs inode isn't torn down and disposed off before another thread issues something like FS.CreateFile. The latter then gets given the vnode ID that just got removed, but with a new uniquifier and a cookie collision occurs in the cache because the cookie is only keyed on the vnode ID whereas the inode is keyed on the vnode ID plus the uniquifier. Fix this by keying the cookie on the uniquifier in addition to the vnode ID and dropping the uniquifier from the auxiliary data supplied. Signed-off-by: David Howells <[email protected]>
1 parent c151599 commit 27a3ee3

File tree

1 file changed

+8
-14
lines changed

1 file changed

+8
-14
lines changed

fs/afs/cache.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
2929

3030
struct fscache_netfs afs_cache_netfs = {
3131
.name = "afs",
32-
.version = 1,
32+
.version = 2,
3333
};
3434

3535
struct fscache_cookie_def afs_cell_cache_index_def = {
@@ -103,7 +103,9 @@ static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
103103
{
104104
const struct afs_vnode *vnode = cookie_netfs_data;
105105
struct {
106-
u32 vnode_id[3];
106+
u32 vnode_id;
107+
u32 unique;
108+
u32 vnode_id_ext[2]; /* Allow for a 96-bit key */
107109
} __packed key;
108110

109111
_enter("{%x,%x,%llx},%p,%u",
@@ -112,9 +114,10 @@ static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
112114

113115
/* Allow for a 96-bit key */
114116
memset(&key, 0, sizeof(key));
115-
key.vnode_id[0] = vnode->fid.vnode;
116-
key.vnode_id[1] = 0;
117-
key.vnode_id[2] = 0;
117+
key.vnode_id = vnode->fid.vnode;
118+
key.unique = vnode->fid.unique;
119+
key.vnode_id_ext[0] = 0;
120+
key.vnode_id_ext[1] = 0;
118121

119122
if (sizeof(key) > bufmax)
120123
return 0;
@@ -140,7 +143,6 @@ static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
140143

141144
struct afs_vnode_cache_aux {
142145
u64 data_version;
143-
u32 fid_unique;
144146
} __packed;
145147

146148
/*
@@ -156,9 +158,7 @@ static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
156158
vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
157159
buffer, bufmax);
158160

159-
memset(&aux, 0, sizeof(aux));
160161
aux.data_version = vnode->status.data_version;
161-
aux.fid_unique = vnode->fid.unique;
162162

163163
if (bufmax < sizeof(aux))
164164
return 0;
@@ -189,12 +189,6 @@ static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
189189
return FSCACHE_CHECKAUX_OBSOLETE;
190190
}
191191

192-
if (vnode->fid.unique != aux.fid_unique) {
193-
_leave(" = OBSOLETE [uniq %x != %x]",
194-
aux.fid_unique, vnode->fid.unique);
195-
return FSCACHE_CHECKAUX_OBSOLETE;
196-
}
197-
198192
if (vnode->status.data_version != aux.data_version) {
199193
_leave(" = OBSOLETE [vers %llx != %llx]",
200194
aux.data_version, vnode->status.data_version);

0 commit comments

Comments
 (0)