ceph: fix direct-io on non-page-aligned buffers

The user buffer may be 512-byte aligned, not page-aligned. We were
assuming the buffer was page-aligned and only accounting for
non-page-aligned io offsets.

Signed-off-by: Henry C Chang <henry_c_chang@tcloudcomputing.com>
Signed-off-by: Sage Weil <sage@newdream.net>

authored by Henry C Chang and committed by Sage Weil ab226e21 d96c9043

+19 -12
+19 -12
fs/ceph/file.c
··· 282 static int striped_read(struct inode *inode, 283 u64 off, u64 len, 284 struct page **pages, int num_pages, 285 - int *checkeof, bool align_to_pages) 286 { 287 struct ceph_fs_client *fsc = ceph_inode_to_client(inode); 288 struct ceph_inode_info *ci = ceph_inode(inode); ··· 308 309 more: 310 if (align_to_pages) 311 - page_align = (pos - io_align) & ~PAGE_MASK; 312 else 313 page_align = pos & ~PAGE_MASK; 314 this_len = left; ··· 377 struct inode *inode = file->f_dentry->d_inode; 378 struct page **pages; 379 u64 off = *poff; 380 - int num_pages = calc_pages_for(off, len); 381 - int ret; 382 383 dout("sync_read on file %p %llu~%u %s\n", file, off, len, 384 (file->f_flags & O_DIRECT) ? "O_DIRECT" : ""); 385 386 - if (file->f_flags & O_DIRECT) 387 pages = ceph_get_direct_page_vector(data, num_pages); 388 - else 389 pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); 390 if (IS_ERR(pages)) 391 return PTR_ERR(pages); 392 ··· 403 goto done; 404 405 ret = striped_read(inode, off, len, pages, num_pages, checkeof, 406 - file->f_flags & O_DIRECT); 407 408 if (ret >= 0 && (file->f_flags & O_DIRECT) == 0) 409 ret = ceph_copy_page_vector_to_user(pages, data, off, ret); ··· 460 int do_sync = 0; 461 int check_caps = 0; 462 int page_align, io_align; 463 int ret; 464 struct timespec mtime = CURRENT_TIME; 465 ··· 476 pos = *offset; 477 478 io_align = pos & ~PAGE_MASK; 479 480 ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left); 481 if (ret < 0) ··· 502 */ 503 more: 504 len = left; 505 - if (file->f_flags & O_DIRECT) 506 /* write from beginning of first page, regardless of 507 io alignment */ 508 - page_align = (pos - io_align) & ~PAGE_MASK; 509 - else 510 page_align = pos & ~PAGE_MASK; 511 req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, 512 ceph_vino(inode), pos, &len, 513 CEPH_OSD_OP_WRITE, flags, ··· 520 &mtime, false, 2, page_align); 521 if (!req) 522 return -ENOMEM; 523 - 524 - num_pages = calc_pages_for(pos, len); 525 526 if (file->f_flags & O_DIRECT) { 527 pages = ceph_get_direct_page_vector(data, num_pages);
··· 282 static int striped_read(struct inode *inode, 283 u64 off, u64 len, 284 struct page **pages, int num_pages, 285 + int *checkeof, bool align_to_pages, 286 + unsigned long buf_align) 287 { 288 struct ceph_fs_client *fsc = ceph_inode_to_client(inode); 289 struct ceph_inode_info *ci = ceph_inode(inode); ··· 307 308 more: 309 if (align_to_pages) 310 + page_align = (pos - io_align + buf_align) & ~PAGE_MASK; 311 else 312 page_align = pos & ~PAGE_MASK; 313 this_len = left; ··· 376 struct inode *inode = file->f_dentry->d_inode; 377 struct page **pages; 378 u64 off = *poff; 379 + int num_pages, ret; 380 381 dout("sync_read on file %p %llu~%u %s\n", file, off, len, 382 (file->f_flags & O_DIRECT) ? "O_DIRECT" : ""); 383 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); 387 + } else { 388 + num_pages = calc_pages_for(off, len); 389 pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); 390 + } 391 if (IS_ERR(pages)) 392 return PTR_ERR(pages); 393 ··· 400 goto done; 401 402 ret = striped_read(inode, off, len, pages, num_pages, checkeof, 403 + file->f_flags & O_DIRECT, 404 + (unsigned long)data & ~PAGE_MASK); 405 406 if (ret >= 0 && (file->f_flags & O_DIRECT) == 0) 407 ret = ceph_copy_page_vector_to_user(pages, data, off, ret); ··· 456 int do_sync = 0; 457 int check_caps = 0; 458 int page_align, io_align; 459 + unsigned long buf_align; 460 int ret; 461 struct timespec mtime = CURRENT_TIME; 462 ··· 471 pos = *offset; 472 473 io_align = pos & ~PAGE_MASK; 474 + buf_align = (unsigned long)data & ~PAGE_MASK; 475 476 ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left); 477 if (ret < 0) ··· 496 */ 497 more: 498 len = left; 499 + if (file->f_flags & O_DIRECT) { 500 /* write from beginning of first page, regardless of 501 io alignment */ 502 + page_align = (pos - io_align + buf_align) & ~PAGE_MASK; 503 + num_pages = calc_pages_for((unsigned long)data, len); 504 + } else { 505 page_align = pos & ~PAGE_MASK; 506 + num_pages = calc_pages_for(pos, len); 507 + } 508 req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, 509 ceph_vino(inode), pos, &len, 510 CEPH_OSD_OP_WRITE, flags, ··· 511 &mtime, false, 2, page_align); 512 if (!req) 513 return -ENOMEM; 514 515 if (file->f_flags & O_DIRECT) { 516 pages = ceph_get_direct_page_vector(data, num_pages);