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

Fix various SMP/locking problems pointed out by Shoobhit Dayal and Arjan van de Ven

parent 3e753cea
...@@ -20,6 +20,7 @@ Patch Contributors ...@@ -20,6 +20,7 @@ Patch Contributors
Zwane Mwaikambo Zwane Mwaikambo
Andi Kleen Andi Kleen
Amrut Joshi Amrut Joshi
Shobhit Dayal
Test case and Bug Report contributors Test case and Bug Report contributors
------------------------------------- -------------------------------------
......
...@@ -207,14 +207,106 @@ int relock_files(struct cifsFileInfo * cifsFile) ...@@ -207,14 +207,106 @@ int relock_files(struct cifsFileInfo * cifsFile)
return rc; return rc;
} }
static int cifs_reopen_file(struct inode *inode, struct file *file)
{
int rc = -EACCES;
int xid, oplock;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode;
char *full_path = NULL;
int desiredAccess = 0x20197;
int disposition = FILE_OPEN;
__u16 netfid;
FILE_ALL_INFO * buf = NULL;
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(file->f_dentry);
cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
desiredAccess = GENERIC_READ;
else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
desiredAccess = GENERIC_WRITE;
else if ((file->f_flags & O_ACCMODE) == O_RDWR)
desiredAccess = GENERIC_ALL;
if (oplockEnabled)
oplock = REQ_OPLOCK;
else
oplock = FALSE;
/* BB pass O_SYNC flag through on file attributes .. BB */
/* Also refresh inode by passing in file_info buf returned by SMBOpen
and calling get_inode_info with returned buf (at least
helps non-Unix server case */
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
if(buf==0) {
if (full_path)
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
}
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
if (rc) {
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;
pCifsInode = CIFS_I(file->f_dentry->d_inode);
if(pCifsInode) {
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
full_path, inode->i_sb);
else
rc = cifs_get_inode_info(&file->f_dentry->d_inode,
full_path, buf, inode->i_sb);
if(oplock == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
} else if(oplock == OPLOCK_READ) {
pCifsInode->clientCanCacheRead = TRUE;
pCifsInode->clientCanCacheAll = FALSE;
} else {
pCifsInode->clientCanCacheRead = FALSE;
pCifsInode->clientCanCacheAll = FALSE;
}
}
} else
rc = -EBADF;
}
if (buf)
kfree(buf);
if (full_path)
kfree(full_path);
FreeXid(xid);
return rc;
}
/* Try to reopen files that were closed when session to server was lost */ /* Try to reopen files that were closed when session to server was lost */
int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo) int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo)
{ {
int rc = 0; int rc = 0;
struct cifsFileInfo *open_file = NULL; struct cifsFileInfo *open_file = NULL;
struct file * file = NULL; struct file * file = NULL;
struct list_head *tmp; struct list_head invalid_file_list;
struct list_head *tmp1; 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 */ /* list all files open on tree connection and mark them invalid */
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
...@@ -222,45 +314,37 @@ int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo) ...@@ -222,45 +314,37 @@ int reopen_files(struct cifsTconInfo * pTcon, struct nls_table * nlsinfo)
open_file = list_entry(tmp,struct cifsFileInfo, tlist); open_file = list_entry(tmp,struct cifsFileInfo, tlist);
if(open_file) { if(open_file) {
open_file->invalidHandle = TRUE; open_file->invalidHandle = TRUE;
list_move(&open_file->tlist,&invalid_file_list);
} }
} }
/* reopen files */ /* reopen files */
for(;;) { list_for_each(tmp,&invalid_file_list) {
/* BB need to fix above to check list end and skip entries we do not need to reopen */ /* BB need to fix above to check list end and skip entries we do not need to reopen */
if(list_empty(&pTcon->openFileList)) { open_file = list_entry(tmp,struct cifsFileInfo, tlist);
break; if(open_file == NULL) {
break;
} else { } else {
open_file = list_entry(tmp,struct cifsFileInfo, tlist); if(open_file->invalidHandle == FALSE) {
if(open_file) { list_move(&open_file->tlist,&pTcon->openFileList);
if(open_file->invalidHandle == FALSE) continue;
continue; }
if(open_file->search_resume_name) { file = open_file->pfile;
kfree(open_file->search_resume_name); if(file->f_dentry == 0) {
} cFYI(1,("Null dentry for file %p",file));
file = open_file->pfile; } else {
list_del(&open_file->flist); write_unlock(&GlobalSMBSeslock);
list_del(&open_file->tlist); rc = cifs_reopen_file(file->f_dentry->d_inode,file);
kfree(open_file); write_lock(&GlobalSMBSeslock);
if(file) { list_move(&open_file->tlist,&pTcon->openFileList);
file->private_data = NULL; if(rc) {
if(file->f_dentry == 0) { cFYI(1,("reconnecting file %s failed with %d",
cFYI(1,("Null dentry for file %p",file)); file->f_dentry->d_name.name,rc));
} else { } else {
write_unlock(&GlobalSMBSeslock); cFYI(1,("reconnection of %s succeeded",
rc = cifs_open(file->f_dentry->d_inode,file); file->f_dentry->d_name.name));
write_lock(&GlobalSMBSeslock);
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); write_unlock(&GlobalSMBSeslock);
......
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