[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:
parent
e4903fb595
commit
a403a0a370
4 changed files with 35 additions and 13 deletions
|
@ -3,7 +3,10 @@ Version 1.50
|
|||
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
|
||||
done with "serverino" mount option). Add support for POSIX Unlink
|
||||
(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
|
||||
------------
|
||||
|
|
|
@ -444,6 +444,13 @@ A partial list of the supported mount options follows:
|
|||
noposixpaths If CIFS Unix extensions are supported, do not request
|
||||
posix path name support (this may cause servers to
|
||||
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.
|
||||
This is necessary for certain applications that break
|
||||
with cifs style mandatory byte range locks (and most
|
||||
|
|
|
@ -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
|
||||
|
||||
w) Add mount option for Linux extension disable per mount, and partial
|
||||
disable per mount (uid off, symlink/fifo/mknod on but what about posix acls?)
|
||||
w) Add support for new vfs entry points for setlease and fallocate
|
||||
|
||||
x) Fix Samba 3 server to handle Linux kernel aio so dbench with lots of
|
||||
processes can proceed better in parallel (on the server)
|
||||
|
|
|
@ -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)
|
||||
return 1;
|
||||
|
||||
if (cifsInode)
|
||||
open_file = find_writable_file(cifsInode);
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue