Commit 239720b7 authored by Pavel Shilovsky's avatar Pavel Shilovsky

Update 2.6.39 sources from stable (v2.6.39.4)

parent defc4d87
......@@ -184,7 +184,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
if (cifs_pdu == NULL || server == NULL)
return -EINVAL;
if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
if (!server->session_estab)
return 0;
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
......
......@@ -200,7 +200,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
spin_unlock(&GlobalMid_Lock);
while (server->tcpStatus == CifsNeedReconnect) {
do {
try_to_freeze();
/* we should try only the port we connected to before */
......@@ -215,7 +215,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
server->tcpStatus = CifsNeedNegotiate;
spin_unlock(&GlobalMid_Lock);
}
}
} while (server->tcpStatus == CifsNeedReconnect);
return rc;
}
......@@ -2452,7 +2452,7 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
cFYI(1, "unix caps which server supports %lld", cap);
/* check for reconnect case in which we do not
want to change the mount behavior if we can avoid it */
if (vol_info == NULL) {
......@@ -2470,6 +2470,9 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
}
}
if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
cERROR(1, "per-share encryption not supported yet");
cap &= CIFS_UNIX_CAP_MASK;
if (vol_info && vol_info->no_psx_acl)
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
......@@ -2518,6 +2521,10 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
cFYI(1, "very large read cap");
if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
cFYI(1, "very large write cap");
if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
cFYI(1, "transport encryption cap");
if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
cFYI(1, "mandatory transport encryption cap");
#endif /* CIFS_DEBUG2 */
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
if (vol_info == NULL) {
......@@ -2569,23 +2576,6 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
else /* default */
cifs_sb->rsize = CIFSMaxBufSize;
if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
cERROR(1, "wsize %d too large, using 4096 instead",
pvolume_info->wsize);
cifs_sb->wsize = 4096;
} else if (pvolume_info->wsize)
cifs_sb->wsize = pvolume_info->wsize;
else
cifs_sb->wsize = min_t(const int,
PAGEVEC_SIZE * PAGE_CACHE_SIZE,
127*1024);
/* old default of CIFSMaxBufSize was too small now
that SMB Write2 can send multiple pages in kvec.
RFC1001 does not describe what happens when frame
bigger than 128K is sent so use that as max in
conjunction with 52K kvec constraint on arch with 4K
page size */
if (cifs_sb->rsize < 2048) {
cifs_sb->rsize = 2048;
/* Windows ME may prefer this */
......@@ -2665,6 +2655,48 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
"mount option supported");
}
/* Prior to 3.0, cifs couldn't handle writes larger than this */
#define CIFS_MAX_WSIZE (PAGEVEC_SIZE * PAGE_CACHE_SIZE)
/*
* When the server doesn't allow large posix writes, only allow a wsize of
* 128k minus the size of the WRITE_AND_X header. That allows for a write up
* to the maximum size described by RFC1002.
*/
#define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4)
/* Make the default the same as the max */
#define CIFS_DEFAULT_WSIZE CIFS_MAX_WSIZE
static unsigned int
cifs_negotiate_wsize(struct cifsTconInfo *tcon, struct smb_vol *pvolume_info)
{
__u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
struct TCP_Server_Info *server = tcon->ses->server;
unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
CIFS_DEFAULT_WSIZE;
/* can server support 24-bit write sizes? (via UNIX extensions) */
if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
/*
* no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
* Limit it to max buffer offered by the server, minus the size of the
* WRITEX header, not including the 4 byte RFC1001 length.
*/
if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
(!(server->capabilities & CAP_UNIX) &&
(server->secMode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
wsize = min_t(unsigned int, wsize,
server->maxBuf - sizeof(WRITE_REQ) + 4);
/* hard limit of CIFS_MAX_WSIZE */
wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
return wsize;
}
static int
is_path_accessible(int xid, struct cifsTconInfo *tcon,
struct cifs_sb_info *cifs_sb, const char *full_path)
......@@ -2838,20 +2870,26 @@ try_mount_again:
goto remote_path_check;
}
/* do not care if following two calls succeed - informational */
if (!tcon->ipc) {
CIFSSMBQFSDeviceInfo(xid, tcon);
CIFSSMBQFSAttributeInfo(xid, tcon);
}
/* tell server which Unix caps we support */
if (tcon->ses->capabilities & CAP_UNIX)
if (tcon->ses->capabilities & CAP_UNIX) {
/* reset of caps checks mount to see if unix extensions
disabled for just this mount */
reset_cifs_unix_caps(xid, tcon, sb, volume_info);
else
if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
(le64_to_cpu(tcon->fsUnixInfo.Capability) &
CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
rc = -EACCES;
goto mount_fail_check;
}
} else
tcon->unix_ext = 0; /* server does not support them */
/* do not care if following two calls succeed - informational */
if (!tcon->ipc) {
CIFSSMBQFSDeviceInfo(xid, tcon);
CIFSSMBQFSAttributeInfo(xid, tcon);
}
/* convert forward to back slashes in prepath here if needed */
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
......@@ -2860,13 +2898,12 @@ try_mount_again:
cifs_sb->rsize = 1024 * 127;
cFYI(DBG2, "no very large read support, rsize now 127K");
}
if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
cifs_sb->wsize = min(cifs_sb->wsize,
(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
cifs_sb->rsize = min(cifs_sb->rsize,
(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
remote_path_check:
/* check if a whole path (including prepath) is not remote */
if (!rc && tcon) {
......@@ -3202,7 +3239,7 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifsSesInfo *ses)
}
if (rc == 0) {
spin_lock(&GlobalMid_Lock);
if (server->tcpStatus != CifsExiting)
if (server->tcpStatus == CifsNeedNegotiate)
server->tcpStatus = CifsGood;
else
rc = -EHOSTDOWN;
......
......@@ -94,6 +94,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode)
if (cifsi->fscache) {
cFYI(1, "CIFS disabling inode cookie (0x%p)",
cifsi->fscache);
fscache_uncache_all_inode_pages(cifsi->fscache, inode);
fscache_relinquish_cookie(cifsi->fscache, 1);
cifsi->fscache = NULL;
}
......
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