nfsd: safer initialization order in find_file()
authorPavel Emelyanov <xemul@openvz.org>
Mon, 17 May 2010 16:00:37 +0000 (20:00 +0400)
committerJ. Bruce Fields <bfields@citi.umich.edu>
Tue, 18 May 2010 16:05:20 +0000 (12:05 -0400)
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>
fs/nfsd/nfs4state.c

index 84b0fe9a262aa3b96c22dbb628f6e5ead61a3a15..296eded356b67b8afba95c61e6d9b2d4877efd86 100644 (file)
@@ -1757,12 +1757,12 @@ alloc_init_file(struct inode *ino)
                INIT_LIST_HEAD(&fp->fi_hash);
                INIT_LIST_HEAD(&fp->fi_stateids);
                INIT_LIST_HEAD(&fp->fi_delegations);
-               spin_lock(&recall_lock);
-               list_add(&fp->fi_hash, &file_hashtbl[hashval]);
-               spin_unlock(&recall_lock);
                fp->fi_inode = igrab(ino);
                fp->fi_id = current_fileid++;
                fp->fi_had_conflict = false;
+               spin_lock(&recall_lock);
+               list_add(&fp->fi_hash, &file_hashtbl[hashval]);
+               spin_unlock(&recall_lock);
                return fp;
        }
        return NULL;