Commit b8fbf88f authored by Pavel Shilovsky's avatar Pavel Shilovsky

Update 3.0 sources from stable (v3.0.40)

parent a6aecd51
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#define CIFS_MIN_RCV_POOL 4 #define CIFS_MIN_RCV_POOL 4
#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */
/* /*
* default attribute cache timeout (jiffies) * default attribute cache timeout (jiffies)
*/ */
......
...@@ -1451,10 +1451,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, ...@@ -1451,10 +1451,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
bool fsuid_only) bool fsuid_only)
{ {
struct cifsFileInfo *open_file; struct cifsFileInfo *open_file, *inv_file = NULL;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
bool any_available = false; bool any_available = false;
int rc; int rc;
unsigned int refind = 0;
/* Having a null inode here (because mapping->host was set to zero by /* Having a null inode here (because mapping->host was set to zero by
the VFS or MM) should not happen but we had reports of on oops (due to the VFS or MM) should not happen but we had reports of on oops (due to
...@@ -1474,40 +1475,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, ...@@ -1474,40 +1475,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
spin_lock(&cifs_file_list_lock); spin_lock(&cifs_file_list_lock);
refind_writable: refind_writable:
if (refind > MAX_REOPEN_ATT) {
spin_unlock(&cifs_file_list_lock);
return NULL;
}
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (!any_available && open_file->pid != current->tgid) if (!any_available && open_file->pid != current->tgid)
continue; continue;
if (fsuid_only && open_file->uid != current_fsuid()) if (fsuid_only && open_file->uid != current_fsuid())
continue; continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
cifsFileInfo_get(open_file);
if (!open_file->invalidHandle) { if (!open_file->invalidHandle) {
/* found a good writable file */ /* found a good writable file */
cifsFileInfo_get(open_file);
spin_unlock(&cifs_file_list_lock); spin_unlock(&cifs_file_list_lock);
return open_file; return open_file;
} else {
if (!inv_file)
inv_file = open_file;
} }
spin_unlock(&cifs_file_list_lock);
/* Had to unlock since following call can block */
rc = cifs_reopen_file(open_file, false);
if (!rc)
return open_file;
/* if it fails, try another handle if possible */
cFYI(1, "wp failed on reopen file");
cifsFileInfo_put(open_file);
spin_lock(&cifs_file_list_lock);
/* else we simply continue to the next entry. Thus
we do not loop on reopen errors. If we
can not reopen the file, for example if we
reconnected to a server with another client
racing to delete or lock the file we would not
make progress if we restarted before the beginning
of the loop here. */
} }
} }
/* couldn't find useable FH with same pid, try any available */ /* couldn't find useable FH with same pid, try any available */
...@@ -1515,7 +1501,30 @@ refind_writable: ...@@ -1515,7 +1501,30 @@ refind_writable:
any_available = true; any_available = true;
goto refind_writable; goto refind_writable;
} }
if (inv_file) {
any_available = false;
cifsFileInfo_get(inv_file);
}
spin_unlock(&cifs_file_list_lock);
if (inv_file) {
rc = cifs_reopen_file(inv_file, false);
if (!rc)
return inv_file;
else {
spin_lock(&cifs_file_list_lock);
list_move_tail(&inv_file->flist,
&cifs_inode->openFileList);
spin_unlock(&cifs_file_list_lock); spin_unlock(&cifs_file_list_lock);
cifsFileInfo_put(inv_file);
spin_lock(&cifs_file_list_lock);
++refind;
goto refind_writable;
}
}
return NULL; return NULL;
} }
......
...@@ -85,9 +85,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, ...@@ -85,9 +85,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
dentry = d_lookup(parent, name); dentry = d_lookup(parent, name);
if (dentry) { if (dentry) {
/* FIXME: check for inode number changes? */ inode = dentry->d_inode;
if (dentry->d_inode != NULL) /* update inode in place if i_ino didn't change */
if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
cifs_fattr_to_inode(inode, fattr);
return dentry; return dentry;
}
d_drop(dentry); d_drop(dentry);
dput(dentry); dput(dentry);
} }
......
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