Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b1cce803 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+41 −53
Original line number Diff line number Diff line
@@ -87,10 +87,6 @@ extern mempool_t *cifs_mid_poolp;

struct workqueue_struct	*cifsiod_wq;

#ifdef CONFIG_CIFS_SMB2
__u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
#endif

/*
 * Bumps refcount for cifs super block.
 * 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)
	 * server, can not assume caching of file data or metadata.
	 */
	cifs_set_oplock_level(cifs_inode, 0);
	cifs_inode->delete_pending = false;
	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);
	cifs_inode->flags = 0;
	spin_lock_init(&cifs_inode->writers_lock);
	cifs_inode->writers = 0;
	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)
	struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
	struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;

	seq_printf(s, ",addr=");
	seq_puts(s, ",addr=");

	switch (server->dstaddr.ss_family) {
	case AF_INET:
@@ -314,7 +306,7 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
			seq_printf(s, "%%%u", sa6->sin6_scope_id);
		break;
	default:
		seq_printf(s, "(unknown)");
		seq_puts(s, "(unknown)");
	}
}

@@ -324,45 +316,45 @@ cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
	if (ses->sectype == Unspecified)
		return;

	seq_printf(s, ",sec=");
	seq_puts(s, ",sec=");

	switch (ses->sectype) {
	case LANMAN:
		seq_printf(s, "lanman");
		seq_puts(s, "lanman");
		break;
	case NTLMv2:
		seq_printf(s, "ntlmv2");
		seq_puts(s, "ntlmv2");
		break;
	case NTLM:
		seq_printf(s, "ntlm");
		seq_puts(s, "ntlm");
		break;
	case Kerberos:
		seq_printf(s, "krb5");
		seq_puts(s, "krb5");
		break;
	case RawNTLMSSP:
		seq_printf(s, "ntlmssp");
		seq_puts(s, "ntlmssp");
		break;
	default:
		/* shouldn't ever happen */
		seq_printf(s, "unknown");
		seq_puts(s, "unknown");
		break;
	}

	if (ses->sign)
		seq_printf(s, "i");
		seq_puts(s, "i");
}

static void
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)
		seq_printf(s, "strict");
		seq_puts(s, "strict");
	else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
		seq_printf(s, "none");
		seq_puts(s, "none");
	else
		seq_printf(s, "loose");
		seq_puts(s, "loose");
}

static void
@@ -395,7 +387,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
	cifs_show_cache_flavor(s, cifs_sb);

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
		seq_printf(s, ",multiuser");
		seq_puts(s, ",multiuser");
	else if (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)
	seq_printf(s, ",uid=%u",
		   from_kuid_munged(&init_user_ns, cifs_sb->mnt_uid));
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
		seq_printf(s, ",forceuid");
		seq_puts(s, ",forceuid");
	else
		seq_printf(s, ",noforceuid");
		seq_puts(s, ",noforceuid");

	seq_printf(s, ",gid=%u",
		   from_kgid_munged(&init_user_ns, cifs_sb->mnt_gid));
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
		seq_printf(s, ",forcegid");
		seq_puts(s, ",forcegid");
	else
		seq_printf(s, ",noforcegid");
		seq_puts(s, ",noforcegid");

	cifs_show_address(s, tcon->ses->server);

