summaryrefslogtreecommitdiff
path: root/fs/bio.c
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-08-27 18:40:03 +0400
committerMark Brown <broonie@linaro.org>2013-08-27 18:40:03 +0400
commitdc1632321ba1e93dde25870e96cebe21b7d52517 (patch)
treed52d934c79b23f91654c571d983e1a6ec41b71fd /fs/bio.c
parent8c193b8dce4f2a2474dc2bc39ec972454df9d439 (diff)
parenta85f9da707366e856c0aad9e329db0cc59475290 (diff)
downloadlinux-dc1632321ba1e93dde25870e96cebe21b7d52517.tar.xz
Merge remote-tracking branch 'asoc/topic/dmic' into asoc-core
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;