[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 <shaggy@us.ibm.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
Steve French 2007-07-26 15:54:16 +00:00
parent e4903fb595
commit a403a0a370
4 changed files with 35 additions and 13 deletions

View file

@ -3,7 +3,10 @@ Version 1.50
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
done with "serverino" mount option). Add support for POSIX Unlink done with "serverino" mount option). Add support for POSIX Unlink
(helps with certain sharing violation cases when server such as (helps with certain sharing violation cases when server such as
Samba supports newer POSIX CIFS Protocol Extensions). Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix"
mount option to allow disabling the CIFS Unix Extensions for just
that mount. Fix hang on spinlock in find_writable_file (race when
reopening file after session crash).
Version 1.49 Version 1.49
------------ ------------

View file

@ -444,6 +444,13 @@ A partial list of the supported mount options follows:
noposixpaths If CIFS Unix extensions are supported, do not request noposixpaths If CIFS Unix extensions are supported, do not request
posix path name support (this may cause servers to posix path name support (this may cause servers to
reject creatingfile with certain reserved characters). reject creatingfile with certain reserved characters).
nounix Disable the CIFS Unix Extensions for this mount (tree
connection). This is rarely needed, but it may be useful
in order to turn off multiple settings all at once (ie
posix acls, posix locks, posix paths, symlink support
and retrieving uids/gids/mode from the server) or to
work around a bug in server which implement the Unix
Extensions.
nobrl Do not send byte range lock requests to the server. nobrl Do not send byte range lock requests to the server.
This is necessary for certain applications that break This is necessary for certain applications that break
with cifs style mandatory byte range locks (and most with cifs style mandatory byte range locks (and most

View file

@ -82,8 +82,7 @@ u) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for
v) mount check for unmatched uids v) mount check for unmatched uids
w) Add mount option for Linux extension disable per mount, and partial w) Add support for new vfs entry points for setlease and fallocate
disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?)
x) Fix Samba 3 server to handle Linux kernel aio so dbench with lots of x) Fix Samba 3 server to handle Linux kernel aio so dbench with lots of
processes can proceed better in parallel (on the server) processes can proceed better in parallel (on the server)

View file

@ -1904,6 +1904,25 @@ static int cifs_readpage(struct file *file, struct page *page)
return rc; 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 /* We do not want to update the file size from server for inodes
open for write - to avoid races with writepage extending open for write - to avoid races with writepage extending
the file - in the future we could consider allowing 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 */ page caching in the current Linux kernel design */
int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file) int is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
{ {
struct cifsFileInfo *open_file = NULL; if (!cifsInode)
return 1;
if (cifsInode) if (is_inode_writable(cifsInode)) {
open_file = find_writable_file(cifsInode); /* This inode is open for write at least once */
if (open_file) {
struct cifs_sb_info *cifs_sb; 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); cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) { if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
/* since no page cache to corrupt on directio /* since no page cache to corrupt on directio