Commit 105b6c05 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.18-smb3-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6

Pull cfis updates from Steve French:
 "Handlecache,  unmount, fiemap and two reconnect fixes"

* tag '5.18-smb3-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: use a different reconnect helper for non-cifsd threads
  cifs: we do not need a spinlock around the tree access during umount
  Adjust cifssb maximum read size
  cifs: truncate the inode and mapping when we simulate fcollapse
  cifs: fix handlecache and multiuser
parents ef510682 dca65818
......@@ -396,11 +396,11 @@ static int cifs_swn_resource_state_changed(struct cifs_swn_reg *swnreg, const ch
switch (state) {
case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE:
cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name);
cifs_mark_tcp_ses_conns_for_reconnect(swnreg->tcon->ses->server, true);
cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
break;
case CIFS_SWN_RESOURCE_STATE_AVAILABLE:
cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name);
cifs_mark_tcp_ses_conns_for_reconnect(swnreg->tcon->ses->server, true);
cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
break;
case CIFS_SWN_RESOURCE_STATE_UNKNOWN:
cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name);
......@@ -498,7 +498,7 @@ static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *a
goto unlock;
}
cifs_mark_tcp_ses_conns_for_reconnect(tcon->ses->server, false);
cifs_signal_cifsd_for_reconnect(tcon->ses->server, false);
unlock:
mutex_unlock(&tcon->ses->server->srv_mutex);
......
......@@ -210,6 +210,9 @@ cifs_read_super(struct super_block *sb)
if (rc)
goto out_no_root;
/* tune readahead according to rsize if readahead size not set on mount */
if (cifs_sb->ctx->rsize == 0)
cifs_sb->ctx->rsize =
tcon->ses->server->ops->negotiate_rsize(tcon, cifs_sb->ctx);
if (cifs_sb->ctx->rasize)
sb->s_bdi->ra_pages = cifs_sb->ctx->rasize / PAGE_SIZE;
else
......@@ -254,6 +257,9 @@ static void cifs_kill_sb(struct super_block *sb)
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_tcon *tcon;
struct cached_fid *cfid;
struct rb_root *root = &cifs_sb->tlink_tree;
struct rb_node *node;
struct tcon_link *tlink;
/*
* We ned to release all dentries for the cached directories
......@@ -263,16 +269,18 @@ static void cifs_kill_sb(struct super_block *sb)
dput(cifs_sb->root);
cifs_sb->root = NULL;
}
tcon = cifs_sb_master_tcon(cifs_sb);
if (tcon) {
node = rb_first(root);
while (node != NULL) {
tlink = rb_entry(node, struct tcon_link, tl_rbnode);
tcon = tlink_tcon(tlink);
cfid = &tcon->crfid;
mutex_lock(&cfid->fid_mutex);
if (cfid->dentry) {
dput(cfid->dentry);
cfid->dentry = NULL;
}
mutex_unlock(&cfid->fid_mutex);
node = rb_next(node);
}
kill_anon_super(sb);
......
......@@ -132,6 +132,9 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
struct smb_hdr *out_buf,
int *bytes_returned);
void
cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
bool all_channels);
void
cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
bool mark_smb_session);
extern int cifs_reconnect(struct TCP_Server_Info *server,
......
......@@ -162,11 +162,51 @@ static void cifs_resolve_server(struct work_struct *work)
mutex_unlock(&server->srv_mutex);
}
/*
* Update the tcpStatus for the server.
* This is used to signal the cifsd thread to call cifs_reconnect
* ONLY cifsd thread should call cifs_reconnect. For any other
* thread, use this function
*
* @server: the tcp ses for which reconnect is needed
* @all_channels: if this needs to be done for all channels
*/
void
cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
bool all_channels)
{
struct TCP_Server_Info *pserver;
struct cifs_ses *ses;
int i;
/* If server is a channel, select the primary channel */
pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
spin_lock(&cifs_tcp_ses_lock);
if (!all_channels) {
pserver->tcpStatus = CifsNeedReconnect;
spin_unlock(&cifs_tcp_ses_lock);
return;
}
list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
spin_lock(&ses->chan_lock);
for (i = 0; i < ses->chan_count; i++)
ses->chans[i].server->tcpStatus = CifsNeedReconnect;
spin_unlock(&ses->chan_lock);
}
spin_unlock(&cifs_tcp_ses_lock);
}
/*
* Mark all sessions and tcons for reconnect.
* IMPORTANT: make sure that this gets called only from
* cifsd thread. For any other thread, use
* cifs_signal_cifsd_for_reconnect
*
* @server: the tcp ses for which reconnect is needed
* @server needs to be previously set to CifsNeedReconnect.
*
* @mark_smb_session: whether even sessions need to be marked
*/
void
cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
......
......@@ -1355,7 +1355,7 @@ static void mark_for_reconnect_if_needed(struct cifs_tcon *tcon, struct dfs_cach
}
cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__);
cifs_mark_tcp_ses_conns_for_reconnect(tcon->ses->server, true);
cifs_signal_cifsd_for_reconnect(tcon->ses->server, true);
}
/* Refresh dfs referral of tcon and mark it for reconnect if needed */
......
......@@ -3740,6 +3740,11 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
break;
}
if (cifs_sb->ctx->rsize == 0)
cifs_sb->ctx->rsize =
server->ops->negotiate_rsize(tlink_tcon(open_file->tlink),
cifs_sb->ctx);
rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
&rsize, credits);
if (rc)
......@@ -4474,6 +4479,11 @@ static void cifs_readahead(struct readahead_control *ractl)
}
}
if (cifs_sb->ctx->rsize == 0)
cifs_sb->ctx->rsize =
server->ops->negotiate_rsize(tlink_tcon(open_file->tlink),
cifs_sb->ctx);
rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
&rsize, credits);
if (rc)
......
......@@ -228,7 +228,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
spin_unlock(&GlobalMid_Lock);
if (reconnect) {
cifs_mark_tcp_ses_conns_for_reconnect(server, false);
cifs_signal_cifsd_for_reconnect(server, false);
}
return mid;
......
......@@ -25,6 +25,7 @@
#include "smb2glob.h"
#include "cifs_ioctl.h"
#include "smbdirect.h"
#include "fscache.h"
#include "fs_context.h"
/* Change credits for different ops and return the total number of credits */
......@@ -3887,29 +3888,38 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
{
int rc;
unsigned int xid;
struct inode *inode;
struct cifsFileInfo *cfile = file->private_data;
struct cifsInodeInfo *cifsi;
__le64 eof;
xid = get_xid();
if (off >= i_size_read(file->f_inode) ||
off + len >= i_size_read(file->f_inode)) {
inode = d_inode(cfile->dentry);
cifsi = CIFS_I(inode);
if (off >= i_size_read(inode) ||
off + len >= i_size_read(inode)) {
rc = -EINVAL;
goto out;
}
rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
i_size_read(file->f_inode) - off - len, off);
i_size_read(inode) - off - len, off);
if (rc < 0)
goto out;
eof = cpu_to_le64(i_size_read(file->f_inode) - len);
eof = cpu_to_le64(i_size_read(inode) - len);
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, cfile->pid, &eof);
if (rc < 0)
goto out;
rc = 0;
cifsi->server_eof = i_size_read(inode) - len;
truncate_setsize(inode, cifsi->server_eof);
fscache_resize_cookie(cifs_inode_cookie(inode), cifsi->server_eof);
out:
free_xid(xid);
return rc;
......
......@@ -430,7 +430,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
* be taken as the remainder of this one. We need to kill the
* socket so the server throws away the partial SMB
*/
cifs_mark_tcp_ses_conns_for_reconnect(server, false);
cifs_signal_cifsd_for_reconnect(server, false);
trace_smb3_partial_send_reconnect(server->CurrentMid,
server->conn_id, server->hostname);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment