aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2014-11-14 08:41:55 -0500
committerIlya Dryomov <idryomov@redhat.com>2014-12-17 12:09:52 -0500
commit31c542a199d79f0f402c2f3e04229464510d47ec (patch)
treefa28ee0ee2f288f334cd141146eb79cbd1b693ce /fs
parentfb01d1f8b0343f1b19be878cee89d089f06e9f38 (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.c43
-rw-r--r--fs/ceph/caps.c11
-rw-r--r--fs/ceph/inode.c16
-rw-r--r--fs/ceph/super.h5
-rw-r--r--fs/ceph/super.h.rej10
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
1321void 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
1321static struct vm_operations_struct ceph_vmops = { 1364static 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
860extern int ceph_get_caps(struct ceph_inode_info *ci, int need, int want, 861extern 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 */
864static inline void __ceph_get_fmode(struct ceph_inode_info *ci, int mode) 865static 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);
882extern int ceph_release(struct inode *inode, struct file *filp); 883extern int ceph_release(struct inode *inode, struct file *filp);
884extern 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 */
885extern const struct file_operations ceph_dir_fops; 888extern 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;