summaryrefslogtreecommitdiff
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilovsky@etersoft.ru>2012-09-19 17:22:45 +0400
committerSteve French <smfrench@gmail.com>2012-09-25 06:46:33 +0400
commit233839b1df65a24c8b67b748fe7b18d86d0ad6d7 (patch)
treeba9af2849063c2213fc0fbecb494967f1e662806 /fs/cifs/dir.c
parent0822f51426b51bd599b3a7e972b14aacaa045a92 (diff)
downloadlinux-233839b1df65a24c8b67b748fe7b18d86d0ad6d7.tar.xz
CIFS: Fix fast lease break after open problem
Now we walk though cifsFileInfo's list for every incoming lease break and look for an equivalent there. That approach misses lease breaks that come just after an open response - we don't have time to populate new cifsFileInfo structure to the list. Fix this by adding new list of pending opens and look for a lease there if we didn't find it in the list of cifsFileInfo structures. Signed-off-by: Pavel Shilovsky <pshilovsky@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 4f2147c5adb6..7c0a81283645 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -382,6 +382,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
struct cifs_fid fid;
+ struct cifs_pending_open open;
__u32 oplock;
struct cifsFileInfo *file_info;
@@ -423,16 +424,21 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
if (server->ops->new_lease_key)
server->ops->new_lease_key(&fid);
+ cifs_add_pending_open(&fid, tlink, &open);
+
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
&oplock, &fid, opened);
- if (rc)
+ if (rc) {
+ cifs_del_pending_open(&open);
goto out;
+ }
rc = finish_open(file, direntry, generic_file_open, opened);
if (rc) {
if (server->ops->close)
server->ops->close(xid, tcon, &fid);
+ cifs_del_pending_open(&open);
goto out;
}
@@ -440,6 +446,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
if (file_info == NULL) {
if (server->ops->close)
server->ops->close(xid, tcon, &fid);
+ cifs_del_pending_open(&open);
rc = -ENOMEM;
}