Commit b1cce803 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull CIFS fixes from Steve French.

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
  CIFS: Fix memory leaks in SMB2_open
  cifs: ensure that vol->username is not NULL before running strlen on it
  Clarify SMB2/SMB3 create context and add missing ones
  Do not send ClientGUID on SMB2.02 dialect
  cifs: Set client guid on per connection basis
  fs/cifs/netmisc.c: convert printk to pr_foo()
  fs/cifs/cifs.c: replace seq_printf by seq_puts
  Update cifs version number to 2.03
  fs: cifs: new helper: file_inode(file)
  cifs: fix potential races in cifs_revalidate_mapping
  cifs: new helper function: cifs_revalidate_mapping
  cifs: convert booleans in cifsInodeInfo to a flags field
  cifs: fix cifs_uniqueid_to_ino_t not to ever return 0
parents 1c54fc1e 663a9621
...@@ -87,10 +87,6 @@ extern mempool_t *cifs_mid_poolp; ...@@ -87,10 +87,6 @@ extern mempool_t *cifs_mid_poolp;
struct workqueue_struct *cifsiod_wq; struct workqueue_struct *cifsiod_wq;
#ifdef CONFIG_CIFS_SMB2
__u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
#endif
/* /*
* Bumps refcount for cifs super block. * Bumps refcount for cifs super block.
* Note that it should be only called if a referece to VFS super block is * Note that it should be only called if a referece to VFS super block is
...@@ -251,11 +247,7 @@ cifs_alloc_inode(struct super_block *sb) ...@@ -251,11 +247,7 @@ cifs_alloc_inode(struct super_block *sb)
* server, can not assume caching of file data or metadata. * server, can not assume caching of file data or metadata.
*/ */
cifs_set_oplock_level(cifs_inode, 0); cifs_set_oplock_level(cifs_inode, 0);
cifs_inode->delete_pending = false; cifs_inode->flags = 0;
cifs_inode->invalid_mapping = false;
clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cifs_inode->flags);
clear_bit(CIFS_INODE_PENDING_WRITERS, &cifs_inode->flags);
clear_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cifs_inode->flags);
spin_lock_init(&cifs_inode->writers_lock); spin_lock_init(&cifs_inode->writers_lock);
cifs_inode->writers = 0; cifs_inode->writers = 0;
cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
...@@ -302,7 +294,7 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) ...@@ -302,7 +294,7 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr; struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
seq_printf(s, ",addr="); seq_puts(s, ",addr=");
switch (server->dstaddr.ss_family) { switch (server->dstaddr.ss_family) {
case AF_INET: case AF_INET:
...@@ -314,7 +306,7 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) ...@@ -314,7 +306,7 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
seq_printf(s, "%%%u", sa6->sin6_scope_id); seq_printf(s, "%%%u", sa6->sin6_scope_id);
break; break;
default: default:
seq_printf(s, "(unknown)"); seq_puts(s, "(unknown)");
} }
} }
...@@ -324,45 +316,45 @@ cifs_show_security(struct seq_file *s, struct cifs_ses *ses) ...@@ -324,45 +316,45 @@ cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
if (ses->sectype == Unspecified) if (ses->sectype == Unspecified)
return; return;
seq_printf(s, ",sec="); seq_puts(s, ",sec=");
switch (ses->sectype) { switch (ses->sectype) {
case LANMAN: case LANMAN:
seq_printf(s, "lanman"); seq_puts(s, "lanman");
break; break;
case NTLMv2: case NTLMv2:
seq_printf(s, "ntlmv2"); seq_puts(s, "ntlmv2");
break; break;
case NTLM: case NTLM:
seq_printf(s, "ntlm"); seq_puts(s, "ntlm");
break; break;
case Kerberos: case Kerberos:
seq_printf(s, "krb5"); seq_puts(s, "krb5");
break; break;
case RawNTLMSSP: case RawNTLMSSP:
seq_printf(s, "ntlmssp"); seq_puts(s, "ntlmssp");
break; break;
default: default:
/* shouldn't ever happen */ /* shouldn't ever happen */
seq_printf(s, "unknown"); seq_puts(s, "unknown");
break; break;
} }
if (ses->sign) if (ses->sign)
seq_printf(s, "i"); seq_puts(s, "i");
} }
static void static void
cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb) cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
{ {
seq_printf(s, ",cache="); seq_puts(s, ",cache=");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
seq_printf(s, "strict"); seq_puts(s, "strict");
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
seq_printf(s, "none"); seq_puts(s, "none");
else else
seq_printf(s, "loose"); seq_puts(s, "loose");
} }
static void static void
...@@ -395,7 +387,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -395,7 +387,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
cifs_show_cache_flavor(s, cifs_sb); cifs_show_cache_flavor(s, cifs_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
seq_printf(s, ",multiuser"); seq_puts(s, ",multiuser");
else if (tcon->ses->user_name) else if (tcon->ses->user_name)
seq_printf(s, ",username=%s", tcon->ses->user_name); seq_printf(s, ",username=%s", tcon->ses->user_name);
...@@ -421,16 +413,16 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -421,16 +413,16 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_printf(s, ",uid=%u", seq_printf(s, ",uid=%u",
from_kuid_munged(&init_user_ns, cifs_sb->mnt_uid)); from_kuid_munged(&init_user_ns, cifs_sb->mnt_uid));
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
seq_printf(s, ",forceuid"); seq_puts(s, ",forceuid");
else else
seq_printf(s, ",noforceuid"); seq_puts(s, ",noforceuid");
seq_printf(s, ",gid=%u", seq_printf(s, ",gid=%u",
from_kgid_munged(&init_user_ns, cifs_sb->mnt_gid)); from_kgid_munged(&init_user_ns, cifs_sb->mnt_gid));
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
seq_printf(s, ",forcegid"); seq_puts(s, ",forcegid");
else else
seq_printf(s, ",noforcegid"); seq_puts(s, ",noforcegid");
cifs_show_address(s, tcon->ses->server); cifs_show_address(s, tcon->ses->server);
...@@ -442,47 +434,47 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -442,47 +434,47 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
cifs_show_nls(s, cifs_sb->local_nls); cifs_show_nls(s, cifs_sb->local_nls);
if (tcon->seal) if (tcon->seal)
seq_printf(s, ",seal"); seq_puts(s, ",seal");
if (tcon->nocase) if (tcon->nocase)
seq_printf(s, ",nocase"); seq_puts(s, ",nocase");
if (tcon->retry) if (tcon->retry)
seq_printf(s, ",hard"); seq_puts(s, ",hard");
if (tcon->unix_ext) if (tcon->unix_ext)
seq_printf(s, ",unix"); seq_puts(s, ",unix");
else else
seq_printf(s, ",nounix"); seq_puts(s, ",nounix");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
seq_printf(s, ",posixpaths"); seq_puts(s, ",posixpaths");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
seq_printf(s, ",setuids"); seq_puts(s, ",setuids");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
seq_printf(s, ",serverino"); seq_puts(s, ",serverino");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
seq_printf(s, ",rwpidforward"); seq_puts(s, ",rwpidforward");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL)
seq_printf(s, ",forcemand"); seq_puts(s, ",forcemand");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
seq_printf(s, ",nouser_xattr"); seq_puts(s, ",nouser_xattr");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
seq_printf(s, ",mapchars"); seq_puts(s, ",mapchars");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
seq_printf(s, ",sfu"); seq_puts(s, ",sfu");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
seq_printf(s, ",nobrl"); seq_puts(s, ",nobrl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
seq_printf(s, ",cifsacl"); seq_puts(s, ",cifsacl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
seq_printf(s, ",dynperm"); seq_puts(s, ",dynperm");
if (root->d_sb->s_flags & MS_POSIXACL) if (root->d_sb->s_flags & MS_POSIXACL)
seq_printf(s, ",acl"); seq_puts(s, ",acl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
seq_printf(s, ",mfsymlinks"); seq_puts(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_puts(s, ",fsc");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)
seq_printf(s, ",nostrictsync"); seq_puts(s, ",nostrictsync");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
seq_printf(s, ",noperm"); seq_puts(s, ",noperm");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
seq_printf(s, ",backupuid=%u", seq_printf(s, ",backupuid=%u",
from_kuid_munged(&init_user_ns, from_kuid_munged(&init_user_ns,
...@@ -1192,10 +1184,6 @@ init_cifs(void) ...@@ -1192,10 +1184,6 @@ init_cifs(void)
spin_lock_init(&cifs_file_list_lock); spin_lock_init(&cifs_file_list_lock);
spin_lock_init(&GlobalMid_Lock); spin_lock_init(&GlobalMid_Lock);
#ifdef CONFIG_CIFS_SMB2
get_random_bytes(cifs_client_guid, SMB2_CLIENT_GUID_SIZE);
#endif
if (cifs_max_pending < 2) { if (cifs_max_pending < 2) {
cifs_max_pending = 2; cifs_max_pending = 2;
cifs_dbg(FYI, "cifs_max_pending set to min of 2\n"); cifs_dbg(FYI, "cifs_max_pending set to min of 2\n");
......
...@@ -22,20 +22,28 @@ ...@@ -22,20 +22,28 @@
#ifndef _CIFSFS_H #ifndef _CIFSFS_H
#define _CIFSFS_H #define _CIFSFS_H
#include <linux/hash.h>
#define ROOT_I 2 #define ROOT_I 2
/* /*
* ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
* so that it will fit. * so that it will fit. We use hash_64 to convert the value to 31 bits, and
* then add 1, to ensure that we don't end up with a 0 as the value.
*/ */
#if BITS_PER_LONG == 64
static inline ino_t static inline ino_t
cifs_uniqueid_to_ino_t(u64 fileid) cifs_uniqueid_to_ino_t(u64 fileid)
{ {
ino_t ino = (ino_t) fileid; return (ino_t)fileid;
if (sizeof(ino_t) < sizeof(u64))
ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8;
return ino;
} }
#else
static inline ino_t
cifs_uniqueid_to_ino_t(u64 fileid)
{
return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
}
#endif
extern struct file_system_type cifs_fs_type; extern struct file_system_type cifs_fs_type;
extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops;
...@@ -67,6 +75,8 @@ extern int cifs_revalidate_dentry_attr(struct dentry *); ...@@ -67,6 +75,8 @@ extern int cifs_revalidate_dentry_attr(struct dentry *);
extern int cifs_revalidate_file(struct file *filp); extern int cifs_revalidate_file(struct file *filp);
extern int cifs_revalidate_dentry(struct dentry *); extern int cifs_revalidate_dentry(struct dentry *);
extern int cifs_invalidate_mapping(struct inode *inode); extern int cifs_invalidate_mapping(struct inode *inode);
extern int cifs_revalidate_mapping(struct inode *inode);
extern int cifs_zap_mapping(struct inode *inode);
extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int cifs_setattr(struct dentry *, struct iattr *); extern int cifs_setattr(struct dentry *, struct iattr *);
...@@ -130,5 +140,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); ...@@ -130,5 +140,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops; extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
#define CIFS_VERSION "2.02" #define CIFS_VERSION "2.03"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -559,6 +559,7 @@ struct TCP_Server_Info { ...@@ -559,6 +559,7 @@ struct TCP_Server_Info {
int echo_credits; /* echo reserved slots */ int echo_credits; /* echo reserved slots */
int oplock_credits; /* oplock break reserved slots */ int oplock_credits; /* oplock break reserved slots */
bool echoes:1; /* enable echoes */ bool echoes:1; /* enable echoes */
__u8 client_guid[SMB2_CLIENT_GUID_SIZE]; /* Client GUID */
#endif #endif
u16 dialect; /* dialect index that server chose */ u16 dialect; /* dialect index that server chose */
bool oplocks:1; /* enable oplocks */ bool oplocks:1; /* enable oplocks */
...@@ -1113,12 +1114,13 @@ struct cifsInodeInfo { ...@@ -1113,12 +1114,13 @@ struct cifsInodeInfo {
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
unsigned int oplock; /* oplock/lease level we have */ unsigned int oplock; /* oplock/lease level we have */
unsigned int epoch; /* used to track lease state changes */ unsigned int epoch; /* used to track lease state changes */
bool delete_pending; /* DELETE_ON_CLOSE is set */
bool invalid_mapping; /* pagecache is invalid */
unsigned long flags;
#define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */ #define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */
#define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */ #define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */
#define CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 (2) /* Downgrade oplock to L2 */ #define CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 (2) /* Downgrade oplock to L2 */
#define CIFS_INO_DELETE_PENDING (3) /* delete pending on server */
#define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */
#define CIFS_INO_LOCK (5) /* lock bit for synchronization */
unsigned long flags;
spinlock_t writers_lock; spinlock_t writers_lock;
unsigned int writers; /* Number of writers on this inode */ unsigned int writers; /* Number of writers on this inode */
unsigned long time; /* jiffies of last update of inode */ unsigned long time; /* jiffies of last update of inode */
......
...@@ -2144,6 +2144,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info) ...@@ -2144,6 +2144,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
sizeof(tcp_ses->srcaddr)); sizeof(tcp_ses->srcaddr));
memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr, memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
sizeof(tcp_ses->dstaddr)); sizeof(tcp_ses->dstaddr));
#ifdef CONFIG_CIFS_SMB2
get_random_bytes(tcp_ses->client_guid, SMB2_CLIENT_GUID_SIZE);
#endif
/* /*
* at this point we are the only ones with the pointer * at this point we are the only ones with the pointer
* to the struct since the kernel thread not created yet * to the struct since the kernel thread not created yet
...@@ -2225,7 +2228,7 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol) ...@@ -2225,7 +2228,7 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
vol->username ? vol->username : "", vol->username ? vol->username : "",
CIFS_MAX_USERNAME_LEN)) CIFS_MAX_USERNAME_LEN))
return 0; return 0;
if (strlen(vol->username) != 0 && if ((vol->username && strlen(vol->username) != 0) &&
ses->password != NULL && ses->password != NULL &&
strncmp(ses->password, strncmp(ses->password,
vol->password ? vol->password : "", vol->password ? vol->password : "",
......
...@@ -335,7 +335,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, ...@@ -335,7 +335,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
spin_unlock(&cifs_file_list_lock); spin_unlock(&cifs_file_list_lock);
if (fid->purge_cache) if (fid->purge_cache)
cifs_invalidate_mapping(inode); cifs_zap_mapping(inode);
file->private_data = cfile; file->private_data = cfile;
return cfile; return cfile;
...@@ -392,7 +392,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) ...@@ -392,7 +392,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
* again and get at least level II oplock. * again and get at least level II oplock.
*/ */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
CIFS_I(inode)->invalid_mapping = true; set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags);
cifs_set_oplock_level(cifsi, 0); cifs_set_oplock_level(cifsi, 0);
} }
spin_unlock(&cifs_file_list_lock); spin_unlock(&cifs_file_list_lock);
...@@ -1529,7 +1529,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, ...@@ -1529,7 +1529,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
*/ */
if (!CIFS_CACHE_WRITE(CIFS_I(inode)) && if (!CIFS_CACHE_WRITE(CIFS_I(inode)) &&
CIFS_CACHE_READ(CIFS_I(inode))) { CIFS_CACHE_READ(CIFS_I(inode))) {
cifs_invalidate_mapping(inode); cifs_zap_mapping(inode);
cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n", cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n",
inode); inode);
CIFS_I(inode)->oplock = 0; CIFS_I(inode)->oplock = 0;
...@@ -2218,7 +2218,7 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, ...@@ -2218,7 +2218,7 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
file->f_path.dentry->d_name.name, datasync); file->f_path.dentry->d_name.name, datasync);
if (!CIFS_CACHE_READ(CIFS_I(inode))) { if (!CIFS_CACHE_READ(CIFS_I(inode))) {
rc = cifs_invalidate_mapping(inode); rc = cifs_zap_mapping(inode);
if (rc) { if (rc) {
cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc); cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc);
rc = 0; /* don't care about it in fsync */ rc = 0; /* don't care about it in fsync */
...@@ -2562,7 +2562,7 @@ ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, ...@@ -2562,7 +2562,7 @@ ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos); written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
if (written > 0) { if (written > 0) {
CIFS_I(inode)->invalid_mapping = true; set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
iocb->ki_pos = pos; iocb->ki_pos = pos;
} }
...@@ -2649,7 +2649,7 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, ...@@ -2649,7 +2649,7 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
* request comes - break it on the client to prevent reading * request comes - break it on the client to prevent reading
* an old data. * an old data.
*/ */
cifs_invalidate_mapping(inode); cifs_zap_mapping(inode);
cifs_dbg(FYI, "Set no oplock for inode=%p after a write operation\n", cifs_dbg(FYI, "Set no oplock for inode=%p after a write operation\n",
inode); inode);
cinode->oplock = 0; cinode->oplock = 0;
...@@ -3112,7 +3112,7 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -3112,7 +3112,7 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
xid = get_xid(); xid = get_xid();
if (!CIFS_CACHE_READ(CIFS_I(inode))) { if (!CIFS_CACHE_READ(CIFS_I(inode))) {
rc = cifs_invalidate_mapping(inode); rc = cifs_zap_mapping(inode);
if (rc) if (rc)
return rc; return rc;
} }
...@@ -3670,7 +3670,7 @@ void cifs_oplock_break(struct work_struct *work) ...@@ -3670,7 +3670,7 @@ void cifs_oplock_break(struct work_struct *work)
if (!CIFS_CACHE_READ(cinode)) { if (!CIFS_CACHE_READ(cinode)) {
rc = filemap_fdatawait(inode->i_mapping); rc = filemap_fdatawait(inode->i_mapping);
mapping_set_error(inode->i_mapping, rc); mapping_set_error(inode->i_mapping, rc);
cifs_invalidate_mapping(inode); cifs_zap_mapping(inode);
} }
cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc); cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/freezer.h>
#include <asm/div64.h> #include <asm/div64.h>
#include "cifsfs.h" #include "cifsfs.h"
#include "cifspdu.h" #include "cifspdu.h"
...@@ -117,7 +118,7 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) ...@@ -117,7 +118,7 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n", cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
__func__, cifs_i->uniqueid); __func__, cifs_i->uniqueid);
cifs_i->invalid_mapping = true; set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
} }
/* /*
...@@ -177,7 +178,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) ...@@ -177,7 +178,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
else else
cifs_i->time = jiffies; cifs_i->time = jiffies;
cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
else
clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
cifs_i->server_eof = fattr->cf_eof; cifs_i->server_eof = fattr->cf_eof;
/* /*
...@@ -1121,7 +1125,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, ...@@ -1121,7 +1125,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
} }
/* try to set DELETE_ON_CLOSE */ /* try to set DELETE_ON_CLOSE */
if (!cifsInode->delete_pending) { if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid, rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
current->tgid); current->tgid);
/* /*
...@@ -1138,7 +1142,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, ...@@ -1138,7 +1142,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
rc = -EBUSY; rc = -EBUSY;
goto undo_rename; goto undo_rename;
} }
cifsInode->delete_pending = true; set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
} }
out_close: out_close:
...@@ -1759,23 +1763,62 @@ int ...@@ -1759,23 +1763,62 @@ int
cifs_invalidate_mapping(struct inode *inode) cifs_invalidate_mapping(struct inode *inode)
{ {
int rc = 0; int rc = 0;
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
cifs_i->invalid_mapping = false;
if (inode->i_mapping && inode->i_mapping->nrpages != 0) { if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
rc = invalidate_inode_pages2(inode->i_mapping); rc = invalidate_inode_pages2(inode->i_mapping);
if (rc) { if (rc)
cifs_dbg(VFS, "%s: could not invalidate inode %p\n", cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
__func__, inode); __func__, inode);
cifs_i->invalid_mapping = true;
}
} }
cifs_fscache_reset_inode_cookie(inode); cifs_fscache_reset_inode_cookie(inode);
return rc; return rc;
} }
/**
* cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
* @word: long word containing the bit lock
*/
static int
cifs_wait_bit_killable(void *word)
{
if (fatal_signal_pending(current))
return -ERESTARTSYS;
freezable_schedule_unsafe();
return 0;
}
int
cifs_revalidate_mapping(struct inode *inode)
{
int rc;
unsigned long *flags = &CIFS_I(inode)->flags;
rc = wait_on_bit_lock(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
TASK_KILLABLE);
if (rc)
return rc;
if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
rc = cifs_invalidate_mapping(inode);
if (rc)
set_bit(CIFS_INO_INVALID_MAPPING, flags);
}
clear_bit_unlock(CIFS_INO_LOCK, flags);
smp_mb__after_atomic();
wake_up_bit(flags, CIFS_INO_LOCK);
return rc;
}
int
cifs_zap_mapping(struct inode *inode)
{
set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
return cifs_revalidate_mapping(inode);
}
int cifs_revalidate_file_attr(struct file *filp) int cifs_revalidate_file_attr(struct file *filp)
{ {
int rc = 0; int rc = 0;
...@@ -1842,9 +1885,7 @@ int cifs_revalidate_file(struct file *filp) ...@@ -1842,9 +1885,7 @@ int cifs_revalidate_file(struct file *filp)
if (rc) if (rc)
return rc; return rc;
if (CIFS_I(inode)->invalid_mapping) return cifs_revalidate_mapping(inode);
rc = cifs_invalidate_mapping(inode);
return rc;
} }
/* revalidate a dentry's inode attributes */ /* revalidate a dentry's inode attributes */
...@@ -1857,9 +1898,7 @@ int cifs_revalidate_dentry(struct dentry *dentry) ...@@ -1857,9 +1898,7 @@ int cifs_revalidate_dentry(struct dentry *dentry)
if (rc) if (rc)
return rc; return rc;
if (CIFS_I(inode)->invalid_mapping) return cifs_revalidate_mapping(inode);
rc = cifs_invalidate_mapping(inode);
return rc;
} }
int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
......
...@@ -85,7 +85,7 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, ...@@ -85,7 +85,7 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file,
goto out_fput; goto out_fput;
} }
src_inode = src_file.file->f_dentry->d_inode; src_inode = file_inode(src_file.file);
/* /*
* Note: cifs case is easier than btrfs since server responsible for * Note: cifs case is easier than btrfs since server responsible for
......
...@@ -795,8 +795,8 @@ cifs_print_status(__u32 status_code) ...@@ -795,8 +795,8 @@ cifs_print_status(__u32 status_code)
while (nt_errs[idx].nt_errstr != NULL) { while (nt_errs[idx].nt_errstr != NULL) {
if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) == if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
(status_code & 0xFFFFFF)) { (status_code & 0xFFFFFF)) {
printk(KERN_NOTICE "Status code returned 0x%08x %s\n", pr_notice("Status code returned 0x%08x %s\n",
status_code, nt_errs[idx].nt_errstr); status_code, nt_errs[idx].nt_errstr);
} }
idx++; idx++;
} }
...@@ -941,8 +941,9 @@ cifs_UnixTimeToNT(struct timespec t) ...@@ -941,8 +941,9 @@ cifs_UnixTimeToNT(struct timespec t)
return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET; return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET;
} }
static int total_days_of_prev_months[] = static const int total_days_of_prev_months[] = {
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
{ {
......
...@@ -1047,6 +1047,7 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock) ...@@ -1047,6 +1047,7 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock)
buf->ccontext.NameOffset = cpu_to_le16(offsetof buf->ccontext.NameOffset = cpu_to_le16(offsetof
(struct create_lease, Name)); (struct create_lease, Name));
buf->ccontext.NameLength = cpu_to_le16(4); buf->ccontext.NameLength = cpu_to_le16(4);
/* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
buf->Name[0] = 'R'; buf->Name[0] = 'R';
buf->Name[1] = 'q'; buf->Name[1] = 'q';
buf->Name[2] = 'L'; buf->Name[2] = 'L';
...@@ -1073,6 +1074,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock) ...@@ -1073,6 +1074,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock)
buf->ccontext.NameOffset = cpu_to_le16(offsetof buf->ccontext.NameOffset = cpu_to_le16(offsetof
(struct create_lease_v2, Name)); (struct create_lease_v2, Name));
buf->ccontext.NameLength = cpu_to_le16(4); buf->ccontext.NameLength = cpu_to_le16(4);
/* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
buf->Name[0] = 'R'; buf->Name[0] = 'R';
buf->Name[1] = 'q'; buf->Name[1] = 'q';
buf->Name[2] = 'L'; buf->Name[2] = 'L';
......
...@@ -375,7 +375,12 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) ...@@ -375,7 +375,12 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities); req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities);
memcpy(req->ClientGUID, cifs_client_guid, SMB2_CLIENT_GUID_SIZE); /* ClientGUID must be zero for SMB2.02 dialect */
if (ses->server->vals->protocol_id == SMB20_PROT_ID)
memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE);
else
memcpy(req->ClientGUID, server->client_guid,
SMB2_CLIENT_GUID_SIZE);
iov[0].iov_base = (char *)req; iov[0].iov_base = (char *)req;
/* 4 for rfc1002 length field */ /* 4 for rfc1002 length field */
...@@ -478,7 +483,8 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) ...@@ -478,7 +483,8 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
vneg_inbuf.Capabilities = vneg_inbuf.Capabilities =
cpu_to_le32(tcon->ses->server->vals->req_capabilities); cpu_to_le32(tcon->ses->server->vals->req_capabilities);
memcpy(vneg_inbuf.Guid, cifs_client_guid, SMB2_CLIENT_GUID_SIZE); memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid,
SMB2_CLIENT_GUID_SIZE);
if (tcon->ses->sign) if (tcon->ses->sign)
vneg_inbuf.SecurityMode = vneg_inbuf.SecurityMode =
...@@ -966,6 +972,7 @@ create_durable_buf(void) ...@@ -966,6 +972,7 @@ create_durable_buf(void)
buf->ccontext.NameOffset = cpu_to_le16(offsetof buf->ccontext.NameOffset = cpu_to_le16(offsetof
(struct create_durable, Name)); (struct create_durable, Name));
buf->ccontext.NameLength = cpu_to_le16(4); buf->ccontext.NameLength = cpu_to_le16(4);
/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */
buf->Name[0] = 'D'; buf->Name[0] = 'D';
buf->Name[1] = 'H'; buf->Name[1] = 'H';
buf->Name[2] = 'n'; buf->Name[2] = 'n';
...@@ -990,6 +997,7 @@ create_reconnect_durable_buf(struct cifs_fid *fid) ...@@ -990,6 +997,7 @@ create_reconnect_durable_buf(struct cifs_fid *fid)
buf->ccontext.NameLength = cpu_to_le16(4); buf->ccontext.NameLength = cpu_to_le16(4);
buf->Data.Fid.PersistentFileId = fid->persistent_fid; buf->Data.Fid.PersistentFileId = fid->persistent_fid;
buf->Data.Fid.VolatileFileId = fid->volatile_fid; buf->Data.Fid.VolatileFileId = fid->volatile_fid;
/* SMB2_CREATE_DURABLE_HANDLE_RECONNECT is "DHnC" */
buf->Name[0] = 'D'; buf->Name[0] = 'D';
buf->Name[1] = 'H'; buf->Name[1] = 'H';
buf->Name[2] = 'n'; buf->Name[2] = 'n';
...@@ -1089,6 +1097,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, ...@@ -1089,6 +1097,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
int rc = 0; int rc = 0;
unsigned int num_iovecs = 2; unsigned int num_iovecs = 2;
__u32 file_attributes = 0; __u32 file_attributes = 0;
char *dhc_buf = NULL, *lc_buf = NULL;
cifs_dbg(FYI, "create/open\n"); cifs_dbg(FYI, "create/open\n");
...@@ -1155,6 +1164,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, ...@@ -1155,6 +1164,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
kfree(copy_path); kfree(copy_path);
return rc; return rc;
} }
lc_buf = iov[num_iovecs-1].iov_base;
} }
if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) { if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) {
...@@ -1169,9 +1179,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, ...@@ -1169,9 +1179,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
if (rc) { if (rc) {
cifs_small_buf_release(req); cifs_small_buf_release(req);
kfree(copy_path); kfree(copy_path);
kfree(iov[num_iovecs-1].iov_base); kfree(lc_buf);
return rc; return rc;
} }
dhc_buf = iov[num_iovecs-1].iov_base;
} }
rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
...@@ -1203,6 +1214,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, ...@@ -1203,6 +1214,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
*oplock = rsp->OplockLevel; *oplock = rsp->OplockLevel;
creat_exit: creat_exit:
kfree(copy_path); kfree(copy_path);
kfree(lc_buf);
kfree(dhc_buf);
free_rsp_buf(resp_buftype, rsp); free_rsp_buf(resp_buftype, rsp);
return rc; return rc;
} }
......
...@@ -183,8 +183,6 @@ struct smb2_symlink_err_rsp { ...@@ -183,8 +183,6 @@ struct smb2_symlink_err_rsp {
#define SMB2_CLIENT_GUID_SIZE 16 #define SMB2_CLIENT_GUID_SIZE 16
extern __u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
struct smb2_negotiate_req { struct smb2_negotiate_req {
struct smb2_hdr hdr; struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 36 */ __le16 StructureSize; /* Must be 36 */
...@@ -437,11 +435,15 @@ struct smb2_tree_disconnect_rsp { ...@@ -437,11 +435,15 @@ struct smb2_tree_disconnect_rsp {
#define SMB2_CREATE_SD_BUFFER "SecD" /* security descriptor */ #define SMB2_CREATE_SD_BUFFER "SecD" /* security descriptor */
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ" #define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ"
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC" #define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC"
#define SMB2_CREATE_ALLOCATION_SIZE "AlSi" #define SMB2_CREATE_ALLOCATION_SIZE "AISi"
#define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc" #define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
#define SMB2_CREATE_TIMEWARP_REQUEST "TWrp" #define SMB2_CREATE_TIMEWARP_REQUEST "TWrp"
#define SMB2_CREATE_QUERY_ON_DISK_ID "QFid" #define SMB2_CREATE_QUERY_ON_DISK_ID "QFid"
#define SMB2_CREATE_REQUEST_LEASE "RqLs" #define SMB2_CREATE_REQUEST_LEASE "RqLs"
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q"
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C"
#define SMB2_CREATE_APP_INSTANCE_ID 0x45BCA66AEFA7F74A9008FA462E144D74
#define SVHDX_OPEN_DEVICE_CONTEXT 0x83CE6F1AD851E0986E34401CC9BCFCE9
struct smb2_create_req { struct smb2_create_req {
struct smb2_hdr hdr; struct smb2_hdr hdr;
......
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