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

Merge tag '6.1-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:

 - memory leak fixes

 - fixes for directory leases, including an important one which fixes a
   problem noticed by git functional tests

 - fixes relating to missing free_xid calls (helpful for
   tracing/debugging of entry/exit into cifs.ko)

 - a multichannel fix

 - a small cleanup fix (use of list_move instead of list_del/list_add)

* tag '6.1-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: update internal module number
  cifs: fix memory leaks in session setup
  cifs: drop the lease for cached directories on rmdir or rename
  smb3: interface count displayed incorrectly
  cifs: Fix memory leak when build ntlmssp negotiate blob failed
  cifs: set rc to -ENOENT if we can not get a dentry for the cached dir
  cifs: use LIST_HEAD() and list_move() to simplify code
  cifs: Fix xid leak in cifs_get_file_info_unix()
  cifs: Fix xid leak in cifs_ses_add_channel()
  cifs: Fix xid leak in cifs_flock()
  cifs: Fix xid leak in cifs_copy_file_range()
  cifs: Fix xid leak in cifs_create()
parents 022c028f 73b1b8d2
Loading
Loading
Loading
Loading
+29 −10
Original line number Diff line number Diff line
@@ -253,9 +253,11 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
		dentry = dget(cifs_sb->root);
	else {
		dentry = path_to_dentry(cifs_sb, path);
		if (IS_ERR(dentry))
		if (IS_ERR(dentry)) {
			rc = -ENOENT;
			goto oshr_free;
		}
	}
	cfid->dentry = dentry;
	cfid->tcon = tcon;
	cfid->time = jiffies;
@@ -338,6 +340,27 @@ smb2_close_cached_fid(struct kref *ref)
	free_cached_dir(cfid);
}

void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon,
			     const char *name, struct cifs_sb_info *cifs_sb)
{
	struct cached_fid *cfid = NULL;
	int rc;

	rc = open_cached_dir(xid, tcon, name, cifs_sb, true, &cfid);
	if (rc) {
		cifs_dbg(FYI, "no cached dir found for rmdir(%s)\n", name);
		return;
	}
	spin_lock(&cfid->cfids->cfid_list_lock);
	if (cfid->has_lease) {
		cfid->has_lease = false;
		kref_put(&cfid->refcount, smb2_close_cached_fid);
	}
	spin_unlock(&cfid->cfids->cfid_list_lock);
	close_cached_dir(cfid);
}


void close_cached_dir(struct cached_fid *cfid)
{
	kref_put(&cfid->refcount, smb2_close_cached_fid);
@@ -378,22 +401,20 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
{
	struct cached_fids *cfids = tcon->cfids;
	struct cached_fid *cfid, *q;
	struct list_head entry;
	LIST_HEAD(entry);

	INIT_LIST_HEAD(&entry);
	spin_lock(&cfids->cfid_list_lock);
	list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
		list_del(&cfid->entry);
		list_add(&cfid->entry, &entry);
		list_move(&cfid->entry, &entry);
		cfids->num_entries--;
		cfid->is_open = false;
		cfid->on_list = false;
		/* To prevent race with smb2_cached_lease_break() */
		kref_get(&cfid->refcount);
	}
	spin_unlock(&cfids->cfid_list_lock);

	list_for_each_entry_safe(cfid, q, &entry, entry) {
		cfid->on_list = false;
		list_del(&cfid->entry);
		cancel_work_sync(&cfid->lease_break);
		if (cfid->has_lease) {
@@ -518,15 +539,13 @@ struct cached_fids *init_cached_dirs(void)
void free_cached_dirs(struct cached_fids *cfids)
{
	struct cached_fid *cfid, *q;
	struct list_head entry;
	LIST_HEAD(entry);

	INIT_LIST_HEAD(&entry);
	spin_lock(&cfids->cfid_list_lock);
	list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
		cfid->on_list = false;
		cfid->is_open = false;
		list_del(&cfid->entry);
		list_add(&cfid->entry, &entry);
		list_move(&cfid->entry, &entry);
	}
	spin_unlock(&cfids->cfid_list_lock);

+4 −0
Original line number Diff line number Diff line
@@ -69,6 +69,10 @@ extern int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
				     struct dentry *dentry,
				     struct cached_fid **cfid);
extern void close_cached_dir(struct cached_fid *cfid);
extern void drop_cached_dir_by_name(const unsigned int xid,
				    struct cifs_tcon *tcon,
				    const char *name,
				    struct cifs_sb_info *cifs_sb);
extern void close_all_cached_dirs(struct cifs_sb_info *cifs_sb);
extern void invalidate_all_cached_dirs(struct cifs_tcon *tcon);
extern int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]);
+5 −2
Original line number Diff line number Diff line
@@ -1302,8 +1302,11 @@ static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
	ssize_t rc;
	struct cifsFileInfo *cfile = dst_file->private_data;

	if (cfile->swapfile)
		return -EOPNOTSUPP;
	if (cfile->swapfile) {
		rc = -EOPNOTSUPP;
		free_xid(xid);
		return rc;
	}

	rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff,
					len, flags);
+2 −2
Original line number Diff line number Diff line
@@ -153,6 +153,6 @@ extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */

/* when changing internal version - update following two lines at same time */
#define SMB3_PRODUCT_BUILD 39
#define CIFS_VERSION   "2.39"
#define SMB3_PRODUCT_BUILD 40
#define CIFS_VERSION   "2.40"
#endif				/* _CIFSFS_H */
+4 −2
Original line number Diff line number Diff line
@@ -543,8 +543,10 @@ int cifs_create(struct user_namespace *mnt_userns, struct inode *inode,
	cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
		 inode, direntry, direntry);

	if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
		return -EIO;
	if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb)))) {
		rc = -EIO;
		goto out_free_xid;
	}

	tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
	rc = PTR_ERR(tlink);
Loading