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

Merge tag 'v7.0-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - Fix potential oops on open failure

 - Fix unmount to better free deferred closes

 - Use proper constant-time MAC comparison function

 - Two buffer allocation size fixes

 - Two minor cleanups

 - make SMB2 kunit tests a distinct module

* tag 'v7.0-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  smb: client: fix oops due to uninitialised var in smb2_unlink()
  cifs: open files should not hold ref on superblock
  smb: client: Compare MACs in constant time
  smb/client: remove unused SMB311_posix_query_info()
  smb/client: fix buffer size for smb311_posix_qinfo in SMB311_posix_query_info()
  smb/client: fix buffer size for smb311_posix_qinfo in smb2_compound_op()
  smb: update some doc references
  smb/client: make SMB2 maperror KUnit tests a separate module
parents 325a118c 048efe12
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -56,4 +56,6 @@ $(obj)/smb2maperror.o: $(obj)/smb2_mapping_table.c
quiet_cmd_gen_smb2_mapping = GEN     $@
      cmd_gen_smb2_mapping = perl $(src)/gen_smb2_mapping $< $@

obj-$(CONFIG_SMB_KUNIT_TESTS) += smb2maperror_test.o

clean-files	+= smb2_mapping_table.c
+5 −2
Original line number Diff line number Diff line
@@ -332,10 +332,14 @@ static void cifs_kill_sb(struct super_block *sb)

	/*
	 * We need to release all dentries for the cached directories
	 * before we kill the sb.
	 * and close all deferred file handles before we kill the sb.
	 */
	if (cifs_sb->root) {
		close_all_cached_dirs(cifs_sb);
		cifs_close_all_deferred_files_sb(cifs_sb);

		/* Wait for all pending oplock breaks to complete */
		flush_workqueue(cifsoplockd_wq);

		/* finally release root dentry */
		dput(cifs_sb->root);
@@ -868,7 +872,6 @@ static void cifs_umount_begin(struct super_block *sb)
	spin_unlock(&tcon->tc_lock);
	spin_unlock(&cifs_tcp_ses_lock);

	cifs_close_all_deferred_files(tcon);
	/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
	/* cancel_notify_requests(tcon); */
	if (tcon->ses && tcon->ses->server) {
+1 −0
Original line number Diff line number Diff line
@@ -261,6 +261,7 @@ void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);

void cifs_close_all_deferred_files(struct cifs_tcon *tcon);

void cifs_close_all_deferred_files_sb(struct cifs_sb_info *cifs_sb);
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
					   struct dentry *dentry);

+0 −11
Original line number Diff line number Diff line
@@ -711,8 +711,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
	mutex_init(&cfile->fh_mutex);
	spin_lock_init(&cfile->file_info_lock);

	cifs_sb_active(inode->i_sb);

	/*
	 * If the server returned a read oplock and we have mandatory brlocks,
	 * set oplock level to None.
@@ -767,7 +765,6 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
	struct inode *inode = d_inode(cifs_file->dentry);
	struct cifsInodeInfo *cifsi = CIFS_I(inode);
	struct cifsLockInfo *li, *tmp;
	struct super_block *sb = inode->i_sb;

	/*
	 * Delete any outstanding lock records. We'll lose them when the file
@@ -785,7 +782,6 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)

	cifs_put_tlink(cifs_file->tlink);
	dput(cifs_file->dentry);
	cifs_sb_deactive(sb);
	kfree(cifs_file->symlink_target);
	kfree(cifs_file);
}
@@ -3163,12 +3159,6 @@ void cifs_oplock_break(struct work_struct *work)
	__u64 persistent_fid, volatile_fid;
	__u16 net_fid;

	/*
	 * Hold a reference to the superblock to prevent it and its inodes from
	 * being freed while we are accessing cinode. Otherwise, _cifsFileInfo_put()
	 * may release the last reference to the sb and trigger inode eviction.
	 */
	cifs_sb_active(sb);
	wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
			TASK_UNINTERRUPTIBLE);

@@ -3253,7 +3243,6 @@ void cifs_oplock_break(struct work_struct *work)
	cifs_put_tlink(tlink);
out:
	cifs_done_oplock_break(cinode);
	cifs_sb_deactive(sb);
}

static int cifs_swap_activate(struct swap_info_struct *sis,
+42 −0
Original line number Diff line number Diff line
@@ -28,6 +28,11 @@
#include "fs_context.h"
#include "cached_dir.h"

struct tcon_list {
	struct list_head entry;
	struct cifs_tcon *tcon;
};

/* The xid serves as a useful identifier for each incoming vfs request,
   in a similar way to the mid which is useful to track each sent smb,
   and CurrentXid can also provide a running counter (although it
@@ -554,6 +559,43 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
	}
}

void cifs_close_all_deferred_files_sb(struct cifs_sb_info *cifs_sb)
{
	struct rb_root *root = &cifs_sb->tlink_tree;
	struct rb_node *node;
	struct cifs_tcon *tcon;
	struct tcon_link *tlink;
	struct tcon_list *tmp_list, *q;
	LIST_HEAD(tcon_head);

	spin_lock(&cifs_sb->tlink_tree_lock);
	for (node = rb_first(root); node; node = rb_next(node)) {
		tlink = rb_entry(node, struct tcon_link, tl_rbnode);
		tcon = tlink_tcon(tlink);
		if (IS_ERR(tcon))
			continue;
		tmp_list = kmalloc_obj(struct tcon_list, GFP_ATOMIC);
		if (tmp_list == NULL)
			break;
		tmp_list->tcon = tcon;
		/* Take a reference on tcon to prevent it from being freed */
		spin_lock(&tcon->tc_lock);
		++tcon->tc_count;
		trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
				    netfs_trace_tcon_ref_get_close_defer_files);
		spin_unlock(&tcon->tc_lock);
		list_add_tail(&tmp_list->entry, &tcon_head);
	}
	spin_unlock(&cifs_sb->tlink_tree_lock);

	list_for_each_entry_safe(tmp_list, q, &tcon_head, entry) {
		cifs_close_all_deferred_files(tmp_list->tcon);
		list_del(&tmp_list->entry);
		cifs_put_tcon(tmp_list->tcon, netfs_trace_tcon_ref_put_close_defer_files);
		kfree(tmp_list);
	}
}

void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
					   struct dentry *dentry)
{
Loading