static int
cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
- struct cifs_tcon *tcon, unsigned int f_flags, __u32 *poplock,
- __u16 *pnetfid, unsigned int xid)
+ struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock,
+ struct cifs_fid *fid, unsigned int xid)
{
int rc;
- int desiredAccess;
+ int desired_access;
int disposition;
int create_options = CREATE_NOT_DIR;
FILE_ALL_INFO *buf;
- desiredAccess = cifs_convert_flags(f_flags);
+ if (!tcon->ses->server->ops->open)
+ return -ENOSYS;
+
+ desired_access = cifs_convert_flags(f_flags);
/*********************************************************************
* open flag mapping table:
if (backup_cred(cifs_sb))
create_options |= CREATE_OPEN_BACKUP_INTENT;
- if (tcon->ses->capabilities & CAP_NT_SMBS)
- rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
- desiredAccess, create_options, pnetfid, poplock, buf,
- cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
- & CIFS_MOUNT_MAP_SPECIAL_CHR);
- else
- rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
- desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
- cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
- & CIFS_MOUNT_MAP_SPECIAL_CHR);
+ rc = tcon->ses->server->ops->open(xid, tcon, full_path, disposition,
+ desired_access, create_options, fid,
+ oplock, buf, cifs_sb);
if (rc)
goto out;
xid);
else
rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
- xid, pnetfid);
+ xid, &fid->netfid);
out:
kfree(buf);
}
struct cifsFileInfo *
-cifs_new_fileinfo(__u16 fileHandle, struct file *file,
+cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
struct tcon_link *tlink, __u32 oplock)
{
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
- struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
- struct cifsFileInfo *pCifsFile;
-
- pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
- if (pCifsFile == NULL)
- return pCifsFile;
-
- pCifsFile->count = 1;
- pCifsFile->netfid = fileHandle;
- pCifsFile->pid = current->tgid;
- pCifsFile->uid = current_fsuid();
- pCifsFile->dentry = dget(dentry);
- pCifsFile->f_flags = file->f_flags;
- pCifsFile->invalidHandle = false;
- pCifsFile->tlink = cifs_get_tlink(tlink);
- mutex_init(&pCifsFile->fh_mutex);
- INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
- INIT_LIST_HEAD(&pCifsFile->llist);
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct cifsFileInfo *cfile;
+
+ cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+ if (cfile == NULL)
+ return cfile;
+
+ cfile->count = 1;
+ cfile->pid = current->tgid;
+ cfile->uid = current_fsuid();
+ cfile->dentry = dget(dentry);
+ cfile->f_flags = file->f_flags;
+ cfile->invalidHandle = false;
+ cfile->tlink = cifs_get_tlink(tlink);
+ mutex_init(&cfile->fh_mutex);
+ INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
+ INIT_LIST_HEAD(&cfile->llist);
+ tlink_tcon(tlink)->ses->server->ops->set_fid(cfile, fid, oplock);
spin_lock(&cifs_file_list_lock);
- list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
+ list_add(&cfile->tlist, &(tlink_tcon(tlink)->openFileList));
/* if readable file instance put first in list*/
if (file->f_mode & FMODE_READ)
- list_add(&pCifsFile->flist, &pCifsInode->openFileList);
+ list_add(&cfile->flist, &cinode->openFileList);
else
- list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
+ list_add_tail(&cfile->flist, &cinode->openFileList);
spin_unlock(&cifs_file_list_lock);
- cifs_set_oplock_level(pCifsInode, oplock);
- pCifsInode->can_cache_brlcks = pCifsInode->clientCanCacheAll;
-
- file->private_data = pCifsFile;
- return pCifsFile;
+ file->private_data = cfile;
+ return cfile;
}
static void cifs_del_lock_waiters(struct cifsLockInfo *lock);
if (list_empty(&cifsi->openFileList)) {
cFYI(1, "closing last open instance for inode %p",
cifs_file->dentry->d_inode);
-
- /* in strict cache mode we need invalidate mapping on the last
- close because it may cause a error when we open this file
- again and get at least level II oplock */
+ /*
+ * In strict cache mode we need invalidate mapping on the last
+ * close because it may cause a error when we open this file
+ * again and get at least level II oplock.
+ */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
CIFS_I(inode)->invalid_mapping = true;
-
cifs_set_oplock_level(cifsi, 0);
}
spin_unlock(&cifs_file_list_lock);
cancel_work_sync(&cifs_file->oplock_break);
if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
+ struct TCP_Server_Info *server = tcon->ses->server;
unsigned int xid;
- int rc;
+ int rc = -ENOSYS;
+
xid = get_xid();
- rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
+ if (server->ops->close)
+ rc = server->ops->close(xid, tcon, &cifs_file->fid);
free_xid(xid);
}
struct cifs_sb_info *cifs_sb;
struct cifs_tcon *tcon;
struct tcon_link *tlink;
- struct cifsFileInfo *pCifsFile = NULL;
+ struct cifsFileInfo *cfile = NULL;
char *full_path = NULL;
bool posix_open_ok = false;
- __u16 netfid;
+ struct cifs_fid fid;
xid = get_xid();
/* can not refresh inode info since size could be stale */
rc = cifs_posix_open(full_path, &inode, inode->i_sb,
cifs_sb->mnt_file_mode /* ignored */,
- file->f_flags, &oplock, &netfid, xid);
+ file->f_flags, &oplock, &fid.netfid, xid);
if (rc == 0) {
cFYI(1, "posix open succeeded");
posix_open_ok = true;
} else if ((rc != -EIO) && (rc != -EREMOTE) &&
(rc != -EOPNOTSUPP)) /* path not found or net err */
goto out;
- /* else fallthrough to retry open the old way on network i/o
- or DFS errors */
+ /*
+ * Else fallthrough to retry open the old way on network i/o
+ * or DFS errors.
+ */
}
if (!posix_open_ok) {
rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
- file->f_flags, &oplock, &netfid, xid);
+ file->f_flags, &oplock, &fid, xid);
if (rc)
goto out;
}
- pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
- if (pCifsFile == NULL) {
- CIFSSMBClose(xid, tcon, netfid);
+ cfile = cifs_new_fileinfo(&fid, file, tlink, oplock);
+ if (cfile == NULL) {
+ if (tcon->ses->server->ops->close)
+ tcon->ses->server->ops->close(xid, tcon, &fid);
rc = -ENOMEM;
goto out;
}
cifs_fscache_set_inode_cookie(inode, file);
if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
- /* time to set mode which we can not set earlier due to
- problems creating new read-only files */
+ /*
+ * Time to set mode which we can not set earlier due to
+ * problems creating new read-only files.
+ */
struct cifs_unix_set_info_args args = {
.mode = inode->i_mode,
.uid = NO_CHANGE_64,
.mtime = NO_CHANGE_64,
.device = 0,
};
- CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid,
- pCifsFile->pid);
+ CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid,
+ cfile->pid);
}
out:
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;
* 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->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);
+ 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.
+ */
- cifs_relock_file(pCifsFile);
+ server->ops->set_fid(cfile, &fid, oplock);
+ cifs_relock_file(cfile);
reopen_error_exit:
kfree(full_path);
{
int rc = 0;
unsigned int xid;
- struct cifsFileInfo *pCFileStruct = file->private_data;
- char *ptmp;
+ struct cifsFileInfo *cfile = file->private_data;
+ char *tmp;
cFYI(1, "Closedir inode = 0x%p", inode);
xid = get_xid();
- if (pCFileStruct) {
- struct cifs_tcon *pTcon = tlink_tcon(pCFileStruct->tlink);
+ if (cfile) {
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
cFYI(1, "Freeing private data in close dir");
spin_lock(&cifs_file_list_lock);
- if (!pCFileStruct->srch_inf.endOfSearch &&
- !pCFileStruct->invalidHandle) {
- pCFileStruct->invalidHandle = true;
+ if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
+ cfile->invalidHandle = true;
spin_unlock(&cifs_file_list_lock);
- rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
- cFYI(1, "Closing uncompleted readdir with rc %d",
- rc);
+ rc = CIFSFindClose(xid, tcon, cfile->fid.netfid);
+ cFYI(1, "Closing uncompleted readdir with rc %d", rc);
/* not much we can do if it fails anyway, ignore rc */
rc = 0;
} else
spin_unlock(&cifs_file_list_lock);
- ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
- if (ptmp) {
+ tmp = cfile->srch_inf.ntwrk_buf_start;
+ if (tmp) {
cFYI(1, "closedir free smb buf in srch struct");
- pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
- if (pCFileStruct->srch_inf.smallBuf)
- cifs_small_buf_release(ptmp);
+ cfile->srch_inf.ntwrk_buf_start = NULL;
+ if (cfile->srch_inf.smallBuf)
+ cifs_small_buf_release(tmp);
else
- cifs_buf_release(ptmp);
+ cifs_buf_release(tmp);
}
- cifs_put_tlink(pCFileStruct->tlink);
+ cifs_put_tlink(cfile->tlink);
kfree(file->private_data);
file->private_data = NULL;
}
cur->OffsetLow = cpu_to_le32((u32)li->offset);
cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
if (++num == max_num) {
- stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
+ stored_rc = cifs_lockv(xid, tcon,
+ cfile->fid.netfid,
(__u8)li->type, 0, num,
buf);
if (stored_rc)
}
if (num) {
- stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
+ stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
(__u8)types[i], 0, num, buf);
if (stored_rc)
rc = stored_rc;
type = CIFS_WRLCK;
lck = list_entry(el, struct lock_to_push, llist);
lck->pid = flock->fl_pid;
- lck->netfid = cfile->netfid;
+ lck->netfid = cfile->fid.netfid;
lck->length = length;
lck->type = type;
lck->offset = flock->fl_start;
cifs_mandatory_lock(unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
__u64 length, __u32 type, int lock, int unlock, bool wait)
{
- return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->netfid,
+ return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->fid.netfid,
current->tgid, length, offset, unlock, lock,
(__u8)type, wait, 0);
}
struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
struct TCP_Server_Info *server = tcon->ses->server;
- __u16 netfid = cfile->netfid;
+ __u16 netfid = cfile->fid.netfid;
if (posix_lck) {
int posix_lock_type;
*/
list_move(&li->llist, &tmp_llist);
if (++num == max_num) {
- stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
+ stored_rc = cifs_lockv(xid, tcon,
+ cfile->fid.netfid,
li->type, num, 0, buf);
if (stored_rc) {
/*
cur++;
}
if (num) {
- stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
+ stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
types[i], num, 0, buf);
if (stored_rc) {
cifs_move_llist(&tmp_llist, &cfile->llist);
struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
struct TCP_Server_Info *server = tcon->ses->server;
- __u16 netfid = cfile->netfid;
+ __u16 netfid = cfile->fid.netfid;
if (posix_lck) {
int posix_lock_type;
tcon->ses->server);
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- netfid = cfile->netfid;
+ netfid = cfile->fid.netfid;
cinode = CIFS_I(file->f_path.dentry->d_inode);
if (cap_unix(tcon->ses) &&
/* iov[0] is reserved for smb header */
iov[1].iov_base = (char *)write_data + total_written;
iov[1].iov_len = len;
- io_parms.netfid = open_file->netfid;
+ io_parms.netfid = open_file->fid.netfid;
io_parms.pid = pid;
io_parms.tcon = pTcon;
io_parms.offset = *poffset;
tcon = tlink_tcon(smbfile->tlink);
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
- rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
+ rc = CIFSSMBFlush(xid, tcon, smbfile->fid.netfid);
free_xid(xid);
mutex_unlock(&inode->i_mutex);
tcon = tlink_tcon(smbfile->tlink);
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
- rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
+ rc = CIFSSMBFlush(xid, tcon, smbfile->fid.netfid);
free_xid(xid);
mutex_unlock(&inode->i_mutex);
if (rc != 0)
break;
}
- io_parms.netfid = open_file->netfid;
+ io_parms.netfid = open_file->fid.netfid;
io_parms.pid = pid;
io_parms.tcon = tcon;
io_parms.offset = *poffset;
* disconnected since oplock already released by the server
*/
if (!cfile->oplock_break_cancelled) {
- rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid,
+ rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->fid.netfid,
current->tgid, 0, 0, 0, 0,
LOCKING_ANDX_OPLOCK_RELEASE, false,
cinode->clientCanCacheRead ? 1 : 0);