History

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

Pull Ceph changes from Sage Weil: "On the RBD side, there is a conversion to blk-mq from Christoph, several long-standing bug fixes from Ilya, and some cleanup from Rickard Strandqvist. On the CephFS side there is a long list of fixes from Zheng, including improved session handling, a few IO path fixes, some dcache management correctness fixes, and several blocking while !TASK_RUNNING fixes. The core code gets a few cleanups and Chaitanya has added support for TCP_NODELAY (which has been used on the server side for ages but we somehow missed on the kernel client). There is also an update to MAINTAINERS to fix up some email addresses and reflect that Ilya and Zheng are doing most of the maintenance for RBD and CephFS these days. Do not be surprised to see a pull request come from one of them in the future if I am unavailable for some reason" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: (27 commits) MAINTAINERS: update Ceph and RBD maintainers libceph: kfree() in put_osd() shouldn't depend on authorizer libceph: fix double __remove_osd() problem rbd: convert to blk-mq ceph: return error for traceless reply race ceph: fix dentry leaks ceph: re-send requests when MDS enters reconnecting stage ceph: show nocephx_require_signatures and notcp_nodelay options libceph: tcp_nodelay support rbd: do not treat standalone as flatten ceph: fix atomic_open snapdir ceph: properly mark empty directory as complete client: include kernel version in client metadata ceph: provide seperate {inode,file}_operations for snapdir ceph: fix request time stamp encoding ceph: fix reading inline data when i_size > PAGE_SIZE ceph: avoid block operation when !TASK_RUNNING (ceph_mdsc_close_sessions) ceph: avoid block operation when !TASK_RUNNING (ceph_get_caps) ceph: avoid block operation when !TASK_RUNNING (ceph_mdsc_sync) rbd: fix error paths in rbd_dev_refresh() ...

Linus Torvalds committed 11 years ago

Commit 4533f6e2 parents 89d3fa4 0f5417c23 files · +444 −488Browse files

Unified · Split

23 files
  1. MAINTAINERS +4 −3
  2. drivers/block/rbd.c +83 −110
  3. fs/ceph/acl.c +0 −14
  4. fs/ceph/addr.c +12 −7
  5. fs/ceph/caps.c +74 −53
  6. fs/ceph/dir.c +25 −8
  7. fs/ceph/file.c +22 −15
  8. fs/ceph/inode.c +22 −19
  9. fs/ceph/mds_client.c +93 −34
  10. fs/ceph/mds_client.h +2 −0
  11. fs/ceph/snap.c +38 −16
  12. fs/ceph/super.c +4 −0
  13. fs/ceph/super.h +4 −1
  14. include/linux/ceph/ceph_fs.h +1 −36
  15. include/linux/ceph/libceph.h +2 −1
  16. include/linux/ceph/messenger.h +3 −1
  17. include/linux/ceph/mon_client.h +1 −8
  18. net/ceph/ceph_common.c +15 −1
  19. net/ceph/ceph_strings.c +0 −14
  20. net/ceph/debugfs.c +0 −2
  21. net/ceph/messenger.c +13 −1
  22. net/ceph/mon_client.c +5 −134
  23. net/ceph/osd_client.c +21 −10
