Commit 6e40cfce authored by Pavel Shilovsky's avatar Pavel Shilovsky

Fixes in 2.6.33

- oplock handling - update from longterm tree
parent 0244d374
...@@ -623,49 +623,6 @@ cifs_get_sb(struct file_system_type *fs_type, ...@@ -623,49 +623,6 @@ cifs_get_sb(struct file_system_type *fs_type,
return 0; return 0;
} }
static ssize_t cifs_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
int retval, read, posix_locking = 0;
struct file_lock pfLock;
struct cifsInodeInfo *cifsInode;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *tcon;
cifs_sb = CIFS_SB(filp->f_path.dentry->d_sb);
tcon = cifs_sb->tcon;
if ((tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
posix_locking = 1;
retval = cifs_revalidate(filp->f_path.dentry);
if (retval < 0)
return (ssize_t)retval;
memset(&pfLock, 0, sizeof(pfLock));
pfLock.fl_type = F_RDLCK;
pfLock.fl_start = *ppos;
pfLock.fl_end = *ppos+len;
cifsInode = CIFS_I(filp->f_path.dentry->d_inode);
if (cifsInode == NULL)
return -ENOENT;
if (!CIFS_I(filp->f_path.dentry->d_inode)->clientCanCacheRead && !posix_locking) {
retval = cifs_lock(filp, F_GETLK | CIFS_NOPOSIXBRL_READ, &pfLock);
if (retval < 0)
return (ssize_t)retval;
if (pfLock.fl_type == F_UNLCK)
read = do_sync_read(filp, buf, len, ppos);
else
return -EACCES;
} else
read = do_sync_read(filp, buf, len, ppos);
if (read == -EACCES && !posix_locking)
read = cifs_user_read(filp, buf, len, ppos);
return read;
}
static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos) unsigned long nr_segs, loff_t pos)
{ {
...@@ -787,7 +744,7 @@ const struct inode_operations cifs_symlink_inode_ops = { ...@@ -787,7 +744,7 @@ const struct inode_operations cifs_symlink_inode_ops = {
}; };
const struct file_operations cifs_file_ops = { const struct file_operations cifs_file_ops = {
.read = cifs_sync_read, .read = do_sync_read,
.write = do_sync_write, .write = do_sync_write,
.aio_read = generic_file_aio_read, .aio_read = generic_file_aio_read,
.aio_write = cifs_file_aio_write, .aio_write = cifs_file_aio_write,
...@@ -1086,7 +1043,7 @@ init_cifs(void) ...@@ -1086,7 +1043,7 @@ init_cifs(void)
goto out_unregister_filesystem; goto out_unregister_filesystem;
#endif #endif
#ifdef CONFIG_CIFS_DFS_UPCALL #ifdef CONFIG_CIFS_DFS_UPCALL
rc = register_key_type(&key_type_dns_resolver); rc = cifs_init_dns_resolver();
if (rc) if (rc)
goto out_unregister_key_type; goto out_unregister_key_type;
#endif #endif
...@@ -1098,7 +1055,7 @@ init_cifs(void) ...@@ -1098,7 +1055,7 @@ init_cifs(void)
out_unregister_resolver_key: out_unregister_resolver_key:
#ifdef CONFIG_CIFS_DFS_UPCALL #ifdef CONFIG_CIFS_DFS_UPCALL
unregister_key_type(&key_type_dns_resolver); cifs_exit_dns_resolver();
out_unregister_key_type: out_unregister_key_type:
#endif #endif
#ifdef CONFIG_CIFS_UPCALL #ifdef CONFIG_CIFS_UPCALL
...@@ -1124,7 +1081,7 @@ exit_cifs(void) ...@@ -1124,7 +1081,7 @@ exit_cifs(void)
cifs_proc_clean(); cifs_proc_clean();
#ifdef CONFIG_CIFS_DFS_UPCALL #ifdef CONFIG_CIFS_DFS_UPCALL
cifs_dfs_release_automount_timer(); cifs_dfs_release_automount_timer();
unregister_key_type(&key_type_dns_resolver); cifs_exit_dns_resolver();
#endif #endif
#ifdef CONFIG_CIFS_UPCALL #ifdef CONFIG_CIFS_UPCALL
unregister_key_type(&cifs_spnego_key_type); unregister_key_type(&cifs_spnego_key_type);
......
...@@ -319,8 +319,6 @@ struct cifsLockInfo { ...@@ -319,8 +319,6 @@ struct cifsLockInfo {
__u8 type; __u8 type;
}; };
#define CIFS_NOPOSIXBRL_READ 64
/* /*
* One of these for each open instance of a file * One of these for each open instance of a file
*/ */
...@@ -469,7 +467,6 @@ struct oplock_q_entry { ...@@ -469,7 +467,6 @@ struct oplock_q_entry {
struct inode *pinode; struct inode *pinode;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
__u16 netfid; __u16 netfid;
__u32 netpid;
}; };
/* for pending dnotify requests */ /* for pending dnotify requests */
...@@ -503,6 +500,7 @@ struct dfs_info3_param { ...@@ -503,6 +500,7 @@ struct dfs_info3_param {
#define CIFS_FATTR_DFS_REFERRAL 0x1 #define CIFS_FATTR_DFS_REFERRAL 0x1
#define CIFS_FATTR_DELETE_PENDING 0x2 #define CIFS_FATTR_DELETE_PENDING 0x2
#define CIFS_FATTR_NEED_REVAL 0x4 #define CIFS_FATTR_NEED_REVAL 0x4
#define CIFS_FATTR_INO_COLLISION 0x8
struct cifs_fattr { struct cifs_fattr {
u32 cf_flags; u32 cf_flags;
......
...@@ -95,8 +95,10 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, ...@@ -95,8 +95,10 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
__u16 fileHandle, struct file *file, __u16 fileHandle, struct file *file,
struct vfsmount *mnt, unsigned int oflags); struct vfsmount *mnt, unsigned int oflags);
extern int cifs_posix_open(char *full_path, struct inode **pinode, extern int cifs_posix_open(char *full_path, struct inode **pinode,
struct vfsmount *mnt, int mode, int oflags, struct vfsmount *mnt,
__u32 *poplock, __u16 *pnetfid, int xid); struct super_block *sb,
int mode, int oflags,
__u32 *poplock, __u16 *pnetfid, int xid);
extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
FILE_UNIX_BASIC_INFO *info, FILE_UNIX_BASIC_INFO *info,
struct cifs_sb_info *cifs_sb); struct cifs_sb_info *cifs_sb);
...@@ -318,12 +320,12 @@ extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, ...@@ -318,12 +320,12 @@ extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
const struct nls_table *cp, int mapChars); const struct nls_table *cp, int mapChars);
extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 netfid, const __u32 netpid, const __u64 len, const __u16 netfid, const __u64 len,
const __u64 offset, const __u32 numUnlock, const __u64 offset, const __u32 numUnlock,
const __u32 numLock, const __u8 lockType, const __u32 numLock, const __u8 lockType,
const bool waitFlag); const bool waitFlag, const __u8 oplock_level);
extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const __u32 netpid, const int get_flag, const __u16 smb_file_id, const int get_flag,
const __u64 len, struct file_lock *, const __u64 len, struct file_lock *,
const __u16 lock_type, const bool waitFlag); const __u16 lock_type, const bool waitFlag);
extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
......
...@@ -1440,6 +1440,8 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, ...@@ -1440,6 +1440,8 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
__u32 bytes_sent; __u32 bytes_sent;
__u16 byte_count; __u16 byte_count;
*nbytes = 0;
/* cFYI(1, ("write at %lld %d bytes", offset, count));*/ /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
if (tcon->ses == NULL) if (tcon->ses == NULL)
return -ECONNABORTED; return -ECONNABORTED;
...@@ -1526,11 +1528,18 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, ...@@ -1526,11 +1528,18 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
cifs_stats_inc(&tcon->num_writes); cifs_stats_inc(&tcon->num_writes);
if (rc) { if (rc) {
cFYI(1, ("Send error in write = %d", rc)); cFYI(1, ("Send error in write = %d", rc));
*nbytes = 0;
} else { } else {
*nbytes = le16_to_cpu(pSMBr->CountHigh); *nbytes = le16_to_cpu(pSMBr->CountHigh);
*nbytes = (*nbytes) << 16; *nbytes = (*nbytes) << 16;
*nbytes += le16_to_cpu(pSMBr->Count); *nbytes += le16_to_cpu(pSMBr->Count);
/*
* Mask off high 16 bits when bytes written as returned by the
* server is greater than bytes requested by the client. Some
* OS/2 servers are known to set incorrect CountHigh values.
*/
if (*nbytes > count)
*nbytes &= 0xFFFF;
} }
cifs_buf_release(pSMB); cifs_buf_release(pSMB);
...@@ -1623,6 +1632,14 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, ...@@ -1623,6 +1632,14 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
*nbytes = le16_to_cpu(pSMBr->CountHigh); *nbytes = le16_to_cpu(pSMBr->CountHigh);
*nbytes = (*nbytes) << 16; *nbytes = (*nbytes) << 16;
*nbytes += le16_to_cpu(pSMBr->Count); *nbytes += le16_to_cpu(pSMBr->Count);
/*
* Mask off high 16 bits when bytes written as returned by the
* server is greater than bytes requested by the client. OS/2
* servers are known to set incorrect CountHigh values.
*/
if (*nbytes > count)
*nbytes &= 0xFFFF;
} }
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
...@@ -1640,9 +1657,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, ...@@ -1640,9 +1657,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
int int
CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const __u32 net_pid, const __u64 len, const __u16 smb_file_id, const __u64 len,
const __u64 offset, const __u32 numUnlock, const __u64 offset, const __u32 numUnlock,
const __u32 numLock, const __u8 lockType, const bool waitFlag) const __u32 numLock, const __u8 lockType,
const bool waitFlag, const __u8 oplock_level)
{ {
int rc = 0; int rc = 0;
LOCK_REQ *pSMB = NULL; LOCK_REQ *pSMB = NULL;
...@@ -1670,11 +1688,12 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, ...@@ -1670,11 +1688,12 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
pSMB->NumberOfLocks = cpu_to_le16(numLock); pSMB->NumberOfLocks = cpu_to_le16(numLock);
pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
pSMB->LockType = lockType; pSMB->LockType = lockType;
pSMB->OplockLevel = oplock_level;
pSMB->AndXCommand = 0xFF; /* none */ pSMB->AndXCommand = 0xFF; /* none */
pSMB->Fid = smb_file_id; /* netfid stays le */ pSMB->Fid = smb_file_id; /* netfid stays le */
if ((numLock != 0) || (numUnlock != 0)) { if ((numLock != 0) || (numUnlock != 0)) {
pSMB->Locks[0].Pid = cpu_to_le16(net_pid); pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
/* BB where to store pid high? */ /* BB where to store pid high? */
pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len); pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32)); pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
...@@ -1708,7 +1727,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, ...@@ -1708,7 +1727,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
int int
CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const __u32 net_pid, const int get_flag, const __u64 len, const __u16 smb_file_id, const int get_flag, const __u64 len,
struct file_lock *pLockData, const __u16 lock_type, struct file_lock *pLockData, const __u16 lock_type,
const bool waitFlag) const bool waitFlag)
{ {
...@@ -1768,7 +1787,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, ...@@ -1768,7 +1787,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
} else } else
pSMB->Timeout = 0; pSMB->Timeout = 0;
parm_data->pid = cpu_to_le32(net_pid); parm_data->pid = cpu_to_le32(current->tgid);
parm_data->start = cpu_to_le64(pLockData->fl_start); parm_data->start = cpu_to_le64(pLockData->fl_start);
parm_data->length = cpu_to_le64(len); /* normalize negative numbers */ parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
......
...@@ -183,13 +183,14 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, ...@@ -183,13 +183,14 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
} }
int cifs_posix_open(char *full_path, struct inode **pinode, int cifs_posix_open(char *full_path, struct inode **pinode,
struct vfsmount *mnt, int mode, int oflags, struct vfsmount *mnt, struct super_block *sb,
__u32 *poplock, __u16 *pnetfid, int xid) int mode, int oflags,
__u32 *poplock, __u16 *pnetfid, int xid)
{ {
int rc; int rc;
FILE_UNIX_BASIC_INFO *presp_data; FILE_UNIX_BASIC_INFO *presp_data;
__u32 posix_flags = 0; __u32 posix_flags = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_fattr fattr; struct cifs_fattr fattr;
cFYI(1, ("posix open %s", full_path)); cFYI(1, ("posix open %s", full_path));
...@@ -242,7 +243,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, ...@@ -242,7 +243,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
/* get new inode and set it up */ /* get new inode and set it up */
if (*pinode == NULL) { if (*pinode == NULL) {
*pinode = cifs_iget(mnt->mnt_sb, &fattr); *pinode = cifs_iget(sb, &fattr);
if (!*pinode) { if (!*pinode) {
rc = -ENOMEM; rc = -ENOMEM;
goto posix_open_ret; goto posix_open_ret;
...@@ -251,7 +252,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode, ...@@ -251,7 +252,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
cifs_fattr_to_inode(*pinode, &fattr); cifs_fattr_to_inode(*pinode, &fattr);
} }
cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); if (mnt)
cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
posix_open_ret: posix_open_ret:
kfree(presp_data); kfree(presp_data);
...@@ -315,14 +317,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -315,14 +317,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (nd && (nd->flags & LOOKUP_OPEN)) if (nd && (nd->flags & LOOKUP_OPEN))
oflags = nd->intent.open.flags; oflags = nd->intent.open.flags;
else else
oflags = FMODE_READ; oflags = FMODE_READ | SMB_O_CREAT;
if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0) && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0) &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP & (CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) { le64_to_cpu(tcon->fsUnixInfo.Capability))) {
rc = cifs_posix_open(full_path, &newinode, nd->path.mnt, rc = cifs_posix_open(full_path, &newinode,
mode, oflags, &oplock, &fileHandle, xid); nd ? nd->path.mnt : NULL,
inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
/* EIO could indicate that (posix open) operation is not /* EIO could indicate that (posix open) operation is not
supported, despite what server claimed in capability supported, despite what server claimed in capability
negotation. EREMOTE indicates DFS junction, which is not negotation. EREMOTE indicates DFS junction, which is not
...@@ -681,6 +684,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -681,6 +684,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
(nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
(nd->intent.open.flags & O_CREAT)) { (nd->intent.open.flags & O_CREAT)) {
rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
parent_dir_inode->i_sb,
nd->intent.open.create_mode, nd->intent.open.create_mode,
nd->intent.open.flags, &oplock, nd->intent.open.flags, &oplock,
&fileHandle, xid); &fileHandle, xid);
......
...@@ -23,12 +23,16 @@ ...@@ -23,12 +23,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/keyctl.h>
#include <linux/key-type.h>
#include <keys/user-type.h> #include <keys/user-type.h>
#include "dns_resolve.h" #include "dns_resolve.h"
#include "cifsglob.h" #include "cifsglob.h"
#include "cifsproto.h" #include "cifsproto.h"
#include "cifs_debug.h" #include "cifs_debug.h"
static const struct cred *dns_resolver_cache;
/* Checks if supplied name is IP address /* Checks if supplied name is IP address
* returns: * returns:
* 1 - name is IP * 1 - name is IP
...@@ -93,6 +97,7 @@ struct key_type key_type_dns_resolver = { ...@@ -93,6 +97,7 @@ struct key_type key_type_dns_resolver = {
int int
dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
{ {
const struct cred *saved_cred;
int rc = -EAGAIN; int rc = -EAGAIN;
struct key *rkey = ERR_PTR(-EAGAIN); struct key *rkey = ERR_PTR(-EAGAIN);
char *name; char *name;
...@@ -132,8 +137,15 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) ...@@ -132,8 +137,15 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
goto skip_upcall; goto skip_upcall;
} }
saved_cred = override_creds(dns_resolver_cache);
rkey = request_key(&key_type_dns_resolver, name, ""); rkey = request_key(&key_type_dns_resolver, name, "");
revert_creds(saved_cred);
if (!IS_ERR(rkey)) { if (!IS_ERR(rkey)) {
if (!(rkey->perm & KEY_USR_VIEW)) {
down_read(&rkey->sem);
rkey->perm |= KEY_USR_VIEW;
up_read(&rkey->sem);
}
len = rkey->type_data.x[0]; len = rkey->type_data.x[0];
data = rkey->payload.data; data = rkey->payload.data;
} else { } else {
...@@ -164,4 +176,61 @@ out: ...@@ -164,4 +176,61 @@ out:
return rc; return rc;
} }
int __init cifs_init_dns_resolver(void)
{
struct cred *cred;
struct key *keyring;
int ret;
printk(KERN_NOTICE "Registering the %s key type\n",
key_type_dns_resolver.name);
/* create an override credential set with a special thread keyring in
* which DNS requests are cached
*
* this is used to prevent malicious redirections from being installed
* with add_key().
*/
cred = prepare_kernel_cred(NULL);
if (!cred)
return -ENOMEM;
keyring = key_alloc(&key_type_keyring, ".dns_resolver", 0, 0, cred,
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ,
KEY_ALLOC_NOT_IN_QUOTA);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto failed_put_cred;
}
ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
if (ret < 0)
goto failed_put_key;
ret = register_key_type(&key_type_dns_resolver);
if (ret < 0)
goto failed_put_key;
/* instruct request_key() to use this special keyring as a cache for
* the results it looks up */
cred->thread_keyring = keyring;
cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
dns_resolver_cache = cred;
return 0;
failed_put_key:
key_put(keyring);
failed_put_cred:
put_cred(cred);
return ret;
}
void __exit cifs_exit_dns_resolver(void)
{
key_revoke(dns_resolver_cache->thread_keyring);
unregister_key_type(&key_type_dns_resolver);
put_cred(dns_resolver_cache);
printk(KERN_NOTICE "Unregistered %s key type\n",
key_type_dns_resolver.name);
}
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
#define _DNS_RESOLVE_H #define _DNS_RESOLVE_H
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/key-type.h> extern int __init cifs_init_dns_resolver(void);
extern struct key_type key_type_dns_resolver; extern void __exit cifs_exit_dns_resolver(void);
extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr); extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr);
#endif /* KERNEL */ #endif /* KERNEL */
......
...@@ -304,10 +304,12 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -304,10 +304,12 @@ int cifs_open(struct inode *inode, struct file *file)
(CIFS_UNIX_POSIX_PATH_OPS_CAP & (CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) { le64_to_cpu(tcon->fsUnixInfo.Capability))) {
int oflags = (int) cifs_posix_convert_flags(file->f_flags); int oflags = (int) cifs_posix_convert_flags(file->f_flags);
oflags |= SMB_O_CREAT;
/* can not refresh inode info since size could be stale */ /* can not refresh inode info since size could be stale */
rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
cifs_sb->mnt_file_mode /* ignored */, inode->i_sb,
oflags, &oplock, &netfid, xid); cifs_sb->mnt_file_mode /* ignored */,
oflags, &oplock, &netfid, xid);
if (rc == 0) { if (rc == 0) {
cFYI(1, ("posix open succeeded")); cFYI(1, ("posix open succeeded"));
/* no need for special case handling of setting mode /* no need for special case handling of setting mode
...@@ -523,8 +525,9 @@ reopen_error_exit: ...@@ -523,8 +525,9 @@ reopen_error_exit:
int oflags = (int) cifs_posix_convert_flags(file->f_flags); int oflags = (int) cifs_posix_convert_flags(file->f_flags);
/* can not refresh inode info since size could be stale */ /* can not refresh inode info since size could be stale */
rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
cifs_sb->mnt_file_mode /* ignored */, inode->i_sb,
oflags, &oplock, &netfid, xid); cifs_sb->mnt_file_mode /* ignored */,
oflags, &oplock, &netfid, xid);
if (rc == 0) { if (rc == 0) {
cFYI(1, ("posix reopen succeeded")); cFYI(1, ("posix reopen succeeded"));
goto reopen_success; goto reopen_success;
...@@ -750,7 +753,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -750,7 +753,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
bool wait_flag = false; bool wait_flag = false;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
__u32 netpid;
__u16 netfid; __u16 netfid;
__u8 lockType = LOCKING_ANDX_LARGE_FILES; __u8 lockType = LOCKING_ANDX_LARGE_FILES;
bool posix_locking = 0; bool posix_locking = 0;
...@@ -813,14 +815,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -813,14 +815,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
} }
netfid = ((struct cifsFileInfo *)file->private_data)->netfid; netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
if ((cmd & CIFS_NOPOSIXBRL_READ) &&
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_WINE_MODE))
netpid = ((struct cifsFileInfo *)file->private_data)->pid;
else
netpid = current->tgid;
cmd &= ~CIFS_NOPOSIXBRL_READ;
if ((tcon->ses->capabilities & CAP_UNIX) && if ((tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
...@@ -835,7 +829,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -835,7 +829,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
posix_lock_type = CIFS_RDLCK; posix_lock_type = CIFS_RDLCK;
else else
posix_lock_type = CIFS_WRLCK; posix_lock_type = CIFS_WRLCK;
rc = CIFSSMBPosixLock(xid, tcon, netfid, netpid, 1 /* get */, rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */,
length, pfLock, length, pfLock,
posix_lock_type, wait_flag); posix_lock_type, wait_flag);
FreeXid(xid); FreeXid(xid);
...@@ -843,13 +837,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -843,13 +837,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
} }
/* BB we could chain these into one lock request BB */ /* BB we could chain these into one lock request BB */
rc = CIFSSMBLock(xid, tcon, netfid, netpid, length, pfLock->fl_start, rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start,
0, 1, lockType, 0 /* wait flag */ ); 0, 1, lockType, 0 /* wait flag */, 0);
if (rc == 0) { if (rc == 0) {
rc = CIFSSMBLock(xid, tcon, netfid, netpid, length, rc = CIFSSMBLock(xid, tcon, netfid, length,
pfLock->fl_start, 1 /* numUnlock */ , pfLock->fl_start, 1 /* numUnlock */ ,
0 /* numLock */ , lockType, 0 /* numLock */ , lockType,
0 /* wait flag */ ); 0 /* wait flag */, 0);
pfLock->fl_type = F_UNLCK; pfLock->fl_type = F_UNLCK;
if (rc != 0) if (rc != 0)
cERROR(1, ("Error unlocking previously locked " cERROR(1, ("Error unlocking previously locked "
...@@ -863,17 +857,16 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -863,17 +857,16 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if (lockType & LOCKING_ANDX_SHARED_LOCK) { if (lockType & LOCKING_ANDX_SHARED_LOCK) {
pfLock->fl_type = F_WRLCK; pfLock->fl_type = F_WRLCK;
} else { } else {
rc = CIFSSMBLock(xid, tcon, netfid, netpid, rc = CIFSSMBLock(xid, tcon, netfid,
length, pfLock->fl_start, 0, 1, length, pfLock->fl_start, 0, 1,
lockType | LOCKING_ANDX_SHARED_LOCK, lockType | LOCKING_ANDX_SHARED_LOCK,
0 /* wait flag */ ); 0 /* wait flag */, 0);
if (rc == 0) { if (rc == 0) {
rc = CIFSSMBLock(xid, tcon, netfid, rc = CIFSSMBLock(xid, tcon, netfid,
netpid, length, length, pfLock->fl_start, 1, 0,
pfLock->fl_start, 1, 0,
lockType | lockType |
LOCKING_ANDX_SHARED_LOCK, LOCKING_ANDX_SHARED_LOCK,
0 /* wait flag */ ); 0 /* wait flag */, 0);
pfLock->fl_type = F_RDLCK; pfLock->fl_type = F_RDLCK;
if (rc != 0) if (rc != 0)
cERROR(1, ("Error unlocking " cERROR(1, ("Error unlocking "
...@@ -908,7 +901,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -908,7 +901,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if (numUnlock == 1) if (numUnlock == 1)
posix_lock_type = CIFS_UNLCK; posix_lock_type = CIFS_UNLCK;
rc = CIFSSMBPosixLock(xid, tcon, netfid, netpid, 0 /* set */, rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */,
length, pfLock, length, pfLock,
posix_lock_type, wait_flag); posix_lock_type, wait_flag);
} else { } else {
...@@ -916,9 +909,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -916,9 +909,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
(struct cifsFileInfo *)file->private_data; (struct cifsFileInfo *)file->private_data;
if (numLock) { if (numLock) {
rc = CIFSSMBLock(xid, tcon, netfid, netpid, length, rc = CIFSSMBLock(xid, tcon, netfid, length,
pfLock->fl_start, pfLock->fl_start, 0, numLock, lockType,
0, numLock, lockType, wait_flag); wait_flag, 0);
if (rc == 0) { if (rc == 0) {
/* For Windows locks we must store them. */ /* For Windows locks we must store them. */
...@@ -938,9 +931,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -938,9 +931,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
(pfLock->fl_start + length) >= (pfLock->fl_start + length) >=
(li->offset + li->length)) { (li->offset + li->length)) {
stored_rc = CIFSSMBLock(xid, tcon, stored_rc = CIFSSMBLock(xid, tcon,
netfid, netpid, netfid, li->length,
li->length, li->offset, li->offset, 1, 0,
1, 0, li->type, false); li->type, false, 0);
if (stored_rc) if (stored_rc)
rc = stored_rc; rc = stored_rc;
else { else {
...@@ -2394,9 +2387,9 @@ cifs_oplock_break(struct slow_work *work) ...@@ -2394,9 +2387,9 @@ cifs_oplock_break(struct slow_work *work)
* disconnected since oplock already released by the server * disconnected since oplock already released by the server
*/ */
if (!cfile->closePend && !cfile->oplock_break_cancelled) { if (!cfile->closePend && !cfile->oplock_break_cancelled) {
rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, cfile->pid, rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0,
0, 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, LOCKING_ANDX_OPLOCK_RELEASE, false,
false); cinode->clientCanCacheRead ? 1 : 0);
cFYI(1, ("Oplock release rc = %d", rc)); cFYI(1, ("Oplock release rc = %d", rc));
} }
} }
......
...@@ -610,6 +610,16 @@ cifs_find_inode(struct inode *inode, void *opaque) ...@@ -610,6 +610,16 @@ cifs_find_inode(struct inode *inode, void *opaque)
if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
return 0; return 0;
/*
* uh oh -- it's a directory. We can't use it since hardlinked dirs are
* verboten. Disable serverino and return it as if it were found, the
* caller can discard it, generate a uniqueid and retry the find
*/
if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) {
fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
cifs_autodisable_serverino(CIFS_SB(inode->i_sb));
}
return 1; return 1;
} }
...@@ -629,15 +639,22 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) ...@@ -629,15 +639,22 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
unsigned long hash; unsigned long hash;
struct inode *inode; struct inode *inode;
retry_iget5_locked:
cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid));
/* hash down to 32-bits on 32-bit arch */ /* hash down to 32-bits on 32-bit arch */
hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
/* we have fattrs in hand, update the inode */
if (inode) { if (inode) {
/* was there a problematic inode number collision? */
if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
iput(inode);
fattr->cf_uniqueid = iunique(sb, ROOT_I);
fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
goto retry_iget5_locked;
}
cifs_fattr_to_inode(inode, fattr); cifs_fattr_to_inode(inode, fattr);
if (sb->s_flags & MS_NOATIME) if (sb->s_flags & MS_NOATIME)
inode->i_flags |= S_NOATIME | S_NOCMTIME; inode->i_flags |= S_NOATIME | S_NOCMTIME;
...@@ -1267,6 +1284,10 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, ...@@ -1267,6 +1284,10 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
if (rc == 0 || rc != -ETXTBSY) if (rc == 0 || rc != -ETXTBSY)
return rc; return rc;
/* open-file renames don't work across directories */
if (to_dentry->d_parent != from_dentry->d_parent)
return rc;
/* open the file to be renamed -- we need DELETE perms */ /* open the file to be renamed -- we need DELETE perms */
rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, FILE_SHARE_ALL, rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, FILE_SHARE_ALL,
CREATE_NOT_DIR, &srcfid, &oplock, NULL, CREATE_NOT_DIR, &srcfid, &oplock, NULL,
...@@ -1507,9 +1528,13 @@ int cifs_revalidate(struct dentry *direntry) ...@@ -1507,9 +1528,13 @@ int cifs_revalidate(struct dentry *direntry)
if (wbrc) if (wbrc)
CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
} }
cFYI(1, ("Invalidating read ahead data on " /* may eventually have to do this for open files too */
"closed file")); if (list_empty(&(cifsInode->openFileList))) {
invalidate_remote_inode(direntry->d_inode); /* changed on server - flush read ahead pages */
cFYI(1, ("Invalidating read ahead data on "
"closed file"));
invalidate_remote_inode(direntry->d_inode);
}
} }
} }
/* mutex_unlock(&direntry->d_inode->i_mutex); */ /* mutex_unlock(&direntry->d_inode->i_mutex); */
......
...@@ -722,15 +722,7 @@ ssetup_ntlmssp_authenticate: ...@@ -722,15 +722,7 @@ ssetup_ntlmssp_authenticate:
/* calculate session key */ /* calculate session key */
setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
if (first_time) /* should this be moved into common code /* FIXME: calculate MAC key */
with similar ntlmv2 path? */
/* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
response BB FIXME, v2_sess_key); */
/* copy session key */
/* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
bcc_ptr += LM2_SESS_KEY_SIZE; */
memcpy(bcc_ptr, (char *)v2_sess_key, memcpy(bcc_ptr, (char *)v2_sess_key,
sizeof(struct ntlmv2_resp)); sizeof(struct ntlmv2_resp));
bcc_ptr += sizeof(struct ntlmv2_resp); bcc_ptr += sizeof(struct ntlmv2_resp);
......
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