|
@@ -78,8 +78,36 @@ static inline int cifs_convert_flags(unsigned int flags)
|
|
return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
|
|
return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
|
|
FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
|
|
FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
|
|
FILE_READ_DATA);
|
|
FILE_READ_DATA);
|
|
|
|
+}
|
|
|
|
|
|
|
|
+static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
|
|
|
|
+{
|
|
|
|
+ fmode_t posix_flags = 0;
|
|
|
|
|
|
|
|
+ if ((flags & O_ACCMODE) == O_RDONLY)
|
|
|
|
+ posix_flags = FMODE_READ;
|
|
|
|
+ else if ((flags & O_ACCMODE) == O_WRONLY)
|
|
|
|
+ posix_flags = FMODE_WRITE;
|
|
|
|
+ else if ((flags & O_ACCMODE) == O_RDWR) {
|
|
|
|
+ /* GENERIC_ALL is too much permission to request
|
|
|
|
+ can cause unnecessary access denied on create */
|
|
|
|
+ /* return GENERIC_ALL; */
|
|
|
|
+ posix_flags = FMODE_READ | FMODE_WRITE;
|
|
|
|
+ }
|
|
|
|
+ /* can not map O_CREAT or O_EXCL or O_TRUNC flags when
|
|
|
|
+ reopening a file. They had their effect on the original open */
|
|
|
|
+ if (flags & O_APPEND)
|
|
|
|
+ posix_flags |= (fmode_t)O_APPEND;
|
|
|
|
+ if (flags & O_SYNC)
|
|
|
|
+ posix_flags |= (fmode_t)O_SYNC;
|
|
|
|
+ if (flags & O_DIRECTORY)
|
|
|
|
+ posix_flags |= (fmode_t)O_DIRECTORY;
|
|
|
|
+ if (flags & O_NOFOLLOW)
|
|
|
|
+ posix_flags |= (fmode_t)O_NOFOLLOW;
|
|
|
|
+ if (flags & O_DIRECT)
|
|
|
|
+ posix_flags |= (fmode_t)O_DIRECT;
|
|
|
|
+
|
|
|
|
+ return posix_flags;
|
|
}
|
|
}
|
|
|
|
|
|
static inline int cifs_get_disposition(unsigned int flags)
|
|
static inline int cifs_get_disposition(unsigned int flags)
|
|
@@ -96,6 +124,80 @@ static inline int cifs_get_disposition(unsigned int flags)
|
|
return FILE_OPEN;
|
|
return FILE_OPEN;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* all arguments to this function must be checked for validity in caller */
|
|
|
|
+static inline int cifs_posix_open_inode_helper(struct inode *inode,
|
|
|
|
+ struct file *file, struct cifsInodeInfo *pCifsInode,
|
|
|
|
+ struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
|
|
|
|
+{
|
|
|
|
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
|
|
|
+/* struct timespec temp; */ /* BB REMOVEME BB */
|
|
|
|
+
|
|
|
|
+ file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
|
|
|
|
+ if (file->private_data == NULL)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
|
|
|
|
+ write_lock(&GlobalSMBSeslock);
|
|
|
|
+ list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
|
|
|
|
+
|
|
|
|
+ pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
|
|
|
|
+ if (pCifsInode == NULL) {
|
|
|
|
+ write_unlock(&GlobalSMBSeslock);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* want handles we can use to read with first
|
|
|
|
+ in the list so we do not have to walk the
|
|
|
|
+ list to search for one in write_begin */
|
|
|
|
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
|
|
|
|
+ list_add_tail(&pCifsFile->flist,
|
|
|
|
+ &pCifsInode->openFileList);
|
|
|
|
+ } else {
|
|
|
|
+ list_add(&pCifsFile->flist,
|
|
|
|
+ &pCifsInode->openFileList);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (pCifsInode->clientCanCacheRead) {
|
|
|
|
+ /* we have the inode open somewhere else
|
|
|
|
+ no need to discard cache data */
|
|
|
|
+ goto psx_client_can_cache;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* BB FIXME need to fix this check to move it earlier into posix_open
|
|
|
|
+ BB fIX following section BB FIXME */
|
|
|
|
+
|
|
|
|
+ /* if not oplocked, invalidate inode pages if mtime or file
|
|
|
|
+ size changed */
|
|
|
|
+/* temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
|
|
|
|
+ if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
|
|
|
|
+ (file->f_path.dentry->d_inode->i_size ==
|
|
|
|
+ (loff_t)le64_to_cpu(buf->EndOfFile))) {
|
|
|
|
+ cFYI(1, ("inode unchanged on server"));
|
|
|
|
+ } else {
|
|
|
|
+ if (file->f_path.dentry->d_inode->i_mapping) {
|
|
|
|
+ rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
|
|
|
|
+ if (rc != 0)
|
|
|
|
+ CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
|
|
|
|
+ }
|
|
|
|
+ cFYI(1, ("invalidating remote inode since open detected it "
|
|
|
|
+ "changed"));
|
|
|
|
+ invalidate_remote_inode(file->f_path.dentry->d_inode);
|
|
|
|
+ } */
|
|
|
|
+
|
|
|
|
+psx_client_can_cache:
|
|
|
|
+ if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
|
|
|
|
+ pCifsInode->clientCanCacheAll = true;
|
|
|
|
+ pCifsInode->clientCanCacheRead = true;
|
|
|
|
+ cFYI(1, ("Exclusive Oplock granted on inode %p",
|
|
|
|
+ file->f_path.dentry->d_inode));
|
|
|
|
+ } else if ((oplock & 0xF) == OPLOCK_READ)
|
|
|
|
+ pCifsInode->clientCanCacheRead = true;
|
|
|
|
+
|
|
|
|
+ /* will have to change the unlock if we reenable the
|
|
|
|
+ filemap_fdatawrite (which does not seem necessary */
|
|
|
|
+ write_unlock(&GlobalSMBSeslock);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/* all arguments to this function must be checked for validity in caller */
|
|
/* all arguments to this function must be checked for validity in caller */
|
|
static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
|
|
static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
|
|
struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
|
|
struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
|
|
@@ -167,7 +269,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
|
int rc = -EACCES;
|
|
int rc = -EACCES;
|
|
int xid, oplock;
|
|
int xid, oplock;
|
|
struct cifs_sb_info *cifs_sb;
|
|
struct cifs_sb_info *cifs_sb;
|
|
- struct cifsTconInfo *pTcon;
|
|
|
|
|
|
+ struct cifsTconInfo *tcon;
|
|
struct cifsFileInfo *pCifsFile;
|
|
struct cifsFileInfo *pCifsFile;
|
|
struct cifsInodeInfo *pCifsInode;
|
|
struct cifsInodeInfo *pCifsInode;
|
|
struct list_head *tmp;
|
|
struct list_head *tmp;
|
|
@@ -180,7 +282,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
|
xid = GetXid();
|
|
xid = GetXid();
|
|
|
|
|
|
cifs_sb = CIFS_SB(inode->i_sb);
|
|
cifs_sb = CIFS_SB(inode->i_sb);
|
|
- pTcon = cifs_sb->tcon;
|
|
|
|
|
|
+ tcon = cifs_sb->tcon;
|
|
|
|
|
|
if (file->f_flags & O_CREAT) {
|
|
if (file->f_flags & O_CREAT) {
|
|
/* search inode for this file and fill in file->private_data */
|
|
/* search inode for this file and fill in file->private_data */
|
|
@@ -220,6 +322,45 @@ int cifs_open(struct inode *inode, struct file *file)
|
|
|
|
|
|
cFYI(1, ("inode = 0x%p file flags are 0x%x for %s",
|
|
cFYI(1, ("inode = 0x%p file flags are 0x%x for %s",
|
|
inode, file->f_flags, full_path));
|
|
inode, file->f_flags, full_path));
|
|
|
|
+
|
|
|
|
+ if (oplockEnabled)
|
|
|
|
+ oplock = REQ_OPLOCK;
|
|
|
|
+ else
|
|
|
|
+ oplock = 0;
|
|
|
|
+
|
|
|
|
+ if (!tcon->broken_posix_open && tcon->unix_ext &&
|
|
|
|
+ (tcon->ses->capabilities & CAP_UNIX) &&
|
|
|
|
+ (CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
|
|
|
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
|
|
|
+ int oflags = (int) cifs_posix_convert_flags(file->f_flags);
|
|
|
|
+ /* 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 */,
|
|
|
|
+ oflags, &oplock, &netfid, xid);
|
|
|
|
+ if (rc == 0) {
|
|
|
|
+ cFYI(1, ("posix open succeeded"));
|
|
|
|
+ /* no need for special case handling of setting mode
|
|
|
|
+ on read only files needed here */
|
|
|
|
+
|
|
|
|
+ cifs_posix_open_inode_helper(inode, file, pCifsInode,
|
|
|
|
+ pCifsFile, oplock, netfid);
|
|
|
|
+ goto out;
|
|
|
|
+ } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
|
|
|
+ if (tcon->ses->serverNOS)
|
|
|
|
+ cERROR(1, ("server %s of type %s returned"
|
|
|
|
+ " unexpected error on SMB posix open"
|
|
|
|
+ ", disabling posix open support."
|
|
|
|
+ " Check if server update available.",
|
|
|
|
+ tcon->ses->serverName,
|
|
|
|
+ tcon->ses->serverNOS));
|
|
|
|
+ tcon->broken_posix_open = 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 */
|
|
|
|
+ }
|
|
|
|
+
|
|
desiredAccess = cifs_convert_flags(file->f_flags);
|
|
desiredAccess = cifs_convert_flags(file->f_flags);
|
|
|
|
|
|
/*********************************************************************
|
|
/*********************************************************************
|
|
@@ -248,11 +389,6 @@ int cifs_open(struct inode *inode, struct file *file)
|
|
|
|
|
|
disposition = cifs_get_disposition(file->f_flags);
|
|
disposition = cifs_get_disposition(file->f_flags);
|
|
|
|
|
|
- if (oplockEnabled)
|
|
|
|
- oplock = REQ_OPLOCK;
|
|
|
|
- else
|
|
|
|
- oplock = 0;
|
|
|
|
-
|
|
|
|
/* BB pass O_SYNC flag through on file attributes .. BB */
|
|
/* BB pass O_SYNC flag through on file attributes .. BB */
|
|
|
|
|
|
/* Also refresh inode by passing in file_info buf returned by SMBOpen
|
|
/* Also refresh inode by passing in file_info buf returned by SMBOpen
|
|
@@ -269,7 +405,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
|
}
|
|
}
|
|
|
|
|
|
if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
|
|
if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
|
|
- rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
|
|
|
|
|
|
+ rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
|
|
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
|
|
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
|
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
|
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
|
|
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
@@ -278,7 +414,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
|
|
|
|
|
if (rc == -EIO) {
|
|
if (rc == -EIO) {
|
|
/* Old server, try legacy style OpenX */
|
|
/* Old server, try legacy style OpenX */
|
|
- rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
|
|
|
|
|
|
+ rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
|
|
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
|
|
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
|
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
|
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
|
|
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
@@ -295,12 +431,12 @@ int cifs_open(struct inode *inode, struct file *file)
|
|
}
|
|
}
|
|
pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
|
|
pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
|
|
write_lock(&GlobalSMBSeslock);
|
|
write_lock(&GlobalSMBSeslock);
|
|
- list_add(&pCifsFile->tlist, &pTcon->openFileList);
|
|
|
|
|
|
+ list_add(&pCifsFile->tlist, &tcon->openFileList);
|
|
|
|
|
|
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
|
|
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
|
|
if (pCifsInode) {
|
|
if (pCifsInode) {
|
|
rc = cifs_open_inode_helper(inode, file, pCifsInode,
|
|
rc = cifs_open_inode_helper(inode, file, pCifsInode,
|
|
- pCifsFile, pTcon,
|
|
|
|
|
|
+ pCifsFile, tcon,
|
|
&oplock, buf, full_path, xid);
|
|
&oplock, buf, full_path, xid);
|
|
} else {
|
|
} else {
|
|
write_unlock(&GlobalSMBSeslock);
|
|
write_unlock(&GlobalSMBSeslock);
|
|
@@ -309,7 +445,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
|
if (oplock & CIFS_CREATE_ACTION) {
|
|
if (oplock & CIFS_CREATE_ACTION) {
|
|
/* time to set mode which we can not set earlier due to
|
|
/* time to set mode which we can not set earlier due to
|
|
problems creating new read-only files */
|
|
problems creating new read-only files */
|
|
- if (pTcon->unix_ext) {
|
|
|
|
|
|
+ if (tcon->unix_ext) {
|
|
struct cifs_unix_set_info_args args = {
|
|
struct cifs_unix_set_info_args args = {
|
|
.mode = inode->i_mode,
|
|
.mode = inode->i_mode,
|
|
.uid = NO_CHANGE_64,
|
|
.uid = NO_CHANGE_64,
|
|
@@ -319,7 +455,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
|
.mtime = NO_CHANGE_64,
|
|
.mtime = NO_CHANGE_64,
|
|
.device = 0,
|
|
.device = 0,
|
|
};
|
|
};
|
|
- CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args,
|
|
|
|
|
|
+ CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
|
|
cifs_sb->local_nls,
|
|
cifs_sb->local_nls,
|
|
cifs_sb->mnt_cifs_flags &
|
|
cifs_sb->mnt_cifs_flags &
|
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
@@ -349,7 +485,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
|
|
int rc = -EACCES;
|
|
int rc = -EACCES;
|
|
int xid, oplock;
|
|
int xid, oplock;
|
|
struct cifs_sb_info *cifs_sb;
|
|
struct cifs_sb_info *cifs_sb;
|
|
- struct cifsTconInfo *pTcon;
|
|
|
|
|
|
+ struct cifsTconInfo *tcon;
|
|
struct cifsFileInfo *pCifsFile;
|
|
struct cifsFileInfo *pCifsFile;
|
|
struct cifsInodeInfo *pCifsInode;
|
|
struct cifsInodeInfo *pCifsInode;
|
|
struct inode *inode;
|
|
struct inode *inode;
|
|
@@ -387,7 +523,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
|
|
}
|
|
}
|
|
|
|
|
|
cifs_sb = CIFS_SB(inode->i_sb);
|
|
cifs_sb = CIFS_SB(inode->i_sb);
|
|
- pTcon = cifs_sb->tcon;
|
|
|
|
|
|
+ tcon = cifs_sb->tcon;
|
|
|
|
|
|
/* can not grab rename sem here because various ops, including
|
|
/* can not grab rename sem here because various ops, including
|
|
those that already have the rename sem can end up causing writepage
|
|
those that already have the rename sem can end up causing writepage
|
|
@@ -404,20 +540,37 @@ reopen_error_exit:
|
|
|
|
|
|
cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
|
|
cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
|
|
inode, file->f_flags, full_path));
|
|
inode, file->f_flags, full_path));
|
|
- desiredAccess = cifs_convert_flags(file->f_flags);
|
|
|
|
|
|
|
|
if (oplockEnabled)
|
|
if (oplockEnabled)
|
|
oplock = REQ_OPLOCK;
|
|
oplock = REQ_OPLOCK;
|
|
else
|
|
else
|
|
oplock = 0;
|
|
oplock = 0;
|
|
|
|
|
|
|
|
+ if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
|
|
|
|
+ (CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
|
|
|
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
|
|
|
+ int oflags = (int) cifs_posix_convert_flags(file->f_flags);
|
|
|
|
+ /* can not refresh inode info since size could be stale */
|
|
|
|
+ rc = cifs_posix_open(full_path, NULL, inode->i_sb,
|
|
|
|
+ cifs_sb->mnt_file_mode /* ignored */,
|
|
|
|
+ oflags, &oplock, &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 */
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ desiredAccess = cifs_convert_flags(file->f_flags);
|
|
|
|
+
|
|
/* Can not refresh inode by passing in file_info buf to be returned
|
|
/* Can not refresh inode by passing in file_info buf to be returned
|
|
by SMBOpen and then calling get_inode_info with returned buf
|
|
by SMBOpen and then calling get_inode_info with returned buf
|
|
since file might have write behind data that needs to be flushed
|
|
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
|
|
and server version of file size can be stale. If we knew for sure
|
|
that inode was not dirty locally we could do this */
|
|
that inode was not dirty locally we could do this */
|
|
|
|
|
|
- rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
|
|
|
|
|
|
+ rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess,
|
|
CREATE_NOT_DIR, &netfid, &oplock, NULL,
|
|
CREATE_NOT_DIR, &netfid, &oplock, NULL,
|
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
@@ -426,6 +579,7 @@ reopen_error_exit:
|
|
cFYI(1, ("cifs_open returned 0x%x", rc));
|
|
cFYI(1, ("cifs_open returned 0x%x", rc));
|
|
cFYI(1, ("oplock: %d", oplock));
|
|
cFYI(1, ("oplock: %d", oplock));
|
|
} else {
|
|
} else {
|
|
|
|
+reopen_success:
|
|
pCifsFile->netfid = netfid;
|
|
pCifsFile->netfid = netfid;
|
|
pCifsFile->invalidHandle = false;
|
|
pCifsFile->invalidHandle = false;
|
|
up(&pCifsFile->fh_sem);
|
|
up(&pCifsFile->fh_sem);
|
|
@@ -439,7 +593,7 @@ reopen_error_exit:
|
|
go to server to get inode info */
|
|
go to server to get inode info */
|
|
pCifsInode->clientCanCacheAll = false;
|
|
pCifsInode->clientCanCacheAll = false;
|
|
pCifsInode->clientCanCacheRead = false;
|
|
pCifsInode->clientCanCacheRead = false;
|
|
- if (pTcon->unix_ext)
|
|
|
|
|
|
+ if (tcon->unix_ext)
|
|
rc = cifs_get_inode_info_unix(&inode,
|
|
rc = cifs_get_inode_info_unix(&inode,
|
|
full_path, inode->i_sb, xid);
|
|
full_path, inode->i_sb, xid);
|
|
else
|
|
else
|
|
@@ -467,7 +621,6 @@ reopen_error_exit:
|
|
cifs_relock_file(pCifsFile);
|
|
cifs_relock_file(pCifsFile);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
kfree(full_path);
|
|
kfree(full_path);
|
|
FreeXid(xid);
|
|
FreeXid(xid);
|
|
return rc;
|
|
return rc;
|
|
@@ -1523,6 +1676,9 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
|
|
{
|
|
{
|
|
int xid;
|
|
int xid;
|
|
int rc = 0;
|
|
int rc = 0;
|
|
|
|
+ struct cifsTconInfo *tcon;
|
|
|
|
+ struct cifsFileInfo *smbfile =
|
|
|
|
+ (struct cifsFileInfo *)file->private_data;
|
|
struct inode *inode = file->f_path.dentry->d_inode;
|
|
struct inode *inode = file->f_path.dentry->d_inode;
|
|
|
|
|
|
xid = GetXid();
|
|
xid = GetXid();
|
|
@@ -1534,7 +1690,12 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
|
|
if (rc == 0) {
|
|
if (rc == 0) {
|
|
rc = CIFS_I(inode)->write_behind_rc;
|
|
rc = CIFS_I(inode)->write_behind_rc;
|
|
CIFS_I(inode)->write_behind_rc = 0;
|
|
CIFS_I(inode)->write_behind_rc = 0;
|
|
|
|
+ tcon = CIFS_SB(inode->i_sb)->tcon;
|
|
|
|
+ if (!rc && tcon && smbfile &&
|
|
|
|
+ !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
|
|
|
|
+ rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
|
|
}
|
|
}
|
|
|
|
+
|
|
FreeXid(xid);
|
|
FreeXid(xid);
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|