MAINTAINERS+4−3
@@ -2433,7 +2433,8 @@ F: arch/powerpc/oprofile/*cell* · 2432 unmodified lines
24332433 F: arch/powerpc/platforms/cell/
24342434
24352435 CEPH DISTRIBUTED FILE SYSTEM CLIENT
2436−M: Sage Weil <sage@inktank.com>
2436+M: Yan, Zheng <zyan@redhat.com>
2437+M: Sage Weil <sage@redhat.com>
24372438 L: ceph-devel@vger.kernel.org
24382439 W: http://ceph.com/
24392440 T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
@@ -7998,8 +7999,8 @@ S: Supported · 5558 unmodified lines
79987999 F: drivers/net/wireless/ath/wcn36xx/
79998000
80008001 RADOS BLOCK DEVICE (RBD)
8001−M: Yehuda Sadeh <yehuda@inktank.com>
8002−M: Sage Weil <sage@inktank.com>
8002+M: Ilya Dryomov <idryomov@gmail.com>
8003+M: Sage Weil <sage@redhat.com>
80038004 M: Alex Elder <elder@kernel.org>
80048005 M: ceph-devel@vger.kernel.org
80058006 W: http://ceph.com/
drivers/block/rbd.c+83−110
@@ -38,6 +38,7 @@ · 37 unmodified lines
3838 #include <linux/kernel.h>
3939 #include <linux/device.h>
4040 #include <linux/module.h>
41+#include <linux/blk-mq.h>
4142 #include <linux/fs.h>
4243 #include <linux/blkdev.h>
4344 #include <linux/slab.h>
@@ -340,9 +341,7 @@ struct rbd_device { · 296 unmodified lines
340341
341342 char name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */
342343
343− struct list_head rq_queue; /* incoming rq queue */
344344 spinlock_t lock; /* queue, flags, open_count */
345− struct work_struct rq_work;
346345
347346 struct rbd_image_header header;
348347 unsigned long flags; /* possibly lock protected */
@@ -360,6 +359,9 @@ struct rbd_device { · 11 unmodified lines
360359 atomic_t parent_ref;
361360 struct rbd_device *parent;
362361
362+ /* Block layer tags. */
363+ struct blk_mq_tag_set tag_set;
364+
363365 /* protects updating the header */
364366 struct rw_semaphore header_rwsem;
365367
@@ -1817,7 +1819,8 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, · 1451 unmodified lines
18171819
18181820 /*
18191821 * We support a 64-bit length, but ultimately it has to be
1820− * passed to blk_end_request(), which takes an unsigned int.
1822+ * passed to the block layer, which just supports a 32-bit
1823+ * length field.
18211824 */
18221825 obj_request->xferred = osd_req->r_reply_op_len[0];
18231826 rbd_assert(obj_request->xferred < (u64)UINT_MAX);
@@ -2275,7 +2278,10 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request) · 451 unmodified lines
22752278 more = obj_request->which < img_request->obj_request_count - 1;
22762279 } else {
22772280 rbd_assert(img_request->rq != NULL);
2278− more = blk_end_request(img_request->rq, result, xferred);
2281+
2282+ more = blk_update_request(img_request->rq, result, xferred);
2283+ if (!more)
2284+ __blk_mq_end_request(img_request->rq, result);
22792285 }
22802286
22812287 return more;
@@ -3304,8 +3310,10 @@ out: · 1022 unmodified lines
33043310 return ret;
33053311 }
33063312
3307−static void rbd_handle_request(struct rbd_device *rbd_dev, struct request *rq)
3313+static void rbd_queue_workfn(struct work_struct *work)
33083314 {
3315+ struct request *rq = blk_mq_rq_from_pdu(work);
3316+ struct rbd_device *rbd_dev = rq->q->queuedata;
33093317 struct rbd_img_request *img_request;
33103318 struct ceph_snap_context *snapc = NULL;
33113319 u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;
@@ -3314,6 +3322,13 @@ static void rbd_handle_request(struct rbd_device *rbd_dev, struct request *rq) · 2 unmodified lines
33143322 u64 mapping_size;
33153323 int result;
33163324
3325+ if (rq->cmd_type != REQ_TYPE_FS) {
3326+ dout("%s: non-fs request type %d\n", __func__,
3327+ (int) rq->cmd_type);
3328+ result = -EIO;
3329+ goto err;
3330+ }
3331+
33173332 if (rq->cmd_flags & REQ_DISCARD)
33183333 op_type = OBJ_OP_DISCARD;
33193334 else if (rq->cmd_flags & REQ_WRITE)
@@ -3359,6 +3374,8 @@ static void rbd_handle_request(struct rbd_device *rbd_dev, struct request *rq) · 39 unmodified lines
33593374 goto err_rq; /* Shouldn't happen */
33603375 }
33613376
3377+ blk_mq_start_request(rq);
3378+
33623379 down_read(&rbd_dev->header_rwsem);
33633380 mapping_size = rbd_dev->mapping.size;
33643381 if (op_type != OBJ_OP_READ) {
@@ -3404,53 +3421,18 @@ err_rq: · 39 unmodified lines
34043421 rbd_warn(rbd_dev, "%s %llx at %llx result %d",
34053422 obj_op_name(op_type), length, offset, result);
34063423 ceph_put_snap_context(snapc);
3407− blk_end_request_all(rq, result);
3424+err:
3425+ blk_mq_end_request(rq, result);
34083426 }
34093427
3410−static void rbd_request_workfn(struct work_struct *work)
3428+static int rbd_queue_rq(struct blk_mq_hw_ctx *hctx,
3429+ const struct blk_mq_queue_data *bd)
34113430 {
3412− struct rbd_device *rbd_dev =
3413− container_of(work, struct rbd_device, rq_work);
3414− struct request *rq, *next;
3415− LIST_HEAD(requests);
3416−
3417− spin_lock_irq(&rbd_dev->lock); /* rq->q->queue_lock */
3418− list_splice_init(&rbd_dev->rq_queue, &requests);
3419− spin_unlock_irq(&rbd_dev->lock);
3431+ struct request *rq = bd->rq;
3432+ struct work_struct *work = blk_mq_rq_to_pdu(rq);
34203433
3421− list_for_each_entry_safe(rq, next, &requests, queuelist) {
3422− list_del_init(&rq->queuelist);
3423− rbd_handle_request(rbd_dev, rq);
3424− }
3425−}
3426−
3427−/*
3428− * Called with q->queue_lock held and interrupts disabled, possibly on
3429− * the way to schedule(). Do not sleep here!
3430− */
3431−static void rbd_request_fn(struct request_queue *q)
3432−{
3433− struct rbd_device *rbd_dev = q->queuedata;
3434− struct request *rq;
3435− int queued = 0;
3436−
3437− rbd_assert(rbd_dev);
3438−
3439− while ((rq = blk_fetch_request(q))) {
3440− /* Ignore any non-FS requests that filter through. */
3441− if (rq->cmd_type != REQ_TYPE_FS) {
3442− dout("%s: non-fs request type %d\n", __func__,
3443− (int) rq->cmd_type);
3444− __blk_end_request_all(rq, 0);
3445− continue;
3446− }
3447−
3448− list_add_tail(&rq->queuelist, &rbd_dev->rq_queue);
3449− queued++;
3450− }
3451−
3452− if (queued)
3453− queue_work(rbd_wq, &rbd_dev->rq_work);
3434+ queue_work(rbd_wq, work);
3435+ return BLK_MQ_RQ_QUEUE_OK;
34543436 }
34553437
34563438 /*
@@ -3511,6 +3493,7 @@ static void rbd_free_disk(struct rbd_device *rbd_dev) · 54 unmodified lines
35113493 del_gendisk(disk);
35123494 if (disk->queue)
35133495 blk_cleanup_queue(disk->queue);
3496+ blk_mq_free_tag_set(&rbd_dev->tag_set);
35143497 }
35153498 put_disk(disk);
35163499 }
@@ -3694,7 +3677,7 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev) · 177 unmodified lines
36943677
36953678 ret = rbd_dev_header_info(rbd_dev);
36963679 if (ret)
3697− return ret;
3680+ goto out;
36983681
36993682 /*
37003683 * If there is a parent, see if it has disappeared due to the
@@ -3703,30 +3686,46 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev) · 2 unmodified lines
37033686 if (rbd_dev->parent) {
37043687 ret = rbd_dev_v2_parent_info(rbd_dev);
37053688 if (ret)
3706− return ret;
3689+ goto out;
37073690 }
37083691
37093692 if (rbd_dev->spec->snap_id == CEPH_NOSNAP) {
3710− if (rbd_dev->mapping.size != rbd_dev->header.image_size)
3711− rbd_dev->mapping.size = rbd_dev->header.image_size;
3693+ rbd_dev->mapping.size = rbd_dev->header.image_size;
37123694 } else {
37133695 /* validate mapped snapshot's EXISTS flag */
37143696 rbd_exists_validate(rbd_dev);
37153697 }
37163698
3699+out:
37173700 up_write(&rbd_dev->header_rwsem);
3718−
3719− if (mapping_size != rbd_dev->mapping.size)
3701+ if (!ret && mapping_size != rbd_dev->mapping.size)
37203702 rbd_dev_update_size(rbd_dev);
37213703
3704+ return ret;
3705+}
3706+
3707+static int rbd_init_request(void *data, struct request *rq,
3708+ unsigned int hctx_idx, unsigned int request_idx,
3709+ unsigned int numa_node)
3710+{
3711+ struct work_struct *work = blk_mq_rq_to_pdu(rq);
3712+
3713+ INIT_WORK(work, rbd_queue_workfn);
37223714 return 0;
37233715 }
37243716
3717+static struct blk_mq_ops rbd_mq_ops = {
3718+ .queue_rq = rbd_queue_rq,
3719+ .map_queue = blk_mq_map_queue,
3720+ .init_request = rbd_init_request,
3721+};
3722+
37253723 static int rbd_init_disk(struct rbd_device *rbd_dev)
37263724 {
37273725 struct gendisk *disk;
37283726 struct request_queue *q;
37293727 u64 segment_size;
3728+ int err;
37303729
37313730 /* create gendisk info */
37323731 disk = alloc_disk(single_major ?
@@ -3744,10 +3743,25 @@ static int rbd_init_disk(struct rbd_device *rbd_dev) · 11 unmodified lines
37443743 disk->fops = &rbd_bd_ops;
37453744 disk->private_data = rbd_dev;
37463745
3747− q = blk_init_queue(rbd_request_fn, &rbd_dev->lock);
3748− if (!q)
3746+ memset(&rbd_dev->tag_set, 0, sizeof(rbd_dev->tag_set));
3747+ rbd_dev->tag_set.ops = &rbd_mq_ops;
3748+ rbd_dev->tag_set.queue_depth = BLKDEV_MAX_RQ;
3749+ rbd_dev->tag_set.numa_node = NUMA_NO_NODE;
3750+ rbd_dev->tag_set.flags =
3751+ BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE;
3752+ rbd_dev->tag_set.nr_hw_queues = 1;
3753+ rbd_dev->tag_set.cmd_size = sizeof(struct work_struct);
3754+
3755+ err = blk_mq_alloc_tag_set(&rbd_dev->tag_set);
3756+ if (err)
37493757 goto out_disk;
37503758
3759+ q = blk_mq_init_queue(&rbd_dev->tag_set);
3760+ if (IS_ERR(q)) {
3761+ err = PTR_ERR(q);
3762+ goto out_tag_set;
3763+ }
3764+
37513765 /* We use the default size, but let's be explicit about it. */
37523766 blk_queue_physical_block_size(q, SECTOR_SIZE);
37533767
@@ -3773,10 +3787,11 @@ static int rbd_init_disk(struct rbd_device *rbd_dev) · 19 unmodified lines
37733787 rbd_dev->disk = disk;
37743788
37753789 return 0;
3790+out_tag_set:
3791+ blk_mq_free_tag_set(&rbd_dev->tag_set);
37763792 out_disk:
37773793 put_disk(disk);
3778−
3779− return -ENOMEM;
3794+ return err;
37803795 }
37813796
37823797 /*
@@ -4033,8 +4048,6 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc, · 250 unmodified lines
40334048 return NULL;
40344049
40354050 spin_lock_init(&rbd_dev->lock);
4036− INIT_LIST_HEAD(&rbd_dev->rq_queue);
4037− INIT_WORK(&rbd_dev->rq_work, rbd_request_workfn);
40384051 rbd_dev->flags = 0;
40394052 atomic_set(&rbd_dev->parent_ref, 0);
40404053 INIT_LIST_HEAD(&rbd_dev->node);
@@ -4274,32 +4287,22 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) · 233 unmodified lines
42744287 }
42754288
42764289 /*
4277− * We always update the parent overlap. If it's zero we
4278− * treat it specially.
4290+ * We always update the parent overlap. If it's zero we issue
4291+ * a warning, as we will proceed as if there was no parent.
42794292 */
4280− rbd_dev->parent_overlap = overlap;
42814293 if (!overlap) {
4282−
4283− /* A null parent_spec indicates it's the initial probe */
4284−
42854294 if (parent_spec) {
4286− /*
4287− * The overlap has become zero, so the clone
4288− * must have been resized down to 0 at some
4289− * point. Treat this the same as a flatten.
4290− */
4291− rbd_dev_parent_put(rbd_dev);
4292− pr_info("%s: clone image now standalone\n",
4293− rbd_dev->disk->disk_name);
4295+ /* refresh, careful to warn just once */
4296+ if (rbd_dev->parent_overlap)
4297+ rbd_warn(rbd_dev,
4298+ "clone now standalone (overlap became 0)");
42944299 } else {
4295− /*
4296− * For the initial probe, if we find the
4297− * overlap is zero we just pretend there was
4298− * no parent image.
4299− */
4300− rbd_warn(rbd_dev, "ignoring parent with overlap 0");
4300+ /* initial probe */
4301+ rbd_warn(rbd_dev, "clone is standalone (overlap 0)");
43014302 }
43024303 }
4304+ rbd_dev->parent_overlap = overlap;
4305+
43034306 out:
43044307 ret = 0;
43054308 out_err:
@@ -4770,36 +4773,6 @@ static inline size_t next_token(const char **buf) · 464 unmodified lines
47704773 return strcspn(*buf, spaces); /* Return token length */
47714774 }
47724775
4773−/*
4774− * Finds the next token in *buf, and if the provided token buffer is
4775− * big enough, copies the found token into it. The result, if
4776− * copied, is guaranteed to be terminated with '\0'. Note that *buf
4777− * must be terminated with '\0' on entry.
4778− *
4779− * Returns the length of the token found (not including the '\0').
4780− * Return value will be 0 if no token is found, and it will be >=
4781− * token_size if the token would not fit.
4782− *
4783− * The *buf pointer will be updated to point beyond the end of the
4784− * found token. Note that this occurs even if the token buffer is
4785− * too small to hold it.
4786− */
4787−static inline size_t copy_token(const char **buf,
4788− char *token,
4789− size_t token_size)
4790−{
4791− size_t len;
4792−
4793− len = next_token(buf);
4794− if (len < token_size) {
4795− memcpy(token, *buf, len);
4796− *(token + len) = '\0';
4797− }
4798− *buf += len;
4799−
4800− return len;
4801−}
4802−
48034776 /*
48044777 * Finds the next token in *buf, dynamically allocates a buffer big
48054778 * enough to hold a copy of it, and copies the token into the new
fs/ceph/acl.c+0−14
@@ -40,20 +40,6 @@ static inline void ceph_set_cached_acl(struct inode *inode, · 39 unmodified lines
4040 spin_unlock(&ci->i_ceph_lock);
4141 }
4242
43−static inline struct posix_acl *ceph_get_cached_acl(struct inode *inode,
44− int type)
45−{
46− struct ceph_inode_info *ci = ceph_inode(inode);
47− struct posix_acl *acl = ACL_NOT_CACHED;
48−
49− spin_lock(&ci->i_ceph_lock);
50− if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 0))
51− acl = get_cached_acl(inode, type);
52− spin_unlock(&ci->i_ceph_lock);
53−
54− return acl;
55−}
56−
5743 struct posix_acl *ceph_get_acl(struct inode *inode, int type)
5844 {
5945 int size;
fs/ceph/addr.c+12−7
@@ -196,17 +196,22 @@ static int readpage_nounlock(struct file *filp, struct page *page) · 195 unmodified lines
196196 u64 len = PAGE_CACHE_SIZE;
197197
198198 if (off >= i_size_read(inode)) {
199− zero_user_segment(page, err, PAGE_CACHE_SIZE);
199+ zero_user_segment(page, 0, PAGE_CACHE_SIZE);
200200 SetPageUptodate(page);
201201 return 0;
202202 }
203203
204− /*
205− * Uptodate inline data should have been added into page cache
206− * while getting Fcr caps.
207− */
208− if (ci->i_inline_version != CEPH_INLINE_NONE)
209− return -EINVAL;
204+ if (ci->i_inline_version != CEPH_INLINE_NONE) {
205+ /*
206+ * Uptodate inline data should have been added
207+ * into page cache while getting Fcr caps.
208+ */
209+ if (off == 0)
210+ return -EINVAL;
211+ zero_user_segment(page, 0, PAGE_CACHE_SIZE);
212+ SetPageUptodate(page);
213+ return 0;
214+ }
210215
211216 err = ceph_readpage_from_fscache(inode, page);
212217 if (err == 0)
fs/ceph/caps.c+74−53
@@ -577,7 +577,6 @@ void ceph_add_cap(struct inode *inode, · 576 unmodified lines
577577 struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc,
578578 realmino);
579579 if (realm) {
580− ceph_get_snap_realm(mdsc, realm);
581580 spin_lock(&realm->inodes_with_caps_lock);
582581 ci->i_snap_realm = realm;
583582 list_add(&ci->i_snap_realm_item,
@@ -1451,8 +1450,8 @@ static int __mark_caps_flushing(struct inode *inode, · 867 unmodified lines
14511450 spin_lock(&mdsc->cap_dirty_lock);
14521451 list_del_init(&ci->i_dirty_item);
14531452
1454− ci->i_cap_flush_seq = ++mdsc->cap_flush_seq;
14551453 if (list_empty(&ci->i_flushing_item)) {
1454+ ci->i_cap_flush_seq = ++mdsc->cap_flush_seq;
14561455 list_add_tail(&ci->i_flushing_item, &session->s_cap_flushing);
14571456 mdsc->num_cap_flushing++;
14581457 dout(" inode %p now flushing seq %lld\n", inode,
@@ -2073,17 +2072,16 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got) · 614 unmodified lines
20732072 * requested from the MDS.
20742073 */
20752074 static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want,
2076− loff_t endoff, int *got, struct page **pinned_page,
2077− int *check_max, int *err)
2075+ loff_t endoff, int *got, int *check_max, int *err)
20782076 {
20792077 struct inode *inode = &ci->vfs_inode;
20802078 int ret = 0;
2081− int have, implemented, _got = 0;
2079+ int have, implemented;
20822080 int file_wanted;
20832081
20842082 dout("get_cap_refs %p need %s want %s\n", inode,
20852083 ceph_cap_string(need), ceph_cap_string(want));
2086−again:
2084+
20872085 spin_lock(&ci->i_ceph_lock);
20882086
20892087 /* make sure file is actually open */
@@ -2138,50 +2136,34 @@ again: · 48 unmodified lines
21382136 inode, ceph_cap_string(have), ceph_cap_string(not),
21392137 ceph_cap_string(revoking));
21402138 if ((revoking & not) == 0) {
2141− _got = need | (have & want);
2142− __take_cap_refs(ci, _got);
2139+ *got = need | (have & want);
2140+ __take_cap_refs(ci, *got);
21432141 ret = 1;
21442142 }
21452143 } else {
2144+ int session_readonly = false;
2145+ if ((need & CEPH_CAP_FILE_WR) && ci->i_auth_cap) {
2146+ struct ceph_mds_session *s = ci->i_auth_cap->session;
2147+ spin_lock(&s->s_cap_lock);
2148+ session_readonly = s->s_readonly;
2149+ spin_unlock(&s->s_cap_lock);
2150+ }
2151+ if (session_readonly) {
2152+ dout("get_cap_refs %p needed %s but mds%d readonly\n",
2153+ inode, ceph_cap_string(need), ci->i_auth_cap->mds);
2154+ *err = -EROFS;
2155+ ret = 1;
2156+ goto out_unlock;
2157+ }
2158+
21462159 dout("get_cap_refs %p have %s needed %s\n", inode,
21472160 ceph_cap_string(have), ceph_cap_string(need));
21482161 }
21492162 out_unlock:
21502163 spin_unlock(&ci->i_ceph_lock);
21512164
2152− if (ci->i_inline_version != CEPH_INLINE_NONE &&
2153− (_got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
2154− i_size_read(inode) > 0) {
2155− int ret1;
2156− struct page *page = find_get_page(inode->i_mapping, 0);
2157− if (page) {
2158− if (PageUptodate(page)) {
2159− *pinned_page = page;
2160− goto out;
2161− }
2162− page_cache_release(page);
2163− }
2164− /*
2165− * drop cap refs first because getattr while holding
2166− * caps refs can cause deadlock.
2167− */
2168− ceph_put_cap_refs(ci, _got);
2169− _got = 0;
2170−
2171− /* getattr request will bring inline data into page cache */
2172− ret1 = __ceph_do_getattr(inode, NULL,
2173− CEPH_STAT_CAP_INLINE_DATA, true);
2174− if (ret1 >= 0) {
2175− ret = 0;
2176− goto again;
2177− }
2178− *err = ret1;
2179− ret = 1;
2180− }
2181−out:
21822165 dout("get_cap_refs %p ret %d got %s\n", inode,
2183− ret, ceph_cap_string(_got));
2184− *got = _got;
2166+ ret, ceph_cap_string(*got));
21852167 return ret;
21862168 }
21872169
@@ -2221,22 +2203,52 @@ static void check_max_size(struct inode *inode, loff_t endoff) · 33 unmodified lines
22212203 int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
22222204 loff_t endoff, int *got, struct page **pinned_page)
22232205 {
2224− int check_max, ret, err;
2206+ int _got, check_max, ret, err = 0;
22252207
22262208 retry:
22272209 if (endoff > 0)
22282210 check_max_size(&ci->vfs_inode, endoff);
2211+ _got = 0;
22292212 check_max = 0;
2230− err = 0;
22312213 ret = wait_event_interruptible(ci->i_cap_wq,
2232− try_get_cap_refs(ci, need, want, endoff,
2233− got, pinned_page,
2234− &check_max, &err));
2214+ try_get_cap_refs(ci, need, want, endoff,
2215+ &_got, &check_max, &err));
22352216 if (err)
22362217 ret = err;
2218+ if (ret < 0)
2219+ return ret;
2220+
22372221 if (check_max)
22382222 goto retry;
2239− return ret;
2223+
2224+ if (ci->i_inline_version != CEPH_INLINE_NONE &&
2225+ (_got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
2226+ i_size_read(&ci->vfs_inode) > 0) {
2227+ struct page *page = find_get_page(ci->vfs_inode.i_mapping, 0);
2228+ if (page) {
2229+ if (PageUptodate(page)) {
2230+ *pinned_page = page;
2231+ goto out;
2232+ }
2233+ page_cache_release(page);
2234+ }
2235+ /*
2236+ * drop cap refs first because getattr while holding
2237+ * caps refs can cause deadlock.
2238+ */
2239+ ceph_put_cap_refs(ci, _got);
2240+ _got = 0;
2241+
2242+ /* getattr request will bring inline data into page cache */
2243+ ret = __ceph_do_getattr(&ci->vfs_inode, NULL,
2244+ CEPH_STAT_CAP_INLINE_DATA, true);
2245+ if (ret < 0)
2246+ return ret;
2247+ goto retry;
2248+ }
2249+out:
2250+ *got = _got;
2251+ return 0;
22402252 }
22412253
22422254 /*
@@ -2432,13 +2444,13 @@ static void invalidate_aliases(struct inode *inode) · 189 unmodified lines
24322444 */
24332445 static void handle_cap_grant(struct ceph_mds_client *mdsc,
24342446 struct inode *inode, struct ceph_mds_caps *grant,
2435− void *snaptrace, int snaptrace_len,
24362447 u64 inline_version,
24372448 void *inline_data, int inline_len,
24382449 struct ceph_buffer *xattr_buf,
24392450 struct ceph_mds_session *session,
24402451 struct ceph_cap *cap, int issued)
24412452 __releases(ci->i_ceph_lock)
2453+ __releases(mdsc->snap_rwsem)
24422454 {
24432455 struct ceph_inode_info *ci = ceph_inode(inode);
24442456 int mds = session->s_mds;
@@ -2639,10 +2651,6 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc, · 194 unmodified lines
26392651 spin_unlock(&ci->i_ceph_lock);
26402652
26412653 if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
2642− down_write(&mdsc->snap_rwsem);
2643− ceph_update_snap_trace(mdsc, snaptrace,
2644− snaptrace + snaptrace_len, false);
2645− downgrade_write(&mdsc->snap_rwsem);
26462654 kick_flushing_inode_caps(mdsc, session, inode);
26472655 up_read(&mdsc->snap_rwsem);
26482656 if (newcaps & ~issued)
@@ -3052,6 +3060,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, · 403 unmodified lines
30523060 struct ceph_cap *cap;
30533061 struct ceph_mds_caps *h;
30543062 struct ceph_mds_cap_peer *peer = NULL;
3063+ struct ceph_snap_realm *realm;
30553064 int mds = session->s_mds;
30563065 int op, issued;
30573066 u32 seq, mseq;
@@ -3153,11 +3162,23 @@ void ceph_handle_caps(struct ceph_mds_session *session, · 95 unmodified lines
31533162 goto done_unlocked;
31543163
31553164 case CEPH_CAP_OP_IMPORT:
3165+ realm = NULL;
3166+ if (snaptrace_len) {
3167+ down_write(&mdsc->snap_rwsem);
3168+ ceph_update_snap_trace(mdsc, snaptrace,
3169+ snaptrace + snaptrace_len,
3170+ false, &realm);
3171+ downgrade_write(&mdsc->snap_rwsem);
3172+ } else {
3173+ down_read(&mdsc->snap_rwsem);
3174+ }
31563175 handle_cap_import(mdsc, inode, h, peer, session,
31573176 &cap, &issued);
3158− handle_cap_grant(mdsc, inode, h, snaptrace, snaptrace_len,
3177+ handle_cap_grant(mdsc, inode, h,
31593178 inline_version, inline_data, inline_len,
31603179 msg->middle, session, cap, issued);
3180+ if (realm)
3181+ ceph_put_snap_realm(mdsc, realm);
31613182 goto done_unlocked;
31623183 }
31633184
@@ -3177,7 +3198,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, · 13 unmodified lines
31773198 case CEPH_CAP_OP_GRANT:
31783199 __ceph_caps_issued(ci, &issued);
31793200 issued |= __ceph_caps_dirty(ci);
3180− handle_cap_grant(mdsc, inode, h, NULL, 0,
3201+ handle_cap_grant(mdsc, inode, h,
31813202 inline_version, inline_data, inline_len,
31823203 msg->middle, session, cap, issued);
31833204 goto done_unlocked;
fs/ceph/dir.c+25−8
@@ -26,8 +26,6 @@ · 25 unmodified lines
2626 * point by name.
2727 */
2828
29−const struct inode_operations ceph_dir_iops;
30−const struct file_operations ceph_dir_fops;
3129 const struct dentry_operations ceph_dentry_ops;
3230
3331 /*
@@ -672,13 +670,17 @@ int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry) · 638 unmodified lines
672670 /*
673671 * We created the item, then did a lookup, and found
674672 * it was already linked to another inode we already
675− * had in our cache (and thus got spliced). Link our
676− * dentry to that inode, but don't hash it, just in
677− * case the VFS wants to dereference it.
673+ * had in our cache (and thus got spliced). To not
674+ * confuse VFS (especially when inode is a directory),
675+ * we don't link our dentry to that inode, return an
676+ * error instead.
677+ *
678+ * This event should be rare and it happens only when
679+ * we talk to old MDS. Recent MDS does not send traceless
680+ * reply for request that creates new inode.
678681 */
679− BUG_ON(!result->d_inode);
680− d_instantiate(dentry, result->d_inode);
681− return 0;
682+ d_drop(result);
683+ return -ESTALE;
682684 }
683685 return PTR_ERR(result);
684686 }
@@ -1335,6 +1337,13 @@ const struct file_operations ceph_dir_fops = { · 650 unmodified lines
13351337 .fsync = ceph_dir_fsync,
13361338 };
13371339
1340+const struct file_operations ceph_snapdir_fops = {
1341+ .iterate = ceph_readdir,
1342+ .llseek = ceph_dir_llseek,
1343+ .open = ceph_open,
1344+ .release = ceph_release,
1345+};
1346+
13381347 const struct inode_operations ceph_dir_iops = {
13391348 .lookup = ceph_lookup,
13401349 .permission = ceph_permission,
@@ -1357,6 +1366,14 @@ const struct inode_operations ceph_dir_iops = { · 16 unmodified lines
13571366 .atomic_open = ceph_atomic_open,
13581367 };
13591368
1369+const struct inode_operations ceph_snapdir_iops = {
1370+ .lookup = ceph_lookup,
1371+ .permission = ceph_permission,
1372+ .getattr = ceph_getattr,
1373+ .mkdir = ceph_mkdir,
1374+ .rmdir = ceph_unlink,
1375+};
1376+
13601377 const struct dentry_operations ceph_dentry_ops = {
13611378 .d_revalidate = ceph_d_revalidate,
13621379 .d_release = ceph_d_release,
fs/ceph/file.c+22−15
@@ -275,10 +275,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, · 274 unmodified lines
275275 err = ceph_mdsc_do_request(mdsc,
276276 (flags & (O_CREAT|O_TRUNC)) ? dir : NULL,
277277 req);
278+ err = ceph_handle_snapdir(req, dentry, err);
278279 if (err)
279280 goto out_req;
280281
281− err = ceph_handle_snapdir(req, dentry, err);
282282 if (err == 0 && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
283283 err = ceph_handle_notrace_create(dir, dentry);
284284
@@ -392,13 +392,14 @@ more: · 107 unmodified lines
392392 if (ret >= 0) {
393393 int didpages;
394394 if (was_short && (pos + ret < inode->i_size)) {
395− u64 tmp = min(this_len - ret,
396− inode->i_size - pos - ret);
395+ int zlen = min(this_len - ret,
396+ inode->i_size - pos - ret);
397+ int zoff = (o_direct ? buf_align : io_align) +
398+ read + ret;
397399 dout(" zero gap %llu to %llu\n",
398− pos + ret, pos + ret + tmp);
399− ceph_zero_page_vector_range(page_align + read + ret,
400− tmp, pages);
401− ret += tmp;
400+ pos + ret, pos + ret + zlen);
401+ ceph_zero_page_vector_range(zoff, zlen, pages);
402+ ret += zlen;
402403 }
403404
404405 didpages = (page_align + ret) >> PAGE_CACHE_SHIFT;
@@ -878,28 +879,34 @@ again: · 473 unmodified lines
878879
879880 i_size = i_size_read(inode);
880881 if (retry_op == READ_INLINE) {
881− /* does not support inline data > PAGE_SIZE */
882− if (i_size > PAGE_CACHE_SIZE) {
883− ret = -EIO;
884− } else if (iocb->ki_pos < i_size) {
882+ BUG_ON(ret > 0 || read > 0);
883+ if (iocb->ki_pos < i_size &&
884+ iocb->ki_pos < PAGE_CACHE_SIZE) {
885885 loff_t end = min_t(loff_t, i_size,
886886 iocb->ki_pos + len);
887+ end = min_t(loff_t, end, PAGE_CACHE_SIZE);
887888 if (statret < end)
888889 zero_user_segment(page, statret, end);
889890 ret = copy_page_to_iter(page,
890891 iocb->ki_pos & ~PAGE_MASK,
891892 end - iocb->ki_pos, to);
892893 iocb->ki_pos += ret;
893− } else {
894− ret = 0;
894+ read += ret;
895+ }
896+ if (iocb->ki_pos < i_size && read < len) {
897+ size_t zlen = min_t(size_t, len - read,
898+ i_size - iocb->ki_pos);
899+ ret = iov_iter_zero(zlen, to);
900+ iocb->ki_pos += ret;
901+ read += ret;
895902 }
896903 __free_pages(page, 0);
897− return ret;
904+ return read;
898905 }
899906
900907 /* hit EOF or hole? */
901908 if (retry_op == CHECK_EOF && iocb->ki_pos < i_size &&
902− ret < len) {
909+ ret < len) {
903910 dout("sync_read hit hole, ppos %lld < size %lld"
904911 ", reading more\n", iocb->ki_pos,
905912 inode->i_size);
fs/ceph/inode.c+22−19
@@ -82,8 +82,8 @@ struct inode *ceph_get_snapdir(struct inode *parent) · 81 unmodified lines
8282 inode->i_mode = parent->i_mode;
8383 inode->i_uid = parent->i_uid;
8484 inode->i_gid = parent->i_gid;
85− inode->i_op = &ceph_dir_iops;
86− inode->i_fop = &ceph_dir_fops;
85+ inode->i_op = &ceph_snapdir_iops;
86+ inode->i_fop = &ceph_snapdir_fops;
8787 ci->i_snap_caps = CEPH_CAP_PIN; /* so we can open */
8888 ci->i_rbytes = 0;
8989 return inode;
@@ -838,30 +838,31 @@ static int fill_inode(struct inode *inode, struct page *locked_page, · 748 unmodified lines
838838 ceph_vinop(inode), inode->i_mode);
839839 }
840840
841− /* set dir completion flag? */
842− if (S_ISDIR(inode->i_mode) &&
843− ci->i_files == 0 && ci->i_subdirs == 0 &&
844− ceph_snap(inode) == CEPH_NOSNAP &&
845− (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) &&
846− (issued & CEPH_CAP_FILE_EXCL) == 0 &&
847− !__ceph_dir_is_complete(ci)) {
848− dout(" marking %p complete (empty)\n", inode);
849− __ceph_dir_set_complete(ci, atomic_read(&ci->i_release_count),
850− ci->i_ordered_count);
851− }
852−
853841 /* were we issued a capability? */
854842 if (info->cap.caps) {
855843 if (ceph_snap(inode) == CEPH_NOSNAP) {
844+ unsigned caps = le32_to_cpu(info->cap.caps);
856845 ceph_add_cap(inode, session,
857846 le64_to_cpu(info->cap.cap_id),
858− cap_fmode,
859− le32_to_cpu(info->cap.caps),
847+ cap_fmode, caps,
860848 le32_to_cpu(info->cap.wanted),
861849 le32_to_cpu(info->cap.seq),
862850 le32_to_cpu(info->cap.mseq),
863851 le64_to_cpu(info->cap.realm),
864852 info->cap.flags, &new_cap);
853+
854+ /* set dir completion flag? */
855+ if (S_ISDIR(inode->i_mode) &&
856+ ci->i_files == 0 && ci->i_subdirs == 0 &&
857+ (caps & CEPH_CAP_FILE_SHARED) &&
858+ (issued & CEPH_CAP_FILE_EXCL) == 0 &&
859+ !__ceph_dir_is_complete(ci)) {
860+ dout(" marking %p complete (empty)\n", inode);
861+ __ceph_dir_set_complete(ci,
862+ atomic_read(&ci->i_release_count),
863+ ci->i_ordered_count);
864+ }
865+
865866 wake = true;
866867 } else {
867868 dout(" %p got snap_caps %s\n", inode,
@@ -1446,12 +1447,14 @@ retry_lookup: · 578 unmodified lines
14461447 }
14471448
14481449 if (!dn->d_inode) {
1449− dn = splice_dentry(dn, in, NULL);
1450− if (IS_ERR(dn)) {
1451− err = PTR_ERR(dn);
1450+ struct dentry *realdn = splice_dentry(dn, in, NULL);
1451+ if (IS_ERR(realdn)) {
1452+ err = PTR_ERR(realdn);
1453+ d_drop(dn);
14521454 dn = NULL;
14531455 goto next_item;
14541456 }
1457+ dn = realdn;
14551458 }
14561459
14571460 di = dn->d_fsdata;
fs/ceph/mds_client.c+93−34
@@ -480,6 +480,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, · 479 unmodified lines
480480 mdsc->max_sessions = newmax;
481481 }
482482 mdsc->sessions[mds] = s;
483+ atomic_inc(&mdsc->num_sessions);
483484 atomic_inc(&s->s_ref); /* one ref to sessions[], one to caller */
484485
485486 ceph_con_open(&s->s_con, CEPH_ENTITY_TYPE_MDS, mds,
@@ -503,6 +504,7 @@ static void __unregister_session(struct ceph_mds_client *mdsc, · 17 unmodified lines
503504 mdsc->sessions[s->s_mds] = NULL;
504505 ceph_con_close(&s->s_con);
505506 ceph_put_mds_session(s);
507+ atomic_dec(&mdsc->num_sessions);
506508 }
507509
508510 /*
@@ -842,8 +844,9 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6 · 333 unmodified lines
842844 struct ceph_options *opt = mdsc->fsc->client->options;
843845 void *p;
844846
845− const char* metadata[3][2] = {
847+ const char* metadata[][2] = {
846848 {"hostname", utsname()->nodename},
849+ {"kernel_version", utsname()->release},
847850 {"entity_id", opt->name ? opt->name : ""},
848851 {NULL, NULL}
849852 };
@@ -1464,19 +1467,33 @@ out_unlocked: · 614 unmodified lines
14641467 return err;
14651468 }
14661469
1470+static int check_cap_flush(struct inode *inode, u64 want_flush_seq)
1471+{
1472+ struct ceph_inode_info *ci = ceph_inode(inode);
1473+ int ret;
1474+ spin_lock(&ci->i_ceph_lock);
1475+ if (ci->i_flushing_caps)
1476+ ret = ci->i_cap_flush_seq >= want_flush_seq;
1477+ else
1478+ ret = 1;
1479+ spin_unlock(&ci->i_ceph_lock);
1480+ return ret;
1481+}
1482+
14671483 /*
14681484 * flush all dirty inode data to disk.
14691485 *
14701486 * returns true if we've flushed through want_flush_seq
14711487 */
1472−static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
1488+static void wait_caps_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq)
14731489 {
1474− int mds, ret = 1;
1490+ int mds;
14751491
14761492 dout("check_cap_flush want %lld\n", want_flush_seq);
14771493 mutex_lock(&mdsc->mutex);
1478− for (mds = 0; ret && mds < mdsc->max_sessions; mds++) {
1494+ for (mds = 0; mds < mdsc->max_sessions; mds++) {
14791495 struct ceph_mds_session *session = mdsc->sessions[mds];
1496+ struct inode *inode = NULL;
14801497
14811498 if (!session)
14821499 continue;
@@ -1489,29 +1506,29 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) · 6 unmodified lines
14891506 list_entry(session->s_cap_flushing.next,
14901507 struct ceph_inode_info,
14911508 i_flushing_item);
1492− struct inode *inode = &ci->vfs_inode;
14931509
1494− spin_lock(&ci->i_ceph_lock);
1495− if (ci->i_cap_flush_seq <= want_flush_seq) {
1510+ if (!check_cap_flush(&ci->vfs_inode, want_flush_seq)) {
14961511 dout("check_cap_flush still flushing %p "
1497− "seq %lld <= %lld to mds%d\n", inode,
1498− ci->i_cap_flush_seq, want_flush_seq,
1499− session->s_mds);
1500− ret = 0;
1512+ "seq %lld <= %lld to mds%d\n",
1513+ &ci->vfs_inode, ci->i_cap_flush_seq,
1514+ want_flush_seq, session->s_mds);
1515+ inode = igrab(&ci->vfs_inode);
15011516 }
1502− spin_unlock(&ci->i_ceph_lock);
15031517 }
15041518 mutex_unlock(&session->s_mutex);
15051519 ceph_put_mds_session(session);
15061520
1507− if (!ret)
1508− return ret;
1521+ if (inode) {
1522+ wait_event(mdsc->cap_flushing_wq,
1523+ check_cap_flush(inode, want_flush_seq));
1524+ iput(inode);
1525+ }
1526+
15091527 mutex_lock(&mdsc->mutex);
15101528 }
15111529
15121530 mutex_unlock(&mdsc->mutex);
15131531 dout("check_cap_flush ok, flushed thru %lld\n", want_flush_seq);
1514− return ret;
15151532 }
15161533
15171534 /*
@@ -1923,7 +1940,11 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, · 405 unmodified lines
19231940 head->num_releases = cpu_to_le16(releases);
19241941
19251942 /* time stamp */
1926− ceph_encode_copy(&p, &req->r_stamp, sizeof(req->r_stamp));
1943+ {
1944+ struct ceph_timespec ts;
1945+ ceph_encode_timespec(&ts, &req->r_stamp);
1946+ ceph_encode_copy(&p, &ts, sizeof(ts));
1947+ }
19271948
19281949 BUG_ON(p > end);
19291950 msg->front.iov_len = p - msg->front.iov_base;
@@ -2012,7 +2033,11 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc, · 82 unmodified lines
20122033
20132034 /* time stamp */
20142035 p = msg->front.iov_base + req->r_request_release_offset;
2015− ceph_encode_copy(&p, &req->r_stamp, sizeof(req->r_stamp));
2036+ {
2037+ struct ceph_timespec ts;
2038+ ceph_encode_timespec(&ts, &req->r_stamp);
2039+ ceph_encode_copy(&p, &ts, sizeof(ts));
2040+ }
20162041
20172042 msg->front.iov_len = p - msg->front.iov_base;
20182043 msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
@@ -2159,6 +2184,8 @@ static void kick_requests(struct ceph_mds_client *mdsc, int mds) · 140 unmodified lines
21592184 p = rb_next(p);
21602185 if (req->r_got_unsafe)
21612186 continue;
2187+ if (req->r_attempts > 0)
2188+ continue; /* only new requests */
21622189 if (req->r_session &&
21632190 req->r_session->s_mds == mds) {
21642191 dout(" kicking tid %llu\n", req->r_tid);
@@ -2286,6 +2313,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) · 121 unmodified lines
22862313 struct ceph_mds_request *req;
22872314 struct ceph_mds_reply_head *head = msg->front.iov_base;
22882315 struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */
2316+ struct ceph_snap_realm *realm;
22892317 u64 tid;
22902318 int err, result;
22912319 int mds = session->s_mds;
@@ -2401,11 +2429,13 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) · 109 unmodified lines
24012429 }
24022430
24032431 /* snap trace */
2432+ realm = NULL;
24042433 if (rinfo->snapblob_len) {
24052434 down_write(&mdsc->snap_rwsem);
24062435 ceph_update_snap_trace(mdsc, rinfo->snapblob,
2407− rinfo->snapblob + rinfo->snapblob_len,
2408− le32_to_cpu(head->op) == CEPH_MDS_OP_RMSNAP);
2436+ rinfo->snapblob + rinfo->snapblob_len,
2437+ le32_to_cpu(head->op) == CEPH_MDS_OP_RMSNAP,
2438+ &realm);
24092439 downgrade_write(&mdsc->snap_rwsem);
24102440 } else {
24112441 down_read(&mdsc->snap_rwsem);
@@ -2423,6 +2453,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) · 11 unmodified lines
24232453 mutex_unlock(&req->r_fill_mutex);
24242454
24252455 up_read(&mdsc->snap_rwsem);
2456+ if (realm)
2457+ ceph_put_snap_realm(mdsc, realm);
24262458 out_err:
24272459 mutex_lock(&mdsc->mutex);
24282460 if (!req->r_aborted) {
@@ -2487,6 +2519,7 @@ static void handle_forward(struct ceph_mds_client *mdsc, · 58 unmodified lines
24872519 dout("forward tid %llu to mds%d (we resend)\n", tid, next_mds);
24882520 BUG_ON(req->r_err);
24892521 BUG_ON(req->r_got_result);
2522+ req->r_attempts = 0;
24902523 req->r_num_fwd = fwd_seq;
24912524 req->r_resend_mds = next_mds;
24922525 put_request_session(req);
@@ -2580,6 +2613,14 @@ static void handle_session(struct ceph_mds_session *session, · 87 unmodified lines
25802613 send_flushmsg_ack(mdsc, session, seq);
25812614 break;
25822615
2616+ case CEPH_SESSION_FORCE_RO:
2617+ dout("force_session_readonly %p\n", session);
2618+ spin_lock(&session->s_cap_lock);
2619+ session->s_readonly = true;
2620+ spin_unlock(&session->s_cap_lock);
2621+ wake_up_session_caps(session, 0);
2622+ break;
2623+
25832624 default:
25842625 pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds);
25852626 WARN_ON(1);
@@ -2610,6 +2651,7 @@ static void replay_unsafe_requests(struct ceph_mds_client *mdsc, · 24 unmodified lines
26102651 struct ceph_mds_session *session)
26112652 {
26122653 struct ceph_mds_request *req, *nreq;
2654+ struct rb_node *p;
26132655 int err;
26142656
26152657 dout("replay_unsafe_requests mds%d\n", session->s_mds);
@@ -2622,6 +2664,28 @@ static void replay_unsafe_requests(struct ceph_mds_client *mdsc, · 6 unmodified lines
26222664 ceph_con_send(&session->s_con, req->r_request);
26232665 }
26242666 }
2667+
2668+ /*
2669+ * also re-send old requests when MDS enters reconnect stage. So that MDS
2670+ * can process completed request in clientreplay stage.
2671+ */
2672+ p = rb_first(&mdsc->request_tree);
2673+ while (p) {
2674+ req = rb_entry(p, struct ceph_mds_request, r_node);
2675+ p = rb_next(p);
2676+ if (req->r_got_unsafe)
2677+ continue;
2678+ if (req->r_attempts == 0)
2679+ continue; /* only old requests */
2680+ if (req->r_session &&
2681+ req->r_session->s_mds == session->s_mds) {
2682+ err = __prepare_send_request(mdsc, req, session->s_mds);
2683+ if (!err) {
2684+ ceph_msg_get(req->r_request);
2685+ ceph_con_send(&session->s_con, req->r_request);
2686+ }
2687+ }
2688+ }
26252689 mutex_unlock(&mdsc->mutex);
26262690 }
26272691
@@ -2787,6 +2851,8 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, · 159 unmodified lines
27872851 spin_unlock(&session->s_gen_ttl_lock);
27882852
27892853 spin_lock(&session->s_cap_lock);
2854+ /* don't know if session is readonly */
2855+ session->s_readonly = 0;
27902856 /*
27912857 * notify __ceph_remove_cap() that we are composing cap reconnect.
27922858 * If a cap get released before being added to the cap reconnect,
@@ -2933,9 +2999,6 @@ static void check_new_map(struct ceph_mds_client *mdsc, · 140 unmodified lines
29332999 mutex_unlock(&s->s_mutex);
29343000 s->s_state = CEPH_MDS_SESSION_RESTARTING;
29353001 }
2936−
2937− /* kick any requests waiting on the recovering mds */
2938− kick_requests(mdsc, i);
29393002 } else if (oldstate == newstate) {
29403003 continue; /* nothing new with this mds */
29413004 }
@@ -3295,6 +3358,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) · 353 unmodified lines
32953358 init_waitqueue_head(&mdsc->session_close_wq);
32963359 INIT_LIST_HEAD(&mdsc->waiting_for_map);
32973360 mdsc->sessions = NULL;
3361+ atomic_set(&mdsc->num_sessions, 0);
32983362 mdsc->max_sessions = 0;
32993363 mdsc->stopping = 0;
33003364 init_rwsem(&mdsc->snap_rwsem);
@@ -3428,14 +3492,17 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc) · 127 unmodified lines
34283492 dout("sync\n");
34293493 mutex_lock(&mdsc->mutex);
34303494 want_tid = mdsc->last_tid;
3431− want_flush = mdsc->cap_flush_seq;
34323495 mutex_unlock(&mdsc->mutex);
3433− dout("sync want tid %lld flush_seq %lld\n", want_tid, want_flush);
34343496
34353497 ceph_flush_dirty_caps(mdsc);
3498+ spin_lock(&mdsc->cap_dirty_lock);
3499+ want_flush = mdsc->cap_flush_seq;
3500+ spin_unlock(&mdsc->cap_dirty_lock);
3501+
3502+ dout("sync want tid %lld flush_seq %lld\n", want_tid, want_flush);
34363503
34373504 wait_unsafe_requests(mdsc, want_tid);
3438− wait_event(mdsc->cap_flushing_wq, check_cap_flush(mdsc, want_flush));
3505+ wait_caps_flush(mdsc, want_flush);
34393506 }
34403507
34413508 /*
@@ -3443,17 +3510,9 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc) · 1 unmodified line
34433510 */
34443511 static bool done_closing_sessions(struct ceph_mds_client *mdsc)
34453512 {
3446− int i, n = 0;
3447−
34483513 if (mdsc->fsc->mount_state == CEPH_MOUNT_SHUTDOWN)
34493514 return true;
3450−
3451− mutex_lock(&mdsc->mutex);
3452− for (i = 0; i < mdsc->max_sessions; i++)
3453− if (mdsc->sessions[i])
3454− n++;
3455− mutex_unlock(&mdsc->mutex);
3456− return n == 0;
3515+ return atomic_read(&mdsc->num_sessions) == 0;
34573516 }
34583517
34593518 /*
fs/ceph/mds_client.h+2−0
@@ -137,6 +137,7 @@ struct ceph_mds_session { · 136 unmodified lines
137137 int s_nr_caps, s_trim_caps;
138138 int s_num_cap_releases;
139139 int s_cap_reconnect;
140+ int s_readonly;
140141 struct list_head s_cap_releases; /* waiting cap_release messages */
141142 struct list_head s_cap_releases_done; /* ready to send */
142143 struct ceph_cap *s_cap_iterator;
@@ -272,6 +273,7 @@ struct ceph_mds_client { · 129 unmodified lines
272273 struct list_head waiting_for_map;
273274
274275 struct ceph_mds_session **sessions; /* NULL for mds if no session */
276+ atomic_t num_sessions;
275277 int max_sessions; /* len of s_mds_sessions */
276278 int stopping; /* true if shutting down */
277279
fs/ceph/snap.c+38−16
@@ -70,13 +70,11 @@ void ceph_get_snap_realm(struct ceph_mds_client *mdsc, · 69 unmodified lines
7070 * safe. we do need to protect against concurrent empty list
7171 * additions, however.
7272 */
73− if (atomic_read(&realm->nref) == 0) {
73+ if (atomic_inc_return(&realm->nref) == 1) {
7474 spin_lock(&mdsc->snap_empty_lock);
7575 list_del_init(&realm->empty_item);
7676 spin_unlock(&mdsc->snap_empty_lock);
7777 }
78−
79− atomic_inc(&realm->nref);
8078 }
8179
8280 static void __insert_snap_realm(struct rb_root *root,
@@ -116,7 +114,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm( · 33 unmodified lines
116114 if (!realm)
117115 return ERR_PTR(-ENOMEM);
118116
119− atomic_set(&realm->nref, 0); /* tree does not take a ref */
117+ atomic_set(&realm->nref, 1); /* for caller */
120118 realm->ino = ino;
121119 INIT_LIST_HEAD(&realm->children);
122120 INIT_LIST_HEAD(&realm->child_item);
@@ -134,8 +132,8 @@ static struct ceph_snap_realm *ceph_create_snap_realm( · 11 unmodified lines
134132 *
135133 * caller must hold snap_rwsem for write.
136134 */
137−struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc,
138− u64 ino)
135+static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,
136+ u64 ino)
139137 {
140138 struct rb_node *n = mdsc->snap_realms.rb_node;
141139 struct ceph_snap_realm *r;
@@ -154,6 +152,16 @@ struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc, · 12 unmodified lines
154152 return NULL;
155153 }
156154
155+struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc,
156+ u64 ino)
157+{
158+ struct ceph_snap_realm *r;
159+ r = __lookup_snap_realm(mdsc, ino);
160+ if (r)
161+ ceph_get_snap_realm(mdsc, r);
162+ return r;
163+}
164+
157165 static void __put_snap_realm(struct ceph_mds_client *mdsc,
158166 struct ceph_snap_realm *realm);
159167
@@ -273,7 +281,6 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, · 113 unmodified lines
273281 }
274282 realm->parent_ino = parentino;
275283 realm->parent = parent;
276− ceph_get_snap_realm(mdsc, parent);
277284 list_add(&realm->child_item, &parent->children);
278285 return 1;
279286 }
@@ -631,12 +638,14 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm) · 351 unmodified lines
631638 * Caller must hold snap_rwsem for write.
632639 */
633640 int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
634− void *p, void *e, bool deletion)
641+ void *p, void *e, bool deletion,
642+ struct ceph_snap_realm **realm_ret)
635643 {
636644 struct ceph_mds_snap_realm *ri; /* encoded */
637645 __le64 *snaps; /* encoded */
638646 __le64 *prior_parent_snaps; /* encoded */
639− struct ceph_snap_realm *realm;
647+ struct ceph_snap_realm *realm = NULL;
648+ struct ceph_snap_realm *first_realm = NULL;
640649 int invalidate = 0;
641650 int err = -ENOMEM;
642651 LIST_HEAD(dirty_realms);
@@ -704,13 +713,18 @@ more: · 61 unmodified lines
704713 dout("done with %llx %p, invalidated=%d, %p %p\n", realm->ino,
705714 realm, invalidate, p, e);
706715
707− if (p < e)
708− goto more;
709−
710716 /* invalidate when we reach the _end_ (root) of the trace */
711− if (invalidate)
717+ if (invalidate && p >= e)
712718 rebuild_snap_realms(realm);
713719
720+ if (!first_realm)
721+ first_realm = realm;
722+ else
723+ ceph_put_snap_realm(mdsc, realm);
724+
725+ if (p < e)
726+ goto more;
727+
714728 /*
715729 * queue cap snaps _after_ we've built the new snap contexts,
716730 * so that i_head_snapc can be set appropriately.
@@ -721,12 +735,21 @@ more: · 4 unmodified lines
721735 queue_realm_cap_snaps(realm);
722736 }
723737
738+ if (realm_ret)
739+ *realm_ret = first_realm;
740+ else
741+ ceph_put_snap_realm(mdsc, first_realm);
742+
724743 __cleanup_empty_realms(mdsc);
725744 return 0;
726745
727746 bad:
728747 err = -EINVAL;
729748 fail:
749+ if (realm && !IS_ERR(realm))
750+ ceph_put_snap_realm(mdsc, realm);
751+ if (first_realm)
752+ ceph_put_snap_realm(mdsc, first_realm);
730753 pr_err("update_snap_trace error %d\n", err);
731754 return err;
732755 }
@@ -844,7 +867,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, · 111 unmodified lines
844867 if (IS_ERR(realm))
845868 goto out;
846869 }
847− ceph_get_snap_realm(mdsc, realm);
848870
849871 dout("splitting snap_realm %llx %p\n", realm->ino, realm);
850872 for (i = 0; i < num_split_inos; i++) {
@@ -905,7 +927,7 @@ skip_inode: · 54 unmodified lines
905927 /* we may have taken some of the old realm's children. */
906928 for (i = 0; i < num_split_realms; i++) {
907929 struct ceph_snap_realm *child =
908− ceph_lookup_snap_realm(mdsc,
930+ __lookup_snap_realm(mdsc,
909931 le64_to_cpu(split_realms[i]));
910932 if (!child)
911933 continue;
@@ -918,7 +940,7 @@ skip_inode: · 6 unmodified lines
918940 * snap, we can avoid queueing cap_snaps.
919941 */
920942 ceph_update_snap_trace(mdsc, p, e,
921− op == CEPH_SNAP_OP_DESTROY);
943+ op == CEPH_SNAP_OP_DESTROY, NULL);
922944
923945 if (op == CEPH_SNAP_OP_SPLIT)
924946 /* we took a reference when we created the realm, above */
fs/ceph/super.c+4−0
@@ -414,6 +414,10 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) · 413 unmodified lines
414414 seq_puts(m, ",noshare");
415415 if (opt->flags & CEPH_OPT_NOCRC)
416416 seq_puts(m, ",nocrc");
417+ if (opt->flags & CEPH_OPT_NOMSGAUTH)
418+ seq_puts(m, ",nocephx_require_signatures");
419+ if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
420+ seq_puts(m, ",notcp_nodelay");
417421
418422 if (opt->name)
419423 seq_printf(m, ",name=%s", opt->name);
fs/ceph/super.h+4−1
@@ -693,7 +693,8 @@ extern void ceph_get_snap_realm(struct ceph_mds_client *mdsc, · 692 unmodified lines
693693 extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
694694 struct ceph_snap_realm *realm);
695695 extern int ceph_update_snap_trace(struct ceph_mds_client *m,
696− void *p, void *e, bool deletion);
696+ void *p, void *e, bool deletion,
697+ struct ceph_snap_realm **realm_ret);
697698 extern void ceph_handle_snap(struct ceph_mds_client *mdsc,
698699 struct ceph_mds_session *session,
699700 struct ceph_msg *msg);
@@ -892,7 +893,9 @@ extern void ceph_fill_inline_data(struct inode *inode, struct page *locked_page, · 192 unmodified lines
892893 int ceph_uninline_data(struct file *filp, struct page *locked_page);
893894 /* dir.c */
894895 extern const struct file_operations ceph_dir_fops;
896+extern const struct file_operations ceph_snapdir_fops;
895897 extern const struct inode_operations ceph_dir_iops;
898+extern const struct inode_operations ceph_snapdir_iops;
896899 extern const struct dentry_operations ceph_dentry_ops, ceph_snap_dentry_ops,
897900 ceph_snapdir_dentry_ops;
898901
include/linux/ceph/ceph_fs.h+1−36
@@ -158,17 +158,6 @@ enum { · 157 unmodified lines
158158 };
159159
160160
161−/* pool operations */
162−enum {
163− POOL_OP_CREATE = 0x01,
164− POOL_OP_DELETE = 0x02,
165− POOL_OP_AUID_CHANGE = 0x03,
166− POOL_OP_CREATE_SNAP = 0x11,
167− POOL_OP_DELETE_SNAP = 0x12,
168− POOL_OP_CREATE_UNMANAGED_SNAP = 0x21,
169− POOL_OP_DELETE_UNMANAGED_SNAP = 0x22,
170−};
171−
172161 struct ceph_mon_request_header {
173162 __le64 have_version;
174163 __le16 session_mon;
@@ -191,31 +180,6 @@ struct ceph_mon_statfs_reply { · 16 unmodified lines
191180 struct ceph_statfs st;
192181 } __attribute__ ((packed));
193182
194−const char *ceph_pool_op_name(int op);
195−
196−struct ceph_mon_poolop {
197− struct ceph_mon_request_header monhdr;
198− struct ceph_fsid fsid;
199− __le32 pool;
200− __le32 op;
201− __le64 auid;
202− __le64 snapid;
203− __le32 name_len;
204−} __attribute__ ((packed));
205−
206−struct ceph_mon_poolop_reply {
207− struct ceph_mon_request_header monhdr;
208− struct ceph_fsid fsid;
209− __le32 reply_code;
210− __le32 epoch;
211− char has_data;
212− char data[0];
213−} __attribute__ ((packed));
214−
215−struct ceph_mon_unmanaged_snap {
216− __le64 snapid;
217−} __attribute__ ((packed));
218−
219183 struct ceph_osd_getmap {
220184 struct ceph_mon_request_header monhdr;
221185 struct ceph_fsid fsid;
@@ -307,6 +271,7 @@ enum { · 85 unmodified lines
307271 CEPH_SESSION_RECALL_STATE,
308272 CEPH_SESSION_FLUSHMSG,
309273 CEPH_SESSION_FLUSHMSG_ACK,
274+ CEPH_SESSION_FORCE_RO,
310275 };
311276
312277 extern const char *ceph_session_op_name(int op);
include/linux/ceph/libceph.h+2−1
@@ -30,8 +30,9 @@ · 29 unmodified lines
3030 #define CEPH_OPT_MYIP (1<<2) /* specified my ip */
3131 #define CEPH_OPT_NOCRC (1<<3) /* no data crc on writes */
3232 #define CEPH_OPT_NOMSGAUTH (1<<4) /* not require cephx message signature */
33+#define CEPH_OPT_TCP_NODELAY (1<<5) /* TCP_NODELAY on TCP sockets */
3334
34−#define CEPH_OPT_DEFAULT (0)
35+#define CEPH_OPT_DEFAULT (CEPH_OPT_TCP_NODELAY)
3536
3637 #define ceph_set_opt(client, opt) \
3738 (client)->options->flags |= CEPH_OPT_##opt;
include/linux/ceph/messenger.h+3−1
@@ -57,6 +57,7 @@ struct ceph_messenger { · 56 unmodified lines
5757
5858 atomic_t stopping;
5959 bool nocrc;
60+ bool tcp_nodelay;
6061
6162 /*
6263 * the global_seq counts connections i (attempt to) initiate
@@ -264,7 +265,8 @@ extern void ceph_messenger_init(struct ceph_messenger *msgr, · 201 unmodified lines
264265 struct ceph_entity_addr *myaddr,
265266 u64 supported_features,
266267 u64 required_features,
267− bool nocrc);
268+ bool nocrc,
269+ bool tcp_nodelay);
268270
269271 extern void ceph_con_init(struct ceph_connection *con, void *private,
270272 const struct ceph_connection_operations *ops,
include/linux/ceph/mon_client.h+1−8
@@ -40,7 +40,7 @@ struct ceph_mon_request { · 39 unmodified lines
4040 };
4141
4242 /*
43− * ceph_mon_generic_request is being used for the statfs, poolop and
43+ * ceph_mon_generic_request is being used for the statfs and
4444 * mon_get_version requests which are being done a bit differently
4545 * because we need to get data back to the caller
4646 */
@@ -50,7 +50,6 @@ struct ceph_mon_generic_request { · 3 unmodified lines
5050 struct rb_node node;
5151 int result;
5252 void *buf;
53− int buf_len;
5453 struct completion completion;
5554 struct ceph_msg *request; /* original request */
5655 struct ceph_msg *reply; /* and reply */
@@ -117,10 +116,4 @@ extern int ceph_monc_open_session(struct ceph_mon_client *monc); · 60 unmodified lines
117116
118117 extern int ceph_monc_validate_auth(struct ceph_mon_client *monc);
119118
120−extern int ceph_monc_create_snapid(struct ceph_mon_client *monc,
121− u32 pool, u64 *snapid);
122−
123−extern int ceph_monc_delete_snapid(struct ceph_mon_client *monc,
124− u32 pool, u64 snapid);
125−
126119 #endif
net/ceph/ceph_common.c+15−1
@@ -239,6 +239,8 @@ enum { · 238 unmodified lines
239239 Opt_nocrc,
240240 Opt_cephx_require_signatures,
241241 Opt_nocephx_require_signatures,
242+ Opt_tcp_nodelay,
243+ Opt_notcp_nodelay,
242244 };
243245
244246 static match_table_t opt_tokens = {
@@ -259,6 +261,8 @@ static match_table_t opt_tokens = { · 14 unmodified lines
259261 {Opt_nocrc, "nocrc"},
260262 {Opt_cephx_require_signatures, "cephx_require_signatures"},
261263 {Opt_nocephx_require_signatures, "nocephx_require_signatures"},
264+ {Opt_tcp_nodelay, "tcp_nodelay"},
265+ {Opt_notcp_nodelay, "notcp_nodelay"},
262266 {-1, NULL}
263267 };
264268
@@ -457,6 +461,7 @@ ceph_parse_options(char *options, const char *dev_name, · 192 unmodified lines
457461 case Opt_nocrc:
458462 opt->flags |= CEPH_OPT_NOCRC;
459463 break;
464+
460465 case Opt_cephx_require_signatures:
461466 opt->flags &= ~CEPH_OPT_NOMSGAUTH;
462467 break;
@@ -464,6 +469,13 @@ ceph_parse_options(char *options, const char *dev_name, · 1 unmodified line
464469 opt->flags |= CEPH_OPT_NOMSGAUTH;
465470 break;
466471
472+ case Opt_tcp_nodelay:
473+ opt->flags |= CEPH_OPT_TCP_NODELAY;
474+ break;
475+ case Opt_notcp_nodelay:
476+ opt->flags &= ~CEPH_OPT_TCP_NODELAY;
477+ break;
478+
467479 default:
468480 BUG_ON(token);
469481 }
@@ -518,10 +530,12 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, · 48 unmodified lines
518530 /* msgr */
519531 if (ceph_test_opt(client, MYIP))
520532 myaddr = &client->options->my_addr;
533+
521534 ceph_messenger_init(&client->msgr, myaddr,
522535 client->supported_features,
523536 client->required_features,
524− ceph_test_opt(client, NOCRC));
537+ ceph_test_opt(client, NOCRC),
538+ ceph_test_opt(client, TCP_NODELAY));
525539
526540 /* subsystems */
527541 err = ceph_monc_init(&client->monc, client);
net/ceph/ceph_strings.c+0−14
@@ -42,17 +42,3 @@ const char *ceph_osd_state_name(int s) · 41 unmodified lines
4242 return "???";
4343 }
4444 }
45−
46−const char *ceph_pool_op_name(int op)
47−{
48− switch (op) {
49− case POOL_OP_CREATE: return "create";
50− case POOL_OP_DELETE: return "delete";
51− case POOL_OP_AUID_CHANGE: return "auid change";
52− case POOL_OP_CREATE_SNAP: return "create snap";
53− case POOL_OP_DELETE_SNAP: return "delete snap";
54− case POOL_OP_CREATE_UNMANAGED_SNAP: return "create unmanaged snap";
55− case POOL_OP_DELETE_UNMANAGED_SNAP: return "delete unmanaged snap";
56− }
57− return "???";
58−}
net/ceph/debugfs.c+0−2
@@ -127,8 +127,6 @@ static int monc_show(struct seq_file *s, void *p) · 126 unmodified lines
127127 op = le16_to_cpu(req->request->hdr.type);
128128 if (op == CEPH_MSG_STATFS)
129129 seq_printf(s, "%llu statfs\n", req->tid);
130− else if (op == CEPH_MSG_POOLOP)
131− seq_printf(s, "%llu poolop\n", req->tid);
132130 else if (op == CEPH_MSG_MON_GET_VERSION)
133131 seq_printf(s, "%llu mon_get_version", req->tid);
134132 else
net/ceph/messenger.c+13−1
@@ -510,6 +510,16 @@ static int ceph_tcp_connect(struct ceph_connection *con) · 509 unmodified lines
510510 return ret;
511511 }
512512
513+ if (con->msgr->tcp_nodelay) {
514+ int optval = 1;
515+
516+ ret = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
517+ (char *)&optval, sizeof(optval));
518+ if (ret)
519+ pr_err("kernel_setsockopt(TCP_NODELAY) failed: %d",
520+ ret);
521+ }
522+
513523 sk_set_memalloc(sock->sk);
514524
515525 con->sock = sock;
@@ -2922,7 +2932,8 @@ void ceph_messenger_init(struct ceph_messenger *msgr, · 2406 unmodified lines
29222932 struct ceph_entity_addr *myaddr,
29232933 u64 supported_features,
29242934 u64 required_features,
2925− bool nocrc)
2935+ bool nocrc,
2936+ bool tcp_nodelay)
29262937 {
29272938 msgr->supported_features = supported_features;
29282939 msgr->required_features = required_features;
@@ -2937,6 +2948,7 @@ void ceph_messenger_init(struct ceph_messenger *msgr, · 8 unmodified lines
29372948 get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce));
29382949 encode_my_addr(msgr);
29392950 msgr->nocrc = nocrc;
2951+ msgr->tcp_nodelay = tcp_nodelay;
29402952
29412953 atomic_set(&msgr->stopping, 0);
29422954
net/ceph/mon_client.c+5−134
@@ -410,7 +410,7 @@ out_unlocked: · 409 unmodified lines
410410 }
411411
412412 /*
413− * generic requests (e.g., statfs, poolop)
413+ * generic requests (currently statfs, mon_get_version)
414414 */
415415 static struct ceph_mon_generic_request *__lookup_generic_req(
416416 struct ceph_mon_client *monc, u64 tid)
@@ -569,7 +569,7 @@ static void handle_statfs_reply(struct ceph_mon_client *monc, · 152 unmodified lines
569569 return;
570570
571571 bad:
572− pr_err("corrupt generic reply, tid %llu\n", tid);
572+ pr_err("corrupt statfs reply, tid %llu\n", tid);
573573 ceph_msg_dump(msg);
574574 }
575575
@@ -588,7 +588,6 @@ int ceph_monc_do_statfs(struct ceph_mon_client *monc, struct ceph_statfs *buf) · 12 unmodified lines
588588
589589 kref_init(&req->kref);
590590 req->buf = buf;
591− req->buf_len = sizeof(*buf);
592591 init_completion(&req->completion);
593592
594593 err = -ENOMEM;
@@ -611,7 +610,7 @@ int ceph_monc_do_statfs(struct ceph_mon_client *monc, struct ceph_statfs *buf) · 16 unmodified lines
611610 err = do_generic_request(monc, req);
612611
613612 out:
614− kref_put(&req->kref, release_generic_request);
613+ put_generic_request(req);
615614 return err;
616615 }
617616 EXPORT_SYMBOL(ceph_monc_do_statfs);
@@ -647,7 +646,7 @@ static void handle_get_version_reply(struct ceph_mon_client *monc, · 29 unmodified lines
647646
648647 return;
649648 bad:
650− pr_err("corrupt mon_get_version reply\n");
649+ pr_err("corrupt mon_get_version reply, tid %llu\n", tid);
651650 ceph_msg_dump(msg);
652651 }
653652
@@ -670,7 +669,6 @@ int ceph_monc_do_get_version(struct ceph_mon_client *monc, const char *what, · 16 unmodified lines
670669
671670 kref_init(&req->kref);
672671 req->buf = newest;
673− req->buf_len = sizeof(*newest);
674672 init_completion(&req->completion);
675673
676674 req->request = ceph_msg_new(CEPH_MSG_MON_GET_VERSION,
@@ -701,133 +699,11 @@ int ceph_monc_do_get_version(struct ceph_mon_client *monc, const char *what, · 24 unmodified lines
701699
702700 mutex_unlock(&monc->mutex);
703701 out:
704− kref_put(&req->kref, release_generic_request);
702+ put_generic_request(req);
705703 return err;
706704 }
707705 EXPORT_SYMBOL(ceph_monc_do_get_version);
708706
709−/*
710− * pool ops
711− */
712−static int get_poolop_reply_buf(const char *src, size_t src_len,
713− char *dst, size_t dst_len)
714−{
715− u32 buf_len;
716−
717− if (src_len != sizeof(u32) + dst_len)
718− return -EINVAL;
719−
720− buf_len = le32_to_cpu(*(__le32 *)src);
721− if (buf_len != dst_len)
722− return -EINVAL;
723−
724− memcpy(dst, src + sizeof(u32), dst_len);
725− return 0;
726−}
727−
728−static void handle_poolop_reply(struct ceph_mon_client *monc,
729− struct ceph_msg *msg)
730−{
731− struct ceph_mon_generic_request *req;
732− struct ceph_mon_poolop_reply *reply = msg->front.iov_base;
733− u64 tid = le64_to_cpu(msg->hdr.tid);
734−
735− if (msg->front.iov_len < sizeof(*reply))
736− goto bad;
737− dout("handle_poolop_reply %p tid %llu\n", msg, tid);
738−
739− mutex_lock(&monc->mutex);
740− req = __lookup_generic_req(monc, tid);
741− if (req) {
742− if (req->buf_len &&
743− get_poolop_reply_buf(msg->front.iov_base + sizeof(*reply),
744− msg->front.iov_len - sizeof(*reply),
745− req->buf, req->buf_len) < 0) {
746− mutex_unlock(&monc->mutex);
747− goto bad;
748− }
749− req->result = le32_to_cpu(reply->reply_code);
750− get_generic_request(req);
751− }
752− mutex_unlock(&monc->mutex);
753− if (req) {
754− complete(&req->completion);
755− put_generic_request(req);
756− }
757− return;
758−
759−bad:
760− pr_err("corrupt generic reply, tid %llu\n", tid);
761− ceph_msg_dump(msg);
762−}
763−
764−/*
765− * Do a synchronous pool op.
766− */
767−static int do_poolop(struct ceph_mon_client *monc, u32 op,
768− u32 pool, u64 snapid,
769− char *buf, int len)
770−{
771− struct ceph_mon_generic_request *req;
772− struct ceph_mon_poolop *h;
773− int err;
774−
775− req = kzalloc(sizeof(*req), GFP_NOFS);
776− if (!req)
777− return -ENOMEM;
778−
779− kref_init(&req->kref);
780− req->buf = buf;
781− req->buf_len = len;
782− init_completion(&req->completion);
783−
784− err = -ENOMEM;
785− req->request = ceph_msg_new(CEPH_MSG_POOLOP, sizeof(*h), GFP_NOFS,
786− true);
787− if (!req->request)
788− goto out;
789− req->reply = ceph_msg_new(CEPH_MSG_POOLOP_REPLY, 1024, GFP_NOFS,
790− true);
791− if (!req->reply)
792− goto out;
793−
794− /* fill out request */
795− req->request->hdr.version = cpu_to_le16(2);
796− h = req->request->front.iov_base;
797− h->monhdr.have_version = 0;
798− h->monhdr.session_mon = cpu_to_le16(-1);
799− h->monhdr.session_mon_tid = 0;
800− h->fsid = monc->monmap->fsid;
801− h->pool = cpu_to_le32(pool);
802− h->op = cpu_to_le32(op);
803− h->auid = 0;
804− h->snapid = cpu_to_le64(snapid);
805− h->name_len = 0;
806−
807− err = do_generic_request(monc, req);
808−
809−out:
810− kref_put(&req->kref, release_generic_request);
811− return err;
812−}
813−
814−int ceph_monc_create_snapid(struct ceph_mon_client *monc,
815− u32 pool, u64 *snapid)
816−{
817− return do_poolop(monc, POOL_OP_CREATE_UNMANAGED_SNAP,
818− pool, 0, (char *)snapid, sizeof(*snapid));
819−
820−}
821−EXPORT_SYMBOL(ceph_monc_create_snapid);
822−
823−int ceph_monc_delete_snapid(struct ceph_mon_client *monc,
824− u32 pool, u64 snapid)
825−{
826− return do_poolop(monc, POOL_OP_CREATE_UNMANAGED_SNAP,
827− pool, snapid, NULL, 0);
828−
829−}
830−
831707 /*
832708 * Resend pending generic requests.
833709 */
@@ -1112,10 +988,6 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) · 278 unmodified lines
1112988 handle_get_version_reply(monc, msg);
1113989 break;
1114990
1115− case CEPH_MSG_POOLOP_REPLY:
1116− handle_poolop_reply(monc, msg);
1117− break;
1118−
1119991 case CEPH_MSG_MON_MAP:
1120992 ceph_monc_handle_map(monc, msg);
1121993 break;
@@ -1154,7 +1026,6 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, · 32 unmodified lines
11541026 case CEPH_MSG_MON_SUBSCRIBE_ACK:
11551027 m = ceph_msg_get(monc->m_subscribe_ack);
11561028 break;
1157− case CEPH_MSG_POOLOP_REPLY:
11581029 case CEPH_MSG_STATFS_REPLY:
11591030 return get_generic_reply(con, hdr, skip);
11601031 case CEPH_MSG_AUTH_REPLY:
net/ceph/osd_client.c+21−10
@@ -1035,10 +1035,11 @@ static void put_osd(struct ceph_osd *osd) · 1034 unmodified lines
10351035 {
10361036 dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
10371037 atomic_read(&osd->o_ref) - 1);
1038− if (atomic_dec_and_test(&osd->o_ref) && osd->o_auth.authorizer) {
1038+ if (atomic_dec_and_test(&osd->o_ref)) {
10391039 struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth;
10401040
1041− ceph_auth_destroy_authorizer(ac, osd->o_auth.authorizer);
1041+ if (osd->o_auth.authorizer)
1042+ ceph_auth_destroy_authorizer(ac, osd->o_auth.authorizer);
10421043 kfree(osd);
10431044 }
10441045 }
@@ -1048,14 +1049,24 @@ static void put_osd(struct ceph_osd *osd) · 3 unmodified lines
10481049 */
10491050 static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
10501051 {
1051− dout("__remove_osd %p\n", osd);
1052+ dout("%s %p osd%d\n", __func__, osd, osd->o_osd);
10521053 WARN_ON(!list_empty(&osd->o_requests));
10531054 WARN_ON(!list_empty(&osd->o_linger_requests));
10541055
1055− rb_erase(&osd->o_node, &osdc->osds);
10561056 list_del_init(&osd->o_osd_lru);
1057− ceph_con_close(&osd->o_con);
1058− put_osd(osd);
1057+ rb_erase(&osd->o_node, &osdc->osds);
1058+ RB_CLEAR_NODE(&osd->o_node);
1059+}
1060+
1061+static void remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
1062+{
1063+ dout("%s %p osd%d\n", __func__, osd, osd->o_osd);
1064+
1065+ if (!RB_EMPTY_NODE(&osd->o_node)) {
1066+ ceph_con_close(&osd->o_con);
1067+ __remove_osd(osdc, osd);
1068+ put_osd(osd);
1069+ }
10591070 }
10601071
10611072 static void remove_all_osds(struct ceph_osd_client *osdc)
@@ -1065,7 +1076,7 @@ static void remove_all_osds(struct ceph_osd_client *osdc) · 3 unmodified lines
10651076 while (!RB_EMPTY_ROOT(&osdc->osds)) {
10661077 struct ceph_osd *osd = rb_entry(rb_first(&osdc->osds),
10671078 struct ceph_osd, o_node);
1068− __remove_osd(osdc, osd);
1079+ remove_osd(osdc, osd);
10691080 }
10701081 mutex_unlock(&osdc->request_mutex);
10711082 }
@@ -1106,7 +1117,7 @@ static void remove_old_osds(struct ceph_osd_client *osdc) · 34 unmodified lines
11061117 list_for_each_entry_safe(osd, nosd, &osdc->osd_lru, o_osd_lru) {
11071118 if (time_before(jiffies, osd->lru_ttl))
11081119 break;
1109− __remove_osd(osdc, osd);
1120+ remove_osd(osdc, osd);
11101121 }
11111122 mutex_unlock(&osdc->request_mutex);
11121123 }
@@ -1121,8 +1132,7 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) · 8 unmodified lines
11211132 dout("__reset_osd %p osd%d\n", osd, osd->o_osd);
11221133 if (list_empty(&osd->o_requests) &&
11231134 list_empty(&osd->o_linger_requests)) {
1124− __remove_osd(osdc, osd);
1125−
1135+ remove_osd(osdc, osd);
11261136 return -ENODEV;
11271137 }
11281138
@@ -1926,6 +1936,7 @@ static void reset_changed_osds(struct ceph_osd_client *osdc) · 797 unmodified lines
19261936 {
19271937 struct rb_node *p, *n;
19281938
1939+ dout("%s %p\n", __func__, osdc);
19291940 for (p = rb_first(&osdc->osds); p; p = n) {
19301941 struct ceph_osd *osd = rb_entry(p, struct ceph_osd, o_node);
19311942