aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-05-16 07:13:17 -0400
committerSteve French <sfrench@us.ibm.com>2012-05-16 21:13:30 -0400
commit6993f74a5bf836210e7f253d5ad3f76d73a95f51 (patch)
tree6b0cf7d6aed03e9d7d0b705cf7ba79792ab062a2 /fs
parent8d5ce4d23c79e0f9861b19fc534f5b2dc636f79c (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.h2
-rw-r--r--fs/cifs/cifssmb.c3
-rw-r--r--fs/cifs/file.c21
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 */
466struct cifs_readdata { 466struct 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
482void cifs_readdata_release(struct kref *refcount);
481int cifs_async_readv(struct cifs_readdata *rdata); 483int 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
2356static void 2357void
2357cifs_readdata_free(struct cifs_readdata *rdata) 2358cifs_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
2657static int 2663static 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;