]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
iov_iter: add a shorten call
authorZach Brown <zach.brown@oracle.com>
Fri, 3 Sep 2010 18:37:58 +0000 (11:37 -0700)
committerDave Kleikamp <dave.kleikamp@oracle.com>
Fri, 13 Jan 2012 00:11:27 +0000 (18:11 -0600)
The generic direct write path wants to shorten its memory vector.  It
does this when it finds that it has to perform a partial write due to
LIMIT_FSIZE.  .direct_IO() always performs IO on all of the referenced
memory because it doesn't have an argument to specify the length of the
IO.

We add an iov_iter operation for this so that the generic path can ask
to shorten the memory vector without having to know what kind it is.
We're happy to shorten the kernel copy of the iovec array, but we refuse
to shorten the bio_vec array and return an error in this case.

Signed-off-by: Zach Brown <zach.brown@oracle.com>
include/linux/fs.h
mm/iov-iter.c

index 2bc507196a15c497533b3597bc7522036a52469e..a1d6f84587fa3b4ec01323949b532e3737b9f386 100644 (file)
@@ -544,6 +544,7 @@ struct iov_iter_ops {
        void (*ii_advance)(struct iov_iter *, size_t);
        int (*ii_fault_in_readable)(struct iov_iter *, size_t);
        size_t (*ii_single_seg_count)(struct iov_iter *);
+       int (*ii_shorten)(struct iov_iter *, size_t);
 };
 
 static inline size_t iov_iter_copy_to_user_atomic(struct page *page,
@@ -578,6 +579,10 @@ static inline size_t iov_iter_single_seg_count(struct iov_iter *i)
 {
        return i->ops->ii_single_seg_count(i);
 }
+static inline int iov_iter_shorten(struct iov_iter *i, size_t count)
+{
+       return i->ops->ii_shorten(i, count);
+}
 
 extern struct iov_iter_ops ii_bvec_ops;
 
index 4724cfa7031e34fdde0822f4009be1ac428c07df..f9b5b906ceae194f91f3a39ff7a7080076446379 100644 (file)
@@ -197,6 +197,11 @@ size_t ii_bvec_single_seg_count(struct iov_iter *i)
                return min(i->count, bvec->bv_len - i->iov_offset);
 }
 
+static int ii_bvec_shorten(struct iov_iter *i, size_t count)
+{
+       return -EINVAL;
+}
+
 struct iov_iter_ops ii_bvec_ops = {
        .ii_copy_to_user_atomic = ii_bvec_copy_to_user_atomic,
        .ii_copy_to_user = ii_bvec_copy_to_user,
@@ -348,6 +353,13 @@ size_t ii_iovec_single_seg_count(struct iov_iter *i)
                return min(i->count, iov->iov_len - i->iov_offset);
 }
 
+static int ii_iovec_shorten(struct iov_iter *i, size_t count)
+{
+       struct iovec *iov = (struct iovec *)i->data;
+       i->nr_segs = iov_shorten(iov, i->nr_segs, count);
+       return 0;
+}
+
 struct iov_iter_ops ii_iovec_ops = {
        .ii_copy_to_user_atomic = ii_iovec_copy_to_user_atomic,
        .ii_copy_to_user = ii_iovec_copy_to_user,
@@ -356,5 +368,6 @@ struct iov_iter_ops ii_iovec_ops = {
        .ii_advance = ii_iovec_advance,
        .ii_fault_in_readable = ii_iovec_fault_in_readable,
        .ii_single_seg_count = ii_iovec_single_seg_count,
+       .ii_shorten = ii_iovec_shorten,
 };
 EXPORT_SYMBOL(ii_iovec_ops);