Commit 31c542a199d79f0f402c2f3e04229464510d47ec

Authored by Yan, Zheng
Committed by Ilya Dryomov
1 parent fb01d1f8b0

ceph: add inline data to pagecache

Request reply and cap message can contain inline data. add inline data
to the page cache if there is Fc cap.

Signed-off-by: Yan, Zheng <zyan@redhat.com>

Showing 6 changed files with 85 additions and 1 deletions Side-by-side Diff

... ... @@ -1318,6 +1318,49 @@
1318 1318 return ret;
1319 1319 }
1320 1320  
  1321 +void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
  1322 + char *data, size_t len)
  1323 +{
  1324 + struct address_space *mapping = inode->i_mapping;
  1325 + struct page *page;
  1326 +
  1327 + if (locked_page) {
  1328 + page = locked_page;
  1329 + } else {
  1330 + if (i_size_read(inode) == 0)
  1331 + return;
  1332 + page = find_or_create_page(mapping, 0,
  1333 + mapping_gfp_mask(mapping) & ~__GFP_FS);
  1334 + if (!page)
  1335 + return;
  1336 + if (PageUptodate(page)) {
  1337 + unlock_page(page);
  1338 + page_cache_release(page);
  1339 + return;
  1340 + }
  1341 + }
  1342 +
  1343 + dout("fill_inline_data %p %llx.%llx len %lu locked_page %p\n",
  1344 + inode, ceph_vinop(inode), len, locked_page);
  1345 +
  1346 + if (len > 0) {
  1347 + void *kaddr = kmap_atomic(page);
  1348 + memcpy(kaddr, data, len);
  1349 + kunmap_atomic(kaddr);
  1350 + }
  1351 +
  1352 + if (page != locked_page) {
  1353 + if (len < PAGE_CACHE_SIZE)
  1354 + zero_user_segment(page, len, PAGE_CACHE_SIZE);
  1355 + else
  1356 + flush_dcache_page(page);
  1357 +
  1358 + SetPageUptodate(page);
  1359 + unlock_page(page);
  1360 + page_cache_release(page);
  1361 + }
  1362 +}
  1363 +
1321 1364 static struct vm_operations_struct ceph_vmops = {
1322 1365 .fault = ceph_filemap_fault,
1323 1366 .page_mkwrite = ceph_page_mkwrite,
... ... @@ -2405,6 +2405,7 @@
2405 2405 bool queue_invalidate = false;
2406 2406 bool queue_revalidate = false;
2407 2407 bool deleted_inode = false;
  2408 + bool fill_inline = false;
2408 2409  
2409 2410 dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
2410 2411 inode, cap, mds, seq, ceph_cap_string(newcaps));
... ... @@ -2578,6 +2579,13 @@
2578 2579 }
2579 2580 BUG_ON(cap->issued & ~cap->implemented);
2580 2581  
  2582 + if (inline_version > 0 && inline_version >= ci->i_inline_version) {
  2583 + ci->i_inline_version = inline_version;
  2584 + if (ci->i_inline_version != CEPH_INLINE_NONE &&
  2585 + (newcaps & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)))
  2586 + fill_inline = true;
  2587 + }
  2588 +
2581 2589 spin_unlock(&ci->i_ceph_lock);
2582 2590  
2583 2591 if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
... ... @@ -2590,6 +2598,9 @@
2590 2598 if (newcaps & ~issued)
2591 2599 wake = true;
2592 2600 }
  2601 +
  2602 + if (fill_inline)
  2603 + ceph_fill_inline_data(inode, NULL, inline_data, inline_len);
2593 2604  
2594 2605 if (queue_trunc) {
2595 2606 ceph_queue_vmtruncate(inode);
... ... @@ -387,6 +387,7 @@
387 387 spin_lock_init(&ci->i_ceph_lock);
388 388  
389 389 ci->i_version = 0;
  390 + ci->i_inline_version = 0;
390 391 ci->i_time_warp_seq = 0;
391 392 ci->i_ceph_flags = 0;
392 393 ci->i_ordered_count = 0;
... ... @@ -676,6 +677,7 @@
676 677 bool wake = false;
677 678 bool queue_trunc = false;
678 679 bool new_version = false;
  680 + bool fill_inline = false;
679 681  
680 682 dout("fill_inode %p ino %llx.%llx v %llu had %llu\n",
681 683 inode, ceph_vinop(inode), le64_to_cpu(info->version),
682 684  
... ... @@ -875,7 +877,21 @@
875 877 ceph_vinop(inode));
876 878 __ceph_get_fmode(ci, cap_fmode);
877 879 }
  880 +
  881 + if (iinfo->inline_version > 0 &&
  882 + iinfo->inline_version >= ci->i_inline_version) {
  883 + int cache_caps = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
  884 + ci->i_inline_version = iinfo->inline_version;
  885 + if (ci->i_inline_version != CEPH_INLINE_NONE &&
  886 + (le32_to_cpu(info->cap.caps) & cache_caps))
  887 + fill_inline = true;
  888 + }
  889 +
878 890 spin_unlock(&ci->i_ceph_lock);
  891 +
  892 + if (fill_inline)
  893 + ceph_fill_inline_data(inode, NULL,
  894 + iinfo->inline_data, iinfo->inline_len);
879 895  
880 896 if (wake)
881 897 wake_up_all(&ci->i_cap_wq);
... ... @@ -253,6 +253,7 @@
253 253 spinlock_t i_ceph_lock;
254 254  
255 255 u64 i_version;
  256 + u64 i_inline_version;
256 257 u32 i_time_warp_seq;
257 258  
258 259 unsigned i_ceph_flags;
... ... @@ -858,7 +859,7 @@
858 859 int mds, int drop, int unless);
859 860  
860 861 extern int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
861   - int *got, loff_t endoff);
  862 + loff_t endoff, int *got, struct page **pinned_page);
862 863  
863 864 /* for counting open files by mode */
864 865 static inline void __ceph_get_fmode(struct ceph_inode_info *ci, int mode)
... ... @@ -880,6 +881,8 @@
880 881 struct file *file, unsigned flags, umode_t mode,
881 882 int *opened);
882 883 extern int ceph_release(struct inode *inode, struct file *filp);
  884 +extern void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
  885 + char *data, size_t len);
883 886  
884 887 /* dir.c */
885 888 extern const struct file_operations ceph_dir_fops;
  1 +--- fs/ceph/super.h
  2 ++++ fs/ceph/super.h
  3 +@@ -254,6 +255,7 @@
  4 + spinlock_t i_ceph_lock;
  5 +
  6 + u64 i_version;
  7 ++ u64 i_inline_version;
  8 + u32 i_time_warp_seq;
  9 +
  10 + unsigned i_ceph_flags;
include/linux/ceph/ceph_fs.h
... ... @@ -552,6 +552,7 @@
552 552  
553 553 int ceph_flags_to_mode(int flags);
554 554  
  555 +#define CEPH_INLINE_NONE ((__u64)-1)
555 556  
556 557 /* capability bits */
557 558 #define CEPH_CAP_PIN 1 /* no specific capabilities beyond the pin */