diff options
author | Yan, Zheng <zyan@redhat.com> | 2014-11-14 08:41:55 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@redhat.com> | 2014-12-17 12:09:52 -0500 |
commit | 31c542a199d79f0f402c2f3e04229464510d47ec (patch) | |
tree | fa28ee0ee2f288f334cd141146eb79cbd1b693ce /fs | |
parent | fb01d1f8b0343f1b19be878cee89d089f06e9f38 (diff) |
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/addr.c | 43 | ||||
-rw-r--r-- | fs/ceph/caps.c | 11 | ||||
-rw-r--r-- | fs/ceph/inode.c | 16 | ||||
-rw-r--r-- | fs/ceph/super.h | 5 | ||||
-rw-r--r-- | fs/ceph/super.h.rej | 10 |
5 files changed, 84 insertions, 1 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index f2c7aa878aa4..4a3f55f27ab4 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
@@ -1318,6 +1318,49 @@ out: | |||
1318 | return ret; | 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 | static struct vm_operations_struct ceph_vmops = { | 1364 | static struct vm_operations_struct ceph_vmops = { |
1322 | .fault = ceph_filemap_fault, | 1365 | .fault = ceph_filemap_fault, |
1323 | .page_mkwrite = ceph_page_mkwrite, | 1366 | .page_mkwrite = ceph_page_mkwrite, |
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index b88ae601f309..6372eb9ce491 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -2405,6 +2405,7 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc, | |||
2405 | bool queue_invalidate = false; | 2405 | bool queue_invalidate = false; |
2406 | bool queue_revalidate = false; | 2406 | bool queue_revalidate = false; |
2407 | bool deleted_inode = false; | 2407 | bool deleted_inode = false; |
2408 | bool fill_inline = false; | ||
2408 | 2409 | ||
2409 | dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", | 2410 | dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", |
2410 | inode, cap, mds, seq, ceph_cap_string(newcaps)); | 2411 | inode, cap, mds, seq, ceph_cap_string(newcaps)); |
@@ -2578,6 +2579,13 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc, | |||
2578 | } | 2579 | } |
2579 | BUG_ON(cap->issued & ~cap->implemented); | 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 | spin_unlock(&ci->i_ceph_lock); | 2589 | spin_unlock(&ci->i_ceph_lock); |
2582 | 2590 | ||
2583 | if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) { | 2591 | if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) { |
@@ -2591,6 +2599,9 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc, | |||
2591 | wake = true; | 2599 | wake = true; |
2592 | } | 2600 | } |
2593 | 2601 | ||
2602 | if (fill_inline) | ||
2603 | ceph_fill_inline_data(inode, NULL, inline_data, inline_len); | ||
2604 | |||
2594 | if (queue_trunc) { | 2605 | if (queue_trunc) { |
2595 | ceph_queue_vmtruncate(inode); | 2606 | ceph_queue_vmtruncate(inode); |
2596 | ceph_queue_revalidate(inode); | 2607 | ceph_queue_revalidate(inode); |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 72607c17e6fd..feea6a8f88ae 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -387,6 +387,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb) | |||
387 | spin_lock_init(&ci->i_ceph_lock); | 387 | spin_lock_init(&ci->i_ceph_lock); |
388 | 388 | ||
389 | ci->i_version = 0; | 389 | ci->i_version = 0; |
390 | ci->i_inline_version = 0; | ||
390 | ci->i_time_warp_seq = 0; | 391 | ci->i_time_warp_seq = 0; |
391 | ci->i_ceph_flags = 0; | 392 | ci->i_ceph_flags = 0; |
392 | ci->i_ordered_count = 0; | 393 | ci->i_ordered_count = 0; |
@@ -676,6 +677,7 @@ static int fill_inode(struct inode *inode, | |||
676 | bool wake = false; | 677 | bool wake = false; |
677 | bool queue_trunc = false; | 678 | bool queue_trunc = false; |
678 | bool new_version = false; | 679 | bool new_version = false; |
680 | bool fill_inline = false; | ||
679 | 681 | ||
680 | dout("fill_inode %p ino %llx.%llx v %llu had %llu\n", | 682 | dout("fill_inode %p ino %llx.%llx v %llu had %llu\n", |
681 | inode, ceph_vinop(inode), le64_to_cpu(info->version), | 683 | inode, ceph_vinop(inode), le64_to_cpu(info->version), |
@@ -875,8 +877,22 @@ static int fill_inode(struct inode *inode, | |||
875 | ceph_vinop(inode)); | 877 | ceph_vinop(inode)); |
876 | __ceph_get_fmode(ci, cap_fmode); | 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 | spin_unlock(&ci->i_ceph_lock); | 890 | spin_unlock(&ci->i_ceph_lock); |
879 | 891 | ||
892 | if (fill_inline) | ||
893 | ceph_fill_inline_data(inode, NULL, | ||
894 | iinfo->inline_data, iinfo->inline_len); | ||
895 | |||
880 | if (wake) | 896 | if (wake) |
881 | wake_up_all(&ci->i_cap_wq); | 897 | wake_up_all(&ci->i_cap_wq); |
882 | 898 | ||
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index fc1c8255dead..b0de9162758b 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -253,6 +253,7 @@ struct ceph_inode_info { | |||
253 | spinlock_t i_ceph_lock; | 253 | spinlock_t i_ceph_lock; |
254 | 254 | ||
255 | u64 i_version; | 255 | u64 i_version; |
256 | u64 i_inline_version; | ||
256 | u32 i_time_warp_seq; | 257 | u32 i_time_warp_seq; |
257 | 258 | ||
258 | unsigned i_ceph_flags; | 259 | unsigned i_ceph_flags; |
@@ -858,7 +859,7 @@ extern int ceph_encode_dentry_release(void **p, struct dentry *dn, | |||
858 | int mds, int drop, int unless); | 859 | int mds, int drop, int unless); |
859 | 860 | ||
860 | extern int ceph_get_caps(struct ceph_inode_info *ci, int need, int want, | 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 | /* for counting open files by mode */ | 864 | /* for counting open files by mode */ |
864 | static inline void __ceph_get_fmode(struct ceph_inode_info *ci, int mode) | 865 | static inline void __ceph_get_fmode(struct ceph_inode_info *ci, int mode) |
@@ -880,6 +881,8 @@ extern int ceph_atomic_open(struct inode *dir, struct dentry *dentry, | |||
880 | struct file *file, unsigned flags, umode_t mode, | 881 | struct file *file, unsigned flags, umode_t mode, |
881 | int *opened); | 882 | int *opened); |
882 | extern int ceph_release(struct inode *inode, struct file *filp); | 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 | /* dir.c */ | 887 | /* dir.c */ |
885 | extern const struct file_operations ceph_dir_fops; | 888 | extern const struct file_operations ceph_dir_fops; |
diff --git a/fs/ceph/super.h.rej b/fs/ceph/super.h.rej new file mode 100644 index 000000000000..88fe3dfadb29 --- /dev/null +++ b/fs/ceph/super.h.rej | |||
@@ -0,0 +1,10 @@ | |||
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; | ||