summaryrefslogtreecommitdiff
path: root/fs/bio.c
diff options
context:
space:
mode:
authorMilosz Tanski <milosz@adfin.com>2013-09-06 16:41:20 +0000
committerMilosz Tanski <milosz@adfin.com>2013-09-06 16:41:20 +0000
commitcd0a2df681ec2af45f50c555c2a39dc92a4dff71 (patch)
tree35d2278a9494582025f3dac08feb2266adef6a4d /fs/bio.c
parentc35455791c1131e7ccbf56ea6fbdd562401c2ce2 (diff)
parent5a6f282a2052bb13171b53f03b34501cf72c33f1 (diff)
Merge tag 'fscache-fixes-for-ceph' into wip-fscache
Patches for Ceph FS-Cache support
Diffstat (limited to 'fs/bio.c')
-rw-r--r--fs/bio.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/fs/bio.c b/fs/bio.c
index 94bbc04dba77..c5eae7251490 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1045,12 +1045,22 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
int bio_uncopy_user(struct bio *bio)
{
struct bio_map_data *bmd = bio->bi_private;
- int ret = 0;
+ struct bio_vec *bvec;
+ int ret = 0, i;
- if (!bio_flagged(bio, BIO_NULL_MAPPED))
- ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
- bmd->nr_sgvecs, bio_data_dir(bio) == READ,
- 0, bmd->is_our_pages);
+ if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
+ /*
+ * if we're in a workqueue, the request is orphaned, so
+ * don't copy into a random user address space, just free.
+ */
+ if (current->mm)
+ ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
+ bmd->nr_sgvecs, bio_data_dir(bio) == READ,
+ 0, bmd->is_our_pages);
+ else if (bmd->is_our_pages)
+ bio_for_each_segment_all(bvec, bio, i)
+ __free_page(bvec->bv_page);
+ }
bio_free_map_data(bmd);
bio_put(bio);
return ret;