]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'aio/master'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 12 Sep 2013 02:54:20 +0000 (12:54 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 12 Sep 2013 02:54:26 +0000 (12:54 +1000)
Conflicts:
fs/block_dev.c
fs/nfs/direct.c

15 files changed:
1  2 
drivers/staging/android/logger.c
drivers/staging/lustre/lustre/llite/file.c
drivers/usb/gadget/inode.c
fs/aio.c
fs/block_dev.c
fs/ocfs2/file.c
fs/read_write.c
fs/udf/file.c
include/linux/aio.h
include/linux/migrate.h
include/linux/mm_types.h
kernel/fork.c
mm/migrate.c
mm/page_io.c
net/socket.c

Simple merge
Simple merge
diff --cc fs/aio.c
index 8ef3157c7943ee6c7b863bd4513c8b0f18367275,6b868f0e0c4c019c3b68712ca230deb979711a98..95c7b1dbdb8b7a229451a19299d6eaeca3d999a3
+++ b/fs/aio.c
@@@ -591,15 -850,11 +850,15 @@@ void aio_complete(struct kiocb *iocb, l
         *  - the sync task helpfully left a reference to itself in the iocb
         */
        if (is_sync_kiocb(iocb)) {
-               BUG_ON(atomic_read(&iocb->ki_users) != 1);
                iocb->ki_user_data = res;
-               atomic_set(&iocb->ki_users, 0);
+               smp_wmb();
+               iocb->ki_ctx = ERR_PTR(-EXDEV);
                wake_up_process(iocb->ki_obj.tsk);
                return;
 +      } else if (is_kernel_kiocb(iocb)) {
 +              iocb->ki_obj.complete(iocb->ki_user_data, res);
 +              aio_kernel_free(iocb);
 +              return;
        }
  
        /*
@@@ -1075,23 -1220,30 +1266,38 @@@ rw_common
                        return ret;
  
                ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
-               if (ret < 0)
+               if (ret < 0) {
+                       if (iovec != &inline_vec)
+                               kfree(iovec);
                        return ret;
+               }
  
                req->ki_nbytes = ret;
-               req->ki_left = ret;
  
-               ret = aio_rw_vect_retry(req, rw, rw_op);
+               /* XXX: move/kill - rw_verify_area()? */
+               /* This matches the pread()/pwrite() logic */
+               if (req->ki_pos < 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (rw == WRITE)
+                       file_start_write(file);
+               ret = rw_op(req, iovec, nr_segs, req->ki_pos);
+               if (rw == WRITE)
+                       file_end_write(file);
                break;
  
-               ret = aio_read_iter(req, req->ki_iter);
 +      case IOCB_CMD_READ_ITER:
-               ret = aio_write_iter(req, req->ki_iter);
++              ret = aio_read_iter(req, (void *)buf);
 +              break;
 +
 +      case IOCB_CMD_WRITE_ITER:
++              ret = aio_write_iter(req, (void *)buf);
 +              break;
 +
        case IOCB_CMD_FDSYNC:
                if (!file->f_op->aio_fsync)
                        return -EINVAL;
        return 0;
  }
  
-       iocb->ki_left = nr;
 +/*
 + * This allocates an iocb that will be used to submit and track completion of
 + * an IO that is issued from kernel space.
 + *
 + * The caller is expected to call the appropriate aio_kernel_init_() functions
 + * and then call aio_kernel_submit().  From that point forward progress is
 + * guaranteed by the file system aio method.  Eventually the caller's
 + * completion callback will be called.
 + *
 + * These iocbs are special.  They don't have a context, we don't limit the
 + * number pending, and they can't be canceled.
 + */
 +struct kiocb *aio_kernel_alloc(gfp_t gfp)
 +{
 +      return kzalloc(sizeof(struct kiocb), gfp);
 +}
 +EXPORT_SYMBOL_GPL(aio_kernel_alloc);
 +
 +void aio_kernel_free(struct kiocb *iocb)
 +{
 +      kfree(iocb);
 +}
 +EXPORT_SYMBOL_GPL(aio_kernel_free);
 +
 +/*
 + * ptr and count can be a buff and bytes or an iov and segs.
 + */
 +void aio_kernel_init_rw(struct kiocb *iocb, struct file *filp,
 +                      size_t nr, loff_t off)
 +{
 +      iocb->ki_filp = filp;
-       iocb->ki_opcode = op;
-       iocb->ki_buf = (char __user *)(unsigned long)ptr;
-       iocb->ki_iter = ptr;
-       ret = aio_run_iocb(iocb, 0);
 +      iocb->ki_nbytes = nr;
 +      iocb->ki_pos = off;
 +      iocb->ki_ctx = (void *)-1;
 +}
 +EXPORT_SYMBOL_GPL(aio_kernel_init_rw);
 +
 +void aio_kernel_init_callback(struct kiocb *iocb,
 +                            void (*complete)(u64 user_data, long res),
 +                            u64 user_data)
 +{
 +      iocb->ki_obj.complete = complete;
 +      iocb->ki_user_data = user_data;
 +}
 +EXPORT_SYMBOL_GPL(aio_kernel_init_callback);
 +
 +/*
 + * The iocb is our responsibility once this is called.  The caller must not
 + * reference it.
 + *
 + * Callers must be prepared for their iocb completion callback to be called the
 + * moment they enter this function.  The completion callback may be called from
 + * any context.
 + *
 + * Returns: 0: the iocb completion callback will be called with the op result
 + * negative errno: the operation was not submitted and the iocb was freed
 + */
 +int aio_kernel_submit(struct kiocb *iocb, unsigned short op, void *ptr)
 +{
 +      int ret;
 +
 +      BUG_ON(!is_kernel_kiocb(iocb));
 +      BUG_ON(!iocb->ki_obj.complete);
 +      BUG_ON(!iocb->ki_filp);
 +
++      ret = aio_run_iocb(iocb, op, ptr, 0);
 +
 +      if (ret)
 +              aio_kernel_free(iocb);
 +
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(aio_kernel_submit);
 +
  static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                         struct iocb *iocb, bool compat)
  {
diff --cc fs/block_dev.c
index f35b74d2549ae86eac73d66ba73b4fcd8cd8f964,8772b155cb30afd6e2a0a78500021ceeef731406..0c97a207b925d9582e96385a9aee1772fa2f891e
@@@ -1541,9 -1542,9 +1541,9 @@@ static ssize_t blkdev_read_iter(struct 
                return 0;
  
        size -= pos;
-       if (size < iocb->ki_left)
+       if (size < iocb->ki_nbytes)
 -              nr_segs = iov_shorten((struct iovec *)iov, nr_segs, size);
 -      return generic_file_aio_read(iocb, iov, nr_segs, pos);
 +              iov_iter_shorten(iter, size);
 +      return generic_file_read_iter(iocb, iter, pos);
  }
  
  /*
diff --cc fs/ocfs2/file.c
index df4c09e6d033b88264944b2dfaf6f7433f03afc5,dd1a4901a54b64960dac4ed6a57ac63fa8816fcf..d95322d9a9c0b86cf19d9bd41241e4228ed2515b
@@@ -2238,9 -2243,9 +2238,9 @@@ static ssize_t ocfs2_file_write_iter(st
                (unsigned long long)OCFS2_I(inode)->ip_blkno,
                file->f_path.dentry->d_name.len,
                file->f_path.dentry->d_name.name,
 -              (unsigned int)nr_segs);
 +              (unsigned long long)pos);
  
-       if (iocb->ki_left == 0)
+       if (iocb->ki_nbytes == 0)
                return 0;
  
        appending = file->f_flags & O_APPEND ? 1 : 0;
diff --cc fs/read_write.c
index c3579a945a4dab7f438c31f89a8a2e8c7ed349c8,e3cd280b158c1132a98c1b53ab2ab8bcdb14de02..296b5711a78b616523215d6e0b8e621433a9b32e
@@@ -390,10 -367,9 +390,9 @@@ ssize_t do_sync_read(struct file *filp
  
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_left = len;
        kiocb.ki_nbytes = len;
  
 -      ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
 +      ret = do_aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
        if (-EIOCBQUEUED == ret)
                ret = wait_on_sync_kiocb(&kiocb);
        *ppos = kiocb.ki_pos;
@@@ -463,10 -416,9 +462,9 @@@ ssize_t do_sync_write(struct file *filp
  
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
-       kiocb.ki_left = len;
        kiocb.ki_nbytes = len;
  
 -      ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
 +      ret = do_aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
        if (-EIOCBQUEUED == ret)
                ret = wait_on_sync_kiocb(&kiocb);
        *ppos = kiocb.ki_pos;
diff --cc fs/udf/file.c
Simple merge
index 2bb87b52cb74a6a2f4ff5d7e2474ebf7a5342344,d9c92daa3944e43a13f285a7baaa1443868cce3d..c08d3ed2ebe223050db04fe0c0235b9760e60b81
@@@ -27,16 -27,13 +27,14 @@@ struct kiocb
   */
  #define KIOCB_CANCELLED               ((void *) (~0ULL))
  
- typedef int (kiocb_cancel_fn)(struct kiocb *, struct io_event *);
+ typedef int (kiocb_cancel_fn)(struct kiocb *);
  
  struct kiocb {
-       atomic_t                ki_users;
        struct file             *ki_filp;
 -      struct kioctx           *ki_ctx;        /* NULL for sync ops */
 +      struct kioctx           *ki_ctx;        /* NULL for sync ops,
 +                                                 -1 for kernel caller */
        kiocb_cancel_fn         *ki_cancel;
-       void                    (*ki_dtor)(struct kiocb *);
+       void                    *private;
  
        union {
                void __user             *user;
@@@ -99,17 -77,8 +84,16 @@@ extern void exit_aio(struct mm_struct *
  extern long do_io_submit(aio_context_t ctx_id, long nr,
                         struct iocb __user *__user *iocbpp, bool compat);
  void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
 +struct kiocb *aio_kernel_alloc(gfp_t gfp);
 +void aio_kernel_free(struct kiocb *iocb);
 +void aio_kernel_init_rw(struct kiocb *iocb, struct file *filp, size_t nr,
 +                      loff_t off);
 +void aio_kernel_init_callback(struct kiocb *iocb,
 +                            void (*complete)(u64 user_data, long res),
 +                            u64 user_data);
 +int aio_kernel_submit(struct kiocb *iocb, unsigned short op, void *ptr);
  #else
  static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
- static inline void aio_put_req(struct kiocb *iocb) { }
  static inline void aio_complete(struct kiocb *iocb, long res, long res2) { }
  struct mm_struct;
  static inline void exit_aio(struct mm_struct *mm) { }
Simple merge
Simple merge
diff --cc kernel/fork.c
Simple merge
diff --cc mm/migrate.c
Simple merge
diff --cc mm/page_io.c
Simple merge
diff --cc net/socket.c
Simple merge