Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a75952b7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  cifs: fix renaming one hardlink on top of another
  [CIFS] fix error in smb_send2
  [CIFS] Reduce number of socket retries in large write path
parents 457d2ee2 ae6884a9
Loading
Loading
Loading
Loading
+5 −1
Original line number Original line Diff line number Diff line
@@ -4,7 +4,11 @@ Various fixes to make delete of open files behavior more predictable
(when delete of an open file fails we mark the file as "delete-on-close"
(when delete of an open file fails we mark the file as "delete-on-close"
in a way that more servers accept, but only if we can first rename the
in a way that more servers accept, but only if we can first rename the
file to a temporary name).  Add experimental support for more safely
file to a temporary name).  Add experimental support for more safely
handling fcntl(F_SETLEASE).
handling fcntl(F_SETLEASE).  Convert cifs to using blocking tcp
sends, and also let tcp autotune the socket send and receive buffers.
This reduces the number of EAGAIN errors returned by TCP/IP in
high stress workloads (and the number of retries on socket writes
when sending large SMBWriteX requests).


Version 1.54
Version 1.54
------------
------------
+2 −0
Original line number Original line Diff line number Diff line
@@ -141,6 +141,8 @@ struct TCP_Server_Info {
	char versionMajor;
	char versionMajor;
	char versionMinor;
	char versionMinor;
	bool svlocal:1;			/* local server or remote */
	bool svlocal:1;			/* local server or remote */
	bool noblocksnd;		/* use blocking sendmsg */
	bool noautotune;		/* do not autotune send buf sizes */
	atomic_t socketUseCount; /* number of open cifs sessions on socket */
	atomic_t socketUseCount; /* number of open cifs sessions on socket */
	atomic_t inFlight;  /* number of requests on the wire to server */
	atomic_t inFlight;  /* number of requests on the wire to server */
#ifdef CONFIG_CIFS_STATS2
#ifdef CONFIG_CIFS_STATS2
+1 −1
Original line number Original line Diff line number Diff line
@@ -36,7 +36,7 @@ extern void cifs_buf_release(void *);
extern struct smb_hdr *cifs_small_buf_get(void);
extern struct smb_hdr *cifs_small_buf_get(void);
extern void cifs_small_buf_release(void *);
extern void cifs_small_buf_release(void *);
extern int smb_send(struct socket *, struct smb_hdr *,
extern int smb_send(struct socket *, struct smb_hdr *,
			unsigned int /* length */ , struct sockaddr *);
			unsigned int /* length */ , struct sockaddr *, bool);
extern unsigned int _GetXid(void);
extern unsigned int _GetXid(void);
extern void _FreeXid(unsigned int);
extern void _FreeXid(unsigned int);
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid));
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid));
+37 −13
Original line number Original line Diff line number Diff line
@@ -92,6 +92,8 @@ struct smb_vol {
	bool seal:1;       /* request transport encryption on share */
	bool seal:1;       /* request transport encryption on share */
	bool nodfs:1;      /* Do not request DFS, even if available */
	bool nodfs:1;      /* Do not request DFS, even if available */
	bool local_lease:1; /* check leases only on local system, not remote */
	bool local_lease:1; /* check leases only on local system, not remote */
	bool noblocksnd:1;
	bool noautotune:1;
	unsigned int rsize;
	unsigned int rsize;
	unsigned int wsize;
	unsigned int wsize;
	unsigned int sockopt;
	unsigned int sockopt;
@@ -102,9 +104,11 @@ struct smb_vol {
static int ipv4_connect(struct sockaddr_in *psin_server,
static int ipv4_connect(struct sockaddr_in *psin_server,
			struct socket **csocket,
			struct socket **csocket,
			char *netb_name,
			char *netb_name,
			char *server_netb_name);
			char *server_netb_name,
			bool noblocksnd,
			bool nosndbuf); /* ipv6 never set sndbuf size */
static int ipv6_connect(struct sockaddr_in6 *psin_server,
static int ipv6_connect(struct sockaddr_in6 *psin_server,
			struct socket **csocket);
			struct socket **csocket, bool noblocksnd);




	/*
	/*
@@ -191,12 +195,13 @@ cifs_reconnect(struct TCP_Server_Info *server)
		try_to_freeze();
		try_to_freeze();
		if (server->protocolType == IPV6) {
		if (server->protocolType == IPV6) {
			rc = ipv6_connect(&server->addr.sockAddr6,
			rc = ipv6_connect(&server->addr.sockAddr6,
					  &server->ssocket);
					  &server->ssocket, server->noautotune);
		} else {
		} else {
			rc = ipv4_connect(&server->addr.sockAddr,
			rc = ipv4_connect(&server->addr.sockAddr,
					&server->ssocket,
					&server->ssocket,
					server->workstation_RFC1001_name,
					server->workstation_RFC1001_name,
					server->server_RFC1001_name);
					server->server_RFC1001_name,
					server->noblocksnd, server->noautotune);
		}
		}
		if (rc) {
		if (rc) {
			cFYI(1, ("reconnect error %d", rc));
			cFYI(1, ("reconnect error %d", rc));
@@ -1192,6 +1197,10 @@ cifs_parse_mount_options(char *options, const char *devname,
			/* ignore */
			/* ignore */
		} else if (strnicmp(data, "rw", 2) == 0) {
		} else if (strnicmp(data, "rw", 2) == 0) {
			vol->rw = true;
			vol->rw = true;
		} else if (strnicmp(data, "noblocksend", 11) == 0) {
			vol->noblocksnd = 1;
		} else if (strnicmp(data, "noautotune", 10) == 0) {
			vol->noautotune = 1;
		} else if ((strnicmp(data, "suid", 4) == 0) ||
		} else if ((strnicmp(data, "suid", 4) == 0) ||
				   (strnicmp(data, "nosuid", 6) == 0) ||
				   (strnicmp(data, "nosuid", 6) == 0) ||
				   (strnicmp(data, "exec", 4) == 0) ||
				   (strnicmp(data, "exec", 4) == 0) ||
@@ -1518,7 +1527,8 @@ static void rfc1002mangle(char *target, char *source, unsigned int length)


static int
static int
ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
	     char *netbios_name, char *target_name)
	     char *netbios_name, char *target_name,
	     bool noblocksnd, bool noautotune)
{
{
	int rc = 0;
	int rc = 0;
	int connected = 0;
	int connected = 0;
@@ -1590,11 +1600,16 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
		 (*csocket)->sk->sk_sndbuf,
		 (*csocket)->sk->sk_sndbuf,
		 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
		 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
	(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
	(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
	if (!noblocksnd)
		(*csocket)->sk->sk_sndtimeo = 3 * HZ;

	/* make the bufsizes depend on wsize/rsize and max requests */
	/* make the bufsizes depend on wsize/rsize and max requests */
	if (noautotune) {
		if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
		if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
			(*csocket)->sk->sk_sndbuf = 200 * 1024;
			(*csocket)->sk->sk_sndbuf = 200 * 1024;
		if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
		if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
			(*csocket)->sk->sk_rcvbuf = 140 * 1024;
			(*csocket)->sk->sk_rcvbuf = 140 * 1024;
	}


	/* send RFC1001 sessinit */
	/* send RFC1001 sessinit */
	if (psin_server->sin_port == htons(RFC1001_PORT)) {
	if (psin_server->sin_port == htons(RFC1001_PORT)) {
@@ -1631,7 +1646,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
			/* sizeof RFC1002_SESSION_REQUEST with no scope */
			/* sizeof RFC1002_SESSION_REQUEST with no scope */
			smb_buf->smb_buf_length = 0x81000044;
			smb_buf->smb_buf_length = 0x81000044;
			rc = smb_send(*csocket, smb_buf, 0x44,
			rc = smb_send(*csocket, smb_buf, 0x44,
				(struct sockaddr *)psin_server);
				(struct sockaddr *)psin_server, noblocksnd);
			kfree(ses_init_buf);
			kfree(ses_init_buf);
			msleep(1); /* RFC1001 layer in at least one server
			msleep(1); /* RFC1001 layer in at least one server
				      requires very short break before negprot
				      requires very short break before negprot
@@ -1651,7 +1666,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
}
}


static int
static int
ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket,
	     bool noblocksnd)
{
{
	int rc = 0;
	int rc = 0;
	int connected = 0;
	int connected = 0;
@@ -1720,6 +1736,9 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
		the default. sock_setsockopt not used because it expects
		the default. sock_setsockopt not used because it expects
		user space buffer */
		user space buffer */
	(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
	(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
	if (!noblocksnd)
		(*csocket)->sk->sk_sndtimeo = 3 * HZ;



	return rc;
	return rc;
}
}
@@ -1983,11 +2002,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
			cFYI(1, ("attempting ipv6 connect"));
			cFYI(1, ("attempting ipv6 connect"));
			/* BB should we allow ipv6 on port 139? */
			/* BB should we allow ipv6 on port 139? */
			/* other OS never observed in Wild doing 139 with v6 */
			/* other OS never observed in Wild doing 139 with v6 */
			rc = ipv6_connect(&sin_server6, &csocket);
			rc = ipv6_connect(&sin_server6, &csocket,
					volume_info.noblocksnd);
		} else
		} else
			rc = ipv4_connect(&sin_server, &csocket,
			rc = ipv4_connect(&sin_server, &csocket,
				  volume_info.source_rfc1001_name,
				  volume_info.source_rfc1001_name,
				  volume_info.target_rfc1001_name);
				  volume_info.target_rfc1001_name,
				  volume_info.noblocksnd,
				  volume_info.noautotune);
		if (rc < 0) {
		if (rc < 0) {
			cERROR(1, ("Error connecting to IPv4 socket. "
			cERROR(1, ("Error connecting to IPv4 socket. "
				   "Aborting operation"));
				   "Aborting operation"));
@@ -2002,6 +2024,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
			sock_release(csocket);
			sock_release(csocket);
			goto out;
			goto out;
		} else {
		} else {
			srvTcp->noblocksnd = volume_info.noblocksnd;
			srvTcp->noautotune = volume_info.noautotune;
			memcpy(&srvTcp->addr.sockAddr, &sin_server,
			memcpy(&srvTcp->addr.sockAddr, &sin_server,
				sizeof(struct sockaddr_in));
				sizeof(struct sockaddr_in));
			atomic_set(&srvTcp->inFlight, 0);
			atomic_set(&srvTcp->inFlight, 0);
+3 −1
Original line number Original line Diff line number Diff line
@@ -1361,9 +1361,11 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
					CIFS_MOUNT_MAP_SPECIAL_CHR);
					CIFS_MOUNT_MAP_SPECIAL_CHR);


		if (tmprc == 0 && (info_buf_source->UniqueId ==
		if (tmprc == 0 && (info_buf_source->UniqueId ==
				   info_buf_target->UniqueId))
				   info_buf_target->UniqueId)) {
			/* same file, POSIX says that this is a noop */
			/* same file, POSIX says that this is a noop */
			rc = 0;
			goto cifs_rename_exit;
			goto cifs_rename_exit;
		}
	} /* else ... BB we could add the same check for Windows by
	} /* else ... BB we could add the same check for Windows by
		     checking the UniqueId via FILE_INTERNAL_INFO */
		     checking the UniqueId via FILE_INTERNAL_INFO */


Loading