Commit a130e9e4 authored by Jeff Layton's avatar Jeff Layton Committed by Greg Kroah-Hartman

cifs: ensure that we always do cifsFileInfo_get under the spinlock

commit 764a1b1a upstream.

The readpages bug is a regression that was introduced in 6993f74a.
This also fixes a couple of similar bugs in the uncached read and write
codepaths.

Also, prevent this sort of thing in the future by having cifsFileInfo_get
take the spinlock itself, and adding a _locked variant for use in places
that are already holding the lock. The _put code has always done that
so this makes for a less confusing interface.
Reviewed-by: default avatarPavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6f51cd3b
...@@ -657,13 +657,13 @@ struct cifs_io_parms { ...@@ -657,13 +657,13 @@ struct cifs_io_parms {
* Take a reference on the file private data. Must be called with * Take a reference on the file private data. Must be called with
* cifs_file_list_lock held. * cifs_file_list_lock held.
*/ */
static inline static inline void
struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file) cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
{ {
++cifs_file->count; ++cifs_file->count;
return cifs_file;
} }
struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file);
void cifsFileInfo_put(struct cifsFileInfo *cifs_file); void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
/* /*
......
...@@ -284,6 +284,15 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, ...@@ -284,6 +284,15 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file,
static void cifs_del_lock_waiters(struct cifsLockInfo *lock); static void cifs_del_lock_waiters(struct cifsLockInfo *lock);
struct cifsFileInfo *
cifsFileInfo_get(struct cifsFileInfo *cifs_file)
{
spin_lock(&cifs_file_list_lock);
cifsFileInfo_get_locked(cifs_file);
spin_unlock(&cifs_file_list_lock);
return cifs_file;
}
/* /*
* Release a reference on the file private data. This may involve closing * Release a reference on the file private data. This may involve closing
* the filehandle out on the server. Must be called without holding * the filehandle out on the server. Must be called without holding
...@@ -1563,7 +1572,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, ...@@ -1563,7 +1572,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
if (!open_file->invalidHandle) { if (!open_file->invalidHandle) {
/* found a good file */ /* found a good file */
/* lock it so it will not be closed on us */ /* lock it so it will not be closed on us */
cifsFileInfo_get(open_file); cifsFileInfo_get_locked(open_file);
spin_unlock(&cifs_file_list_lock); spin_unlock(&cifs_file_list_lock);
return open_file; return open_file;
} /* else might as well continue, and look for } /* else might as well continue, and look for
...@@ -1615,7 +1624,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, ...@@ -1615,7 +1624,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
if (!open_file->invalidHandle) { if (!open_file->invalidHandle) {
/* found a good writable file */ /* found a good writable file */
cifsFileInfo_get(open_file); cifsFileInfo_get_locked(open_file);
spin_unlock(&cifs_file_list_lock); spin_unlock(&cifs_file_list_lock);
return open_file; return open_file;
} else { } else {
...@@ -1632,7 +1641,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, ...@@ -1632,7 +1641,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
if (inv_file) { if (inv_file) {
any_available = false; any_available = false;
cifsFileInfo_get(inv_file); cifsFileInfo_get_locked(inv_file);
} }
spin_unlock(&cifs_file_list_lock); spin_unlock(&cifs_file_list_lock);
...@@ -3082,8 +3091,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, ...@@ -3082,8 +3091,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
break; break;
} }
spin_lock(&cifs_file_list_lock);
spin_unlock(&cifs_file_list_lock);
rdata->cfile = cifsFileInfo_get(open_file); rdata->cfile = cifsFileInfo_get(open_file);
rdata->mapping = mapping; rdata->mapping = mapping;
rdata->offset = offset; rdata->offset = offset;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment