Commit dabcbb1b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch '3.2-without-smb2' of git://git.samba.org/sfrench/cifs-2.6

* '3.2-without-smb2' of git://git.samba.org/sfrench/cifs-2.6: (52 commits)
  Fix build break when freezer not configured
  Add definition for share encryption
  CIFS: Make cifs_push_locks send as many locks at once as possible
  CIFS: Send as many mandatory unlock ranges at once as possible
  CIFS: Implement caching mechanism for posix brlocks
  CIFS: Implement caching mechanism for mandatory brlocks
  CIFS: Fix DFS handling in cifs_get_file_info
  CIFS: Fix error handling in cifs_readv_complete
  [CIFS] Fixup trivial checkpatch warning
  [CIFS] Show nostrictsync and noperm mount options in /proc/mounts
  cifs, freezer: add wait_event_freezekillable and have cifs use it
  cifs: allow cifs_max_pending to be readable under /sys/module/cifs/parameters
  cifs: tune bdi.ra_pages in accordance with the rsize
  cifs: allow for larger rsize= options and change defaults
  cifs: convert cifs_readpages to use async reads
  cifs: add cifs_async_readv
  cifs: fix protocol definition for READ_RSP
  cifs: add a callback function to receive the rest of the frame
  cifs: break out 3rd receive phase into separate function
  cifs: find mid earlier in receive codepath
  ...
