Commit dc709bd1 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [CIFS] Do not send Query All EAs SMB when mount option nouser_xattr
  [CIFS] endian errors in lanman protocol support
  [CIFS] Fix oops in cifs_close due to unitialized lock sem and list in
  [CIFS] Fix oops when negotiating lanman and no password specified
  [CIFS]
  [CIFS] Allow cifsd to suspend if connection is lost
  [CIFS] Make midState usage more consistent
  [CIFS] spinlock protect read of last srv response time in timeout path
  [CIFS] Do not time out posix brl requests when using new posix setfileinfo
parents d9629953 ea4c07d7
Version 1.45
------------
Do not time out lockw calls when using posix extensions. Do not
time out requests if server still responding reasonably fast
on requests on other threads. Improve POSIX locking emulation,
(lock cancel now works, and unlock of merged range works even
to Windows servers now). Fix oops on mount to lanman servers
(win9x, os/2 etc.) when null password. Do not send listxattr
(SMB to query all EAs) if nouser_xattr specified.
Version 1.44
------------
Rewritten sessionsetup support, including support for legacy SMB
......
......@@ -408,7 +408,7 @@ A partial list of the supported mount options follows:
user_xattr Allow getting and setting user xattrs as OS/2 EAs (extended
attributes) to the server (default) e.g. via setfattr
and getfattr utilities.
nouser_xattr Do not allow getfattr/setfattr to get/set xattrs
nouser_xattr Do not allow getfattr/setfattr to get/set/list xattrs
mapchars Translate six of the seven reserved characters (not backslash)
*?<>|:
to the remap range (above 0xF000), which also
......
......@@ -277,7 +277,8 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
return;
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
if(ses->password)
strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
if(extended_security & CIFSSEC_MAY_PLNTXT) {
......
......@@ -402,7 +402,6 @@ static struct quotactl_ops cifs_quotactl_ops = {
};
#endif
#ifdef CONFIG_CIFS_EXPERIMENTAL
static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
{
struct cifs_sb_info *cifs_sb;
......@@ -422,7 +421,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
tcon->tidStatus = CifsExiting;
up(&tcon->tconSem);
/* cancel_brl_requests(tcon); */
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
/* cancel_notify_requests(tcon); */
if(tcon->ses && tcon->ses->server)
{
......@@ -438,7 +437,6 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
return;
}
#endif
static int cifs_remount(struct super_block *sb, int *flags, char *data)
{
......@@ -457,9 +455,7 @@ struct super_operations cifs_super_ops = {
unless later we add lazy close of inodes or unless the kernel forgets to call
us with the same number of releases (closes) as opens */
.show_options = cifs_show_options,
#ifdef CONFIG_CIFS_EXPERIMENTAL
.umount_begin = cifs_umount_begin,
#endif
.remount_fs = cifs_remount,
};
......
......@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg);
#define CIFS_VERSION "1.44"
#define CIFS_VERSION "1.45"
#endif /* _CIFSFS_H */
......@@ -3,6 +3,7 @@
*
* Copyright (C) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
......@@ -158,7 +159,8 @@ struct TCP_Server_Info {
/* 16th byte of RFC1001 workstation name is always null */
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
__u32 sequence_number; /* needed for CIFS PDU signature */
char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
unsigned long lstrp; /* when we got last response from this server */
};
/*
......@@ -266,14 +268,14 @@ struct cifsTconInfo {
};
/*
* This info hangs off the cifsFileInfo structure. This is used to track
* byte stream locks on the file
* This info hangs off the cifsFileInfo structure, pointed to by llist.
* This is used to track byte stream locks on the file
*/
struct cifsLockInfo {
struct cifsLockInfo *next;
int start;
int length;
int type;
struct list_head llist; /* pointer to next cifsLockInfo */
__u64 offset;
__u64 length;
__u8 type;
};
/*
......@@ -304,6 +306,8 @@ struct cifsFileInfo {
/* lock scope id (0 if none) */
struct file * pfile; /* needed for writepage */
struct inode * pInode; /* needed for oplock break */
struct semaphore lock_sem;
struct list_head llist; /* list of byte range locks we have. */
unsigned closePend:1; /* file is marked to close */
unsigned invalidHandle:1; /* file closed via session abend */
atomic_t wrtPending; /* handle in use - defer close */
......
......@@ -50,6 +50,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
struct kvec *, int /* nvec to send */,
int * /* type of buf returned */ , const int long_op);
extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *,
struct smb_hdr * /* input */ ,
struct smb_hdr * /* out */ ,
int * /* bytes returned */);
extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
......
......@@ -477,7 +477,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
/* BB get server time for time conversions and add
code to use it and timezone since this is not UTC */
if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
memcpy(server->cryptKey, rsp->EncryptionKey,
CIFS_CRYPTO_KEY_SIZE);
} else if (server->secMode & SECMODE_PW_ENCRYPT) {
......@@ -1460,8 +1460,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
pSMB->hdr.smb_buf_length += count;
pSMB->ByteCount = cpu_to_le16(count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
if (waitFlag) {
rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned);
} else {
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, timeout);
}
cifs_stats_inc(&tcon->num_locks);
if (rc) {
cFYI(1, ("Send error in Lock = %d", rc));
......@@ -1484,6 +1489,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
char *data_offset;
struct cifs_posix_lock *parm_data;
int rc = 0;
int timeout = 0;
int bytes_returned = 0;
__u16 params, param_offset, offset, byte_count, count;
......@@ -1503,7 +1509,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
offset = param_offset + params;
......@@ -1529,8 +1534,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
(((char *) &pSMB->hdr.Protocol) + offset);
parm_data->lock_type = cpu_to_le16(lock_type);
if(waitFlag)
if(waitFlag) {
timeout = 3; /* blocking operation, no timeout */
parm_data->lock_flags = cpu_to_le16(1);
pSMB->Timeout = cpu_to_le32(-1);
} else
pSMB->Timeout = 0;
parm_data->pid = cpu_to_le32(current->tgid);
parm_data->start = cpu_to_le64(pLockData->fl_start);
parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
......@@ -1541,8 +1551,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (waitFlag) {
rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned);
} else {
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, timeout);
}
if (rc) {
cFYI(1, ("Send error in Posix Lock = %d", rc));
} else if (get_flag) {
......
......@@ -182,6 +182,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
{
try_to_freeze();
if(server->protocolType == IPV6) {
rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
} else {
......@@ -612,6 +613,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
#ifdef CONFIG_CIFS_STATS2
mid_entry->when_received = jiffies;
#endif
/* so we do not time out requests to server
which is still responding (since server could
be busy but not dead) */
server->lstrp = jiffies;
break;
}
}
......@@ -1266,33 +1271,35 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) {
cFYI(1, ("Next tcon - "));
cFYI(1, ("Next tcon"));
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if (tcon->ses) {
if (tcon->ses->server) {
cFYI(1,
(" old ip addr: %x == new ip %x ?",
("old ip addr: %x == new ip %x ?",
tcon->ses->server->addr.sockAddr.sin_addr.
s_addr, new_target_ip_addr));
if (tcon->ses->server->addr.sockAddr.sin_addr.
s_addr == new_target_ip_addr) {
/* BB lock tcon and server and tcp session and increment use count here? */
/* BB lock tcon, server and tcp session and increment use count here? */
/* found a match on the TCP session */
/* BB check if reconnection needed */
cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
cFYI(1,("IP match, old UNC: %s new: %s",
tcon->treeName, uncName));
if (strncmp
(tcon->treeName, uncName,
MAX_TREE_SIZE) == 0) {
cFYI(1,
("Matched UNC, old user: %s == new: %s ?",
("and old usr: %s new: %s",
tcon->treeName, uncName));
if (strncmp
(tcon->ses->userName,
userName,
MAX_USERNAME_SIZE) == 0) {
read_unlock(&GlobalSMBSeslock);
return tcon;/* also matched user (smb session)*/
/* matched smb session
(user name */
return tcon;
}
}
}
......@@ -1969,7 +1976,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
cFYI(1,("Negotiate caps 0x%x",(int)cap));
#ifdef CONFIG_CIFS_DEBUG2
if(cap & CIFS_UNIX_FCNTL_CAP)
cFYI(1,("FCNTL cap"));
if(cap & CIFS_UNIX_EXTATTR_CAP)
cFYI(1,("EXTATTR cap"));
if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
cFYI(1,("POSIX path cap"));
if(cap & CIFS_UNIX_XATTR_CAP)
cFYI(1,("XATTR cap"));
if(cap & CIFS_UNIX_POSIX_ACL_CAP)
cFYI(1,("POSIX ACL cap"));
#endif /* CIFS_DEBUG2 */
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
cFYI(1,("setting capabilities failed"));
}
......
......@@ -267,6 +267,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pCifsFile->invalidHandle = FALSE;
pCifsFile->closePend = FALSE;
init_MUTEX(&pCifsFile->fh_sem);
init_MUTEX(&pCifsFile->lock_sem);
INIT_LIST_HEAD(&pCifsFile->llist);
atomic_set(&pCifsFile->wrtPending,0);
/* set the following in open now
pCifsFile->pfile = file; */
write_lock(&GlobalSMBSeslock);
......
......@@ -5,6 +5,7 @@
*
* Copyright (C) International Business Machines Corp., 2002,2003
* Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
......@@ -47,6 +48,8 @@ static inline struct cifsFileInfo *cifs_init_private(
private_data->netfid = netfid;
private_data->pid = current->tgid;
init_MUTEX(&private_data->fh_sem);
init_MUTEX(&private_data->lock_sem);
INIT_LIST_HEAD(&private_data->llist);
private_data->pfile = file; /* needed for writepage */
private_data->pInode = inode;
private_data->invalidHandle = FALSE;
......@@ -473,6 +476,8 @@ int cifs_close(struct inode *inode, struct file *file)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
if (pSMBFile) {
struct cifsLockInfo *li, *tmp;
pSMBFile->closePend = TRUE;
if (pTcon) {
/* no sense reconnecting to close a file that is
......@@ -496,6 +501,16 @@ int cifs_close(struct inode *inode, struct file *file)
pSMBFile->netfid);
}
}
/* Delete any outstanding lock records.
We'll lose them when the file is closed anyway. */
down(&pSMBFile->lock_sem);
list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
list_del(&li->llist);
kfree(li);
}
up(&pSMBFile->lock_sem);
write_lock(&GlobalSMBSeslock);
list_del(&pSMBFile->flist);
list_del(&pSMBFile->tlist);
......@@ -570,6 +585,21 @@ int cifs_closedir(struct inode *inode, struct file *file)
return rc;
}
static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
__u64 offset, __u8 lockType)
{
struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
if (li == NULL)
return -ENOMEM;
li->offset = offset;
li->length = len;
li->type = lockType;
down(&fid->lock_sem);
list_add(&li->llist, &fid->llist);
up(&fid->lock_sem);
return 0;
}
int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
{
int rc, xid;
......@@ -581,6 +611,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
struct cifsTconInfo *pTcon;
__u16 netfid;
__u8 lockType = LOCKING_ANDX_LARGE_FILES;
int posix_locking;
length = 1 + pfLock->fl_end - pfLock->fl_start;
rc = -EACCES;
......@@ -639,15 +670,14 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
}
netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability));
/* BB add code here to normalize offset and length to
account for negative length which we can not accept over the
wire */
if (IS_GETLK(cmd)) {
if(experimEnabled &&
(cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_FCNTL_CAP &
le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
if(posix_locking) {
int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
......@@ -683,10 +713,15 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
FreeXid(xid);
return rc;
}
if (experimEnabled &&
(cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_FCNTL_CAP &
le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
if (!numLock && !numUnlock) {
/* if no lock or unlock then nothing
to do since we do not know what it is */
FreeXid(xid);
return -EOPNOTSUPP;
}
if (posix_locking) {
int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
......@@ -695,18 +730,46 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if(numUnlock == 1)
posix_lock_type = CIFS_UNLCK;
else if(numLock == 0) {
/* if no lock or unlock then nothing
to do since we do not know what it is */
FreeXid(xid);
return -EOPNOTSUPP;
}
rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
length, pfLock,
posix_lock_type, wait_flag);
} else
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
numUnlock, numLock, lockType, wait_flag);
} else {
struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
if (numLock) {
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
0, numLock, lockType, wait_flag);
if (rc == 0) {
/* For Windows locks we must store them. */
rc = store_file_lock(fid, length,
pfLock->fl_start, lockType);
}
} else if (numUnlock) {
/* For each stored lock that this unlock overlaps
completely, unlock it. */
int stored_rc = 0;
struct cifsLockInfo *li, *tmp;
down(&fid->lock_sem);
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
if (pfLock->fl_start <= li->offset &&
length >= li->length) {
stored_rc = CIFSSMBLock(xid, pTcon, netfid,
li->length, li->offset,
1, 0, li->type, FALSE);
if (stored_rc)
rc = stored_rc;
list_del(&li->llist);
kfree(li);
}
}
up(&fid->lock_sem);
}
}
if (pfLock->fl_flags & FL_POSIX)
posix_lock_file_wait(file, pfLock);
FreeXid(xid);
......
......@@ -72,6 +72,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{ERRinvlevel,-EOPNOTSUPP},
{ERRdirnotempty, -ENOTEMPTY},
{ERRnotlocked, -ENOLCK},
{ERRcancelviolation, -ENOLCK},
{ERRalreadyexists, -EEXIST},
{ERRmoredata, -EOVERFLOW},
{ERReasnotsupported,-EOPNOTSUPP},
......
......@@ -556,7 +556,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
FIND_FILE_STANDARD_INFO * pFindData =
(FIND_FILE_STANDARD_INFO *)current_entry;
filename = &pFindData->FileName[0];
len = le32_to_cpu(pFindData->FileNameLength);
len = pFindData->FileNameLength;
} else {
cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
}
......
......@@ -372,7 +372,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
/* no capabilities flags in old lanman negotiation */
pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE;
pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
/* BB calculate hash with password */
/* and copy into bcc */
......
......@@ -95,6 +95,7 @@
#define ERRinvlevel 124
#define ERRdirnotempty 145
#define ERRnotlocked 158
#define ERRcancelviolation 173
#define ERRalreadyexists 183
#define ERRbadpipe 230
#define ERRpipebusy 231
......
This diff is collapsed.
......@@ -330,11 +330,15 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
sb = direntry->d_inode->i_sb;
if(sb == NULL)
return -EIO;
xid = GetXid();
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
return -EOPNOTSUPP;
xid = GetXid();
full_path = build_path_from_dentry(direntry);
if(full_path == NULL) {
FreeXid(xid);
......
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