Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
ceph: handle partial result from get_user_pages
ceph: mark user pages dirty on direct-io reads
ceph: fix null pointer dereference in ceph_init_dentry for nfs reexport
ceph: fix direct-io on non-page-aligned buffers
ceph: fix msgr_init error path

+41 -30
+2 -1
fs/ceph/dir.c
··· 40 40 if (dentry->d_fsdata) 41 41 return 0; 42 42 43 - if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) 43 + if (dentry->d_parent == NULL || /* nfs fh_to_dentry */ 44 + ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) 44 45 dentry->d_op = &ceph_dentry_ops; 45 46 else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR) 46 47 dentry->d_op = &ceph_snapdir_dentry_ops;
+23 -16
fs/ceph/file.c
··· 282 282 static int striped_read(struct inode *inode, 283 283 u64 off, u64 len, 284 284 struct page **pages, int num_pages, 285 - int *checkeof, bool align_to_pages) 285 + int *checkeof, bool align_to_pages, 286 + unsigned long buf_align) 286 287 { 287 288 struct ceph_fs_client *fsc = ceph_inode_to_client(inode); 288 289 struct ceph_inode_info *ci = ceph_inode(inode); ··· 308 307 309 308 more: 310 309 if (align_to_pages) 311 - page_align = (pos - io_align) & ~PAGE_MASK; 310 + page_align = (pos - io_align + buf_align) & ~PAGE_MASK; 312 311 else 313 312 page_align = pos & ~PAGE_MASK; 314 313 this_len = left; ··· 377 376 struct inode *inode = file->f_dentry->d_inode; 378 377 struct page **pages; 379 378 u64 off = *poff; 380 - int num_pages = calc_pages_for(off, len); 381 - int ret; 379 + int num_pages, ret; 382 380 383 381 dout("sync_read on file %p %llu~%u %s\n", file, off, len, 384 382 (file->f_flags & O_DIRECT) ? "O_DIRECT" : ""); 385 383 386 - if (file->f_flags & O_DIRECT) 387 - pages = ceph_get_direct_page_vector(data, num_pages); 388 - else 384 + if (file->f_flags & O_DIRECT) { 385 + num_pages = calc_pages_for((unsigned long)data, len); 386 + pages = ceph_get_direct_page_vector(data, num_pages, true); 387 + } else { 388 + num_pages = calc_pages_for(off, len); 389 389 pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); 390 + } 390 391 if (IS_ERR(pages)) 391 392 return PTR_ERR(pages); 392 393 ··· 403 400 goto done; 404 401 405 402 ret = striped_read(inode, off, len, pages, num_pages, checkeof, 406 - file->f_flags & O_DIRECT); 403 + file->f_flags & O_DIRECT, 404 + (unsigned long)data & ~PAGE_MASK); 407 405 408 406 if (ret >= 0 && (file->f_flags & O_DIRECT) == 0) 409 407 ret = ceph_copy_page_vector_to_user(pages, data, off, ret); ··· 413 409 414 410 done: 415 411 if (file->f_flags & O_DIRECT) 416 - ceph_put_page_vector(pages, num_pages); 412 + ceph_put_page_vector(pages, num_pages, true); 417 413 else 418 414 ceph_release_page_vector(pages, num_pages); 419 415 dout("sync_read result %d\n", ret); ··· 460 456 int do_sync = 0; 461 457 int check_caps = 0; 462 458 int page_align, io_align; 459 + unsigned long buf_align; 463 460 int ret; 464 461 struct timespec mtime = CURRENT_TIME; 465 462 ··· 476 471 pos = *offset; 477 472 478 473 io_align = pos & ~PAGE_MASK; 474 + buf_align = (unsigned long)data & ~PAGE_MASK; 479 475 480 476 ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left); 481 477 if (ret < 0) ··· 502 496 */ 503 497 more: 504 498 len = left; 505 - if (file->f_flags & O_DIRECT) 499 + if (file->f_flags & O_DIRECT) { 506 500 /* write from beginning of first page, regardless of 507 501 io alignment */ 508 - page_align = (pos - io_align) & ~PAGE_MASK; 509 - else 502 + page_align = (pos - io_align + buf_align) & ~PAGE_MASK; 503 + num_pages = calc_pages_for((unsigned long)data, len); 504 + } else { 510 505 page_align = pos & ~PAGE_MASK; 506 + num_pages = calc_pages_for(pos, len); 507 + } 511 508 req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, 512 509 ceph_vino(inode), pos, &len, 513 510 CEPH_OSD_OP_WRITE, flags, ··· 521 512 if (!req) 522 513 return -ENOMEM; 523 514 524 - num_pages = calc_pages_for(pos, len); 525 - 526 515 if (file->f_flags & O_DIRECT) { 527 - pages = ceph_get_direct_page_vector(data, num_pages); 516 + pages = ceph_get_direct_page_vector(data, num_pages, false); 528 517 if (IS_ERR(pages)) { 529 518 ret = PTR_ERR(pages); 530 519 goto out; ··· 572 565 } 573 566 574 567 if (file->f_flags & O_DIRECT) 575 - ceph_put_page_vector(pages, num_pages); 568 + ceph_put_page_vector(pages, num_pages, false); 576 569 else if (file->f_flags & O_SYNC) 577 570 ceph_release_page_vector(pages, num_pages); 578 571
+4 -2
include/linux/ceph/libceph.h
··· 227 227 extern void ceph_release_page_vector(struct page **pages, int num_pages); 228 228 229 229 extern struct page **ceph_get_direct_page_vector(const char __user *data, 230 - int num_pages); 231 - extern void ceph_put_page_vector(struct page **pages, int num_pages); 230 + int num_pages, 231 + bool write_page); 232 + extern void ceph_put_page_vector(struct page **pages, int num_pages, 233 + bool dirty); 232 234 extern void ceph_release_page_vector(struct page **pages, int num_pages); 233 235 extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); 234 236 extern int ceph_copy_user_to_page_vector(struct page **pages,
+3 -5
net/ceph/messenger.c
··· 97 97 int ceph_msgr_init(void) 98 98 { 99 99 ceph_msgr_wq = create_workqueue("ceph-msgr"); 100 - if (IS_ERR(ceph_msgr_wq)) { 101 - int ret = PTR_ERR(ceph_msgr_wq); 102 - pr_err("msgr_init failed to create workqueue: %d\n", ret); 103 - ceph_msgr_wq = NULL; 104 - return ret; 100 + if (!ceph_msgr_wq) { 101 + pr_err("msgr_init failed to create workqueue\n"); 102 + return -ENOMEM; 105 103 } 106 104 return 0; 107 105 }
+9 -6
net/ceph/pagevec.c
··· 13 13 * build a vector of user pages 14 14 */ 15 15 struct page **ceph_get_direct_page_vector(const char __user *data, 16 - int num_pages) 16 + int num_pages, bool write_page) 17 17 { 18 18 struct page **pages; 19 19 int rc; ··· 24 24 25 25 down_read(&current->mm->mmap_sem); 26 26 rc = get_user_pages(current, current->mm, (unsigned long)data, 27 - num_pages, 0, 0, pages, NULL); 27 + num_pages, write_page, 0, pages, NULL); 28 28 up_read(&current->mm->mmap_sem); 29 - if (rc < 0) 29 + if (rc < num_pages) 30 30 goto fail; 31 31 return pages; 32 32 33 33 fail: 34 - kfree(pages); 34 + ceph_put_page_vector(pages, rc > 0 ? rc : 0, false); 35 35 return ERR_PTR(rc); 36 36 } 37 37 EXPORT_SYMBOL(ceph_get_direct_page_vector); 38 38 39 - void ceph_put_page_vector(struct page **pages, int num_pages) 39 + void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty) 40 40 { 41 41 int i; 42 42 43 - for (i = 0; i < num_pages; i++) 43 + for (i = 0; i < num_pages; i++) { 44 + if (dirty) 45 + set_page_dirty_lock(pages[i]); 44 46 put_page(pages[i]); 47 + } 45 48 kfree(pages); 46 49 } 47 50 EXPORT_SYMBOL(ceph_put_page_vector);