parents 5619a693 e0c8ea1a
...@@ -745,4 +745,18 @@ installed and something like the following lines should be added to the ...@@ -745,4 +745,18 @@ installed and something like the following lines should be added to the
create cifs.spnego * * /usr/local/sbin/cifs.upcall %k create cifs.spnego * * /usr/local/sbin/cifs.upcall %k
create dns_resolver * * /usr/local/sbin/cifs.upcall %k create dns_resolver * * /usr/local/sbin/cifs.upcall %k
CIFS kernel module parameters
=============================
These module parameters can be specified or modified either during the time of
module loading or during the runtime by using the interface
/proc/module/cifs/parameters/<param>
i.e. echo "value" > /sys/module/cifs/parameters/<param>
1. echo_retries - The number of echo attempts before giving up and
reconnecting to the server. The default is 5. The value 0
means never reconnect.
2. enable_oplocks - Enable or disable oplocks. Oplocks are enabled by default.
[Y/y/1]. To disable use any of [N/n/0].
...@@ -511,7 +511,7 @@ static const struct file_operations cifsFYI_proc_fops = { ...@@ -511,7 +511,7 @@ static const struct file_operations cifsFYI_proc_fops = {
static int cifs_oplock_proc_show(struct seq_file *m, void *v) static int cifs_oplock_proc_show(struct seq_file *m, void *v)
{ {
seq_printf(m, "%d\n", oplockEnabled); seq_printf(m, "%d\n", enable_oplocks);
return 0; return 0;
} }
...@@ -526,13 +526,16 @@ static ssize_t cifs_oplock_proc_write(struct file *file, ...@@ -526,13 +526,16 @@ static ssize_t cifs_oplock_proc_write(struct file *file,
char c; char c;
int rc; int rc;
printk(KERN_WARNING "CIFS: The /proc/fs/cifs/OplockEnabled interface "
"will be removed in kernel version 3.4. Please migrate to "
"using the 'enable_oplocks' module parameter in cifs.ko.\n");
rc = get_user(c, buffer); rc = get_user(c, buffer);
if (rc) if (rc)
return rc; return rc;
if (c == '0' || c == 'n' || c == 'N') if (c == '0' || c == 'n' || c == 'N')
oplockEnabled = 0; enable_oplocks = false;
else if (c == '1' || c == 'y' || c == 'Y') else if (c == '1' || c == 'y' || c == 'Y')
oplockEnabled = 1; enable_oplocks = true;
return count; return count;
} }
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */
#define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */
#define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */ #define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */
#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */
#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */
struct cifs_sb_info { struct cifs_sb_info {
struct rb_root tlink_tree; struct rb_root tlink_tree;
...@@ -55,6 +57,8 @@ struct cifs_sb_info { ...@@ -55,6 +57,8 @@ struct cifs_sb_info {
atomic_t active; atomic_t active;
uid_t mnt_uid; uid_t mnt_uid;
gid_t mnt_gid; gid_t mnt_gid;
uid_t mnt_backupuid;
gid_t mnt_backupgid;
mode_t mnt_file_mode; mode_t mnt_file_mode;
mode_t mnt_dir_mode; mode_t mnt_dir_mode;
unsigned int mnt_cifs_flags; unsigned int mnt_cifs_flags;
......
This diff is collapsed.
...@@ -37,83 +37,8 @@ ...@@ -37,83 +37,8 @@
* the sequence number before this function is called. Also, this function * the sequence number before this function is called. Also, this function
* should be called with the server->srv_mutex held. * should be called with the server->srv_mutex held.
*/ */
static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, static int cifs_calc_signature(const struct kvec *iov, int n_vec,
struct TCP_Server_Info *server, char *signature) struct TCP_Server_Info *server, char *signature)
{
int rc;
if (cifs_pdu == NULL || signature == NULL || server == NULL)
return -EINVAL;
if (!server->secmech.sdescmd5) {
cERROR(1, "%s: Can't generate signature\n", __func__);
return -1;
}
rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
if (rc) {
cERROR(1, "%s: Could not init md5\n", __func__);
return rc;
}
rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
server->session_key.response, server->session_key.len);
if (rc) {
cERROR(1, "%s: Could not update with response\n", __func__);
return rc;
}
rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length));
if (rc) {
cERROR(1, "%s: Could not update with payload\n", __func__);
return rc;
}
rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
if (rc)
cERROR(1, "%s: Could not generate md5 hash\n", __func__);
return rc;
}
/* must be called with server->srv_mutex held */
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
__u32 *pexpected_response_sequence_number)
{
int rc = 0;
char smb_signature[20];
if ((cifs_pdu == NULL) || (server == NULL))
return -EINVAL;
if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
server->tcpStatus == CifsNeedNegotiate)
return rc;
if (!server->session_estab) {
strncpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
return rc;
}
cifs_pdu->Signature.Sequence.SequenceNumber =
cpu_to_le32(server->sequence_number);
cifs_pdu->Signature.Sequence.Reserved = 0;
*pexpected_response_sequence_number = server->sequence_number++;
server->sequence_number++;
rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
if (rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
return rc;
}
static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
struct TCP_Server_Info *server, char *signature)
{ {
int i; int i;
int rc; int rc;
...@@ -179,7 +104,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, ...@@ -179,7 +104,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
{ {
int rc = 0; int rc = 0;
char smb_signature[20]; char smb_signature[20];
struct smb_hdr *cifs_pdu = iov[0].iov_base; struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
if ((cifs_pdu == NULL) || (server == NULL)) if ((cifs_pdu == NULL) || (server == NULL))
return -EINVAL; return -EINVAL;
...@@ -189,7 +114,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, ...@@ -189,7 +114,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
return rc; return rc;
if (!server->session_estab) { if (!server->session_estab) {
strncpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8); memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
return rc; return rc;
} }
...@@ -200,7 +125,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, ...@@ -200,7 +125,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
*pexpected_response_sequence_number = server->sequence_number++; *pexpected_response_sequence_number = server->sequence_number++;
server->sequence_number++; server->sequence_number++;
rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); rc = cifs_calc_signature(iov, n_vec, server, smb_signature);
if (rc) if (rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8); memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else else
...@@ -209,13 +134,27 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, ...@@ -209,13 +134,27 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
return rc; return rc;
} }
int cifs_verify_signature(struct smb_hdr *cifs_pdu, /* must be called with server->srv_mutex held */
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
__u32 *pexpected_response_sequence_number)
{
struct kvec iov;
iov.iov_base = cifs_pdu;
iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;
return cifs_sign_smb2(&iov, 1, server,
pexpected_response_sequence_number);
}
int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
struct TCP_Server_Info *server, struct TCP_Server_Info *server,
__u32 expected_sequence_number) __u32 expected_sequence_number)
{ {
unsigned int rc; unsigned int rc;
char server_response_sig[8]; char server_response_sig[8];
char what_we_think_sig_should_be[20]; char what_we_think_sig_should_be[20];
struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
if (cifs_pdu == NULL || server == NULL) if (cifs_pdu == NULL || server == NULL)
return -EINVAL; return -EINVAL;
...@@ -247,8 +186,8 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, ...@@ -247,8 +186,8 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
cifs_pdu->Signature.Sequence.Reserved = 0; cifs_pdu->Signature.Sequence.Reserved = 0;
mutex_lock(&server->srv_mutex); mutex_lock(&server->srv_mutex);
rc = cifs_calculate_signature(cifs_pdu, server, rc = cifs_calc_signature(iov, nr_iov, server,
what_we_think_sig_should_be); what_we_think_sig_should_be);
mutex_unlock(&server->srv_mutex); mutex_unlock(&server->srv_mutex);
if (rc) if (rc)
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
int cifsFYI = 0; int cifsFYI = 0;
int cifsERROR = 1; int cifsERROR = 1;
int traceSMB = 0; int traceSMB = 0;
unsigned int oplockEnabled = 1; bool enable_oplocks = true;
unsigned int linuxExtEnabled = 1; unsigned int linuxExtEnabled = 1;
unsigned int lookupCacheEnabled = 1; unsigned int lookupCacheEnabled = 1;
unsigned int multiuser_mount = 0; unsigned int multiuser_mount = 0;
...@@ -74,7 +74,7 @@ module_param(cifs_min_small, int, 0); ...@@ -74,7 +74,7 @@ module_param(cifs_min_small, int, 0);
MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 " MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
"Range: 2 to 256"); "Range: 2 to 256");
unsigned int cifs_max_pending = CIFS_MAX_REQ; unsigned int cifs_max_pending = CIFS_MAX_REQ;
module_param(cifs_max_pending, int, 0); module_param(cifs_max_pending, int, 0444);
MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
"Default: 50 Range: 2 to 256"); "Default: 50 Range: 2 to 256");
unsigned short echo_retries = 5; unsigned short echo_retries = 5;
...@@ -82,6 +82,10 @@ module_param(echo_retries, ushort, 0644); ...@@ -82,6 +82,10 @@ module_param(echo_retries, ushort, 0644);
MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and " MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
"reconnecting server. Default: 5. 0 means " "reconnecting server. Default: 5. 0 means "
"never reconnect."); "never reconnect.");
module_param(enable_oplocks, bool, 0644);
MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks (bool). Default:"
"y/Y/1");
extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_req_poolp;
extern mempool_t *cifs_mid_poolp; extern mempool_t *cifs_mid_poolp;
...@@ -132,12 +136,12 @@ cifs_read_super(struct super_block *sb) ...@@ -132,12 +136,12 @@ cifs_read_super(struct super_block *sb)
else else
sb->s_d_op = &cifs_dentry_ops; sb->s_d_op = &cifs_dentry_ops;
#ifdef CIFS_NFSD_EXPORT #ifdef CONFIG_CIFS_NFSD_EXPORT
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
cFYI(1, "export ops supported"); cFYI(1, "export ops supported");
sb->s_export_op = &cifs_export_ops; sb->s_export_op = &cifs_export_ops;
} }
#endif /* CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
return 0; return 0;
...@@ -432,6 +436,12 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) ...@@ -432,6 +436,12 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
seq_printf(s, ",mfsymlinks"); seq_printf(s, ",mfsymlinks");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
seq_printf(s, ",fsc"); seq_printf(s, ",fsc");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)
seq_printf(s, ",nostrictsync");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
seq_printf(s, ",noperm");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
seq_printf(s, ",strictcache");
seq_printf(s, ",rsize=%d", cifs_sb->rsize); seq_printf(s, ",rsize=%d", cifs_sb->rsize);
seq_printf(s, ",wsize=%d", cifs_sb->wsize); seq_printf(s, ",wsize=%d", cifs_sb->wsize);
...@@ -530,7 +540,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) ...@@ -530,7 +540,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
char *full_path = NULL; char *full_path = NULL;
char *s, *p; char *s, *p;
char sep; char sep;
int xid;
full_path = cifs_build_path_to_root(vol, cifs_sb, full_path = cifs_build_path_to_root(vol, cifs_sb,
cifs_sb_master_tcon(cifs_sb)); cifs_sb_master_tcon(cifs_sb));
...@@ -539,7 +548,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) ...@@ -539,7 +548,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
cFYI(1, "Get root dentry for %s", full_path); cFYI(1, "Get root dentry for %s", full_path);
xid = GetXid();
sep = CIFS_DIR_SEP(cifs_sb); sep = CIFS_DIR_SEP(cifs_sb);
dentry = dget(sb->s_root); dentry = dget(sb->s_root);
p = s = full_path; p = s = full_path;
...@@ -570,7 +578,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) ...@@ -570,7 +578,6 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
dput(dentry); dput(dentry);
dentry = child; dentry = child;
} while (!IS_ERR(dentry)); } while (!IS_ERR(dentry));
_FreeXid(xid);
kfree(full_path); kfree(full_path);
return dentry; return dentry;
} }
...@@ -942,7 +949,8 @@ cifs_init_once(void *inode) ...@@ -942,7 +949,8 @@ cifs_init_once(void *inode)
struct cifsInodeInfo *cifsi = inode; struct cifsInodeInfo *cifsi = inode;
inode_init_once(&cifsi->vfs_inode); inode_init_once(&cifsi->vfs_inode);
INIT_LIST_HEAD(&cifsi->lockList); INIT_LIST_HEAD(&cifsi->llist);
mutex_init(&cifsi->lock_mutex);
} }
static int static int
......
...@@ -121,9 +121,9 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); ...@@ -121,9 +121,9 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
#ifdef CIFS_NFSD_EXPORT #ifdef CONFIG_CIFS_NFSD_EXPORT
extern const struct export_operations cifs_export_ops; extern const struct export_operations cifs_export_ops;
#endif /* CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
#define CIFS_VERSION "1.75" #define CIFS_VERSION "1.75"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -167,6 +167,8 @@ struct smb_vol { ...@@ -167,6 +167,8 @@ struct smb_vol {
uid_t cred_uid; uid_t cred_uid;
uid_t linux_uid; uid_t linux_uid;
gid_t linux_gid; gid_t linux_gid;
uid_t backupuid;
gid_t backupgid;
mode_t file_mode; mode_t file_mode;
mode_t dir_mode; mode_t dir_mode;
unsigned secFlg; unsigned secFlg;
...@@ -179,6 +181,8 @@ struct smb_vol { ...@@ -179,6 +181,8 @@ struct smb_vol {
bool noperm:1; bool noperm:1;
bool no_psx_acl:1; /* set if posix acl support should be disabled */ bool no_psx_acl:1; /* set if posix acl support should be disabled */
bool cifs_acl:1; bool cifs_acl:1;
bool backupuid_specified; /* mount option backupuid is specified */
bool backupgid_specified; /* mount option backupgid is specified */
bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ bool no_xattr:1; /* set if xattr (EA) support should be disabled*/
bool server_ino:1; /* use inode numbers from server ie UniqueId */ bool server_ino:1; /* use inode numbers from server ie UniqueId */
bool direct_io:1; bool direct_io:1;
...@@ -219,7 +223,8 @@ struct smb_vol { ...@@ -219,7 +223,8 @@ struct smb_vol {
CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \ CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \
CIFS_MOUNT_NOPOSIXBRL | CIFS_MOUNT_NOSSYNC | \ CIFS_MOUNT_NOPOSIXBRL | CIFS_MOUNT_NOSSYNC | \
CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \ CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \
CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO) CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \
CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID)
#define CIFS_MS_MASK (MS_RDONLY | MS_MANDLOCK | MS_NOEXEC | MS_NOSUID | \ #define CIFS_MS_MASK (MS_RDONLY | MS_MANDLOCK | MS_NOEXEC | MS_NOSUID | \
MS_NODEV | MS_SYNCHRONOUS) MS_NODEV | MS_SYNCHRONOUS)
...@@ -286,7 +291,13 @@ struct TCP_Server_Info { ...@@ -286,7 +291,13 @@ struct TCP_Server_Info {
bool sec_kerberosu2u; /* supports U2U Kerberos */ bool sec_kerberosu2u; /* supports U2U Kerberos */
bool sec_kerberos; /* supports plain Kerberos */ bool sec_kerberos; /* supports plain Kerberos */
bool sec_mskerberos; /* supports legacy MS Kerberos */ bool sec_mskerberos; /* supports legacy MS Kerberos */
bool large_buf; /* is current buffer large? */
struct delayed_work echo; /* echo ping workqueue job */ struct delayed_work echo; /* echo ping workqueue job */
struct kvec *iov; /* reusable kvec array for receives */
unsigned int nr_iov; /* number of kvecs in array */
char *smallbuf; /* pointer to current "small" buffer */
char *bigbuf; /* pointer to current "big" buffer */
unsigned int total_read; /* total amount of data read in this pass */
#ifdef CONFIG_CIFS_FSCACHE #ifdef CONFIG_CIFS_FSCACHE
struct fscache_cookie *fscache; /* client index cache cookie */ struct fscache_cookie *fscache; /* client index cache cookie */
#endif #endif
...@@ -485,9 +496,13 @@ extern struct cifs_tcon *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb); ...@@ -485,9 +496,13 @@ extern struct cifs_tcon *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb);
*/ */
struct cifsLockInfo { struct cifsLockInfo {
struct list_head llist; /* pointer to next cifsLockInfo */ struct list_head llist; /* pointer to next cifsLockInfo */
struct list_head blist; /* pointer to locks blocked on this */
wait_queue_head_t block_q;
__u64 offset; __u64 offset;
__u64 length; __u64 length;
__u32 pid;
__u8 type; __u8 type;
__u16 netfid;
}; };
/* /*
...@@ -520,8 +535,6 @@ struct cifsFileInfo { ...@@ -520,8 +535,6 @@ struct cifsFileInfo {
struct dentry *dentry; struct dentry *dentry;
unsigned int f_flags; unsigned int f_flags;
struct tcon_link *tlink; struct tcon_link *tlink;
struct mutex lock_mutex;
struct list_head llist; /* list of byte range locks we have. */
bool invalidHandle:1; /* file closed via session abend */ bool invalidHandle:1; /* file closed via session abend */
bool oplock_break_cancelled:1; bool oplock_break_cancelled:1;
int count; /* refcount protected by cifs_file_list_lock */ int count; /* refcount protected by cifs_file_list_lock */
...@@ -554,7 +567,9 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file); ...@@ -554,7 +567,9 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
*/ */
struct cifsInodeInfo { struct cifsInodeInfo {
struct list_head lockList; struct list_head llist; /* brlocks for this inode */
bool can_cache_brlcks;
struct mutex lock_mutex; /* protect two fields above */
/* BB add in lists for dirty pages i.e. write caching info for oplock */ /* BB add in lists for dirty pages i.e. write caching info for oplock */
struct list_head openFileList; struct list_head openFileList;
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
...@@ -643,8 +658,24 @@ static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon, ...@@ -643,8 +658,24 @@ static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon,
struct mid_q_entry; struct mid_q_entry;
/* /*
* This is the prototype for the mid callback function. When creating one, * This is the prototype for the mid receive function. This function is for
* take special care to avoid deadlocks. Things to bear in mind: * receiving the rest of the SMB frame, starting with the WordCount (which is
* just after the MID in struct smb_hdr). Note:
*
* - This will be called by cifsd, with no locks held.
* - The mid will still be on the pending_mid_q.
* - mid->resp_buf will point to the current buffer.
*
* Returns zero on a successful receive, or an error. The receive state in
* the TCP_Server_Info will also be updated.
*/
typedef int (mid_receive_t)(struct TCP_Server_Info *server,
struct mid_q_entry *mid);
/*
* This is the prototype for the mid callback function. This is called once the
* mid has been received off of the socket. When creating one, take special
* care to avoid deadlocks. Things to bear in mind:
* *
* - it will be called by cifsd, with no locks held * - it will be called by cifsd, with no locks held
* - the mid will be removed from any lists * - the mid will be removed from any lists
...@@ -662,9 +693,10 @@ struct mid_q_entry { ...@@ -662,9 +693,10 @@ struct mid_q_entry {
unsigned long when_sent; /* time when smb send finished */ unsigned long when_sent; /* time when smb send finished */
unsigned long when_received; /* when demux complete (taken off wire) */ unsigned long when_received; /* when demux complete (taken off wire) */
#endif #endif
mid_receive_t *receive; /* call receive callback */
mid_callback_t *callback; /* call completion callback */ mid_callback_t *callback; /* call completion callback */
void *callback_data; /* general purpose pointer for callback */ void *callback_data; /* general purpose pointer for callback */
struct smb_hdr *resp_buf; /* response buffer */ struct smb_hdr *resp_buf; /* pointer to received SMB header */
int midState; /* wish this were enum but can not pass to wait_event */ int midState; /* wish this were enum but can not pass to wait_event */
__u8 command; /* smb command code */ __u8 command; /* smb command code */
bool largeBuf:1; /* if valid response, is pointer to large buf */ bool largeBuf:1; /* if valid response, is pointer to large buf */
...@@ -964,7 +996,8 @@ GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions ...@@ -964,7 +996,8 @@ GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
to be established on existing mount if we to be established on existing mount if we
have the uid/password or Kerberos credential have the uid/password or Kerberos credential
or equivalent for current user */ or equivalent for current user */
GLOBAL_EXTERN unsigned int oplockEnabled; /* enable or disable oplocks */
GLOBAL_EXTERN bool enable_oplocks;
GLOBAL_EXTERN unsigned int lookupCacheEnabled; GLOBAL_EXTERN unsigned int lookupCacheEnabled;
GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent
with more secure ntlmssp2 challenge/resp */ with more secure ntlmssp2 challenge/resp */
...@@ -978,10 +1011,16 @@ GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ ...@@ -978,10 +1011,16 @@ GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
/* reconnect after this many failed echo attempts */ /* reconnect after this many failed echo attempts */
GLOBAL_EXTERN unsigned short echo_retries; GLOBAL_EXTERN unsigned short echo_retries;
#ifdef CONFIG_CIFS_ACL
GLOBAL_EXTERN struct rb_root uidtree; GLOBAL_EXTERN struct rb_root uidtree;
GLOBAL_EXTERN struct rb_root gidtree; GLOBAL_EXTERN struct rb_root gidtree;
GLOBAL_EXTERN spinlock_t siduidlock; GLOBAL_EXTERN spinlock_t siduidlock;
GLOBAL_EXTERN spinlock_t sidgidlock; GLOBAL_EXTERN spinlock_t sidgidlock;
GLOBAL_EXTERN struct rb_root siduidtree;
GLOBAL_EXTERN struct rb_root sidgidtree;
GLOBAL_EXTERN spinlock_t uidsidlock;
GLOBAL_EXTERN spinlock_t gidsidlock;
#endif /* CONFIG_CIFS_ACL */
void cifs_oplock_break(struct work_struct *work); void cifs_oplock_break(struct work_struct *work);
......
...@@ -1089,9 +1089,7 @@ typedef struct smb_com_read_rsp { ...@@ -1089,9 +1089,7 @@ typedef struct smb_com_read_rsp {
__le16 DataLengthHigh; __le16 DataLengthHigh;
__u64 Reserved2; __u64 Reserved2;
__u16 ByteCount; __u16 ByteCount;
__u8 Pad; /* BB check for whether padded to DWORD /* read response data immediately follows */
boundary and optimum performance here */
char Data[1];
} __attribute__((packed)) READ_RSP; } __attribute__((packed)) READ_RSP;
typedef struct locking_andx_range { typedef struct locking_andx_range {
...@@ -1913,6 +1911,10 @@ typedef struct whoami_rsp_data { /* Query level 0x202 */ ...@@ -1913,6 +1911,10 @@ typedef struct whoami_rsp_data { /* Query level 0x202 */
/* SETFSInfo Levels */ /* SETFSInfo Levels */
#define SMB_SET_CIFS_UNIX_INFO 0x200 #define SMB_SET_CIFS_UNIX_INFO 0x200
/* level 0x203 is defined above in list of QFS info levels */
/* #define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203 */
/* Level 0x200 request structure follows */
typedef struct smb_com_transaction2_setfsi_req { typedef struct smb_com_transaction2_setfsi_req {
struct smb_hdr hdr; /* wct = 15 */ struct smb_hdr hdr; /* wct = 15 */
__le16 TotalParameterCount; __le16 TotalParameterCount;
...@@ -1940,13 +1942,39 @@ typedef struct smb_com_transaction2_setfsi_req { ...@@ -1940,13 +1942,39 @@ typedef struct smb_com_transaction2_setfsi_req {
__le64 ClientUnixCap; /* Data end */ __le64 ClientUnixCap; /* Data end */
} __attribute__((packed)) TRANSACTION2_SETFSI_REQ; } __attribute__((packed)) TRANSACTION2_SETFSI_REQ;
/* level 0x203 request structure follows */
typedef struct smb_com_transaction2_setfs_enc_req {
struct smb_hdr hdr; /* wct = 15 */
__le16 TotalParameterCount;
__le16 TotalDataCount;
__le16 MaxParameterCount;
__le16 MaxDataCount;
__u8 MaxSetupCount;
__u8 Reserved;
__le16 Flags;
__le32 Timeout;
__u16 Reserved2;
__le16 ParameterCount; /* 4 */
__le16 ParameterOffset;
__le16 DataCount; /* 12 */
__le16 DataOffset;
__u8 SetupCount; /* one */
__u8 Reserved3;
__le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
__le16 ByteCount;
__u8 Pad;
__u16 Reserved4; /* Parameters start. */
__le16 InformationLevel;/* Parameters end. */
/* NTLMSSP Blob, Data start. */
} __attribute__((packed)) TRANSACTION2_SETFSI_ENC_REQ;
/* response for setfsinfo levels 0x200 and 0x203 */
typedef struct smb_com_transaction2_setfsi_rsp { typedef struct smb_com_transaction2_setfsi_rsp {
struct smb_hdr hdr; /* wct = 10 */ struct smb_hdr hdr; /* wct = 10 */
struct trans2_resp t2; struct trans2_resp t2;
__u16 ByteCount; __u16 ByteCount;
} __attribute__((packed)) TRANSACTION2_SETFSI_RSP; } __attribute__((packed)) TRANSACTION2_SETFSI_RSP;
typedef struct smb_com_transaction2_get_dfs_refer_req { typedef struct smb_com_transaction2_get_dfs_refer_req {
struct smb_hdr hdr; /* wct = 15 */ struct smb_hdr hdr; /* wct = 15 */
__le16 TotalParameterCount; __le16 TotalParameterCount;
...@@ -2098,13 +2126,13 @@ typedef struct { ...@@ -2098,13 +2126,13 @@ typedef struct {
#define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and #define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and
QFS PROXY call */ QFS PROXY call */
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
/* Can not set pathnames cap yet until we send new posix create SMB since /* presumably don't need the 0x20 POSIX_PATH_OPS_CAP since we never send
otherwise server can treat such handles opened with older ntcreatex LockingX instead of posix locking call on unix sess (and we do not expect
(by a new client which knows how to send posix path ops) LockingX to use different (ie Windows) semantics than posix locking on
as non-posix handles (can affect write behavior with byte range locks. the same session (if WINE needs to do this later, we can add this cap
We can add back in POSIX_PATH_OPS cap when Posix Create/Mkdir finished */ back in later */
/* #define CIFS_UNIX_CAP_MASK 0x000000fb */ /* #define CIFS_UNIX_CAP_MASK 0x000000fb */
#define CIFS_UNIX_CAP_MASK 0x000000db #define CIFS_UNIX_CAP_MASK 0x000003db
#else #else
#define CIFS_UNIX_CAP_MASK 0x00000013 #define CIFS_UNIX_CAP_MASK 0x00000013
#endif /* CONFIG_CIFS_POSIX */ #endif /* CONFIG_CIFS_POSIX */
......
...@@ -69,8 +69,9 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, ...@@ -69,8 +69,9 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
struct TCP_Server_Info *server); struct TCP_Server_Info *server);
extern void DeleteMidQEntry(struct mid_q_entry *midEntry); extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
unsigned int nvec, mid_callback_t *callback, unsigned int nvec, mid_receive_t *receive,
void *cbdata, bool ignore_pend); mid_callback_t *callback, void *cbdata,
bool ignore_pend);
extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
struct smb_hdr * /* input */ , struct smb_hdr * /* input */ ,
struct smb_hdr * /* out */ , struct smb_hdr * /* out */ ,
...@@ -90,6 +91,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid, ...@@ -90,6 +91,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
extern bool is_valid_oplock_break(struct smb_hdr *smb, extern bool is_valid_oplock_break(struct smb_hdr *smb,
struct TCP_Server_Info *); struct TCP_Server_Info *);
extern bool backup_cred(struct cifs_sb_info *);
extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
unsigned int bytes_written); unsigned int bytes_written);
...@@ -145,12 +147,19 @@ extern int cifs_get_inode_info_unix(struct inode **pinode, ...@@ -145,12 +147,19 @@ extern int cifs_get_inode_info_unix(struct inode **pinode,
extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
struct cifs_fattr *fattr, struct inode *inode, struct cifs_fattr *fattr, struct inode *inode,
const char *path, const __u16 *pfid); const char *path, const __u16 *pfid);
extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64,
uid_t, gid_t);
extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
const char *, u32 *); const char *, u32 *);
extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
const char *); const char *, int);
extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
unsigned int to_read);
extern int cifs_readv_from_socket(struct TCP_Server_Info *server,
struct kvec *iov_orig, unsigned int nr_segs,
unsigned int to_read);
extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
struct cifs_sb_info *cifs_sb); struct cifs_sb_info *cifs_sb);
extern int cifs_match_super(struct super_block *, void *); extern int cifs_match_super(struct super_block *, void *);
...@@ -359,14 +368,17 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, ...@@ -359,14 +368,17 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
int remap_special_chars); int remap_special_chars);
extern int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid,
const __u8 lock_type, const __u32 num_unlock,
const __u32 num_lock, LOCKING_ANDX_RANGE *buf);
extern int CIFSSMBLock(const int xid, struct cifs_tcon *tcon, extern int CIFSSMBLock(const int xid, struct cifs_tcon *tcon,
const __u16 netfid, const __u64 len, const __u16 netfid, const __u32 netpid, 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 __u8 oplock_level); const bool waitFlag, const __u8 oplock_level);
extern int CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon, extern int CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon,
const __u16 smb_file_id, const int get_flag, const __u16 smb_file_id, const __u32 netpid,
const __u64 len, struct file_lock *, const int get_flag, 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 cifs_tcon *tcon); extern int CIFSSMBTDis(const int xid, struct cifs_tcon *tcon);
extern int CIFSSMBEcho(struct TCP_Server_Info *server); extern int CIFSSMBEcho(struct TCP_Server_Info *server);
...@@ -380,7 +392,7 @@ extern void tconInfoFree(struct cifs_tcon *); ...@@ -380,7 +392,7 @@ extern void tconInfoFree(struct cifs_tcon *);
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
__u32 *); __u32 *);
extern int cifs_verify_signature(struct smb_hdr *, extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
struct TCP_Server_Info *server, struct TCP_Server_Info *server,
__u32 expected_sequence_number); __u32 expected_sequence_number);
extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *); extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *);
...@@ -419,7 +431,7 @@ extern int CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, ...@@ -419,7 +431,7 @@ extern int CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon,
extern int CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, extern int CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon,
__u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
extern int CIFSSMBSetCIFSACL(const int, struct cifs_tcon *, __u16, extern int CIFSSMBSetCIFSACL(const int, struct cifs_tcon *, __u16,
struct cifs_ntsd *, __u32); struct cifs_ntsd *, __u32, int);
extern int CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon, extern int CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
const unsigned char *searchName, const unsigned char *searchName,
char *acl_inf, const int buflen, const int acl_type, char *acl_inf, const int buflen, const int acl_type,
...@@ -440,6 +452,24 @@ extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); ...@@ -440,6 +452,24 @@ extern int E_md4hash(const unsigned char *passwd, unsigned char *p16);
extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
unsigned char *p24); unsigned char *p24);
/* asynchronous read support */
struct cifs_readdata {
struct cifsFileInfo *cfile;
struct address_space *mapping;
__u64 offset;
unsigned int bytes;
pid_t pid;
int result;
struct list_head pages;
struct work_struct work;
unsigned int nr_iov;
struct kvec iov[1];
};
struct cifs_readdata *cifs_readdata_alloc(unsigned int nr_pages);
void cifs_readdata_free(struct cifs_readdata *rdata);
int cifs_async_readv(struct cifs_readdata *rdata);
/* asynchronous write support */ /* asynchronous write support */
struct cifs_writedata { struct cifs_writedata {
struct kref refcount; struct kref refcount;
......
This diff is collapsed.
This diff is collapsed.
...@@ -171,7 +171,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -171,7 +171,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
} }
tcon = tlink_tcon(tlink); tcon = tlink_tcon(tlink);
if (oplockEnabled) if (enable_oplocks)
oplock = REQ_OPLOCK; oplock = REQ_OPLOCK;
if (nd) if (nd)
...@@ -244,6 +244,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -244,6 +244,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (!tcon->unix_ext && (mode & S_IWUGO) == 0) if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
create_options |= CREATE_OPTION_READONLY; create_options |= CREATE_OPTION_READONLY;
if (backup_cred(cifs_sb))
create_options |= CREATE_OPEN_BACKUP_INTENT;
if (tcon->ses->capabilities & CAP_NT_SMBS) if (tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, tcon, full_path, disposition, rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
desiredAccess, create_options, desiredAccess, create_options,
...@@ -357,6 +360,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -357,6 +360,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
{ {
int rc = -EPERM; int rc = -EPERM;
int xid; int xid;
int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *pTcon; struct cifs_tcon *pTcon;
...@@ -431,9 +435,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -431,9 +435,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
return rc; return rc;
} }
/* FIXME: would WRITE_OWNER | WRITE_DAC be better? */ if (backup_cred(cifs_sb))
create_options |= CREATE_OPEN_BACKUP_INTENT;
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, GENERIC_WRITE, create_options,
&fileHandle, &oplock, buf, cifs_sb->local_nls, &fileHandle, &oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) if (rc)
...@@ -642,8 +648,16 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) ...@@ -642,8 +648,16 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
if (direntry->d_inode) { if (direntry->d_inode) {
if (cifs_revalidate_dentry(direntry)) if (cifs_revalidate_dentry(direntry))
return 0; return 0;
else else {
/*
* Forcibly invalidate automounting directory inodes
* (remote DFS directories) so to have them
* instantiated again for automount
*/
if (IS_AUTOMOUNT(direntry->d_inode))
return 0;
return 1; return 1;
}
} }
/* /*
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#include "cifs_debug.h" #include "cifs_debug.h"
#include "cifsfs.h" #include "cifsfs.h"
#ifdef CIFS_NFSD_EXPORT #ifdef CONFIG_CIFS_NFSD_EXPORT
static struct dentry *cifs_get_parent(struct dentry *dentry) static struct dentry *cifs_get_parent(struct dentry *dentry)
{ {
/* BB need to add code here eventually to enable export via NFSD */ /* BB need to add code here eventually to enable export via NFSD */
...@@ -63,5 +63,5 @@ const struct export_operations cifs_export_ops = { ...@@ -63,5 +63,5 @@ const struct export_operations cifs_export_ops = {
.encode_fs = */ .encode_fs = */
}; };
#endif /* CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
This diff is collapsed.
...@@ -562,7 +562,16 @@ int cifs_get_file_info(struct file *filp) ...@@ -562,7 +562,16 @@ int cifs_get_file_info(struct file *filp)
xid = GetXid(); xid = GetXid();
rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
if (rc == -EOPNOTSUPP || rc == -EINVAL) { switch (rc) {
case 0:
cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
break;
case -EREMOTE:
cifs_create_dfs_fattr(&fattr, inode->i_sb);
rc = 0;
break;
case -EOPNOTSUPP:
case -EINVAL:
/* /*
* FIXME: legacy server -- fall back to path-based call? * FIXME: legacy server -- fall back to path-based call?
* for now, just skip revalidating and mark inode for * for now, just skip revalidating and mark inode for
...@@ -570,18 +579,14 @@ int cifs_get_file_info(struct file *filp) ...@@ -570,18 +579,14 @@ int cifs_get_file_info(struct file *filp)
*/ */
rc = 0; rc = 0;
CIFS_I(inode)->time = 0; CIFS_I(inode)->time = 0;
default:
goto cgfi_exit; goto cgfi_exit;
} else if (rc == -EREMOTE) { }
cifs_create_dfs_fattr(&fattr, inode->i_sb);
rc = 0;
} else if (rc)
goto cgfi_exit;
/* /*
* don't bother with SFU junk here -- just mark inode as needing * don't bother with SFU junk here -- just mark inode as needing
* revalidation. * revalidation.
*/ */
cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
fattr.cf_uniqueid = CIFS_I(inode)->uniqueid; fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
cifs_fattr_to_inode(inode, &fattr); cifs_fattr_to_inode(inode, &fattr);
...@@ -2096,6 +2101,8 @@ static int ...@@ -2096,6 +2101,8 @@ static int
cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
{ {
int xid; int xid;
uid_t uid = NO_CHANGE_32;
gid_t gid = NO_CHANGE_32;
struct inode *inode = direntry->d_inode; struct inode *inode = direntry->d_inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsInodeInfo *cifsInode = CIFS_I(inode); struct cifsInodeInfo *cifsInode = CIFS_I(inode);
...@@ -2146,13 +2153,25 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) ...@@ -2146,13 +2153,25 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
goto cifs_setattr_exit; goto cifs_setattr_exit;
} }
/* if (attrs->ia_valid & ATTR_UID)
* Without unix extensions we can't send ownership changes to the uid = attrs->ia_uid;
* server, so silently ignore them. This is consistent with how
* local DOS/Windows filesystems behave (VFAT, NTFS, etc). With if (attrs->ia_valid & ATTR_GID)
* CIFSACL support + proper Windows to Unix idmapping, we may be gid = attrs->ia_gid;
* able to support this in the future.
*/ #ifdef CONFIG_CIFS_ACL
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) {
rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
uid, gid);
if (rc) {
cFYI(1, "%s: Setting id failed with error: %d",
__func__, rc);
goto cifs_setattr_exit;
}
}
} else
#endif /* CONFIG_CIFS_ACL */
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
...@@ -2161,15 +2180,12 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) ...@@ -2161,15 +2180,12 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
attrs->ia_valid &= ~ATTR_MODE; attrs->ia_valid &= ~ATTR_MODE;
if (attrs->ia_valid & ATTR_MODE) { if (attrs->ia_valid & ATTR_MODE) {
cFYI(1, "Mode changed to 0%o", attrs->ia_mode);
mode = attrs->ia_mode; mode = attrs->ia_mode;
}
if (attrs->ia_valid & ATTR_MODE) {
rc = 0; rc = 0;
#ifdef CONFIG_CIFS_ACL #ifdef CONFIG_CIFS_ACL
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
rc = mode_to_cifs_acl(inode, full_path, mode); rc = id_mode_to_cifs_acl(inode, full_path, mode,
NO_CHANGE_32, NO_CHANGE_32);
if (rc) { if (rc) {
cFYI(1, "%s: Setting ACL failed with error: %d", cFYI(1, "%s: Setting ACL failed with error: %d",
__func__, rc); __func__, rc);
......
...@@ -183,14 +183,20 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) ...@@ -183,14 +183,20 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
static int static int
CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon, CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon,
const char *fromName, const char *toName, const char *fromName, const char *toName,
const struct nls_table *nls_codepage, int remap) struct cifs_sb_info *cifs_sb)
{ {
int rc; int rc;
int oplock = 0; int oplock = 0;
int remap;
int create_options = CREATE_NOT_DIR;
__u16 netfid = 0; __u16 netfid = 0;
u8 *buf; u8 *buf;
unsigned int bytes_written = 0; unsigned int bytes_written = 0;
struct cifs_io_parms io_parms; struct cifs_io_parms io_parms;
struct nls_table *nls_codepage;
nls_codepage = cifs_sb->local_nls;
remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
if (!buf) if (!buf)
...@@ -202,8 +208,11 @@ CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon, ...@@ -202,8 +208,11 @@ CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon,
return rc; return rc;
} }
if (backup_cred(cifs_sb))
create_options |= CREATE_OPEN_BACKUP_INTENT;
rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE, rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
CREATE_NOT_DIR, &netfid, &oplock, NULL, create_options, &netfid, &oplock, NULL,
nls_codepage, remap); nls_codepage, remap);
if (rc != 0) { if (rc != 0) {
kfree(buf); kfree(buf);
...@@ -559,9 +568,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) ...@@ -559,9 +568,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
/* BB what if DFS and this volume is on different share? BB */ /* BB what if DFS and this volume is on different share? BB */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname,
cifs_sb->local_nls, cifs_sb);
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
else if (pTcon->unix_ext) else if (pTcon->unix_ext)
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
cifs_sb->local_nls); cifs_sb->local_nls);
......
...@@ -420,19 +420,22 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid) ...@@ -420,19 +420,22 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid)
} }
int int
checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int total_read)
{ {
__u32 len = be32_to_cpu(smb->smb_buf_length); __u32 rfclen = be32_to_cpu(smb->smb_buf_length);
__u32 clc_len; /* calculated length */ __u32 clc_len; /* calculated length */
cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len); cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x",
total_read, rfclen);
if (length < 2 + sizeof(struct smb_hdr)) { /* is this frame too small to even get to a BCC? */
if ((length >= sizeof(struct smb_hdr) - 1) if (total_read < 2 + sizeof(struct smb_hdr)) {
if ((total_read >= sizeof(struct smb_hdr) - 1)
&& (smb->Status.CifsError != 0)) { && (smb->Status.CifsError != 0)) {
/* it's an error return */
smb->WordCount = 0; smb->WordCount = 0;
/* some error cases do not return wct and bcc */ /* some error cases do not return wct and bcc */
return 0; return 0;
} else if ((length == sizeof(struct smb_hdr) + 1) && } else if ((total_read == sizeof(struct smb_hdr) + 1) &&
(smb->WordCount == 0)) { (smb->WordCount == 0)) {
char *tmp = (char *)smb; char *tmp = (char *)smb;
/* Need to work around a bug in two servers here */ /* Need to work around a bug in two servers here */
...@@ -452,39 +455,35 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) ...@@ -452,39 +455,35 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
} else { } else {
cERROR(1, "Length less than smb header size"); cERROR(1, "Length less than smb header size");
} }
return 1; return -EIO;
}
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
cERROR(1, "smb length greater than MaxBufSize, mid=%d",
smb->Mid);
return 1;
} }
/* otherwise, there is enough to get to the BCC */
if (check_smb_hdr(smb, mid)) if (check_smb_hdr(smb, mid))
return 1; return -EIO;
clc_len = smbCalcSize(smb); clc_len = smbCalcSize(smb);
if (4 + len != length) { if (4 + rfclen != total_read) {
cERROR(1, "Length read does not match RFC1001 length %d", cERROR(1, "Length read does not match RFC1001 length %d",
len); rfclen);
return 1; return -EIO;
} }
if (4 + len != clc_len) { if (4 + rfclen != clc_len) {
/* check if bcc wrapped around for large read responses */ /* check if bcc wrapped around for large read responses */
if ((len > 64 * 1024) && (len > clc_len)) { if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
/* check if lengths match mod 64K */ /* check if lengths match mod 64K */
if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
return 0; /* bcc wrapped */ return 0; /* bcc wrapped */
} }
cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u", cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u",
clc_len, 4 + len, smb->Mid); clc_len, 4 + rfclen, smb->Mid);
if (4 + len < clc_len) { if (4 + rfclen < clc_len) {
cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u", cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u",
len, smb->Mid); rfclen, smb->Mid);
return 1; return -EIO;
} else if (len > clc_len + 512) { } else if (rfclen > clc_len + 512) {
/* /*
* Some servers (Windows XP in particular) send more * Some servers (Windows XP in particular) send more
* data than the lengths in the SMB packet would * data than the lengths in the SMB packet would
...@@ -495,8 +494,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) ...@@ -495,8 +494,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
* data to 512 bytes. * data to 512 bytes.
*/ */
cERROR(1, "RFC1001 size %u more than 512 bytes larger " cERROR(1, "RFC1001 size %u more than 512 bytes larger "
"than SMB for mid=%u", len, smb->Mid); "than SMB for mid=%u", rfclen, smb->Mid);
return 1; return -EIO;
} }
} }
return 0; return 0;
...@@ -676,3 +675,18 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) ...@@ -676,3 +675,18 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
cinode->clientCanCacheRead = false; cinode->clientCanCacheRead = false;
} }
} }
bool
backup_cred(struct cifs_sb_info *cifs_sb)
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) {
if (cifs_sb->mnt_backupuid == current_fsuid())
return true;
}
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) {
if (in_group_p(cifs_sb->mnt_backupgid))
return true;
}
return false;
}
...@@ -124,7 +124,9 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) ...@@ -124,7 +124,9 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
/* that we use in next few lines */ /* that we use in next few lines */
/* Note that header is initialized to zero in header_assemble */ /* Note that header is initialized to zero in header_assemble */
pSMB->req.AndXCommand = 0xFF; pSMB->req.AndXCommand = 0xFF;
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32,
CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
USHRT_MAX));
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
pSMB->req.VcNumber = get_next_vcnum(ses); pSMB->req.VcNumber = get_next_vcnum(ses);
......
...@@ -265,91 +265,6 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) ...@@ -265,91 +265,6 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
return rc; return rc;
} }
#if 0 /* currently unused */
/* Does both the NT and LM owfs of a user's password */
static void
nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
{
char passwd[514];
memset(passwd, '\0', 514);
if (strlen(pwd) < 513)
strcpy(passwd, pwd);
else
memcpy(passwd, pwd, 512);
/* Calculate the MD4 hash (NT compatible) of the password */
memset(nt_p16, '\0', 16);
E_md4hash(passwd, nt_p16);
/* Mangle the passwords into Lanman format */
passwd[14] = '\0';
/* strupper(passwd); */
/* Calculate the SMB (lanman) hash functions of the password */
memset(p16, '\0', 16);
E_P16((unsigned char *) passwd, (unsigned char *) p16);
/* clear out local copy of user's password (just being paranoid). */
memset(passwd, '\0', sizeof(passwd));
}
#endif
/* Does the NTLMv2 owfs of a user's password */
#if 0 /* function not needed yet - but will be soon */
static void
ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
const char *domain_n, unsigned char kr_buf[16],
const struct nls_table *nls_codepage)
{
wchar_t *user_u;
wchar_t *dom_u;
int user_l, domain_l;
struct HMACMD5Context ctx;
/* might as well do one alloc to hold both (user_u and dom_u) */
user_u = kmalloc(2048 * sizeof(wchar_t), GFP_KERNEL);
if (user_u == NULL)
return;
dom_u = user_u + 1024;
/* push_ucs2(NULL, user_u, user_n, (user_l+1)*2,
STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2,
STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
/* BB user and domain may need to be uppercased */
user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
user_l++; /* trailing null */
domain_l++;
hmac_md5_init_limK_to_64(owf, 16, &ctx);
hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
hmac_md5_final(kr_buf, &ctx);
kfree(user_u);
}
#endif
/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
#if 0 /* currently unused */
static void
NTLMSSPOWFencrypt(unsigned char passwd[8],
unsigned char *ntlmchalresp, unsigned char p24[24])
{
unsigned char p21[21];
memset(p21, '\0', 21);
memcpy(p21, passwd, 8);
memset(p21 + 8, 0xbd, 8);
E_P24(p21, ntlmchalresp, p24);
}
#endif
/* Does the NT MD4 hash then des encryption. */ /* Does the NT MD4 hash then des encryption. */
int int
SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
...@@ -369,39 +284,3 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) ...@@ -369,39 +284,3 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
rc = E_P24(p21, c8, p24); rc = E_P24(p21, c8, p24);
return rc; return rc;
} }
/* Does the md5 encryption from the NT hash for NTLMv2. */
/* These routines will be needed later */
#if 0
static void
SMBOWFencrypt_ntv2(const unsigned char kr[16],
const struct data_blob *srv_chal,
const struct data_blob *cli_chal, unsigned char resp_buf[16])
{
struct HMACMD5Context ctx;
hmac_md5_init_limK_to_64(kr, 16, &ctx);
hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
hmac_md5_final(resp_buf, &ctx);
}
static void
SMBsesskeygen_ntv2(const unsigned char kr[16],
const unsigned char *nt_resp, __u8 sess_key[16])
{
struct HMACMD5Context ctx;
hmac_md5_init_limK_to_64(kr, 16, &ctx);
hmac_md5_update(nt_resp, 16, &ctx);
hmac_md5_final((unsigned char *) sess_key, &ctx);
}
static void
SMBsesskeygen_ntv1(const unsigned char kr[16],
const unsigned char *nt_resp, __u8 sess_key[16])
{
mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
}
#endif
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/freezer.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <linux/mempool.h> #include <linux/mempool.h>
...@@ -324,7 +325,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) ...@@ -324,7 +325,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
{ {
int error; int error;
error = wait_event_killable(server->response_q, error = wait_event_freezekillable(server->response_q,
midQ->midState != MID_REQUEST_SUBMITTED); midQ->midState != MID_REQUEST_SUBMITTED);
if (error < 0) if (error < 0)
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -339,8 +340,8 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) ...@@ -339,8 +340,8 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
*/ */
int int
cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
unsigned int nvec, mid_callback_t *callback, void *cbdata, unsigned int nvec, mid_receive_t *receive,
bool ignore_pend) mid_callback_t *callback, void *cbdata, bool ignore_pend)
{ {
int rc; int rc;
struct mid_q_entry *mid; struct mid_q_entry *mid;
...@@ -374,6 +375,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, ...@@ -374,6 +375,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
goto out_err; goto out_err;
} }
mid->receive = receive;
mid->callback = callback; mid->callback = callback;
mid->callback_data = cbdata; mid->callback_data = cbdata;
mid->midState = MID_REQUEST_SUBMITTED; mid->midState = MID_REQUEST_SUBMITTED;
...@@ -496,13 +498,18 @@ int ...@@ -496,13 +498,18 @@ int
cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
bool log_error) bool log_error)
{ {
dump_smb(mid->resp_buf, unsigned int len = be32_to_cpu(mid->resp_buf->smb_buf_length) + 4;
min_t(u32, 92, be32_to_cpu(mid->resp_buf->smb_buf_length)));
dump_smb(mid->resp_buf, min_t(u32, 92, len));
/* convert the length into a more usable form */ /* convert the length into a more usable form */
if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
struct kvec iov;
iov.iov_base = mid->resp_buf;
iov.iov_len = len;
/* FIXME: add code to kill session */ /* FIXME: add code to kill session */
if (cifs_verify_signature(mid->resp_buf, server, if (cifs_verify_signature(&iov, 1, server,
mid->sequence_number + 1) != 0) mid->sequence_number + 1) != 0)
cERROR(1, "Unexpected SMB signature"); cERROR(1, "Unexpected SMB signature");
} }
......
...@@ -173,7 +173,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, ...@@ -173,7 +173,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
#ifdef CONFIG_CIFS_ACL #ifdef CONFIG_CIFS_ACL
memcpy(pacl, ea_value, value_size); memcpy(pacl, ea_value, value_size);
rc = set_cifs_acl(pacl, value_size, rc = set_cifs_acl(pacl, value_size,
direntry->d_inode, full_path); direntry->d_inode, full_path, CIFS_ACL_DACL);
if (rc == 0) /* force revalidate of the inode */ if (rc == 0) /* force revalidate of the inode */
CIFS_I(direntry->d_inode)->time = 0; CIFS_I(direntry->d_inode)->time = 0;
kfree(pacl); kfree(pacl);
......
...@@ -135,10 +135,25 @@ static inline void set_freezable_with_signal(void) ...@@ -135,10 +135,25 @@ static inline void set_freezable_with_signal(void)
} }
/* /*
* Freezer-friendly wrappers around wait_event_interruptible() and * Freezer-friendly wrappers around wait_event_interruptible(),
* wait_event_interruptible_timeout(), originally defined in <linux/wait.h> * wait_event_killable() and wait_event_interruptible_timeout(), originally
* defined in <linux/wait.h>
*/ */
#define wait_event_freezekillable(wq, condition) \
({ \
int __retval; \
do { \
__retval = wait_event_killable(wq, \
(condition) || freezing(current)); \
if (__retval && !freezing(current)) \
break; \
else if (!(condition)) \
__retval = -ERESTARTSYS; \
} while (try_to_freeze()); \
__retval; \
})
#define wait_event_freezable(wq, condition) \ #define wait_event_freezable(wq, condition) \
({ \ ({ \
int __retval; \ int __retval; \
...@@ -190,6 +205,9 @@ static inline void set_freezable_with_signal(void) {} ...@@ -190,6 +205,9 @@ static inline void set_freezable_with_signal(void) {}
#define wait_event_freezable_timeout(wq, condition, timeout) \ #define wait_event_freezable_timeout(wq, condition, timeout) \
wait_event_interruptible_timeout(wq, condition, timeout) wait_event_interruptible_timeout(wq, condition, timeout)
#define wait_event_freezekillable(wq, condition) \
wait_event_killable(wq, condition)
#endif /* !CONFIG_FREEZER */ #endif /* !CONFIG_FREEZER */
#endif /* FREEZER_H_INCLUDED */ #endif /* FREEZER_H_INCLUDED */
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