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

Commit 6993f74a authored by Jeff Layton's avatar Jeff Layton Committed by Steve French
Browse files

cifs: add refcounting to cifs_readdata structures



This isn't strictly necessary for the async readpages code, but the
uncached version will need to be able to collect the replies after
issuing the calls. Add a kref to cifs_readdata and use change the
code to take and put references appropriately.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
parent 8d5ce4d2
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -464,6 +464,7 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,

/* asynchronous read support */
struct cifs_readdata {
	struct kref			refcount;
	struct cifsFileInfo		*cfile;
	struct address_space		*mapping;
	__u64				offset;
@@ -478,6 +479,7 @@ struct cifs_readdata {
	struct kvec			iov[1];
};

void cifs_readdata_release(struct kref *refcount);
int cifs_async_readv(struct cifs_readdata *rdata);

/* asynchronous write support */
+3 −0
Original line number Diff line number Diff line
@@ -1635,12 +1635,15 @@ cifs_async_readv(struct cifs_readdata *rdata)
	rdata->iov[0].iov_base = smb;
	rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;

	kref_get(&rdata->refcount);
	rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
			     cifs_readv_receive, cifs_readv_callback,
			     rdata, false);

	if (rc == 0)
		cifs_stats_inc(&tcon->num_reads);
	else
		kref_put(&rdata->refcount, cifs_readdata_release);

	cifs_small_buf_release(smb);
	return rc;
+14 −7
Original line number Diff line number Diff line
@@ -2347,16 +2347,22 @@ cifs_readdata_alloc(unsigned int nr_vecs, work_func_t complete)
	rdata = kzalloc(sizeof(*rdata) +
			sizeof(struct kvec) * nr_vecs, GFP_KERNEL);
	if (rdata != NULL) {
		kref_init(&rdata->refcount);
		INIT_WORK(&rdata->work, complete);
		INIT_LIST_HEAD(&rdata->pages);
	}
	return rdata;
}

static void
cifs_readdata_free(struct cifs_readdata *rdata)
void
cifs_readdata_release(struct kref *refcount)
{
	struct cifs_readdata *rdata = container_of(refcount,
					struct cifs_readdata, refcount);

	if (rdata->cfile)
		cifsFileInfo_put(rdata->cfile);

	kfree(rdata);
}

@@ -2651,7 +2657,7 @@ cifs_readv_complete(struct work_struct *work)

		page_cache_release(page);
	}
	cifs_readdata_free(rdata);
	kref_put(&rdata->refcount, cifs_readdata_release);
}

static int
@@ -2837,9 +2843,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
		}

		spin_lock(&cifs_file_list_lock);
		cifsFileInfo_get(open_file);
		spin_unlock(&cifs_file_list_lock);
		rdata->cfile = open_file;
		rdata->cfile = cifsFileInfo_get(open_file);
		rdata->mapping = mapping;
		rdata->offset = offset;
		rdata->bytes = bytes;
@@ -2864,9 +2869,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
				unlock_page(page);
				page_cache_release(page);
			}
			cifs_readdata_free(rdata);
			kref_put(&rdata->refcount, cifs_readdata_release);
			break;
		}

		kref_put(&rdata->refcount, cifs_readdata_release);
	}

	return rc;