diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-12-21 00:32:20 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-12-21 00:32:20 -0500 |
| commit | 9d5004fcf6e4e8caa9efbc25c9f85059b165329c (patch) | |
| tree | 7f1b53d5487ffabb7be6e1f5b5b964448651b5bc /fs | |
| parent | 453434cf3fdcd3954bb52460e37d4945a0913d3e (diff) | |
| parent | 361cf40519a491f68b28ad90225e4611c4bf8e12 (diff) | |
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
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/ceph/dir.c | 3 | ||||
| -rw-r--r-- | fs/ceph/file.c | 39 |
2 files changed, 25 insertions, 17 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 158c700fdca5..d902948a90d8 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
| @@ -40,7 +40,8 @@ int ceph_init_dentry(struct dentry *dentry) | |||
| 40 | if (dentry->d_fsdata) | 40 | if (dentry->d_fsdata) |
| 41 | return 0; | 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 | dentry->d_op = &ceph_dentry_ops; | 45 | dentry->d_op = &ceph_dentry_ops; |
| 45 | else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR) | 46 | else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR) |
| 46 | dentry->d_op = &ceph_snapdir_dentry_ops; | 47 | dentry->d_op = &ceph_snapdir_dentry_ops; |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 8d79b8912e31..7d0e4a82d898 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
| @@ -282,7 +282,8 @@ int ceph_release(struct inode *inode, struct file *file) | |||
| 282 | static int striped_read(struct inode *inode, | 282 | static int striped_read(struct inode *inode, |
| 283 | u64 off, u64 len, | 283 | u64 off, u64 len, |
| 284 | struct page **pages, int num_pages, | 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 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); | 288 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
| 288 | struct ceph_inode_info *ci = ceph_inode(inode); | 289 | struct ceph_inode_info *ci = ceph_inode(inode); |
| @@ -307,7 +308,7 @@ static int striped_read(struct inode *inode, | |||
| 307 | 308 | ||
| 308 | more: | 309 | more: |
| 309 | if (align_to_pages) | 310 | if (align_to_pages) |
| 310 | page_align = (pos - io_align) & ~PAGE_MASK; | 311 | page_align = (pos - io_align + buf_align) & ~PAGE_MASK; |
| 311 | else | 312 | else |
| 312 | page_align = pos & ~PAGE_MASK; | 313 | page_align = pos & ~PAGE_MASK; |
| 313 | this_len = left; | 314 | this_len = left; |
| @@ -376,16 +377,18 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data, | |||
| 376 | struct inode *inode = file->f_dentry->d_inode; | 377 | struct inode *inode = file->f_dentry->d_inode; |
| 377 | struct page **pages; | 378 | struct page **pages; |
| 378 | u64 off = *poff; | 379 | u64 off = *poff; |
| 379 | int num_pages = calc_pages_for(off, len); | 380 | int num_pages, ret; |
| 380 | int ret; | ||
| 381 | 381 | ||
| 382 | dout("sync_read on file %p %llu~%u %s\n", file, off, len, | 382 | dout("sync_read on file %p %llu~%u %s\n", file, off, len, |
| 383 | (file->f_flags & O_DIRECT) ? "O_DIRECT" : ""); | 383 | (file->f_flags & O_DIRECT) ? "O_DIRECT" : ""); |
| 384 | 384 | ||
| 385 | if (file->f_flags & O_DIRECT) | 385 | if (file->f_flags & O_DIRECT) { |
| 386 | pages = ceph_get_direct_page_vector(data, num_pages); | 386 | num_pages = calc_pages_for((unsigned long)data, len); |
| 387 | else | 387 | pages = ceph_get_direct_page_vector(data, num_pages, true); |
| 388 | } else { | ||
| 389 | num_pages = calc_pages_for(off, len); | ||
| 388 | pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); | 390 | pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); |
| 391 | } | ||
| 389 | if (IS_ERR(pages)) | 392 | if (IS_ERR(pages)) |
| 390 | return PTR_ERR(pages); | 393 | return PTR_ERR(pages); |
| 391 | 394 | ||
| @@ -400,7 +403,8 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data, | |||
| 400 | goto done; | 403 | goto done; |
| 401 | 404 | ||
| 402 | ret = striped_read(inode, off, len, pages, num_pages, checkeof, | 405 | ret = striped_read(inode, off, len, pages, num_pages, checkeof, |
| 403 | file->f_flags & O_DIRECT); | 406 | file->f_flags & O_DIRECT, |
| 407 | (unsigned long)data & ~PAGE_MASK); | ||
| 404 | 408 | ||
| 405 | if (ret >= 0 && (file->f_flags & O_DIRECT) == 0) | 409 | if (ret >= 0 && (file->f_flags & O_DIRECT) == 0) |
| 406 | ret = ceph_copy_page_vector_to_user(pages, data, off, ret); | 410 | ret = ceph_copy_page_vector_to_user(pages, data, off, ret); |
| @@ -409,7 +413,7 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data, | |||
| 409 | 413 | ||
| 410 | done: | 414 | done: |
| 411 | if (file->f_flags & O_DIRECT) | 415 | if (file->f_flags & O_DIRECT) |
| 412 | ceph_put_page_vector(pages, num_pages); | 416 | ceph_put_page_vector(pages, num_pages, true); |
| 413 | else | 417 | else |
| 414 | ceph_release_page_vector(pages, num_pages); | 418 | ceph_release_page_vector(pages, num_pages); |
| 415 | dout("sync_read result %d\n", ret); | 419 | dout("sync_read result %d\n", ret); |
| @@ -456,6 +460,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, | |||
| 456 | int do_sync = 0; | 460 | int do_sync = 0; |
| 457 | int check_caps = 0; | 461 | int check_caps = 0; |
| 458 | int page_align, io_align; | 462 | int page_align, io_align; |
| 463 | unsigned long buf_align; | ||
| 459 | int ret; | 464 | int ret; |
| 460 | struct timespec mtime = CURRENT_TIME; | 465 | struct timespec mtime = CURRENT_TIME; |
| 461 | 466 | ||
| @@ -471,6 +476,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, | |||
| 471 | pos = *offset; | 476 | pos = *offset; |
| 472 | 477 | ||
| 473 | io_align = pos & ~PAGE_MASK; | 478 | io_align = pos & ~PAGE_MASK; |
| 479 | buf_align = (unsigned long)data & ~PAGE_MASK; | ||
| 474 | 480 | ||
| 475 | ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left); | 481 | ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left); |
| 476 | if (ret < 0) | 482 | if (ret < 0) |
| @@ -496,12 +502,15 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, | |||
| 496 | */ | 502 | */ |
| 497 | more: | 503 | more: |
| 498 | len = left; | 504 | len = left; |
| 499 | if (file->f_flags & O_DIRECT) | 505 | if (file->f_flags & O_DIRECT) { |
| 500 | /* write from beginning of first page, regardless of | 506 | /* write from beginning of first page, regardless of |
| 501 | io alignment */ | 507 | io alignment */ |
| 502 | page_align = (pos - io_align) & ~PAGE_MASK; | 508 | page_align = (pos - io_align + buf_align) & ~PAGE_MASK; |
| 503 | else | 509 | num_pages = calc_pages_for((unsigned long)data, len); |
| 510 | } else { | ||
| 504 | page_align = pos & ~PAGE_MASK; | 511 | page_align = pos & ~PAGE_MASK; |
| 512 | num_pages = calc_pages_for(pos, len); | ||
| 513 | } | ||
| 505 | req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, | 514 | req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, |
| 506 | ceph_vino(inode), pos, &len, | 515 | ceph_vino(inode), pos, &len, |
| 507 | CEPH_OSD_OP_WRITE, flags, | 516 | CEPH_OSD_OP_WRITE, flags, |
| @@ -512,10 +521,8 @@ more: | |||
| 512 | if (!req) | 521 | if (!req) |
| 513 | return -ENOMEM; | 522 | return -ENOMEM; |
| 514 | 523 | ||
| 515 | num_pages = calc_pages_for(pos, len); | ||
| 516 | |||
| 517 | if (file->f_flags & O_DIRECT) { | 524 | if (file->f_flags & O_DIRECT) { |
| 518 | pages = ceph_get_direct_page_vector(data, num_pages); | 525 | pages = ceph_get_direct_page_vector(data, num_pages, false); |
| 519 | if (IS_ERR(pages)) { | 526 | if (IS_ERR(pages)) { |
| 520 | ret = PTR_ERR(pages); | 527 | ret = PTR_ERR(pages); |
| 521 | goto out; | 528 | goto out; |
| @@ -565,7 +572,7 @@ more: | |||
| 565 | } | 572 | } |
| 566 | 573 | ||
| 567 | if (file->f_flags & O_DIRECT) | 574 | if (file->f_flags & O_DIRECT) |
| 568 | ceph_put_page_vector(pages, num_pages); | 575 | ceph_put_page_vector(pages, num_pages, false); |
| 569 | else if (file->f_flags & O_SYNC) | 576 | else if (file->f_flags & O_SYNC) |
| 570 | ceph_release_page_vector(pages, num_pages); | 577 | ceph_release_page_vector(pages, num_pages); |
| 571 | 578 | ||
