提交 2ae78ba8 编写于 作者: P Pavel Shilovsky 提交者: Steve French

CIFS: Move reopen code to ops struct

Signed-off-by: NPavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: NSteve French <smfrench@gmail.com>
上级 25364138
...@@ -459,59 +459,66 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -459,59 +459,66 @@ int cifs_open(struct inode *inode, struct file *file)
return rc; 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) static int cifs_relock_file(struct cifsFileInfo *cifsFile)
{ {
int rc = 0; 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; 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; int rc = -EACCES;
unsigned int xid; unsigned int xid;
__u32 oplock; __u32 oplock;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct cifsInodeInfo *pCifsInode; struct TCP_Server_Info *server;
struct cifsInodeInfo *cinode;
struct inode *inode; struct inode *inode;
char *full_path = NULL; char *full_path = NULL;
int desiredAccess; int desired_access;
int disposition = FILE_OPEN; int disposition = FILE_OPEN;
int create_options = CREATE_NOT_DIR; int create_options = CREATE_NOT_DIR;
__u16 netfid; struct cifs_fid fid;
xid = get_xid(); xid = get_xid();
mutex_lock(&pCifsFile->fh_mutex); mutex_lock(&cfile->fh_mutex);
if (!pCifsFile->invalidHandle) { if (!cfile->invalidHandle) {
mutex_unlock(&pCifsFile->fh_mutex); mutex_unlock(&cfile->fh_mutex);
rc = 0; rc = 0;
free_xid(xid); free_xid(xid);
return rc; return rc;
} }
inode = pCifsFile->dentry->d_inode; inode = cfile->dentry->d_inode;
cifs_sb = CIFS_SB(inode->i_sb); 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 * Can not grab rename sem here because various ops, including those
to get called and if the server was down that means we end up here, * that already have the rename sem can end up causing writepage to get
and we can never tell if the caller already has the rename_sem */ * called and if the server was down that means we end up here, and we
full_path = build_path_from_dentry(pCifsFile->dentry); * can never tell if the caller already has the rename_sem.
*/
full_path = build_path_from_dentry(cfile->dentry);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
mutex_unlock(&pCifsFile->fh_mutex); mutex_unlock(&cfile->fh_mutex);
free_xid(xid); free_xid(xid);
return rc; return rc;
} }
cFYI(1, "inode = 0x%p file flags 0x%x for %s", cFYI(1, "inode = 0x%p file flags 0x%x for %s", inode, cfile->f_flags,
inode, pCifsFile->f_flags, full_path); full_path);
if (tcon->ses->server->oplocks) if (tcon->ses->server->oplocks)
oplock = REQ_OPLOCK; oplock = REQ_OPLOCK;
...@@ -525,69 +532,69 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) ...@@ -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 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
* original open. Must mask them off for a reopen. * 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); ~(O_CREAT | O_EXCL | O_TRUNC);
rc = cifs_posix_open(full_path, NULL, inode->i_sb, rc = cifs_posix_open(full_path, NULL, inode->i_sb,
cifs_sb->mnt_file_mode /* ignored */, cifs_sb->mnt_file_mode /* ignored */,
oflags, &oplock, &netfid, xid); oflags, &oplock, &fid.netfid, xid);
if (rc == 0) { if (rc == 0) {
cFYI(1, "posix reopen succeeded"); cFYI(1, "posix reopen succeeded");
goto reopen_success; 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)) if (backup_cred(cifs_sb))
create_options |= CREATE_OPEN_BACKUP_INTENT; 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 * Can not refresh inode by passing in file_info buf to be returned by
since file might have write behind data that needs to be flushed * CIFSSMBOpen and then calling get_inode_info with returned buf since
and server version of file size can be stale. If we knew for sure * file might have write behind data that needs to be flushed and server
that inode was not dirty locally we could do this */ * 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, rc = server->ops->open(xid, tcon, full_path, disposition,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & desired_access, create_options, &fid, &oplock,
CIFS_MOUNT_MAP_SPECIAL_CHR); NULL, cifs_sb);
if (rc) { if (rc) {
mutex_unlock(&pCifsFile->fh_mutex); mutex_unlock(&cfile->fh_mutex);
cFYI(1, "cifs_open returned 0x%x", rc); cFYI(1, "cifs_reopen returned 0x%x", rc);
cFYI(1, "oplock: %d", oplock); cFYI(1, "oplock: %d", oplock);
goto reopen_error_exit; goto reopen_error_exit;
} }
reopen_success: reopen_success:
pCifsFile->fid.netfid = netfid; cfile->invalidHandle = false;
pCifsFile->invalidHandle = false; mutex_unlock(&cfile->fh_mutex);
mutex_unlock(&pCifsFile->fh_mutex); cinode = CIFS_I(inode);
pCifsInode = CIFS_I(inode);
if (can_flush) { if (can_flush) {
rc = filemap_write_and_wait(inode->i_mapping); rc = filemap_write_and_wait(inode->i_mapping);
mapping_set_error(inode->i_mapping, rc); mapping_set_error(inode->i_mapping, rc);
if (tcon->unix_ext) if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, rc = cifs_get_inode_info_unix(&inode, full_path,
full_path, inode->i_sb, xid); inode->i_sb, xid);
else else
rc = cifs_get_inode_info(&inode, rc = cifs_get_inode_info(&inode, full_path, NULL,
full_path, NULL, inode->i_sb, inode->i_sb, xid, NULL);
xid, NULL); }
} /* else we are writing out data to server already /*
and could deadlock if we tried to flush data, and * Else we are writing out data to server already and could deadlock if
since we do not know if we have data that would * we tried to flush data, and since we do not know if we have data that
invalidate the current end of file on the server * would invalidate the current end of file on the server we can not go
we can not go to the server to get the new inod * to the server to get the new inode info.
info */ */
cifs_set_oplock_level(pCifsInode, oplock); server->ops->set_fid(cfile, &fid, oplock);
cifs_relock_file(cfile);
cifs_relock_file(pCifsFile);
reopen_error_exit: reopen_error_exit:
kfree(full_path); kfree(full_path);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册