5 cifs/smb3 fixes, 3 for stable
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmI4zfoACgkQiiy9cAdy T1F5cQwAiAoZ3aMPLhr2pq9EAWtAy413opNIGwxmqAYMGsFKunMfjtMBdNx0y6g+ rEkImRA315U9MobFqndRJgmwIdztimxqst9jZEZJPuMO0Yt3WMXU6YIoYd/rbcJ2 XxBuOwhm9fW56qQv6M9xGXuE6r47VhhHTTpQh9nMWlvH6sad5Rzwzjt2ycrOAmKL Jn65LTmwTCK4htkXJWzGFwxSB31ueQ2cEDpA0IlDtnlYlcBJ1lSmoEL6muIVKn+h ynWvY4k39xa83GF9t1BDCGFsXx4htxD3+LSP4Gb07Rp1n+ZMcwUHk1cGFBRRaise IzcLgLV8cwiruHQgqkGKW5b4DplFv7ScEj8iqO/Dve5kDmXNFzgPFygJKSDCLr/j IsrGpZfGINwiMDgI+R6jxCnLgEfswFbEHYhwZtRxguuav1JLGtLfHCb3G84nPJQu 4sRfk3euYkkGP3IYW0uQw4tfhjDaB8m17EHQLzWw/RYAzUdsA67Ocvn/F8kdbF76 YBXhJhrA =ai8m -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
105b6c05c5
@ -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 @@ unmask:
|
||||
* 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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user