Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/netsmb Fix detection of SMB capabilities according to th...
details: https://anonhg.NetBSD.org/src/rev/f01928c3c249
branches: trunk
changeset: 748270:f01928c3c249
user: tron <tron%NetBSD.org@localhost>
date: Sun Oct 18 22:53:36 2009 +0000
description:
Fix detection of SMB capabilities according to the CIFS spec:
1.) SMB_CAP_LARGE_FILES advertises support for 64-bit file offsets.
2.) SMB_CAP_LARGE_READX and SMB_CAP_LARGE_WRITEX advertise support for
large reads and writes (larger than 64KB).
The code previously only used SMB_CAP_LARGE_READX and SMB_CAP_LARGE_WRITEX
which is not correct and doesn't work for the Apple Time Capsule which
only supports SMB_CAP_LARGE_FILES. With these changes SMBFS can copy a
5GB to a Time Capsule and read it back without problems.
Thanks a lot to Allen Briggs for pointing out the broke assumptions
and explaining the CIFS spec to me. This fixes PR kern/42175.
diffstat:
sys/netsmb/smb_smb.c | 49 ++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 42 insertions(+), 7 deletions(-)
diffs (106 lines):
diff -r 9543ed4f2b5c -r f01928c3c249 sys/netsmb/smb_smb.c
--- a/sys/netsmb/smb_smb.c Sun Oct 18 21:58:37 2009 +0000
+++ b/sys/netsmb/smb_smb.c Sun Oct 18 22:53:36 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: smb_smb.c,v 1.30 2009/03/18 16:00:24 cegger Exp $ */
+/* $NetBSD: smb_smb.c,v 1.31 2009/10/18 22:53:36 tron Exp $ */
/*
* Copyright (c) 2000-2001 Boris Popov
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smb_smb.c,v 1.30 2009/03/18 16:00:24 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smb_smb.c,v 1.31 2009/10/18 22:53:36 tron Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -594,6 +594,22 @@
u_int16_t residhi, residlo, off, doff;
u_int32_t resid;
+ if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_FILES) &&
+ uio->uio_offset >= (1LL << 32)) {
+ /* Cannot read at/beyond 4G */
+ return (EFBIG);
+ }
+
+ if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_WRITEX)) {
+ size_t blksz;
+
+ blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 64;
+ if (blksz > 0xffff)
+ blksz = 0xffff;
+
+ *len = min(blksz, *len);
+ }
+
error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
if (error)
return error;
@@ -674,8 +690,26 @@
u_int8_t wc;
u_int16_t resid;
+ if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_FILES) &&
+ uio->uio_offset >= (1LL << 32)) {
+ /* Cannot write at/beyond 4G */
+ return (EFBIG);
+ }
+
+ if (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_WRITEX) {
+ *len = min(SSTOVC(ssp)->vc_wxmax, *len);
+ } else {
+ size_t blksz;
+
+ blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 64;
+ if (blksz > 0xffff)
+ blksz = 0xffff;
+
+ *len = min(blksz, *len);
+ }
+
error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
- if (error)
+ if (error != 0)
return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
@@ -687,7 +721,6 @@
mb_put_uint32le(mbp, 0); /* MBZ (timeout) */
mb_put_uint16le(mbp, 0); /* !write-thru */
mb_put_uint16le(mbp, 0);
- *len = min(SSTOVC(ssp)->vc_wxmax, *len);
mb_put_uint16le(mbp, *len >> 16);
mb_put_uint16le(mbp, *len);
mb_put_uint16le(mbp, 64); /* data offset from header start */
@@ -785,7 +818,8 @@
{
size_t tsize, len, resid;
int error = 0;
- int rx = (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_READX);
+ bool rx = (SMB_CAPS(SSTOVC(ssp)) &
+ (SMB_CAP_LARGE_FILES|SMB_CAP_LARGE_READX)) != 0;
resid = 0; /* XXX gcc */
@@ -866,7 +900,8 @@
{
int error = 0;
size_t len, tsize, resid;
- int wx = (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_WRITEX);
+ bool wx = (SMB_CAPS(SSTOVC(ssp)) &
+ (SMB_CAP_LARGE_FILES|SMB_CAP_LARGE_WRITEX)) != 0;
resid = 0; /* XXX gcc */
@@ -877,7 +912,7 @@
error = smb_smb_writex(ssp, fid, &len, &resid, uio, scred);
else
error = smb_smb_write(ssp, fid, &len, &resid, uio, scred);
- if (error)
+ if (error != 0)
break;
if (resid < len) {
error = EIO;
Home |
Main Index |
Thread Index |
Old Index