diff options
Diffstat (limited to 'fs/smb/client/file.c')
-rw-r--r-- | fs/smb/client/file.c | 121 |
1 files changed, 84 insertions, 37 deletions
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index cb907e18cc35..474dadeb1593 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -97,8 +97,12 @@ retry: cifs_trace_rw_credits_write_prepare); #ifdef CONFIG_CIFS_SMB_DIRECT - if (server->smbd_conn) - stream->sreq_max_segs = server->smbd_conn->max_frmr_depth; + if (server->smbd_conn) { + const struct smbdirect_socket_parameters *sp = + smbd_get_parameters(server->smbd_conn); + + stream->sreq_max_segs = sp->max_frmr_depth; + } #endif } @@ -187,8 +191,12 @@ static int cifs_prepare_read(struct netfs_io_subrequest *subreq) cifs_trace_rw_credits_read_submit); #ifdef CONFIG_CIFS_SMB_DIRECT - if (server->smbd_conn) - rreq->io_streams[0].sreq_max_segs = server->smbd_conn->max_frmr_depth; + if (server->smbd_conn) { + const struct smbdirect_socket_parameters *sp = + smbd_get_parameters(server->smbd_conn); + + rreq->io_streams[0].sreq_max_segs = sp->max_frmr_depth; + } #endif return 0; } @@ -944,6 +952,66 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, } } +int cifs_file_flush(const unsigned int xid, struct inode *inode, + struct cifsFileInfo *cfile) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct cifs_tcon *tcon; + int rc; + + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC) + return 0; + + if (cfile && (OPEN_FMODE(cfile->f_flags) & FMODE_WRITE)) { + tcon = tlink_tcon(cfile->tlink); + return tcon->ses->server->ops->flush(xid, tcon, + &cfile->fid); + } + rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile); + if (!rc) { + tcon = tlink_tcon(cfile->tlink); + rc = tcon->ses->server->ops->flush(xid, tcon, &cfile->fid); + cifsFileInfo_put(cfile); + } else if (rc == -EBADF) { + rc = 0; + } + return rc; +} + +static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry) +{ + struct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry)); + struct inode *inode = d_inode(dentry); + struct cifsFileInfo *cfile = NULL; + struct TCP_Server_Info *server; + struct cifs_tcon *tcon; + int rc; + + rc = filemap_write_and_wait(inode->i_mapping); + if (is_interrupt_error(rc)) + return -ERESTARTSYS; + mapping_set_error(inode->i_mapping, rc); + + cfile = find_writable_file(cinode, FIND_WR_FSUID_ONLY); + rc = cifs_file_flush(xid, inode, cfile); + if (!rc) { + if (cfile) { + tcon = tlink_tcon(cfile->tlink); + server = tcon->ses->server; + rc = server->ops->set_file_size(xid, tcon, + cfile, 0, false); + } + if (!rc) { + netfs_resize_file(&cinode->netfs, 0, true); + cifs_setsize(inode, 0); + inode->i_blocks = 0; + } + } + if (cfile) + cifsFileInfo_put(cfile); + return rc; +} + int cifs_open(struct inode *inode, struct file *file) { @@ -996,6 +1064,12 @@ int cifs_open(struct inode *inode, struct file *file) file->f_op = &cifs_file_direct_ops; } + if (file->f_flags & O_TRUNC) { + rc = cifs_do_truncate(xid, file_dentry(file)); + if (rc) + goto out; + } + /* Get the cached handle as SMB2 close is deferred */ if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) { rc = cifs_get_writable_path(tcon, full_path, @@ -2677,13 +2751,10 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, int datasync) { - unsigned int xid; - int rc = 0; - struct cifs_tcon *tcon; - struct TCP_Server_Info *server; struct cifsFileInfo *smbfile = file->private_data; struct inode *inode = file_inode(file); - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + unsigned int xid; + int rc; rc = file_write_and_wait_range(file, start, end); if (rc) { @@ -2691,39 +2762,15 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, return rc; } - xid = get_xid(); - - cifs_dbg(FYI, "Sync file - name: %pD datasync: 0x%x\n", - file, datasync); + cifs_dbg(FYI, "%s: name=%pD datasync=0x%x\n", __func__, file, datasync); if (!CIFS_CACHE_READ(CIFS_I(inode))) { rc = cifs_zap_mapping(inode); - if (rc) { - cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc); - rc = 0; /* don't care about it in fsync */ - } + cifs_dbg(FYI, "%s: invalidate mapping: rc = %d\n", __func__, rc); } - tcon = tlink_tcon(smbfile->tlink); - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { - server = tcon->ses->server; - if (server->ops->flush == NULL) { - rc = -ENOSYS; - goto strict_fsync_exit; - } - - if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { - smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); - if (smbfile) { - rc = server->ops->flush(xid, tcon, &smbfile->fid); - cifsFileInfo_put(smbfile); - } else - cifs_dbg(FYI, "ignore fsync for file not open for write\n"); - } else - rc = server->ops->flush(xid, tcon, &smbfile->fid); - } - -strict_fsync_exit: + xid = get_xid(); + rc = cifs_file_flush(xid, inode, smbfile); free_xid(xid); return rc; } |