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 ...@@ -396,11 +396,11 @@ static int cifs_swn_resource_state_changed(struct cifs_swn_reg *swnreg, const ch
switch (state) { switch (state) {
case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE: case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE:
cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name); 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; break;
case CIFS_SWN_RESOURCE_STATE_AVAILABLE: case CIFS_SWN_RESOURCE_STATE_AVAILABLE:
cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name); 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; break;
case CIFS_SWN_RESOURCE_STATE_UNKNOWN: case CIFS_SWN_RESOURCE_STATE_UNKNOWN:
cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name); 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 ...@@ -498,7 +498,7 @@ static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *a
goto unlock; goto unlock;
} }
cifs_mark_tcp_ses_conns_for_reconnect(tcon->ses->server, false); cifs_signal_cifsd_for_reconnect(tcon->ses->server, false);
unlock: unlock:
mutex_unlock(&tcon->ses->server->srv_mutex); mutex_unlock(&tcon->ses->server->srv_mutex);
......
...@@ -210,6 +210,9 @@ cifs_read_super(struct super_block *sb) ...@@ -210,6 +210,9 @@ cifs_read_super(struct super_block *sb)
if (rc) if (rc)
goto out_no_root; goto out_no_root;
/* tune readahead according to rsize if readahead size not set on mount */ /* 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) if (cifs_sb->ctx->rasize)
sb->s_bdi->ra_pages = cifs_sb->ctx->rasize / PAGE_SIZE; sb->s_bdi->ra_pages = cifs_sb->ctx->rasize / PAGE_SIZE;
else else
...@@ -254,6 +257,9 @@ static void cifs_kill_sb(struct super_block *sb) ...@@ -254,6 +257,9 @@ static void cifs_kill_sb(struct super_block *sb)
struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct cached_fid *cfid; 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 * We ned to release all dentries for the cached directories
...@@ -263,16 +269,18 @@ static void cifs_kill_sb(struct super_block *sb) ...@@ -263,16 +269,18 @@ static void cifs_kill_sb(struct super_block *sb)
dput(cifs_sb->root); dput(cifs_sb->root);
cifs_sb->root = NULL; cifs_sb->root = NULL;
} }
tcon = cifs_sb_master_tcon(cifs_sb); node = rb_first(root);
if (tcon) { while (node != NULL) {
tlink = rb_entry(node, struct tcon_link, tl_rbnode);
tcon = tlink_tcon(tlink);
cfid = &tcon->crfid; cfid = &tcon->crfid;
mutex_lock(&cfid->fid_mutex); mutex_lock(&cfid->fid_mutex);
if (cfid->dentry) { if (cfid->dentry) {
dput(cfid->dentry); dput(cfid->dentry);
cfid->dentry = NULL; cfid->dentry = NULL;
} }
mutex_unlock(&cfid->fid_mutex); mutex_unlock(&cfid->fid_mutex);
node = rb_next(node);
} }
kill_anon_super(sb); kill_anon_super(sb);
......
...@@ -132,6 +132,9 @@ extern int SendReceiveBlockingLock(const unsigned int xid, ...@@ -132,6 +132,9 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
struct smb_hdr *out_buf, struct smb_hdr *out_buf,
int *bytes_returned); int *bytes_returned);
void 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, cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
bool mark_smb_session); bool mark_smb_session);
extern int cifs_reconnect(struct TCP_Server_Info *server, extern int cifs_reconnect(struct TCP_Server_Info *server,
......
...@@ -162,11 +162,51 @@ static void cifs_resolve_server(struct work_struct *work) ...@@ -162,11 +162,51 @@ static void cifs_resolve_server(struct work_struct *work)
mutex_unlock(&server->srv_mutex); 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. * 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. * @server needs to be previously set to CifsNeedReconnect.
* * @mark_smb_session: whether even sessions need to be marked
*/ */
void void
cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, 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 ...@@ -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_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 */ /* 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, ...@@ -3740,6 +3740,11 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
break; 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, rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
&rsize, credits); &rsize, credits);
if (rc) if (rc)
...@@ -4474,6 +4479,11 @@ static void cifs_readahead(struct readahead_control *ractl) ...@@ -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, rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
&rsize, credits); &rsize, credits);
if (rc) if (rc)
......
...@@ -228,7 +228,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server) ...@@ -228,7 +228,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
if (reconnect) { if (reconnect) {
cifs_mark_tcp_ses_conns_for_reconnect(server, false); cifs_signal_cifsd_for_reconnect(server, false);
} }
return mid; return mid;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "smb2glob.h" #include "smb2glob.h"
#include "cifs_ioctl.h" #include "cifs_ioctl.h"
#include "smbdirect.h" #include "smbdirect.h"
#include "fscache.h"
#include "fs_context.h" #include "fs_context.h"
/* Change credits for different ops and return the total number of credits */ /* 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, ...@@ -3887,29 +3888,38 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
{ {
int rc; int rc;
unsigned int xid; unsigned int xid;
struct inode *inode;
struct cifsFileInfo *cfile = file->private_data; struct cifsFileInfo *cfile = file->private_data;
struct cifsInodeInfo *cifsi;
__le64 eof; __le64 eof;
xid = get_xid(); xid = get_xid();
if (off >= i_size_read(file->f_inode) || inode = d_inode(cfile->dentry);
off + len >= i_size_read(file->f_inode)) { cifsi = CIFS_I(inode);
if (off >= i_size_read(inode) ||
off + len >= i_size_read(inode)) {
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
rc = smb2_copychunk_range(xid, cfile, cfile, off + len, 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) if (rc < 0)
goto out; 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, rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, cfile->pid, &eof); cfile->fid.volatile_fid, cfile->pid, &eof);
if (rc < 0) if (rc < 0)
goto out; goto out;
rc = 0; 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: out:
free_xid(xid); free_xid(xid);
return rc; return rc;
......
...@@ -430,7 +430,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, ...@@ -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 * be taken as the remainder of this one. We need to kill the
* socket so the server throws away the partial SMB * 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, trace_smb3_partial_send_reconnect(server->CurrentMid,
server->conn_id, server->hostname); 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