diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-05-16 07:13:17 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2012-05-16 21:13:30 -0400 |
commit | 6993f74a5bf836210e7f253d5ad3f76d73a95f51 (patch) | |
tree | 6b0cf7d6aed03e9d7d0b705cf7ba79792ab062a2 /fs | |
parent | 8d5ce4d23c79e0f9861b19fc534f5b2dc636f79c (diff) |
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: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 3 | ||||
-rw-r--r-- | fs/cifs/file.c | 21 |
3 files changed, 19 insertions, 7 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index f309b43848f..63e91c79564 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -464,6 +464,7 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, | |||
464 | 464 | ||
465 | /* asynchronous read support */ | 465 | /* asynchronous read support */ |
466 | struct cifs_readdata { | 466 | struct cifs_readdata { |
467 | struct kref refcount; | ||
467 | struct cifsFileInfo *cfile; | 468 | struct cifsFileInfo *cfile; |
468 | struct address_space *mapping; | 469 | struct address_space *mapping; |
469 | __u64 offset; | 470 | __u64 offset; |
@@ -478,6 +479,7 @@ struct cifs_readdata { | |||
478 | struct kvec iov[1]; | 479 | struct kvec iov[1]; |
479 | }; | 480 | }; |
480 | 481 | ||
482 | void cifs_readdata_release(struct kref *refcount); | ||
481 | int cifs_async_readv(struct cifs_readdata *rdata); | 483 | int cifs_async_readv(struct cifs_readdata *rdata); |
482 | 484 | ||
483 | /* asynchronous write support */ | 485 | /* asynchronous write support */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 3aa1fcc1515..45633da461a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1635,12 +1635,15 @@ cifs_async_readv(struct cifs_readdata *rdata) | |||
1635 | rdata->iov[0].iov_base = smb; | 1635 | rdata->iov[0].iov_base = smb; |
1636 | rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; | 1636 | rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; |
1637 | 1637 | ||
1638 | kref_get(&rdata->refcount); | ||
1638 | rc = cifs_call_async(tcon->ses->server, rdata->iov, 1, | 1639 | rc = cifs_call_async(tcon->ses->server, rdata->iov, 1, |
1639 | cifs_readv_receive, cifs_readv_callback, | 1640 | cifs_readv_receive, cifs_readv_callback, |
1640 | rdata, false); | 1641 | rdata, false); |
1641 | 1642 | ||
1642 | if (rc == 0) | 1643 | if (rc == 0) |
1643 | cifs_stats_inc(&tcon->num_reads); | 1644 | cifs_stats_inc(&tcon->num_reads); |
1645 | else | ||
1646 | kref_put(&rdata->refcount, cifs_readdata_release); | ||
1644 | 1647 | ||
1645 | cifs_small_buf_release(smb); | 1648 | cifs_small_buf_release(smb); |
1646 | return rc; | 1649 | return rc; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 183381d9c4c..ae285e0cf67 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2347,16 +2347,22 @@ cifs_readdata_alloc(unsigned int nr_vecs, work_func_t complete) | |||
2347 | rdata = kzalloc(sizeof(*rdata) + | 2347 | rdata = kzalloc(sizeof(*rdata) + |
2348 | sizeof(struct kvec) * nr_vecs, GFP_KERNEL); | 2348 | sizeof(struct kvec) * nr_vecs, GFP_KERNEL); |
2349 | if (rdata != NULL) { | 2349 | if (rdata != NULL) { |
2350 | kref_init(&rdata->refcount); | ||
2350 | INIT_WORK(&rdata->work, complete); | 2351 | INIT_WORK(&rdata->work, complete); |
2351 | INIT_LIST_HEAD(&rdata->pages); | 2352 | INIT_LIST_HEAD(&rdata->pages); |
2352 | } | 2353 | } |
2353 | return rdata; | 2354 | return rdata; |
2354 | } | 2355 | } |
2355 | 2356 | ||
2356 | static void | 2357 | void |
2357 | cifs_readdata_free(struct cifs_readdata *rdata) | 2358 | cifs_readdata_release(struct kref *refcount) |
2358 | { | 2359 | { |
2359 | cifsFileInfo_put(rdata->cfile); | 2360 | struct cifs_readdata *rdata = container_of(refcount, |
2361 | struct cifs_readdata, refcount); | ||
2362 | |||
2363 | if (rdata->cfile) | ||
2364 | cifsFileInfo_put(rdata->cfile); | ||
2365 | |||
2360 | kfree(rdata); | 2366 | kfree(rdata); |
2361 | } | 2367 | } |
2362 | 2368 | ||
@@ -2651,7 +2657,7 @@ cifs_readv_complete(struct work_struct *work) | |||
2651 | 2657 | ||
2652 | page_cache_release(page); | 2658 | page_cache_release(page); |
2653 | } | 2659 | } |
2654 | cifs_readdata_free(rdata); | 2660 | kref_put(&rdata->refcount, cifs_readdata_release); |
2655 | } | 2661 | } |
2656 | 2662 | ||
2657 | static int | 2663 | static int |
@@ -2837,9 +2843,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
2837 | } | 2843 | } |
2838 | 2844 | ||
2839 | spin_lock(&cifs_file_list_lock); | 2845 | spin_lock(&cifs_file_list_lock); |
2840 | cifsFileInfo_get(open_file); | ||
2841 | spin_unlock(&cifs_file_list_lock); | 2846 | spin_unlock(&cifs_file_list_lock); |
2842 | rdata->cfile = open_file; | 2847 | rdata->cfile = cifsFileInfo_get(open_file); |
2843 | rdata->mapping = mapping; | 2848 | rdata->mapping = mapping; |
2844 | rdata->offset = offset; | 2849 | rdata->offset = offset; |
2845 | rdata->bytes = bytes; | 2850 | rdata->bytes = bytes; |
@@ -2864,9 +2869,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
2864 | unlock_page(page); | 2869 | unlock_page(page); |
2865 | page_cache_release(page); | 2870 | page_cache_release(page); |
2866 | } | 2871 | } |
2867 | cifs_readdata_free(rdata); | 2872 | kref_put(&rdata->refcount, cifs_readdata_release); |
2868 | break; | 2873 | break; |
2869 | } | 2874 | } |
2875 | |||
2876 | kref_put(&rdata->refcount, cifs_readdata_release); | ||
2870 | } | 2877 | } |
2871 | 2878 | ||
2872 | return rc; | 2879 | return rc; |