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 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) 384 + if (file->f_flags & O_DIRECT) { 385 + num_pages = calc_pages_for((unsigned long)data, len); 387 386 pages = ceph_get_direct_page_vector(data, num_pages); 388 - else 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); ··· 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, ··· 520 511 &mtime, false, 2, page_align); 521 512 if (!req) 522 513 return -ENOMEM; 523 - 524 - num_pages = calc_pages_for(pos, len); 525 514 526 515 if (file->f_flags & O_DIRECT) { 527 516 pages = ceph_get_direct_page_vector(data, num_pages);