Merge tag 'compat-ioctl-5.5' of git://git.kernel.org:/pub/scm/linux/kernel/git/arnd...
[linux-2.6-block.git] / fs / ceph / file.c
index 6092ccea50d2f1f75eafc84b5722dc70c34630db..11929d2bb594c8d5f3d68c7a93946a8966da836f 100644 (file)
@@ -462,6 +462,9 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
                err = ceph_security_init_secctx(dentry, mode, &as_ctx);
                if (err < 0)
                        goto out_ctx;
+       } else if (!d_in_lookup(dentry)) {
+               /* If it's not being looked up, it's negative */
+               return -ENOENT;
        }
 
        /* do the open */
@@ -750,6 +753,9 @@ static void ceph_aio_complete(struct inode *inode,
        if (!atomic_dec_and_test(&aio_req->pending_reqs))
                return;
 
+       if (aio_req->iocb->ki_flags & IOCB_DIRECT)
+               inode_dio_end(inode);
+
        ret = aio_req->error;
        if (!ret)
                ret = aio_req->total_len;
@@ -1088,6 +1094,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
                                              CEPH_CAP_FILE_RD);
 
                list_splice(&aio_req->osd_reqs, &osd_reqs);
+               inode_dio_begin(inode);
                while (!list_empty(&osd_reqs)) {
                        req = list_first_entry(&osd_reqs,
                                               struct ceph_osd_request,
@@ -1261,14 +1268,24 @@ again:
        dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n",
             inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, inode);
 
+       if (iocb->ki_flags & IOCB_DIRECT)
+               ceph_start_io_direct(inode);
+       else
+               ceph_start_io_read(inode);
+
        if (fi->fmode & CEPH_FILE_MODE_LAZY)
                want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
        else
                want = CEPH_CAP_FILE_CACHE;
        ret = ceph_get_caps(filp, CEPH_CAP_FILE_RD, want, -1,
                            &got, &pinned_page);
-       if (ret < 0)
+       if (ret < 0) {
+               if (iocb->ki_flags & IOCB_DIRECT)
+                       ceph_end_io_direct(inode);
+               else
+                       ceph_end_io_read(inode);
                return ret;
+       }
 
        if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
            (iocb->ki_flags & IOCB_DIRECT) ||
@@ -1280,16 +1297,12 @@ again:
 
                if (ci->i_inline_version == CEPH_INLINE_NONE) {
                        if (!retry_op && (iocb->ki_flags & IOCB_DIRECT)) {
-                               ceph_start_io_direct(inode);
                                ret = ceph_direct_read_write(iocb, to,
                                                             NULL, NULL);
-                               ceph_end_io_direct(inode);
                                if (ret >= 0 && ret < len)
                                        retry_op = CHECK_EOF;
                        } else {
-                               ceph_start_io_read(inode);
                                ret = ceph_sync_read(iocb, to, &retry_op);
-                               ceph_end_io_read(inode);
                        }
                } else {
                        retry_op = READ_INLINE;
@@ -1300,11 +1313,10 @@ again:
                     inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
                     ceph_cap_string(got));
                ceph_add_rw_context(fi, &rw_ctx);
-               ceph_start_io_read(inode);
                ret = generic_file_read_iter(iocb, to);
-               ceph_end_io_read(inode);
                ceph_del_rw_context(fi, &rw_ctx);
        }
+
        dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n",
             inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret);
        if (pinned_page) {
@@ -1312,6 +1324,12 @@ again:
                pinned_page = NULL;
        }
        ceph_put_cap_refs(ci, got);
+
+       if (iocb->ki_flags & IOCB_DIRECT)
+               ceph_end_io_direct(inode);
+       else
+               ceph_end_io_read(inode);
+
        if (retry_op > HAVE_RETRIED && ret >= 0) {
                int statret;
                struct page *page = NULL;
@@ -1956,10 +1974,18 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
        if (ceph_test_mount_opt(src_fsc, NOCOPYFROM))
                return -EOPNOTSUPP;
 
+       /*
+        * Striped file layouts require that we copy partial objects, but the
+        * OSD copy-from operation only supports full-object copies.  Limit
+        * this to non-striped file layouts for now.
+        */
        if ((src_ci->i_layout.stripe_unit != dst_ci->i_layout.stripe_unit) ||
-           (src_ci->i_layout.stripe_count != dst_ci->i_layout.stripe_count) ||
-           (src_ci->i_layout.object_size != dst_ci->i_layout.object_size))
+           (src_ci->i_layout.stripe_count != 1) ||
+           (dst_ci->i_layout.stripe_count != 1) ||
+           (src_ci->i_layout.object_size != dst_ci->i_layout.object_size)) {
+               dout("Invalid src/dst files layout\n");
                return -EOPNOTSUPP;
+       }
 
        if (len < src_ci->i_layout.object_size)
                return -EOPNOTSUPP; /* no remote copy will be done */