aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/addr.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2015-04-30 02:40:54 -0400
committerIlya Dryomov <idryomov@gmail.com>2015-06-25 04:49:28 -0400
commit5dda377cf0a6bd43f64a3c1efb670d7c668e7b29 (patch)
tree5b2fddcbf62d8c2b076d2e1040bdd6f5a21e8012 /fs/ceph/addr.c
parent7b06a826e7c52d77ce801e5960ecf0338eafe886 (diff)
ceph: set i_head_snapc when getting CEPH_CAP_FILE_WR reference
In most cases that snap context is needed, we are holding reference of CEPH_CAP_FILE_WR. So we can set ceph inode's i_head_snapc when getting the CEPH_CAP_FILE_WR reference, and make codes get snap context from i_head_snapc. This makes the code simpler. Another benefit of this change is that we can handle snap notification more elegantly. Especially when snap context is updated while someone else is doing write. The old queue cap_snap code may set cap_snap's context to ether the old context or the new snap context, depending on if i_head_snapc is set. The new queue capp_snap code always set cap_snap's context to the old snap context. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/addr.c')
-rw-r--r--fs/ceph/addr.c37
1 files changed, 14 insertions, 23 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index ccc4325aa5c5..5f53ac0d9d7c 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -87,17 +87,21 @@ static int ceph_set_page_dirty(struct page *page)
87 inode = mapping->host; 87 inode = mapping->host;
88 ci = ceph_inode(inode); 88 ci = ceph_inode(inode);
89 89
90 /*
91 * Note that we're grabbing a snapc ref here without holding
92 * any locks!
93 */
94 snapc = ceph_get_snap_context(ci->i_snap_realm->cached_context);
95
96 /* dirty the head */ 90 /* dirty the head */
97 spin_lock(&ci->i_ceph_lock); 91 spin_lock(&ci->i_ceph_lock);
98 if (ci->i_head_snapc == NULL) 92 BUG_ON(ci->i_wr_ref == 0); // caller should hold Fw reference
99 ci->i_head_snapc = ceph_get_snap_context(snapc); 93 if (__ceph_have_pending_cap_snap(ci)) {
100 ++ci->i_wrbuffer_ref_head; 94 struct ceph_cap_snap *capsnap =
95 list_last_entry(&ci->i_cap_snaps,
96 struct ceph_cap_snap,
97 ci_item);
98 snapc = ceph_get_snap_context(capsnap->context);
99 capsnap->dirty_pages++;
100 } else {
101 BUG_ON(!ci->i_head_snapc);
102 snapc = ceph_get_snap_context(ci->i_head_snapc);
103 ++ci->i_wrbuffer_ref_head;
104 }
101 if (ci->i_wrbuffer_ref == 0) 105 if (ci->i_wrbuffer_ref == 0)
102 ihold(inode); 106 ihold(inode);
103 ++ci->i_wrbuffer_ref; 107 ++ci->i_wrbuffer_ref;
@@ -1033,7 +1037,6 @@ static int ceph_update_writeable_page(struct file *file,
1033{ 1037{
1034 struct inode *inode = file_inode(file); 1038 struct inode *inode = file_inode(file);
1035 struct ceph_inode_info *ci = ceph_inode(inode); 1039 struct ceph_inode_info *ci = ceph_inode(inode);
1036 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
1037 loff_t page_off = pos & PAGE_CACHE_MASK; 1040 loff_t page_off = pos & PAGE_CACHE_MASK;
1038 int pos_in_page = pos & ~PAGE_CACHE_MASK; 1041 int pos_in_page = pos & ~PAGE_CACHE_MASK;
1039 int end_in_page = pos_in_page + len; 1042 int end_in_page = pos_in_page + len;
@@ -1045,10 +1048,6 @@ retry_locked:
1045 /* writepages currently holds page lock, but if we change that later, */ 1048 /* writepages currently holds page lock, but if we change that later, */
1046 wait_on_page_writeback(page); 1049 wait_on_page_writeback(page);
1047 1050
1048 /* check snap context */
1049 BUG_ON(!ci->i_snap_realm);
1050 down_read(&mdsc->snap_rwsem);
1051 BUG_ON(!ci->i_snap_realm->cached_context);
1052 snapc = page_snap_context(page); 1051 snapc = page_snap_context(page);
1053 if (snapc && snapc != ci->i_head_snapc) { 1052 if (snapc && snapc != ci->i_head_snapc) {
1054 /* 1053 /*
@@ -1056,7 +1055,6 @@ retry_locked:
1056 * context! is it writeable now? 1055 * context! is it writeable now?
1057 */ 1056 */
1058 oldest = get_oldest_context(inode, NULL); 1057 oldest = get_oldest_context(inode, NULL);
1059 up_read(&mdsc->snap_rwsem);
1060 1058
1061 if (snapc->seq > oldest->seq) { 1059 if (snapc->seq > oldest->seq) {
1062 ceph_put_snap_context(oldest); 1060 ceph_put_snap_context(oldest);
@@ -1113,7 +1111,6 @@ retry_locked:
1113 } 1111 }
1114 1112
1115 /* we need to read it. */ 1113 /* we need to read it. */
1116 up_read(&mdsc->snap_rwsem);
1117 r = readpage_nounlock(file, page); 1114 r = readpage_nounlock(file, page);
1118 if (r < 0) 1115 if (r < 0)
1119 goto fail_nosnap; 1116 goto fail_nosnap;
@@ -1158,16 +1155,13 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
1158 1155
1159/* 1156/*
1160 * we don't do anything in here that simple_write_end doesn't do 1157 * we don't do anything in here that simple_write_end doesn't do
1161 * except adjust dirty page accounting and drop read lock on 1158 * except adjust dirty page accounting
1162 * mdsc->snap_rwsem.
1163 */ 1159 */
1164static int ceph_write_end(struct file *file, struct address_space *mapping, 1160static int ceph_write_end(struct file *file, struct address_space *mapping,
1165 loff_t pos, unsigned len, unsigned copied, 1161 loff_t pos, unsigned len, unsigned copied,
1166 struct page *page, void *fsdata) 1162 struct page *page, void *fsdata)
1167{ 1163{
1168 struct inode *inode = file_inode(file); 1164 struct inode *inode = file_inode(file);
1169 struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
1170 struct ceph_mds_client *mdsc = fsc->mdsc;
1171 unsigned from = pos & (PAGE_CACHE_SIZE - 1); 1165 unsigned from = pos & (PAGE_CACHE_SIZE - 1);
1172 int check_cap = 0; 1166 int check_cap = 0;
1173 1167
@@ -1189,7 +1183,6 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
1189 set_page_dirty(page); 1183 set_page_dirty(page);
1190 1184
1191 unlock_page(page); 1185 unlock_page(page);
1192 up_read(&mdsc->snap_rwsem);
1193 page_cache_release(page); 1186 page_cache_release(page);
1194 1187
1195 if (check_cap) 1188 if (check_cap)
@@ -1315,7 +1308,6 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1315 struct inode *inode = file_inode(vma->vm_file); 1308 struct inode *inode = file_inode(vma->vm_file);
1316 struct ceph_inode_info *ci = ceph_inode(inode); 1309 struct ceph_inode_info *ci = ceph_inode(inode);
1317 struct ceph_file_info *fi = vma->vm_file->private_data; 1310 struct ceph_file_info *fi = vma->vm_file->private_data;
1318 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
1319 struct page *page = vmf->page; 1311 struct page *page = vmf->page;
1320 loff_t off = page_offset(page); 1312 loff_t off = page_offset(page);
1321 loff_t size = i_size_read(inode); 1313 loff_t size = i_size_read(inode);
@@ -1374,7 +1366,6 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1374 if (ret == 0) { 1366 if (ret == 0) {
1375 /* success. we'll keep the page locked. */ 1367 /* success. we'll keep the page locked. */
1376 set_page_dirty(page); 1368 set_page_dirty(page);
1377 up_read(&mdsc->snap_rwsem);
1378 ret = VM_FAULT_LOCKED; 1369 ret = VM_FAULT_LOCKED;
1379 } else { 1370 } else {
1380 if (ret == -ENOMEM) 1371 if (ret == -ENOMEM)