aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/rbd.c2
-rw-r--r--fs/ceph/addr.c193
-rw-r--r--fs/ceph/caps.c2
-rw-r--r--fs/ceph/inode.c46
-rw-r--r--fs/ceph/ioctl.c34
-rw-r--r--fs/ceph/ioctl.h55
-rw-r--r--fs/ceph/mds_client.c11
-rw-r--r--fs/ceph/super.c61
-rw-r--r--fs/ceph/super.h19
-rw-r--r--include/linux/ceph/libceph.h4
-rw-r--r--include/linux/ceph/messenger.h3
-rw-r--r--net/ceph/Kconfig14
-rw-r--r--net/ceph/ceph_common.c47
-rw-r--r--net/ceph/messenger.c130
-rw-r--r--net/ceph/mon_client.c79
-rw-r--r--net/ceph/msgpool.c4
-rw-r--r--net/ceph/osd_client.c34
17 files changed, 483 insertions, 255 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index fe3c3249cec4..65cc424359b0 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -260,7 +260,7 @@ static struct rbd_client *rbd_client_create(struct ceph_options *opt,
260 kref_init(&rbdc->kref); 260 kref_init(&rbdc->kref);
261 INIT_LIST_HEAD(&rbdc->node); 261 INIT_LIST_HEAD(&rbdc->node);
262 262
263 rbdc->client = ceph_create_client(opt, rbdc); 263 rbdc->client = ceph_create_client(opt, rbdc, 0, 0);
264 if (IS_ERR(rbdc->client)) 264 if (IS_ERR(rbdc->client))
265 goto out_rbdc; 265 goto out_rbdc;
266 opt = NULL; /* Now rbdc->client is responsible for opt */ 266 opt = NULL; /* Now rbdc->client is responsible for opt */
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 5a3953db8118..4144caf2f9d3 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -228,102 +228,155 @@ static int ceph_readpage(struct file *filp, struct page *page)
228} 228}
229 229
230/* 230/*
231 * Build a vector of contiguous pages from the provided page list. 231 * Finish an async read(ahead) op.
232 */ 232 */
233static struct page **page_vector_from_list(struct list_head *page_list, 233static void finish_read(struct ceph_osd_request *req, struct ceph_msg *msg)
234 unsigned *nr_pages)
235{ 234{
236 struct page **pages; 235 struct inode *inode = req->r_inode;
237 struct page *page; 236 struct ceph_osd_reply_head *replyhead;
238 int next_index, contig_pages = 0; 237 int rc, bytes;
238 int i;
239 239
240 /* build page vector */ 240 /* parse reply */
241 pages = kmalloc(sizeof(*pages) * *nr_pages, GFP_NOFS); 241 replyhead = msg->front.iov_base;
242 if (!pages) 242 WARN_ON(le32_to_cpu(replyhead->num_ops) == 0);
243 return ERR_PTR(-ENOMEM); 243 rc = le32_to_cpu(replyhead->result);
244 bytes = le32_to_cpu(msg->hdr.data_len);
244 245
245 BUG_ON(list_empty(page_list)); 246 dout("finish_read %p req %p rc %d bytes %d\n", inode, req, rc, bytes);
246 next_index = list_entry(page_list->prev, struct page, lru)->index; 247
247 list_for_each_entry_reverse(page, page_list, lru) { 248 /* unlock all pages, zeroing any data we didn't read */
248 if (page->index == next_index) { 249 for (i = 0; i < req->r_num_pages; i++, bytes -= PAGE_CACHE_SIZE) {
249 dout("readpages page %d %p\n", contig_pages, page); 250 struct page *page = req->r_pages[i];
250 pages[contig_pages] = page; 251
251 contig_pages++; 252 if (bytes < (int)PAGE_CACHE_SIZE) {
252 next_index++; 253 /* zero (remainder of) page */
253 } else { 254 int s = bytes < 0 ? 0 : bytes;
254 break; 255 zero_user_segment(page, s, PAGE_CACHE_SIZE);
255 } 256 }
257 dout("finish_read %p uptodate %p idx %lu\n", inode, page,
258 page->index);
259 flush_dcache_page(page);
260 SetPageUptodate(page);
261 unlock_page(page);
262 page_cache_release(page);
256 } 263 }
257 *nr_pages = contig_pages; 264 kfree(req->r_pages);
258 return pages;
259} 265}
260 266
261/* 267/*
262 * Read multiple pages. Leave pages we don't read + unlock in page_list; 268 * start an async read(ahead) operation. return nr_pages we submitted
263 * the caller (VM) cleans them up. 269 * a read for on success, or negative error code.
264 */ 270 */
265static int ceph_readpages(struct file *file, struct address_space *mapping, 271static int start_read(struct inode *inode, struct list_head *page_list, int max)
266 struct list_head *page_list, unsigned nr_pages)
267{ 272{
268 struct inode *inode = file->f_dentry->d_inode;
269 struct ceph_inode_info *ci = ceph_inode(inode);
270 struct ceph_osd_client *osdc = 273 struct ceph_osd_client *osdc =
271 &ceph_inode_to_client(inode)->client->osdc; 274 &ceph_inode_to_client(inode)->client->osdc;
272 int rc = 0; 275 struct ceph_inode_info *ci = ceph_inode(inode);
273 struct page **pages; 276 struct page *page = list_entry(page_list->prev, struct page, lru);
274 loff_t offset; 277 struct ceph_osd_request *req;
278 u64 off;
275 u64 len; 279 u64 len;
280 int i;
281 struct page **pages;
282 pgoff_t next_index;
283 int nr_pages = 0;
284 int ret;
276 285
277 dout("readpages %p file %p nr_pages %d\n", 286 off = page->index << PAGE_CACHE_SHIFT;
278 inode, file, nr_pages);
279
280 pages = page_vector_from_list(page_list, &nr_pages);
281 if (IS_ERR(pages))
282 return PTR_ERR(pages);
283 287
284 /* guess read extent */ 288 /* count pages */
285 offset = pages[0]->index << PAGE_CACHE_SHIFT; 289 next_index = page->index;
290 list_for_each_entry_reverse(page, page_list, lru) {
291 if (page->index != next_index)
292 break;
293 nr_pages++;
294 next_index++;
295 if (max && nr_pages == max)
296 break;
297 }
286 len = nr_pages << PAGE_CACHE_SHIFT; 298 len = nr_pages << PAGE_CACHE_SHIFT;
287 rc = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout, 299 dout("start_read %p nr_pages %d is %lld~%lld\n", inode, nr_pages,
288 offset, &len, 300 off, len);
289 ci->i_truncate_seq, ci->i_truncate_size, 301
290 pages, nr_pages, 0); 302 req = ceph_osdc_new_request(osdc, &ci->i_layout, ceph_vino(inode),
291 if (rc == -ENOENT) 303 off, &len,
292 rc = 0; 304 CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ,
293 if (rc < 0) 305 NULL, 0,
294 goto out; 306 ci->i_truncate_seq, ci->i_truncate_size,
295 307 NULL, false, 1, 0);
296 for (; !list_empty(page_list) && len > 0; 308 if (!req)
297 rc -= PAGE_CACHE_SIZE, len -= PAGE_CACHE_SIZE) { 309 return -ENOMEM;
298 struct page *page =
299 list_entry(page_list->prev, struct page, lru);
300 310
311 /* build page vector */
312 nr_pages = len >> PAGE_CACHE_SHIFT;
313 pages = kmalloc(sizeof(*pages) * nr_pages, GFP_NOFS);
314 ret = -ENOMEM;
315 if (!pages)
316 goto out;
317 for (i = 0; i < nr_pages; ++i) {
318 page = list_entry(page_list->prev, struct page, lru);
319 BUG_ON(PageLocked(page));
301 list_del(&page->lru); 320 list_del(&page->lru);
302 321
303 if (rc < (int)PAGE_CACHE_SIZE) { 322 dout("start_read %p adding %p idx %lu\n", inode, page,
304 /* zero (remainder of) page */ 323 page->index);
305 int s = rc < 0 ? 0 : rc; 324 if (add_to_page_cache_lru(page, &inode->i_data, page->index,
306 zero_user_segment(page, s, PAGE_CACHE_SIZE);
307 }
308
309 if (add_to_page_cache_lru(page, mapping, page->index,
310 GFP_N