From a403a0a370946e7dbcda6464a3509089daee54bc Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 26 Jul 2007 15:54:16 +0000 Subject: [CIFS] Fix hang in find_writable_file Caused by unneeded reopen during reconnect while spinlock held. Fixes kernel bugzilla bug #7903 Thanks to Lin Feng Shen for testing this, and Amit Arora for some nice problem determination to narrow this down. Acked-by: Dave Kleikamp Signed-off-by: Steve French --- fs/cifs/file.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'fs/cifs/file.c') diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e13592afca9..894b1f7b299 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1904,6 +1904,25 @@ static int cifs_readpage(struct file *file, struct page *page) return rc; } +static int is_inode_writable(struct cifsInodeInfo *cifs_inode) +{ + struct cifsFileInfo *open_file; + + read_lock(&GlobalSMBSeslock); + list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { + if (open_file->closePend) + continue; + if (open_file->pfile && + ((open_file->pfile->f_flags & O_RDWR) || + (open_file->pfile->f_flags & O_WRONLY))) { + read_unlock(&GlobalSMBSeslock); + return 1; + } + } + read_unlock(&GlobalSMBSeslock); + return 0; +} + /* We do not want to update the file size from server for inodes open for write - to avoid races with writepage extending the file - in the future we could consider allowing @@ -1912,19 +1931,13 @@ static int cifs_readpage(struct file *file, struct page *page) page caching in the current Linux kernel design */ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file) { - struct cifsFileInfo *open_file = NULL; - - if (cifsInode) - open_file = find_writable_file(cifsInode); + if (!cifsInode) + return 1; - if (open_file) { + if (is_inode_writable(cifsInode)) { + /* This inode is open for write at least once */ struct cifs_sb_info *cifs_sb; - /* there is not actually a write pending so let - this handle go free and allow it to - be closable if needed */ - atomic_dec(&open_file->wrtPending); - cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb); if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) { /* since no page cache to corrupt on directio -- cgit v1.2.3