diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-13 12:24:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-13 12:24:40 -0500 |
commit | ca4ba96e02e932a0c9997a40fd51253b5b2d0f9d (patch) | |
tree | ca7cc57de628ec777d0fcda3425fcbba8b53d4ca /fs | |
parent | 4aeabc6b5ca3b9d025f287978096e138bdfbdd35 (diff) | |
parent | 583d0fef756a7615e50f0f68ea0892a497d03971 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull Ceph updates from Sage Weil:
"There are several patches from Ilya fixing RBD allocation lifecycle
issues, a series adding a nocephx_sign_messages option (and associated
bug fixes/cleanups), several patches from Zheng improving the
(directory) fsync behavior, a big improvement in IO for direct-io
requests when striping is enabled from Caifeng, and several other
small fixes and cleanups"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
libceph: clear msg->con in ceph_msg_release() only
libceph: add nocephx_sign_messages option
libceph: stop duplicating client fields in messenger
libceph: drop authorizer check from cephx msg signing routines
libceph: msg signing callouts don't need con argument
libceph: evaluate osd_req_op_data() arguments only once
ceph: make fsync() wait unsafe requests that created/modified inode
ceph: add request to i_unsafe_dirops when getting unsafe reply
libceph: introduce ceph_x_authorizer_cleanup()
ceph: don't invalidate page cache when inode is no longer used
rbd: remove duplicate calls to rbd_dev_mapping_clear()
rbd: set device_type::release instead of device::release
rbd: don't free rbd_dev outside of the release callback
rbd: return -ENOMEM instead of pool id if rbd_dev_create() fails
libceph: use local variable cursor instead of &msg->cursor
libceph: remove con argument in handle_reply()
ceph: combine as many iovec as possile into one OSD request
ceph: fix message length computation
ceph: fix a comment typo
rbd: drop null test before destroy functions
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/cache.c | 2 | ||||
-rw-r--r-- | fs/ceph/caps.c | 76 | ||||
-rw-r--r-- | fs/ceph/file.c | 87 | ||||
-rw-r--r-- | fs/ceph/inode.c | 1 | ||||
-rw-r--r-- | fs/ceph/mds_client.c | 57 | ||||
-rw-r--r-- | fs/ceph/mds_client.h | 3 | ||||
-rw-r--r-- | fs/ceph/super.h | 1 |
7 files changed, 161 insertions, 66 deletions
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c index 834f9f3723fb..a4766ded1ba7 100644 --- a/fs/ceph/cache.c +++ b/fs/ceph/cache.c | |||
@@ -88,7 +88,7 @@ static uint16_t ceph_fscache_inode_get_key(const void *cookie_netfs_data, | |||
88 | const struct ceph_inode_info* ci = cookie_netfs_data; | 88 | const struct ceph_inode_info* ci = cookie_netfs_data; |
89 | uint16_t klen; | 89 | uint16_t klen; |
90 | 90 | ||
91 | /* use ceph virtual inode (id + snaphot) */ | 91 | /* use ceph virtual inode (id + snapshot) */ |
92 | klen = sizeof(ci->i_vino); | 92 | klen = sizeof(ci->i_vino); |
93 | if (klen > maxbuf) | 93 | if (klen > maxbuf) |
94 | return 0; | 94 | return 0; |
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 27b566874bc1..c69e1253b47b 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -1655,9 +1655,8 @@ retry_locked: | |||
1655 | !S_ISDIR(inode->i_mode) && /* ignore readdir cache */ | 1655 | !S_ISDIR(inode->i_mode) && /* ignore readdir cache */ |
1656 | ci->i_wrbuffer_ref == 0 && /* no dirty pages... */ | 1656 | ci->i_wrbuffer_ref == 0 && /* no dirty pages... */ |
1657 | inode->i_data.nrpages && /* have cached pages */ | 1657 | inode->i_data.nrpages && /* have cached pages */ |
1658 | (file_wanted == 0 || /* no open files */ | 1658 | (revoking & (CEPH_CAP_FILE_CACHE| |
1659 | (revoking & (CEPH_CAP_FILE_CACHE| | 1659 | CEPH_CAP_FILE_LAZYIO)) && /* or revoking cache */ |
1660 | CEPH_CAP_FILE_LAZYIO))) && /* or revoking cache */ | ||
1661 | !tried_invalidate) { | 1660 | !tried_invalidate) { |
1662 | dout("check_caps trying to invalidate on %p\n", inode); | 1661 | dout("check_caps trying to invalidate on %p\n", inode); |
1663 | if (try_nonblocking_invalidate(inode) < 0) { | 1662 | if (try_nonblocking_invalidate(inode) < 0) { |
@@ -1971,49 +1970,46 @@ out: | |||
1971 | } | 1970 | } |
1972 | 1971 | ||
1973 | /* | 1972 | /* |
1974 | * wait for any uncommitted directory operations to commit. | 1973 | * wait for any unsafe requests to complete. |
1975 | */ | 1974 | */ |
1976 | static int unsafe_dirop_wait(struct inode *inode) | 1975 | static int unsafe_request_wait(struct inode *inode) |
1977 | { | 1976 | { |
1978 | struct ceph_inode_info *ci = ceph_inode(inode); | 1977 | struct ceph_inode_info *ci = ceph_inode(inode); |
1979 | struct list_head *head = &ci->i_unsafe_dirops; | 1978 | struct ceph_mds_request *req1 = NULL, *req2 = NULL; |
1980 | struct ceph_mds_request *req; | 1979 | int ret, err = 0; |
1981 | u64 last_tid; | ||
1982 | int ret = 0; | ||
1983 | |||
1984 | if (!S_ISDIR(inode->i_mode)) | ||
1985 | return 0; | ||
1986 | 1980 | ||
1987 | spin_lock(&ci->i_unsafe_lock); | 1981 | spin_lock(&ci->i_unsafe_lock); |
1988 | if (list_empty(head)) | 1982 | if (S_ISDIR(inode->i_mode) && !list_empty(&ci->i_unsafe_dirops)) { |
1989 | goto out; | 1983 | req1 = list_last_entry(&ci->i_unsafe_dirops, |
1990 | 1984 | struct ceph_mds_request, | |
1991 | req = list_last_entry(head, struct ceph_mds_request, | 1985 | r_unsafe_dir_item); |
1992 | r_unsafe_dir_item); | 1986 | ceph_mdsc_get_request(req1); |
1993 | last_tid = req->r_tid; | 1987 | } |
1994 | 1988 | if (!list_empty(&ci->i_unsafe_iops)) { | |
1995 | do { | 1989 | req2 = list_last_entry(&ci->i_unsafe_iops, |
1996 | ceph_mdsc_get_request(req); | 1990 | struct ceph_mds_request, |
1997 | spin_unlock(&ci->i_unsafe_lock); | 1991 | r_unsafe_target_item); |
1992 | ceph_mdsc_get_request(req2); | ||
1993 | } | ||
1994 | spin_unlock(&ci->i_unsafe_lock); | ||
1998 | 1995 | ||
1999 | dout("unsafe_dirop_wait %p wait on tid %llu (until %llu)\n", | 1996 | dout("unsafe_requeset_wait %p wait on tid %llu %llu\n", |
2000 | inode, req->r_tid, last_tid); | 1997 | inode, req1 ? req1->r_tid : 0ULL, req2 ? req2->r_tid : 0ULL); |
2001 | ret = !wait_for_completion_timeout(&req->r_safe_completion, | 1998 | if (req1) { |
2002 | ceph_timeout_jiffies(req->r_timeout)); | 1999 | ret = !wait_for_completion_timeout(&req1->r_safe_completion, |
2000 | ceph_timeout_jiffies(req1->r_timeout)); | ||
2003 | if (ret) | 2001 | if (ret) |
2004 | ret = -EIO; /* timed out */ | 2002 | err = -EIO; |
2005 | 2003 | ceph_mdsc_put_request(req1); | |
2006 | ceph_mdsc_put_request(req); | 2004 | } |
2007 | 2005 | if (req2) { | |
2008 | spin_lock(&ci->i_unsafe_lock); | 2006 | ret = !wait_for_completion_timeout(&req2->r_safe_completion, |
2009 | if (ret || list_empty(head)) | 2007 | ceph_timeout_jiffies(req2->r_timeout)); |
2010 | break; | 2008 | if (ret) |
2011 | req = list_first_entry(head, struct ceph_mds_request, | 2009 | err = -EIO; |
2012 | r_unsafe_dir_item); | 2010 | ceph_mdsc_put_request(req2); |
2013 | } while (req->r_tid < last_tid); | 2011 | } |
2014 | out: | 2012 | return err; |
2015 | spin_unlock(&ci->i_unsafe_lock); | ||
2016 | return ret; | ||
2017 | } | 2013 | } |
2018 | 2014 | ||
2019 | int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync) | 2015 | int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
@@ -2039,7 +2035,7 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
2039 | dirty = try_flush_caps(inode, &flush_tid); | 2035 | dirty = try_flush_caps(inode, &flush_tid); |
2040 | dout("fsync dirty caps are %s\n", ceph_cap_string(dirty)); | 2036 | dout("fsync dirty caps are %s\n", ceph_cap_string(dirty)); |
2041 | 2037 | ||
2042 | ret = unsafe_dirop_wait(inode); | 2038 | ret = unsafe_request_wait(inode); |
2043 | 2039 | ||
2044 | /* | 2040 | /* |
2045 | * only wait on non-file metadata writeback (the mds | 2041 | * only wait on non-file metadata writeback (the mds |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 0c62868b5c56..3c68e6aee2f0 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -34,6 +34,74 @@ | |||
34 | * need to wait for MDS acknowledgement. | 34 | * need to wait for MDS acknowledgement. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | /* | ||
38 | * Calculate the length sum of direct io vectors that can | ||
39 | * be combined into one page vector. | ||
40 | */ | ||
41 | static size_t dio_get_pagev_size(const struct iov_iter *it) | ||
42 | { | ||
43 | const struct iovec *iov = it->iov; | ||
44 | const struct iovec *iovend = iov + it->nr_segs; | ||
45 | size_t size; | ||
46 | |||
47 | size = iov->iov_len - it->iov_offset; | ||
48 | /* | ||
49 | * An iov can be page vectored when both the current tail | ||
50 | * and the next base are page aligned. | ||
51 | */ | ||
52 | while (PAGE_ALIGNED((iov->iov_base + iov->iov_len)) && | ||
53 | (++iov < iovend && PAGE_ALIGNED((iov->iov_base)))) { | ||
54 | size += iov->iov_len; | ||
55 | } | ||
56 | dout("dio_get_pagevlen len = %zu\n", size); | ||
57 | return size; | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * Allocate a page vector based on (@it, @nbytes). | ||
62 | * The return value is the tuple describing a page vector, | ||
63 | * that is (@pages, @page_align, @num_pages). | ||
64 | */ | ||
65 | static struct page ** | ||
66 | dio_get_pages_alloc(const struct iov_iter *it, size_t nbytes, | ||
67 | size_t *page_align, int *num_pages) | ||
68 | { | ||
69 | struct iov_iter tmp_it = *it; | ||
70 | size_t align; | ||
71 | struct page **pages; | ||
72 | int ret = 0, idx, npages; | ||
73 | |||
74 | align = (unsigned long)(it->iov->iov_base + it->iov_offset) & | ||
75 | (PAGE_SIZE - 1); | ||
76 | npages = calc_pages_for(align, nbytes); | ||
77 | pages = kmalloc(sizeof(*pages) * npages, GFP_KERNEL); | ||
78 | if (!pages) { | ||
79 | pages = vmalloc(sizeof(*pages) * npages); | ||
80 | if (!pages) | ||
81 | return ERR_PTR(-ENOMEM); | ||
82 | } | ||
83 | |||
84 | for (idx = 0; idx < npages; ) { | ||
85 | size_t start; | ||
86 | ret = iov_iter_get_pages(&tmp_it, pages + idx, nbytes, | ||
87 | npages - idx, &start); | ||
88 | if (ret < 0) | ||
89 | goto fail; | ||
90 | |||
91 | iov_iter_advance(&tmp_it, ret); | ||
92 | nbytes -= ret; | ||
93 | idx += (ret + start + PAGE_SIZE - 1) / PAGE_SIZE; | ||
94 | } | ||
95 | |||
96 | BUG_ON(nbytes != 0); | ||
97 | *num_pages = npages; | ||
98 | *page_align = align; | ||
99 | dout("dio_get_pages_alloc: got %d pages align %zu\n", npages, align); | ||
100 | return pages; | ||
101 | fail: | ||
102 | ceph_put_page_vector(pages, idx, false); | ||
103 | return ERR_PTR(ret); | ||
104 | } | ||
37 | 105 | ||
38 | /* | 106 | /* |
39 | * Prepare an open request. Preallocate ceph_cap to avoid an | 107 | * Prepare an open request. Preallocate ceph_cap to avoid an |
@@ -458,11 +526,10 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i, | |||
458 | size_t start; | 526 | size_t start; |
459 | ssize_t n; | 527 | ssize_t n; |
460 | 528 | ||
461 | n = iov_iter_get_pages_alloc(i, &pages, INT_MAX, &start); | 529 | n = dio_get_pagev_size(i); |
462 | if (n < 0) | 530 | pages = dio_get_pages_alloc(i, n, &start, &num_pages); |
463 | return n; | 531 | if (IS_ERR(pages)) |
464 | 532 | return PTR_ERR(pages); | |
465 | num_pages = (n + start + PAGE_SIZE - 1) / PAGE_SIZE; | ||
466 | 533 | ||
467 | ret = striped_read(inode, off, n, | 534 | ret = striped_read(inode, off, n, |
468 | pages, num_pages, checkeof, | 535 | pages, num_pages, checkeof, |
@@ -592,7 +659,7 @@ ceph_sync_direct_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos, | |||
592 | CEPH_OSD_FLAG_WRITE; | 659 | CEPH_OSD_FLAG_WRITE; |
593 | 660 | ||
594 | while (iov_iter_count(from) > 0) { | 661 | while (iov_iter_count(from) > 0) { |
595 | u64 len = iov_iter_single_seg_count(from); | 662 | u64 len = dio_get_pagev_size(from); |
596 | size_t start; | 663 | size_t start; |
597 | ssize_t n; | 664 | ssize_t n; |
598 | 665 | ||
@@ -611,14 +678,14 @@ ceph_sync_direct_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos, | |||
611 | 678 | ||
612 | osd_req_op_init(req, 1, CEPH_OSD_OP_STARTSYNC, 0); | 679 | osd_req_op_init(req, 1, CEPH_OSD_OP_STARTSYNC, 0); |
613 | 680 | ||
614 | n = iov_iter_get_pages_alloc(from, &pages, len, &start); | 681 | n = len; |
615 | if (unlikely(n < 0)) { | 682 | pages = dio_get_pages_alloc(from, len, &start, &num_pages); |
616 | ret = n; | 683 | if (IS_ERR(pages)) { |
617 | ceph_osdc_put_request(req); | 684 | ceph_osdc_put_request(req); |
685 | ret = PTR_ERR(pages); | ||
618 | break; | 686 | break; |
619 | } | 687 | } |
620 | 688 | ||
621 | num_pages = (n + start + PAGE_SIZE - 1) / PAGE_SIZE; | ||
622 | /* | 689 | /* |
623 | * throw out any page cache pages in this range. this | 690 | * throw out any page cache pages in this range. this |
624 | * may block. | 691 | * may block. |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 96d2bd829902..498dcfa2dcdb 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -452,6 +452,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb) | |||
452 | 452 | ||
453 | INIT_LIST_HEAD(&ci->i_unsafe_writes); | 453 | INIT_LIST_HEAD(&ci->i_unsafe_writes); |
454 | INIT_LIST_HEAD(&ci->i_unsafe_dirops); | 454 | INIT_LIST_HEAD(&ci->i_unsafe_dirops); |
455 | INIT_LIST_HEAD(&ci->i_unsafe_iops); | ||
455 | spin_lock_init(&ci->i_unsafe_lock); | 456 | spin_lock_init(&ci->i_unsafe_lock); |
456 | 457 | ||
457 | ci->i_snap_realm = NULL; | 458 | ci->i_snap_realm = NULL; |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 51cb02da75d9..e7b130a637f9 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -633,13 +633,8 @@ static void __register_request(struct ceph_mds_client *mdsc, | |||
633 | mdsc->oldest_tid = req->r_tid; | 633 | mdsc->oldest_tid = req->r_tid; |
634 | 634 | ||
635 | if (dir) { | 635 | if (dir) { |
636 | struct ceph_inode_info *ci = ceph_inode(dir); | ||
637 | |||
638 | ihold(dir); | 636 | ihold(dir); |
639 | spin_lock(&ci->i_unsafe_lock); | ||
640 | req->r_unsafe_dir = dir; | 637 | req->r_unsafe_dir = dir; |
641 | list_add_tail(&req->r_unsafe_dir_item, &ci->i_unsafe_dirops); | ||
642 | spin_unlock(&ci->i_unsafe_lock); | ||
643 | } | 638 | } |
644 | } | 639 | } |
645 | 640 | ||
@@ -665,13 +660,20 @@ static void __unregister_request(struct ceph_mds_client *mdsc, | |||
665 | rb_erase(&req->r_node, &mdsc->request_tree); | 660 | rb_erase(&req->r_node, &mdsc->request_tree); |
666 | RB_CLEAR_NODE(&req->r_node); | 661 | RB_CLEAR_NODE(&req->r_node); |
667 | 662 | ||
668 | if (req->r_unsafe_dir) { | 663 | if (req->r_unsafe_dir && req->r_got_unsafe) { |
669 | struct ceph_inode_info *ci = ceph_inode(req->r_unsafe_dir); | 664 | struct ceph_inode_info *ci = ceph_inode(req->r_unsafe_dir); |
670 | |||
671 | spin_lock(&ci->i_unsafe_lock); | 665 | spin_lock(&ci->i_unsafe_lock); |
672 | list_del_init(&req->r_unsafe_dir_item); | 666 | list_del_init(&req->r_unsafe_dir_item); |
673 | spin_unlock(&ci->i_unsafe_lock); | 667 | spin_unlock(&ci->i_unsafe_lock); |
668 | } | ||
669 | if (req->r_target_inode && req->r_got_unsafe) { | ||
670 | struct ceph_inode_info *ci = ceph_inode(req->r_target_inode); | ||
671 | spin_lock(&ci->i_unsafe_lock); | ||
672 | list_del_init(&req->r_unsafe_target_item); | ||
673 | spin_unlock(&ci->i_unsafe_lock); | ||
674 | } | ||
674 | 675 | ||
676 | if (req->r_unsafe_dir) { | ||
675 | iput(req->r_unsafe_dir); | 677 | iput(req->r_unsafe_dir); |
676 | req->r_unsafe_dir = NULL; | 678 | req->r_unsafe_dir = NULL; |
677 | } | 679 | } |
@@ -1430,6 +1432,13 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) | |||
1430 | if ((used | wanted) & CEPH_CAP_ANY_WR) | 1432 | if ((used | wanted) & CEPH_CAP_ANY_WR) |
1431 | goto out; | 1433 | goto out; |
1432 | } | 1434 | } |
1435 | /* The inode has cached pages, but it's no longer used. | ||
1436 | * we can safely drop it */ | ||
1437 | if (wanted == 0 && used == CEPH_CAP_FILE_CACHE && | ||
1438 | !(oissued & CEPH_CAP_FILE_CACHE)) { | ||
1439 | used = 0; | ||
1440 | oissued = 0; | ||
1441 | } | ||
1433 | if ((used | wanted) & ~oissued & mine) | 1442 | if ((used | wanted) & ~oissued & mine) |
1434 | goto out; /* we need these caps */ | 1443 | goto out; /* we need these caps */ |
1435 | 1444 | ||
@@ -1438,7 +1447,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) | |||
1438 | /* we aren't the only cap.. just remove us */ | 1447 | /* we aren't the only cap.. just remove us */ |
1439 | __ceph_remove_cap(cap, true); | 1448 | __ceph_remove_cap(cap, true); |
1440 | } else { | 1449 | } else { |
1441 | /* try to drop referring dentries */ | 1450 | /* try dropping referring dentries */ |
1442 | spin_unlock(&ci->i_ceph_lock); | 1451 | spin_unlock(&ci->i_ceph_lock); |
1443 | d_prune_aliases(inode); | 1452 | d_prune_aliases(inode); |
1444 | dout("trim_caps_cb %p cap %p pruned, count now %d\n", | 1453 | dout("trim_caps_cb %p cap %p pruned, count now %d\n", |
@@ -1704,6 +1713,7 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode) | |||
1704 | req->r_started = jiffies; | 1713 | req->r_started = jiffies; |
1705 | req->r_resend_mds = -1; | 1714 | req->r_resend_mds = -1; |
1706 | INIT_LIST_HEAD(&req->r_unsafe_dir_item); | 1715 | INIT_LIST_HEAD(&req->r_unsafe_dir_item); |
1716 | INIT_LIST_HEAD(&req->r_unsafe_target_item); | ||
1707 | req->r_fmode = -1; | 1717 | req->r_fmode = -1; |
1708 | kref_init(&req->r_kref); | 1718 | kref_init(&req->r_kref); |
1709 | INIT_LIST_HEAD(&req->r_wait); | 1719 | INIT_LIST_HEAD(&req->r_wait); |
@@ -1935,7 +1945,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, | |||
1935 | 1945 | ||
1936 | len = sizeof(*head) + | 1946 | len = sizeof(*head) + |
1937 | pathlen1 + pathlen2 + 2*(1 + sizeof(u32) + sizeof(u64)) + | 1947 | pathlen1 + pathlen2 + 2*(1 + sizeof(u32) + sizeof(u64)) + |
1938 | sizeof(struct timespec); | 1948 | sizeof(struct ceph_timespec); |
1939 | 1949 | ||
1940 | /* calculate (max) length for cap releases */ | 1950 | /* calculate (max) length for cap releases */ |
1941 | len += sizeof(struct ceph_mds_request_release) * | 1951 | len += sizeof(struct ceph_mds_request_release) * |
@@ -2477,6 +2487,14 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2477 | } else { | 2487 | } else { |
2478 | req->r_got_unsafe = true; | 2488 | req->r_got_unsafe = true; |
2479 | list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe); | 2489 | list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe); |
2490 | if (req->r_unsafe_dir) { | ||
2491 | struct ceph_inode_info *ci = | ||
2492 | ceph_inode(req->r_unsafe_dir); | ||
2493 | spin_lock(&ci->i_unsafe_lock); | ||
2494 | list_add_tail(&req->r_unsafe_dir_item, | ||
2495 | &ci->i_unsafe_dirops); | ||
2496 | spin_unlock(&ci->i_unsafe_lock); | ||
2497 | } | ||
2480 | } | 2498 | } |
2481 | 2499 | ||
2482 | dout("handle_reply tid %lld result %d\n", tid, result); | 2500 | dout("handle_reply tid %lld result %d\n", tid, result); |
@@ -2518,6 +2536,13 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
2518 | up_read(&mdsc->snap_rwsem); | 2536 | up_read(&mdsc->snap_rwsem); |
2519 | if (realm) | 2537 | if (realm) |
2520 | ceph_put_snap_realm(mdsc, realm); | 2538 | ceph_put_snap_realm(mdsc, realm); |
2539 | |||
2540 | if (err == 0 && req->r_got_unsafe && req->r_target_inode) { | ||
2541 | struct ceph_inode_info *ci = ceph_inode(req->r_target_inode); | ||
2542 | spin_lock(&ci->i_unsafe_lock); | ||
2543 | list_add_tail(&req->r_unsafe_target_item, &ci->i_unsafe_iops); | ||
2544 | spin_unlock(&ci->i_unsafe_lock); | ||
2545 | } | ||
2521 | out_err: | 2546 | out_err: |
2522 | mutex_lock(&mdsc->mutex); | 2547 | mutex_lock(&mdsc->mutex); |
2523 | if (!req->r_aborted) { | 2548 | if (!req->r_aborted) { |
@@ -3917,17 +3942,19 @@ static struct ceph_msg *mds_alloc_msg(struct ceph_connection *con, | |||
3917 | return msg; | 3942 | return msg; |
3918 | } | 3943 | } |
3919 | 3944 | ||
3920 | static int sign_message(struct ceph_connection *con, struct ceph_msg *msg) | 3945 | static int mds_sign_message(struct ceph_msg *msg) |
3921 | { | 3946 | { |
3922 | struct ceph_mds_session *s = con->private; | 3947 | struct ceph_mds_session *s = msg->con->private; |
3923 | struct ceph_auth_handshake *auth = &s->s_auth; | 3948 | struct ceph_auth_handshake *auth = &s->s_auth; |
3949 | |||
3924 | return ceph_auth_sign_message(auth, msg); | 3950 | return ceph_auth_sign_message(auth, msg); |
3925 | } | 3951 | } |
3926 | 3952 | ||
3927 | static int check_message_signature(struct ceph_connection *con, struct ceph_msg *msg) | 3953 | static int mds_check_message_signature(struct ceph_msg *msg) |
3928 | { | 3954 | { |
3929 | struct ceph_mds_session *s = con->private; | 3955 | struct ceph_mds_session *s = msg->con->private; |
3930 | struct ceph_auth_handshake *auth = &s->s_auth; | 3956 | struct ceph_auth_handshake *auth = &s->s_auth; |
3957 | |||
3931 | return ceph_auth_check_message_signature(auth, msg); | 3958 | return ceph_auth_check_message_signature(auth, msg); |
3932 | } | 3959 | } |
3933 | 3960 | ||
@@ -3940,8 +3967,8 @@ static const struct ceph_connection_operations mds_con_ops = { | |||
3940 | .invalidate_authorizer = invalidate_authorizer, | 3967 | .invalidate_authorizer = invalidate_authorizer, |
3941 | .peer_reset = peer_reset, | 3968 | .peer_reset = peer_reset, |
3942 | .alloc_msg = mds_alloc_msg, | 3969 | .alloc_msg = mds_alloc_msg, |
3943 | .sign_message = sign_message, | 3970 | .sign_message = mds_sign_message, |
3944 | .check_message_signature = check_message_signature, | 3971 | .check_message_signature = mds_check_message_signature, |
3945 | }; | 3972 | }; |
3946 | 3973 | ||
3947 | /* eof */ | 3974 | /* eof */ |
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index f575eafe2261..ccf11ef0ca87 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h | |||
@@ -236,6 +236,9 @@ struct ceph_mds_request { | |||
236 | struct inode *r_unsafe_dir; | 236 | struct inode *r_unsafe_dir; |
237 | struct list_head r_unsafe_dir_item; | 237 | struct list_head r_unsafe_dir_item; |
238 | 238 | ||
239 | /* unsafe requests that modify the target inode */ | ||
240 | struct list_head r_unsafe_target_item; | ||
241 | |||
239 | struct ceph_mds_session *r_session; | 242 | struct ceph_mds_session *r_session; |
240 | 243 | ||
241 | int r_attempts; /* resend attempts */ | 244 | int r_attempts; /* resend attempts */ |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 2f2460d23a06..75b7d125ce66 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -342,6 +342,7 @@ struct ceph_inode_info { | |||
342 | 342 | ||
343 | struct list_head i_unsafe_writes; /* uncommitted sync writes */ | 343 | struct list_head i_unsafe_writes; /* uncommitted sync writes */ |
344 | struct list_head i_unsafe_dirops; /* uncommitted mds dir ops */ | 344 | struct list_head i_unsafe_dirops; /* uncommitted mds dir ops */ |
345 | struct list_head i_unsafe_iops; /* uncommitted mds inode ops */ | ||
345 | spinlock_t i_unsafe_lock; | 346 | spinlock_t i_unsafe_lock; |
346 | 347 | ||
347 | struct ceph_snap_realm *i_snap_realm; /* snap realm (if caps) */ | 348 | struct ceph_snap_realm *i_snap_realm; /* snap realm (if caps) */ |