Commit a093070b authored by Steve French's avatar Steve French Committed by Steve French

finish off move from reopening all files on reconnection (which takes too long...

finish off move from reopening all files on reconnection (which takes too long under heavy stress) to reopen file as needed after reconnection to server.
parent 1915ad84
......@@ -211,7 +211,6 @@ struct cifsFileInfo {
struct inode * pInode; /* needed for oplock break */
int endOfSearch:1; /* we have reached end of search */
int closePend:1; /* file is marked to close */
int reopenPend:1; /* reopen of file in progress */
int emptyDir:1;
int invalidHandle:1; /* file closed via session abend */
char * search_resume_name;
......
......@@ -75,7 +75,6 @@ extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb);
extern int reopen_files(struct cifsTconInfo *, struct nls_table *);
extern int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table * nls_info);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
......
......@@ -41,11 +41,30 @@ static struct {
int index;
char *name;
} protocols[] = {
{
CIFS_PROT, "\2NT LM 0.12"}, {
BAD_PROT, "\2"}
{CIFS_PROT, "\2NT LM 0.12"},
{BAD_PROT, "\2"}
};
/* Mark as invalid, all open files on tree connections since they
were closed when session to server was lost */
void mark_open_files_invalid(struct cifsTconInfo * pTcon)
{
struct cifsFileInfo *open_file = NULL;
struct list_head * tmp;
struct list_head * tmp1;
/* list all files open on tree connection and mark them invalid */
write_lock(&GlobalSMBSeslock);
list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
open_file = list_entry(tmp,struct cifsFileInfo, tlist);
if(open_file) {
open_file->invalidHandle = TRUE;
}
}
write_unlock(&GlobalSMBSeslock);
}
int
smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
void **request_buf /* returned */ ,
......@@ -75,15 +94,14 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
if(tcon->ses->status == CifsNeedReconnect)
rc = setup_session(0, tcon->ses, nls_codepage);
if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
nls_codepage);
up(&tcon->ses->sesSem);
cFYI(1, ("reconnect tcon rc = %d", rc));
/* Remove call to reopen files here -
it is safer (and faster) to reopen
files as needed in read and write */
/* if(!rc)
reopen_files(tcon,nls_codepage);*/
/* Removed call to reopen open files here -
it is safer (and faster) to reopen files
one at a time as needed in read and write */
} else {
up(&tcon->ses->sesSem);
}
......
......@@ -224,8 +224,19 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
if(inode == NULL)
return -EBADF;
if (file->private_data) {
pCifsFile = (struct cifsFileInfo *) file->private_data;
} else
return -EBADF;
xid = GetXid();
down(&inode->i_sem);
if(pCifsFile->invalidHandle == FALSE) {
up(&inode->i_sem);
FreeXid(xid);
return 0;
}
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
......@@ -239,6 +250,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
desiredAccess = GENERIC_WRITE;
else if ((file->f_flags & O_ACCMODE) == O_RDWR)
desiredAccess = GENERIC_ALL;
if (oplockEnabled)
oplock = REQ_OPLOCK;
else
......@@ -251,6 +263,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
helps non-Unix server case */
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
if(buf==0) {
up(&inode->i_sem);
if (full_path)
kfree(full_path);
FreeXid(xid);
......@@ -259,14 +272,13 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
if (rc) {
up(&inode->i_sem);
cFYI(1, ("cifs_open returned 0x%x ", rc));
cFYI(1, ("oplock: %d ", oplock));
} else {
if (file->private_data) {
pCifsFile = (struct cifsFileInfo *) file->private_data;
pCifsFile->netfid = netfid;
pCifsFile->invalidHandle = FALSE;
up(&inode->i_sem);
pCifsInode = CIFS_I(file->f_dentry->d_inode);
if(pCifsInode) {
if (pTcon->ses->capabilities & CAP_UNIX)
......@@ -288,8 +300,6 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
pCifsInode->clientCanCacheAll = FALSE;
}
}
} else
rc = -EBADF;
}
if (buf)
......@@ -300,68 +310,6 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
return rc;
}
/* Try to reopen files that were closed when session to server was lost */
int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo)
{
int rc = 0;
struct cifsFileInfo *open_file = NULL;
struct file * file = NULL;
struct list_head invalid_file_list;
struct list_head * tmp;
struct list_head * tmp1;
INIT_LIST_HEAD(&invalid_file_list);
/* list all files open on tree connection and mark them invalid */
write_lock(&GlobalSMBSeslock);
list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
open_file = list_entry(tmp,struct cifsFileInfo, tlist);
if(open_file) {
open_file->invalidHandle = TRUE;
list_move(&open_file->tlist,&invalid_file_list);
}
}
/* reopen files */
list_for_each_safe(tmp,tmp1, &invalid_file_list) {
/* BB need to fix above to check list end and skip entries we do not need to reopen */
open_file = list_entry(tmp,struct cifsFileInfo, tlist);
if(open_file == NULL) {
break;
} else {
if((open_file->invalidHandle == FALSE) &&
(open_file->closePend == FALSE)) {
list_move(&open_file->tlist,&pTcon->openFileList);
continue;
}
file = open_file->pfile;
if(file->f_dentry == 0) {
cFYI(1,("Null dentry for file %p",file));
} else {
write_unlock(&GlobalSMBSeslock);
rc = cifs_reopen_file(file->f_dentry->d_inode,file);
write_lock(&GlobalSMBSeslock);
if(file->private_data == NULL) {
tmp = invalid_file_list.next;
tmp1 = tmp->next;
continue;
}
list_move(&open_file->tlist,&pTcon->openFileList);
if(rc) {
cFYI(1,("reconnecting file %s failed with %d",
file->f_dentry->d_name.name,rc));
} else {
cFYI(1,("reconnection of %s succeeded",
file->f_dentry->d_name.name));
}
}
}
}
write_unlock(&GlobalSMBSeslock);
return rc;
}
int
cifs_close(struct inode *inode, struct file *file)
{
......@@ -544,6 +492,7 @@ cifs_write(struct file * file, const char *write_data,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid, long_op;
struct cifsFileInfo * open_file;
xid = GetXid();
......@@ -558,6 +507,8 @@ cifs_write(struct file * file, const char *write_data,
FreeXid(xid);
return -EBADF;
}
open_file = (struct cifsFileInfo *) file->private_data;
if (*poffset > file->f_dentry->d_inode->i_size)
long_op = 2; /* writes past end of file can take a long time */
......@@ -566,12 +517,20 @@ cifs_write(struct file * file, const char *write_data,
for (total_written = 0; write_size > total_written;
total_written += bytes_written) {
rc = -EAGAIN;
while(rc == -EAGAIN) {
if ((open_file->invalidHandle) && (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,file);
if(rc != 0)
break;
}
rc = CIFSSMBWrite(xid, pTcon,
((struct cifsFileInfo *) file->
private_data)->netfid,
open_file->netfid,
write_size - total_written, *poffset,
&bytes_written,
write_data + total_written, long_op);
}
if (rc || (bytes_written == 0)) {
if (total_written)
break;
......@@ -744,14 +703,12 @@ cifs_commit_write(struct file *file, struct page *page, unsigned offset,
cifs_sb = CIFS_SB(inode->i_sb);
rc = -EAGAIN;
while(rc == -EAGAIN) {
if((open_file->invalidHandle == TRUE) &&
(open_file->closePend == FALSE)) {
open_file->reopenPend = TRUE;
if((open_file->invalidHandle) &&
(!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,file);
open_file->reopenPend = FALSE;
}
if(rc != 0)
break;
}
rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
position, open_file->netfid,
open_file->pid,FALSE);
......@@ -852,6 +809,7 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
struct cifsTconInfo *pTcon;
int xid;
char * current_offset;
struct cifsFileInfo * open_file;
xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
......@@ -861,13 +819,21 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
FreeXid(xid);
return -EBADF;
}
open_file = (struct cifsFileInfo *)file->private_data;
for (total_read = 0,current_offset=read_data; read_size > total_read;
total_read += bytes_read,current_offset+=bytes_read) {
current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
rc = -EAGAIN;
while(rc == -EAGAIN) {
if ((open_file->invalidHandle) && (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,file);
if(rc != 0)
break;
}
rc = CIFSSMBRead(xid, pTcon,
((struct cifsFileInfo *) file->
private_data)->netfid,
open_file->netfid,
current_read_size, *poffset,
&bytes_read, &current_offset);
if (rc || (bytes_read == 0)) {
......@@ -880,6 +846,7 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
} else
*poffset += bytes_read;
}
}
FreeXid(xid);
return total_read;
......@@ -964,13 +931,14 @@ cifs_readpages(struct file *file, struct address_space *mapping,
char * smb_read_data = 0;
struct smb_com_read_rsp * pSMBr;
struct pagevec lru_pvec;
struct cifsFileInfo * open_file;
xid = GetXid();
if (file->private_data == NULL) {
FreeXid(xid);
return -EBADF;
}
open_file = (struct cifsFileInfo *)file->private_data;
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
......@@ -994,16 +962,23 @@ cifs_readpages(struct file *file, struct address_space *mapping,
read_size = (num_pages - i) * PAGE_CACHE_SIZE;
/* Read size needs to be in multiples of one page */
read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
rc = -EAGAIN;
while(rc == -EAGAIN) {
if ((open_file->invalidHandle) && (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,file);
if(rc != 0)
break;
}
rc = CIFSSMBRead(xid, pTcon,
((struct cifsFileInfo *) file->
private_data)->netfid,
open_file->netfid,
read_size, offset,
&bytes_read, &smb_read_data);
}
if ((rc < 0) || (smb_read_data == NULL)) {
cFYI(1,("Read error in readpages: %d",rc));
/* clean up remaing pages off list */
spin_lock(&mapping->page_lock);
while (!list_empty(page_list) && (i < num_pages)) {
page = list_entry(page_list->prev, struct page, list);
......
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