Browse Source

Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6

Pull CIFS fixes from Steve French.

* 'for-linus' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: reinstate the forcegid option
  Convert properly UTF-8 to UTF-16
  [CIFS] WARN_ON_ONCE if kernel_sendmsg() returns -ENOSPC
Linus Torvalds 12 years ago
parent
commit
fc81c038c2
3 changed files with 37 additions and 0 deletions
  1. 22 0
      fs/cifs/cifs_unicode.c
  2. 9 0
      fs/cifs/connect.c
  3. 6 0
      fs/cifs/transport.c

+ 22 - 0
fs/cifs/cifs_unicode.c

@@ -203,6 +203,27 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len,
 	int i;
 	int i;
 	wchar_t wchar_to; /* needed to quiet sparse */
 	wchar_t wchar_to; /* needed to quiet sparse */
 
 
+	/* special case for utf8 to handle no plane0 chars */
+	if (!strcmp(codepage->charset, "utf8")) {
+		/*
+		 * convert utf8 -> utf16, we assume we have enough space
+		 * as caller should have assumed conversion does not overflow
+		 * in destination len is length in wchar_t units (16bits)
+		 */
+		i  = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN,
+				       (wchar_t *) to, len);
+
+		/* if success terminate and exit */
+		if (i >= 0)
+			goto success;
+		/*
+		 * if fails fall back to UCS encoding as this
+		 * function should not return negative values
+		 * currently can fail only if source contains
+		 * invalid encoded characters
+		 */
+	}
+
 	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
 	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
 		charlen = codepage->char2uni(from, len, &wchar_to);
 		charlen = codepage->char2uni(from, len, &wchar_to);
 		if (charlen < 1) {
 		if (charlen < 1) {
@@ -215,6 +236,7 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len,
 		put_unaligned_le16(wchar_to, &to[i]);
 		put_unaligned_le16(wchar_to, &to[i]);
 	}
 	}
 
 
+success:
 	put_unaligned_le16(0, &to[i]);
 	put_unaligned_le16(0, &to[i]);
 	return i;
 	return i;
 }
 }

+ 9 - 0
fs/cifs/connect.c

@@ -67,6 +67,7 @@ enum {
 	/* Mount options that take no arguments */
 	/* Mount options that take no arguments */
 	Opt_user_xattr, Opt_nouser_xattr,
 	Opt_user_xattr, Opt_nouser_xattr,
 	Opt_forceuid, Opt_noforceuid,
 	Opt_forceuid, Opt_noforceuid,
+	Opt_forcegid, Opt_noforcegid,
 	Opt_noblocksend, Opt_noautotune,
 	Opt_noblocksend, Opt_noautotune,
 	Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
 	Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
 	Opt_mapchars, Opt_nomapchars, Opt_sfu,
 	Opt_mapchars, Opt_nomapchars, Opt_sfu,
@@ -117,6 +118,8 @@ static const match_table_t cifs_mount_option_tokens = {
 	{ Opt_nouser_xattr, "nouser_xattr" },
 	{ Opt_nouser_xattr, "nouser_xattr" },
 	{ Opt_forceuid, "forceuid" },
 	{ Opt_forceuid, "forceuid" },
 	{ Opt_noforceuid, "noforceuid" },
 	{ Opt_noforceuid, "noforceuid" },
+	{ Opt_forcegid, "forcegid" },
+	{ Opt_noforcegid, "noforcegid" },
 	{ Opt_noblocksend, "noblocksend" },
 	{ Opt_noblocksend, "noblocksend" },
 	{ Opt_noautotune, "noautotune" },
 	{ Opt_noautotune, "noautotune" },
 	{ Opt_hard, "hard" },
 	{ Opt_hard, "hard" },
@@ -1195,6 +1198,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 		case Opt_noforceuid:
 		case Opt_noforceuid:
 			override_uid = 0;
 			override_uid = 0;
 			break;
 			break;
+		case Opt_forcegid:
+			override_gid = 1;
+			break;
+		case Opt_noforcegid:
+			override_gid = 0;
+			break;
 		case Opt_noblocksend:
 		case Opt_noblocksend:
 			vol->noblocksnd = 1;
 			vol->noblocksnd = 1;
 			break;
 			break;

+ 6 - 0
fs/cifs/transport.c

@@ -183,6 +183,12 @@ smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
 		rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
 		rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
 				    n_vec - first_vec, remaining);
 				    n_vec - first_vec, remaining);
 		if (rc == -ENOSPC || rc == -EAGAIN) {
 		if (rc == -ENOSPC || rc == -EAGAIN) {
+			/*
+			 * Catch if a low level driver returns -ENOSPC. This
+			 * WARN_ON will be removed by 3.10 if no one reports
+			 * seeing this.
+			 */
+			WARN_ON_ONCE(rc == -ENOSPC);
 			i++;
 			i++;
 			if (i >= 14 || (!server->noblocksnd && (i > 2))) {
 			if (i >= 14 || (!server->noblocksnd && (i > 2))) {
 				cERROR(1, "sends on sock %p stuck for 15 "
 				cERROR(1, "sends on sock %p stuck for 15 "