diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2010-05-17 12:00:37 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2010-05-18 12:05:20 -0400 |
commit | 47cee541a46a73b20dc279bf4c4690f776f6c81b (patch) | |
tree | d54461a8fd6a4c70d5b092334ccf38359bcd4994 /fs | |
parent | b7299f44394336f51b526247a870d47d28f4f97c (diff) |
nfsd: safer initialization order in find_file()
The alloc_init_file() first adds a file to the hash and then
initializes its fi_inode, fi_id and fi_had_conflict.
The uninitialized fi_inode could thus be erroneously checked by
the find_file(), so move the hash insertion lower.
The client_mutex should prevent this race in practice; however, we
eventually hope to make less use of the client_mutex, so the ordering
here is an accident waiting to happen.
I didn't find whether the same can be true for two other fields,
but the common sense tells me it's better to initialize an object
before putting it into a global hash table :)
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/nfs4state.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 84b0fe9a262a..296eded356b6 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1757,12 +1757,12 @@ alloc_init_file(struct inode *ino) | |||
1757 | INIT_LIST_HEAD(&fp->fi_hash); | 1757 | INIT_LIST_HEAD(&fp->fi_hash); |
1758 | INIT_LIST_HEAD(&fp->fi_stateids); | 1758 | INIT_LIST_HEAD(&fp->fi_stateids); |
1759 | INIT_LIST_HEAD(&fp->fi_delegations); | 1759 | INIT_LIST_HEAD(&fp->fi_delegations); |
1760 | spin_lock(&recall_lock); | ||
1761 | list_add(&fp->fi_hash, &file_hashtbl[hashval]); | ||
1762 | spin_unlock(&recall_lock); | ||
1763 | fp->fi_inode = igrab(ino); | 1760 | fp->fi_inode = igrab(ino); |
1764 | fp->fi_id = current_fileid++; | 1761 | fp->fi_id = current_fileid++; |
1765 | fp->fi_had_conflict = false; | 1762 | fp->fi_had_conflict = false; |
1763 | spin_lock(&recall_lock); | ||
1764 | list_add(&fp->fi_hash, &file_hashtbl[hashval]); | ||
1765 | spin_unlock(&recall_lock); | ||
1766 | return fp; | 1766 | return fp; |
1767 | } | 1767 | } |
1768 | return NULL; | 1768 | return NULL; |