ceph: fix uninline data function
[firefly-linux-kernel-4.4.55.git] / fs / ceph / addr.c
index 24be059fd1f8e073b7ee1d250b20f0bcdab16da0..cab1cf5a330bbbcd4eca974aa6780f5f0f1f894e 100644 (file)
@@ -196,17 +196,22 @@ static int readpage_nounlock(struct file *filp, struct page *page)
        u64 len = PAGE_CACHE_SIZE;
 
        if (off >= i_size_read(inode)) {
-               zero_user_segment(page, err, PAGE_CACHE_SIZE);
+               zero_user_segment(page, 0, PAGE_CACHE_SIZE);
                SetPageUptodate(page);
                return 0;
        }
 
-       /*
-        * Uptodate inline data should have been added into page cache
-        * while getting Fcr caps.
-        */
-       if (ci->i_inline_version != CEPH_INLINE_NONE)
-               return -EINVAL;
+       if (ci->i_inline_version != CEPH_INLINE_NONE) {
+               /*
+                * Uptodate inline data should have been added
+                * into page cache while getting Fcr caps.
+                */
+               if (off == 0)
+                       return -EINVAL;
+               zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+               SetPageUptodate(page);
+               return 0;
+       }
 
        err = ceph_readpage_from_fscache(inode, page);
        if (err == 0)
@@ -1141,6 +1146,10 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
                     inode, page, (int)pos, (int)len);
 
                r = ceph_update_writeable_page(file, pos, len, page);
+               if (r < 0)
+                       page_cache_release(page);
+               else
+                       *pagep = page;
        } while (r == -EAGAIN);
 
        return r;
@@ -1530,19 +1539,27 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
 
        osd_req_op_extent_osd_data_pages(req, 1, &page, len, 0, false, false);
 
-       err = osd_req_op_xattr_init(req, 0, CEPH_OSD_OP_CMPXATTR,
-                                   "inline_version", &inline_version,
-                                   sizeof(inline_version),
-                                   CEPH_OSD_CMPXATTR_OP_GT,
-                                   CEPH_OSD_CMPXATTR_MODE_U64);
-       if (err)
-               goto out_put;
-
-       err = osd_req_op_xattr_init(req, 2, CEPH_OSD_OP_SETXATTR,
-                                   "inline_version", &inline_version,
-                                   sizeof(inline_version), 0, 0);
-       if (err)
-               goto out_put;
+       {
+               __le64 xattr_buf = cpu_to_le64(inline_version);
+               err = osd_req_op_xattr_init(req, 0, CEPH_OSD_OP_CMPXATTR,
+                                           "inline_version", &xattr_buf,
+                                           sizeof(xattr_buf),
+                                           CEPH_OSD_CMPXATTR_OP_GT,
+                                           CEPH_OSD_CMPXATTR_MODE_U64);
+               if (err)
+                       goto out_put;
+       }
+
+       {
+               char xattr_buf[32];
+               int xattr_len = snprintf(xattr_buf, sizeof(xattr_buf),
+                                        "%llu", inline_version);
+               err = osd_req_op_xattr_init(req, 2, CEPH_OSD_OP_SETXATTR,
+                                           "inline_version",
+                                           xattr_buf, xattr_len, 0, 0);
+               if (err)
+                       goto out_put;
+       }
 
        ceph_osdc_build_request(req, 0, NULL, CEPH_NOSNAP, &inode->i_mtime);
        err = ceph_osdc_start_request(&fsc->client->osdc, req, false);