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>
This commit is contained in:
parent
fb01d1f8b0
commit
31c542a199
|
@ -1318,6 +1318,49 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
|
||||||
|
char *data, size_t len)
|
||||||
|
{
|
||||||
|
struct address_space *mapping = inode->i_mapping;
|
||||||
|
struct page *page;
|
||||||
|
|
||||||
|
if (locked_page) {
|
||||||
|
page = locked_page;
|
||||||
|
} else {
|
||||||
|
if (i_size_read(inode) == 0)
|
||||||
|
return;
|
||||||
|
page = find_or_create_page(mapping, 0,
|
||||||
|
mapping_gfp_mask(mapping) & ~__GFP_FS);
|
||||||
|
if (!page)
|
||||||
|
return;
|
||||||
|
if (PageUptodate(page)) {
|
||||||
|
unlock_page(page);
|
||||||
|
page_cache_release(page);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dout("fill_inline_data %p %llx.%llx len %lu locked_page %p\n",
|
||||||
|
inode, ceph_vinop(inode), len, locked_page);
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
void *kaddr = kmap_atomic(page);
|
||||||
|
memcpy(kaddr, data, len);
|
||||||
|
kunmap_atomic(kaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page != locked_page) {
|
||||||
|
if (len < PAGE_CACHE_SIZE)
|
||||||
|
zero_user_segment(page, len, PAGE_CACHE_SIZE);
|
||||||
|
else
|
||||||
|
flush_dcache_page(page);
|
||||||
|
|
||||||
|
SetPageUptodate(page);
|
||||||
|
unlock_page(page);
|
||||||
|
page_cache_release(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct vm_operations_struct ceph_vmops = {
|
static struct vm_operations_struct ceph_vmops = {
|
||||||
.fault = ceph_filemap_fault,
|
.fault = ceph_filemap_fault,
|
||||||
.page_mkwrite = ceph_page_mkwrite,
|
.page_mkwrite = ceph_page_mkwrite,
|
||||||
|
|
|
@ -2405,6 +2405,7 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
|
||||||
bool queue_invalidate = false;
|
bool queue_invalidate = false;
|
||||||
bool queue_revalidate = false;
|
bool queue_revalidate = false;
|
||||||
bool deleted_inode = false;
|
bool deleted_inode = false;
|
||||||
|
bool fill_inline = false;
|
||||||
|
|
||||||
dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
|
dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
|
||||||
inode, cap, mds, seq, ceph_cap_string(newcaps));
|
inode, cap, mds, seq, ceph_cap_string(newcaps));
|
||||||
|
@ -2578,6 +2579,13 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
|
||||||
}
|
}
|
||||||
BUG_ON(cap->issued & ~cap->implemented);
|
BUG_ON(cap->issued & ~cap->implemented);
|
||||||
|
|
||||||
|
if (inline_version > 0 && inline_version >= ci->i_inline_version) {
|
||||||
|
ci->i_inline_version = inline_version;
|
||||||
|
if (ci->i_inline_version != CEPH_INLINE_NONE &&
|
||||||
|
(newcaps & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)))
|
||||||
|
fill_inline = true;
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
|
||||||
if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
|
if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
|
||||||
|
@ -2591,6 +2599,9 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
|
||||||
wake = true;
|
wake = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fill_inline)
|
||||||
|
ceph_fill_inline_data(inode, NULL, inline_data, inline_len);
|
||||||
|
|
||||||
if (queue_trunc) {
|
if (queue_trunc) {
|
||||||
ceph_queue_vmtruncate(inode);
|
ceph_queue_vmtruncate(inode);
|
||||||
ceph_queue_revalidate(inode);
|
ceph_queue_revalidate(inode);
|
||||||
|
|
|
@ -387,6 +387,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
|
||||||
spin_lock_init(&ci->i_ceph_lock);
|
spin_lock_init(&ci->i_ceph_lock);
|
||||||
|
|
||||||
ci->i_version = 0;
|
ci->i_version = 0;
|
||||||
|
ci->i_inline_version = 0;
|
||||||
ci->i_time_warp_seq = 0;
|
ci->i_time_warp_seq = 0;
|
||||||
ci->i_ceph_flags = 0;
|
ci->i_ceph_flags = 0;
|
||||||
ci->i_ordered_count = 0;
|
ci->i_ordered_count = 0;
|
||||||
|
@ -676,6 +677,7 @@ static int fill_inode(struct inode *inode,
|
||||||
bool wake = false;
|
bool wake = false;
|
||||||
bool queue_trunc = false;
|
bool queue_trunc = false;
|
||||||
bool new_version = false;
|
bool new_version = false;
|
||||||
|
bool fill_inline = false;
|
||||||
|
|
||||||
dout("fill_inode %p ino %llx.%llx v %llu had %llu\n",
|
dout("fill_inode %p ino %llx.%llx v %llu had %llu\n",
|
||||||
inode, ceph_vinop(inode), le64_to_cpu(info->version),
|
inode, ceph_vinop(inode), le64_to_cpu(info->version),
|
||||||
|
@ -875,8 +877,22 @@ static int fill_inode(struct inode *inode,
|
||||||
ceph_vinop(inode));
|
ceph_vinop(inode));
|
||||||
__ceph_get_fmode(ci, cap_fmode);
|
__ceph_get_fmode(ci, cap_fmode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iinfo->inline_version > 0 &&
|
||||||
|
iinfo->inline_version >= ci->i_inline_version) {
|
||||||
|
int cache_caps = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
|
||||||
|
ci->i_inline_version = iinfo->inline_version;
|
||||||
|
if (ci->i_inline_version != CEPH_INLINE_NONE &&
|
||||||
|
(le32_to_cpu(info->cap.caps) & cache_caps))
|
||||||
|
fill_inline = true;
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
|
||||||
|
if (fill_inline)
|
||||||
|
ceph_fill_inline_data(inode, NULL,
|
||||||
|
iinfo->inline_data, iinfo->inline_len);
|
||||||
|
|
||||||
if (wake)
|
if (wake)
|
||||||
wake_up_all(&ci->i_cap_wq);
|
wake_up_all(&ci->i_cap_wq);
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,7 @@ struct ceph_inode_info {
|
||||||
spinlock_t i_ceph_lock;
|
spinlock_t i_ceph_lock;
|
||||||
|
|
||||||
u64 i_version;
|
u64 i_version;
|
||||||
|
u64 i_inline_version;
|
||||||
u32 i_time_warp_seq;
|
u32 i_time_warp_seq;
|
||||||
|
|
||||||
unsigned i_ceph_flags;
|
unsigned i_ceph_flags;
|
||||||
|
@ -858,7 +859,7 @@ extern int ceph_encode_dentry_release(void **p, struct dentry *dn,
|
||||||
int mds, int drop, int unless);
|
int mds, int drop, int unless);
|
||||||
|
|
||||||
extern int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
|
extern int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
|
||||||
int *got, loff_t endoff);
|
loff_t endoff, int *got, struct page **pinned_page);
|
||||||
|
|
||||||
/* for counting open files by mode */
|
/* for counting open files by mode */
|
||||||
static inline void __ceph_get_fmode(struct ceph_inode_info *ci, int mode)
|
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,
|
||||||
struct file *file, unsigned flags, umode_t mode,
|
struct file *file, unsigned flags, umode_t mode,
|
||||||
int *opened);
|
int *opened);
|
||||||
extern int ceph_release(struct inode *inode, struct file *filp);
|
extern int ceph_release(struct inode *inode, struct file *filp);
|
||||||
|
extern void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
|
||||||
|
char *data, size_t len);
|
||||||
|
|
||||||
/* dir.c */
|
/* dir.c */
|
||||||
extern const struct file_operations ceph_dir_fops;
|
extern const struct file_operations ceph_dir_fops;
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
--- fs/ceph/super.h
|
||||||
|
+++ fs/ceph/super.h
|
||||||
|
@@ -254,6 +255,7 @@
|
||||||
|
spinlock_t i_ceph_lock;
|
||||||
|
|
||||||
|
u64 i_version;
|
||||||
|
+ u64 i_inline_version;
|
||||||
|
u32 i_time_warp_seq;
|
||||||
|
|
||||||
|
unsigned i_ceph_flags;
|
|
@ -552,6 +552,7 @@ struct ceph_filelock {
|
||||||
|
|
||||||
int ceph_flags_to_mode(int flags);
|
int ceph_flags_to_mode(int flags);
|
||||||
|
|
||||||
|
#define CEPH_INLINE_NONE ((__u64)-1)
|
||||||
|
|
||||||
/* capability bits */
|
/* capability bits */
|
||||||
#define CEPH_CAP_PIN 1 /* no specific capabilities beyond the pin */
|
#define CEPH_CAP_PIN 1 /* no specific capabilities beyond the pin */
|
||||||
|
|
Loading…
Reference in New Issue