summaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorJeff Layton2012-05-16 13:13:17 +0200
committerSteve French2012-05-17 03:13:30 +0200
commit6993f74a5bf836210e7f253d5ad3f76d73a95f51 (patch)
tree6b0cf7d6aed03e9d7d0b705cf7ba79792ab062a2 /fs/cifs/file.c
parentcifs: abstract out function to marshal the iovec for readv receives (diff)
downloadkernel-qcow2-linux-6993f74a5bf836210e7f253d5ad3f76d73a95f51.tar.gz
kernel-qcow2-linux-6993f74a5bf836210e7f253d5ad3f76d73a95f51.tar.xz
kernel-qcow2-linux-6993f74a5bf836210e7f253d5ad3f76d73a95f51.zip
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/cifs/file.c')
-rw-r--r--fs/cifs/file.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 183381d9c4c1..ae285e0cf67b 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)
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)
{
- cifsFileInfo_put(rdata->cfile);
+ 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;