Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 326258
b: refs/heads/master
c: 2ae78ba
h: refs/heads/master
v: v3
  • Loading branch information
Pavel Shilovsky authored and Steve French committed Sep 25, 2012
1 parent 84e7566 commit f645add
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 58 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 253641388a49259f6bfefecfb14fa057ca58dc21
refs/heads/master: 2ae78ba85cd7b4c3a164434ab1f6c9e515c6fa1d
121 changes: 64 additions & 57 deletions trunk/fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,59 +459,66 @@ int cifs_open(struct inode *inode, struct file *file)
return rc;
}

/* Try to reacquire byte range locks that were released when session */
/* to server was lost */
/*
* Try to reacquire byte range locks that were released when session
* to server was lost
*/
static int cifs_relock_file(struct cifsFileInfo *cifsFile)
{
int rc = 0;

/* BB list all locks open on this file and relock */
/* BB list all locks open on this file and relock */

return rc;
}

static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
static int
cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
{
int rc = -EACCES;
unsigned int xid;
__u32 oplock;
struct cifs_sb_info *cifs_sb;
struct cifs_tcon *tcon;
struct cifsInodeInfo *pCifsInode;
struct TCP_Server_Info *server;
struct cifsInodeInfo *cinode;
struct inode *inode;
char *full_path = NULL;
int desiredAccess;
int desired_access;
int disposition = FILE_OPEN;
int create_options = CREATE_NOT_DIR;
__u16 netfid;
struct cifs_fid fid;

xid = get_xid();
mutex_lock(&pCifsFile->fh_mutex);
if (!pCifsFile->invalidHandle) {
mutex_unlock(&pCifsFile->fh_mutex);
mutex_lock(&cfile->fh_mutex);
if (!cfile->invalidHandle) {
mutex_unlock(&cfile->fh_mutex);
rc = 0;
free_xid(xid);
return rc;
}

inode = pCifsFile->dentry->d_inode;
inode = cfile->dentry->d_inode;
cifs_sb = CIFS_SB(inode->i_sb);
tcon = tlink_tcon(pCifsFile->tlink);
tcon = tlink_tcon(cfile->tlink);
server = tcon->ses->server;

/* can not grab rename sem here because various ops, including
those that already have the rename sem can end up causing writepage
to get called and if the server was down that means we end up here,
and we can never tell if the caller already has the rename_sem */
full_path = build_path_from_dentry(pCifsFile->dentry);
/*
* Can not grab rename sem here because various ops, including those
* that already have the rename sem can end up causing writepage to get
* called and if the server was down that means we end up here, and we
* can never tell if the caller already has the rename_sem.
*/
full_path = build_path_from_dentry(cfile->dentry);
if (full_path == NULL) {
rc = -ENOMEM;
mutex_unlock(&pCifsFile->fh_mutex);
mutex_unlock(&cfile->fh_mutex);
free_xid(xid);
return rc;
}

cFYI(1, "inode = 0x%p file flags 0x%x for %s",
inode, pCifsFile->f_flags, full_path);
cFYI(1, "inode = 0x%p file flags 0x%x for %s", inode, cfile->f_flags,
full_path);

if (tcon->ses->server->oplocks)
oplock = REQ_OPLOCK;
Expand All @@ -525,69 +532,69 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
* O_CREAT, O_EXCL and O_TRUNC already had their effect on the
* original open. Must mask them off for a reopen.
*/
unsigned int oflags = pCifsFile->f_flags &
unsigned int oflags = cfile->f_flags &
~(O_CREAT | O_EXCL | O_TRUNC);

rc = cifs_posix_open(full_path, NULL, inode->i_sb,
cifs_sb->mnt_file_mode /* ignored */,
oflags, &oplock, &netfid, xid);
cifs_sb->mnt_file_mode /* ignored */,
oflags, &oplock, &fid.netfid, xid);
if (rc == 0) {
cFYI(1, "posix reopen succeeded");
goto reopen_success;
}
/* fallthrough to retry open the old way on errors, especially
in the reconnect path it is important to retry hard */
/*
* fallthrough to retry open the old way on errors, especially
* in the reconnect path it is important to retry hard
*/
}

desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
desired_access = cifs_convert_flags(cfile->f_flags);

if (backup_cred(cifs_sb))
create_options |= CREATE_OPEN_BACKUP_INTENT;

/* Can not refresh inode by passing in file_info buf to be returned
by SMBOpen and then calling get_inode_info with returned buf
since file might have write behind data that needs to be flushed
and server version of file size can be stale. If we knew for sure
that inode was not dirty locally we could do this */

rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
create_options, &netfid, &oplock, NULL,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
/*
* Can not refresh inode by passing in file_info buf to be returned by
* CIFSSMBOpen and then calling get_inode_info with returned buf since
* file might have write behind data that needs to be flushed and server
* version of file size can be stale. If we knew for sure that inode was
* not dirty locally we could do this.
*/
rc = server->ops->open(xid, tcon, full_path, disposition,
desired_access, create_options, &fid, &oplock,
NULL, cifs_sb);
if (rc) {
mutex_unlock(&pCifsFile->fh_mutex);
cFYI(1, "cifs_open returned 0x%x", rc);
mutex_unlock(&cfile->fh_mutex);
cFYI(1, "cifs_reopen returned 0x%x", rc);
cFYI(1, "oplock: %d", oplock);
goto reopen_error_exit;
}

reopen_success:
pCifsFile->fid.netfid = netfid;
pCifsFile->invalidHandle = false;
mutex_unlock(&pCifsFile->fh_mutex);
pCifsInode = CIFS_I(inode);
cfile->invalidHandle = false;
mutex_unlock(&cfile->fh_mutex);
cinode = CIFS_I(inode);

if (can_flush) {
rc = filemap_write_and_wait(inode->i_mapping);
mapping_set_error(inode->i_mapping, rc);

if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode,
full_path, inode->i_sb, xid);
rc = cifs_get_inode_info_unix(&inode, full_path,
inode->i_sb, xid);
else
rc = cifs_get_inode_info(&inode,
full_path, NULL, inode->i_sb,
xid, NULL);
} /* else we are writing out data to server already
and could deadlock if we tried to flush data, and
since we do not know if we have data that would
invalidate the current end of file on the server
we can not go to the server to get the new inod
info */

cifs_set_oplock_level(pCifsInode, oplock);

cifs_relock_file(pCifsFile);
rc = cifs_get_inode_info(&inode, full_path, NULL,
inode->i_sb, xid, NULL);
}
/*
* Else we are writing out data to server already and could deadlock if
* we tried to flush data, and since we do not know if we have data that
* would invalidate the current end of file on the server we can not go
* to the server to get the new inode info.
*/

server->ops->set_fid(cfile, &fid, oplock);
cifs_relock_file(cfile);

reopen_error_exit:
kfree(full_path);
Expand Down

0 comments on commit f645add

Please sign in to comment.