@@ -442,47 +434,47 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
	cifs_show_nls(s, cifs_sb->local_nls);

	if (tcon->seal)
		seq_printf(s, ",seal");
		seq_puts(s, ",seal");
	if (tcon->nocase)
		seq_printf(s, ",nocase");
		seq_puts(s, ",nocase");
	if (tcon->retry)
		seq_printf(s, ",hard");
		seq_puts(s, ",hard");
	if (tcon->unix_ext)
		seq_printf(s, ",unix");
		seq_puts(s, ",unix");
	else
		seq_printf(s, ",nounix");
		seq_puts(s, ",nounix");
	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)
		seq_printf(s, ",setuids");
		seq_puts(s, ",setuids");
	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)
		seq_printf(s, ",rwpidforward");
		seq_puts(s, ",rwpidforward");
	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)
		seq_printf(s, ",nouser_xattr");
		seq_puts(s, ",nouser_xattr");
	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)
		seq_printf(s, ",sfu");
		seq_puts(s, ",sfu");
	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)
		seq_printf(s, ",cifsacl");
		seq_puts(s, ",cifsacl");
	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)
		seq_printf(s, ",acl");
		seq_puts(s, ",acl");
	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)
		seq_printf(s, ",fsc");
		seq_puts(s, ",fsc");
	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)
		seq_printf(s, ",noperm");
		seq_puts(s, ",noperm");
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
		seq_printf(s, ",backupuid=%u",
			   from_kuid_munged(&init_user_ns,
@@ -1192,10 +1184,6 @@ init_cifs(void)
	spin_lock_init(&cifs_file_list_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) {
		cifs_max_pending = 2;
		cifs_dbg(FYI, "cifs_max_pending set to min of 2\n");
+16 −6
Original line number Diff line number Diff line
@@ -22,20 +22,28 @@
#ifndef _CIFSFS_H
#define _CIFSFS_H

#include <linux/hash.h>

#define ROOT_I 2

/*
 * 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
cifs_uniqueid_to_ino_t(u64 fileid)
{
	ino_t ino = (ino_t) fileid;
	if (sizeof(ino_t) < sizeof(u64))
		ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8;
	return ino;
	return (ino_t)fileid;
}
#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 const struct address_space_operations cifs_addr_ops;
@@ -67,6 +75,8 @@ extern int cifs_revalidate_dentry_attr(struct dentry *);
extern int cifs_revalidate_file(struct file *filp);
extern int cifs_revalidate_dentry(struct dentry *);
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_setattr(struct dentry *, struct iattr *);

@@ -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;
#endif /* CONFIG_CIFS_NFSD_EXPORT */

#define CIFS_VERSION   "2.02"
#define CIFS_VERSION   "2.03"
#endif				/* _CIFSFS_H */
+5 −3
Original line number Diff line number Diff line
@@ -559,6 +559,7 @@ struct TCP_Server_Info {
	int echo_credits;  /* echo reserved slots */
	int oplock_credits;  /* oplock break reserved slots */
	bool echoes:1; /* enable echoes */
	__u8 client_guid[SMB2_CLIENT_GUID_SIZE]; /* Client GUID */
#endif
	u16 dialect; /* dialect index that server chose */
	bool oplocks:1; /* enable oplocks */
@@ -1113,12 +1114,13 @@ struct cifsInodeInfo {
	__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
	unsigned int oplock;		/* oplock/lease level we have */
	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_WRITERS	  (1) /* Writes in progress */
#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;
	unsigned int writers;		/* Number of writers on this inode */
	unsigned long time;		/* jiffies of last update of inode */
+4 −1
Original line number Diff line number Diff line
@@ -2144,6 +2144,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
	       sizeof(tcp_ses->srcaddr));
	memcpy(&tcp_ses->dstaddr, &volume_info->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
	 * 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)
			    vol->username ? vol->username : "",
			    CIFS_MAX_USERNAME_LEN))
			return 0;
		if (strlen(vol->username) != 0 &&
		if ((vol->username && strlen(vol->username) != 0) &&
		    ses->password != NULL &&
		    strncmp(ses->password,
			    vol->password ? vol->password : "",
+8 −8
Original line number Diff line number Diff line
@@ -335,7 +335,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
	spin_unlock(&cifs_file_list_lock);

	if (fid->purge_cache)
		cifs_invalidate_mapping(inode);
		cifs_zap_mapping(inode);

	file->private_data = cfile;
	return cfile;
@@ -392,7 +392,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
		 * again and get at least level II oplock.
		 */
		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);
	}
	spin_unlock(&cifs_file_list_lock);
@@ -1529,7 +1529,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
		 */
		if (!CIFS_CACHE_WRITE(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",
				 inode);
			CIFS_I(inode)->oplock = 0;
@@ -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);

	if (!CIFS_CACHE_READ(CIFS_I(inode))) {
		rc = cifs_invalidate_mapping(inode);
		rc = cifs_zap_mapping(inode);
		if (rc) {
			cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc);
			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,

	written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos);
	if (written > 0) {
		CIFS_I(inode)->invalid_mapping = true;
		set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
		iocb->ki_pos = pos;
	}

@@ -2649,7 +2649,7 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
		 * request comes - break it on the client to prevent reading
		 * 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",
			 inode);
		cinode->oplock = 0;
@@ -3112,7 +3112,7 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
	xid = get_xid();

	if (!CIFS_CACHE_READ(CIFS_I(inode))) {
		rc = cifs_invalidate_mapping(inode);
		rc = cifs_zap_mapping(inode);
		if (rc)
			return rc;
	}
@@ -3670,7 +3670,7 @@ void cifs_oplock_break(struct work_struct *work)
		if (!CIFS_CACHE_READ(cinode)) {
			rc = filemap_fdatawait(inode->i_mapping);
			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);
	}
Loading