]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.7-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Jan 2013 18:01:46 +0000 (10:01 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Jan 2013 18:01:46 +0000 (10:01 -0800)
added patches:
ceph-call-handle_cap_grant-for-cap-import-message.patch
ceph-don-t-add-dirty-inode-to-dirty-list-if-caps-is-in-migration.patch
ceph-don-t-reference-req-after-put.patch
ceph-don-t-update-i_max_size-when-handling-non-auth-cap.patch
ceph-fix-__ceph_do_pending_vmtruncate.patch
ceph-fix-infinite-loop-in-__wake_requests.patch
libceph-avoid-using-freed-osd-in-__kick_osd_requests.patch
libceph-fix-osdmap-decode-error-paths.patch
libceph-fix-protocol-feature-mismatch-failure-path.patch
libceph-remove-osdtimeout-option.patch
libceph-unlock-unprocessed-pages-in-start_read-error-path.patch
rbd-do-not-allow-remove-of-mounted-on-image.patch
rbd-fix-bug-in-rbd_dev_id_put.patch
rbd-fix-read-only-option-name.patch
rbd-get-rid-of-rbd_max_seg_name_len.patch
rbd-increase-maximum-snapshot-name-length.patch
rbd-remove-linger-unconditionally.patch
rbd-remove-snapshots-on-error-in-rbd_add.patch
rbd-zero-return-code-in-rbd_dev_image_id.patch

20 files changed:
queue-3.7/ceph-call-handle_cap_grant-for-cap-import-message.patch [new file with mode: 0644]
queue-3.7/ceph-don-t-add-dirty-inode-to-dirty-list-if-caps-is-in-migration.patch [new file with mode: 0644]
queue-3.7/ceph-don-t-reference-req-after-put.patch [new file with mode: 0644]
queue-3.7/ceph-don-t-update-i_max_size-when-handling-non-auth-cap.patch [new file with mode: 0644]
queue-3.7/ceph-fix-__ceph_do_pending_vmtruncate.patch [new file with mode: 0644]
queue-3.7/ceph-fix-infinite-loop-in-__wake_requests.patch [new file with mode: 0644]
queue-3.7/libceph-avoid-using-freed-osd-in-__kick_osd_requests.patch [new file with mode: 0644]
queue-3.7/libceph-fix-osdmap-decode-error-paths.patch [new file with mode: 0644]
queue-3.7/libceph-fix-protocol-feature-mismatch-failure-path.patch [new file with mode: 0644]
queue-3.7/libceph-remove-osdtimeout-option.patch [new file with mode: 0644]
queue-3.7/libceph-unlock-unprocessed-pages-in-start_read-error-path.patch [new file with mode: 0644]
queue-3.7/rbd-do-not-allow-remove-of-mounted-on-image.patch [new file with mode: 0644]
queue-3.7/rbd-fix-bug-in-rbd_dev_id_put.patch [new file with mode: 0644]
queue-3.7/rbd-fix-read-only-option-name.patch [new file with mode: 0644]
queue-3.7/rbd-get-rid-of-rbd_max_seg_name_len.patch [new file with mode: 0644]
queue-3.7/rbd-increase-maximum-snapshot-name-length.patch [new file with mode: 0644]
queue-3.7/rbd-remove-linger-unconditionally.patch [new file with mode: 0644]
queue-3.7/rbd-remove-snapshots-on-error-in-rbd_add.patch [new file with mode: 0644]
queue-3.7/rbd-zero-return-code-in-rbd_dev_image_id.patch [new file with mode: 0644]
queue-3.7/series

diff --git a/queue-3.7/ceph-call-handle_cap_grant-for-cap-import-message.patch b/queue-3.7/ceph-call-handle_cap_grant-for-cap-import-message.patch
new file mode 100644 (file)
index 0000000..7ae90a4
--- /dev/null
@@ -0,0 +1,50 @@
+From 0747d15ddb5eac0e83376e2722e3654ae01d252f Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+Date: Mon, 19 Nov 2012 10:49:09 +0800
+Subject: ceph: call handle_cap_grant() for cap import message
+
+
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+
+(cherry picked from commit 0e5e1774a92e6fe9c511585de8f078b4c4c68dbb)
+
+If client sends cap message that requests new max size during
+exporting caps, the exporting MDS will drop the message quietly.
+So the client may wait for the reply that updates the max size
+forever. call handle_cap_grant() for cap import message can
+avoid this issue.
+
+Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
+Signed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/caps.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/ceph/caps.c
++++ b/fs/ceph/caps.c
+@@ -2749,6 +2749,7 @@ static void handle_cap_import(struct cep
+       /* make sure we re-request max_size, if necessary */
+       spin_lock(&ci->i_ceph_lock);
++      ci->i_wanted_max_size = 0;  /* reset */
+       ci->i_requested_max_size = 0;
+       spin_unlock(&ci->i_ceph_lock);
+ }
+@@ -2844,8 +2845,6 @@ void ceph_handle_caps(struct ceph_mds_se
+       case CEPH_CAP_OP_IMPORT:
+               handle_cap_import(mdsc, inode, h, session,
+                                 snaptrace, snaptrace_len);
+-              ceph_check_caps(ceph_inode(inode), 0, session);
+-              goto done_unlocked;
+       }
+       /* the rest require a cap */
+@@ -2862,6 +2861,7 @@ void ceph_handle_caps(struct ceph_mds_se
+       switch (op) {
+       case CEPH_CAP_OP_REVOKE:
+       case CEPH_CAP_OP_GRANT:
++      case CEPH_CAP_OP_IMPORT:
+               handle_cap_grant(inode, h, session, cap, msg->middle);
+               goto done_unlocked;
diff --git a/queue-3.7/ceph-don-t-add-dirty-inode-to-dirty-list-if-caps-is-in-migration.patch b/queue-3.7/ceph-don-t-add-dirty-inode-to-dirty-list-if-caps-is-in-migration.patch
new file mode 100644 (file)
index 0000000..0ce4c5f
--- /dev/null
@@ -0,0 +1,41 @@
+From f409f158fb190ab9915fd94dce367e462a0c02f6 Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+Date: Mon, 19 Nov 2012 10:49:07 +0800
+Subject: ceph: Don't add dirty inode to dirty list if caps is in migration
+
+
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+
+(cherry picked from commit 0685235ffd9dbdb9ccbda587f8a3c83ad1d5a921)
+
+Add dirty inode to cap_dirty_migrating list instead, this can avoid
+ceph_flush_dirty_caps() entering infinite loop.
+
+Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
+Signed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/caps.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/fs/ceph/caps.c
++++ b/fs/ceph/caps.c
+@@ -1349,11 +1349,15 @@ int __ceph_mark_dirty_caps(struct ceph_i
+               if (!ci->i_head_snapc)
+                       ci->i_head_snapc = ceph_get_snap_context(
+                               ci->i_snap_realm->cached_context);
+-              dout(" inode %p now dirty snapc %p\n", &ci->vfs_inode,
+-                      ci->i_head_snapc);
++              dout(" inode %p now dirty snapc %p auth cap %p\n",
++                   &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap);
+               BUG_ON(!list_empty(&ci->i_dirty_item));
+               spin_lock(&mdsc->cap_dirty_lock);
+-              list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
++              if (ci->i_auth_cap)
++                      list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
++              else
++                      list_add(&ci->i_dirty_item,
++                               &mdsc->cap_dirty_migrating);
+               spin_unlock(&mdsc->cap_dirty_lock);
+               if (ci->i_flushing_caps == 0) {
+                       ihold(inode);
diff --git a/queue-3.7/ceph-don-t-reference-req-after-put.patch b/queue-3.7/ceph-don-t-reference-req-after-put.patch
new file mode 100644 (file)
index 0000000..dfa2c89
--- /dev/null
@@ -0,0 +1,38 @@
+From a6bbcd6741d53b326a2a3a7edef6e15334de6ea3 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Thu, 29 Nov 2012 08:37:03 -0600
+Subject: ceph: don't reference req after put
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 7d5f24812bd182a2471cb69c1c2baf0648332e1f)
+
+In __unregister_request(), there is a call to list_del_init()
+referencing a request that was the subject of a call to
+ceph_osdc_put_request() on the previous line.  This is not
+safe, because the request structure could have been freed
+by the time we reach the list_del_init().
+
+Fix this by reversing the order of these lines.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/osd_client.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -873,9 +873,9 @@ static void __unregister_request(struct
+                       req->r_osd = NULL;
+       }
++      list_del_init(&req->r_req_lru_item);
+       ceph_osdc_put_request(req);
+-      list_del_init(&req->r_req_lru_item);
+       if (osdc->num_requests == 0) {
+               dout(" no requests, canceling timeout\n");
+               __cancel_osd_timeout(osdc);
diff --git a/queue-3.7/ceph-don-t-update-i_max_size-when-handling-non-auth-cap.patch b/queue-3.7/ceph-don-t-update-i_max_size-when-handling-non-auth-cap.patch
new file mode 100644 (file)
index 0000000..72f7353
--- /dev/null
@@ -0,0 +1,30 @@
+From 76c834d784c36bda3a8d56f5cdf3e1282b0979f9 Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+Date: Mon, 19 Nov 2012 10:49:04 +0800
+Subject: ceph: Don't update i_max_size when handling non-auth cap
+
+
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+
+(cherry picked from commit 5e62ad30157d0da04cf40c6d1a2f4bc840948b9c)
+
+The cap from non-auth mds doesn't have a meaningful max_size value.
+
+Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
+Signed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/caps.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ceph/caps.c
++++ b/fs/ceph/caps.c
+@@ -2388,7 +2388,7 @@ static void handle_cap_grant(struct inod
+                           &atime);
+       /* max size increase? */
+-      if (max_size != ci->i_max_size) {
++      if (ci->i_auth_cap == cap && max_size != ci->i_max_size) {
+               dout("max_size %lld -> %llu\n", ci->i_max_size, max_size);
+               ci->i_max_size = max_size;
+               if (max_size >= ci->i_wanted_max_size) {
diff --git a/queue-3.7/ceph-fix-__ceph_do_pending_vmtruncate.patch b/queue-3.7/ceph-fix-__ceph_do_pending_vmtruncate.patch
new file mode 100644 (file)
index 0000000..2c0000a
--- /dev/null
@@ -0,0 +1,55 @@
+From 0e6789acaba2e40768a778a1e553c92723a19a30 Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+Date: Mon, 19 Nov 2012 10:49:08 +0800
+Subject: ceph: Fix __ceph_do_pending_vmtruncate
+
+
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+
+(cherry picked from commit a85f50b6ef93fbbb2ae932ce9b2376509d172796)
+
+we should set i_truncate_pending to 0 after page cache is truncated
+to i_truncate_size
+
+Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
+Signed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/inode.c |   15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/fs/ceph/inode.c
++++ b/fs/ceph/inode.c
+@@ -1466,7 +1466,7 @@ void __ceph_do_pending_vmtruncate(struct
+ {
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       u64 to;
+-      int wrbuffer_refs, wake = 0;
++      int wrbuffer_refs, finish = 0;
+ retry:
+       spin_lock(&ci->i_ceph_lock);
+@@ -1498,15 +1498,18 @@ retry:
+       truncate_inode_pages(inode->i_mapping, to);
+       spin_lock(&ci->i_ceph_lock);
+-      ci->i_truncate_pending--;
+-      if (ci->i_truncate_pending == 0)
+-              wake = 1;
++      if (to == ci->i_truncate_size) {
++              ci->i_truncate_pending = 0;
++              finish = 1;
++      }
+       spin_unlock(&ci->i_ceph_lock);
++      if (!finish)
++              goto retry;
+       if (wrbuffer_refs == 0)
+               ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);
+-      if (wake)
+-              wake_up_all(&ci->i_cap_wq);
++
++      wake_up_all(&ci->i_cap_wq);
+ }
diff --git a/queue-3.7/ceph-fix-infinite-loop-in-__wake_requests.patch b/queue-3.7/ceph-fix-infinite-loop-in-__wake_requests.patch
new file mode 100644 (file)
index 0000000..12abc6c
--- /dev/null
@@ -0,0 +1,41 @@
+From 0fd2af5e838e87cf449c657b6e19535b64da6c4c Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+Date: Mon, 19 Nov 2012 10:49:06 +0800
+Subject: ceph: Fix infinite loop in __wake_requests
+
+
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+
+(cherry picked from commit ed75ec2cd19b47efcd292b6e23f58e56f4c5bc34)
+
+__wake_requests() will enter infinite loop if we use it to wake
+requests in the session->s_waiting list. __wake_requests() deletes
+requests from the list and __do_request() adds requests back to
+the list.
+
+Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
+Signed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/mds_client.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -1876,9 +1876,14 @@ finish:
+ static void __wake_requests(struct ceph_mds_client *mdsc,
+                           struct list_head *head)
+ {
+-      struct ceph_mds_request *req, *nreq;
++      struct ceph_mds_request *req;
++      LIST_HEAD(tmp_list);
+-      list_for_each_entry_safe(req, nreq, head, r_wait) {
++      list_splice_init(head, &tmp_list);
++
++      while (!list_empty(&tmp_list)) {
++              req = list_entry(tmp_list.next,
++                               struct ceph_mds_request, r_wait);
+               list_del_init(&req->r_wait);
+               __do_request(mdsc, req);
+       }
diff --git a/queue-3.7/libceph-avoid-using-freed-osd-in-__kick_osd_requests.patch b/queue-3.7/libceph-avoid-using-freed-osd-in-__kick_osd_requests.patch
new file mode 100644 (file)
index 0000000..d15abd0
--- /dev/null
@@ -0,0 +1,48 @@
+From f4a3fea610cb6a9fc9cb722a0765194e19b82e7b Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Fri, 7 Dec 2012 09:57:58 -0600
+Subject: libceph: avoid using freed osd in __kick_osd_requests()
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 685a7555ca69030739ddb57a47f0ea8ea80196a4)
+
+If an osd has no requests and no linger requests, __reset_osd()
+will just remove it with a call to __remove_osd().  That drops
+a reference to the osd, and therefore the osd may have been free
+by the time __reset_osd() returns.  That function offers no
+indication this may have occurred, and as a result the osd will
+continue to be used even when it's no longer valid.
+
+Change__reset_osd() so it returns an error (ENODEV) when it
+deletes the osd being reset.  And change __kick_osd_requests() so it
+returns immediately (before referencing osd again) if __reset_osd()
+returns *any* error.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/osd_client.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -581,7 +581,7 @@ static void __kick_osd_requests(struct c
+       dout("__kick_osd_requests osd%d\n", osd->o_osd);
+       err = __reset_osd(osdc, osd);
+-      if (err == -EAGAIN)
++      if (err)
+               return;
+       list_for_each_entry(req, &osd->o_requests, r_osd_item) {
+@@ -752,6 +752,7 @@ static int __reset_osd(struct ceph_osd_c
+       if (list_empty(&osd->o_requests) &&
+           list_empty(&osd->o_linger_requests)) {
+               __remove_osd(osdc, osd);
++              ret = -ENODEV;
+       } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd],
+                         &osd->o_con.peer_addr,
+                         sizeof(osd->o_con.peer_addr)) == 0 &&
diff --git a/queue-3.7/libceph-fix-osdmap-decode-error-paths.patch b/queue-3.7/libceph-fix-osdmap-decode-error-paths.patch
new file mode 100644 (file)
index 0000000..1aaa420
--- /dev/null
@@ -0,0 +1,103 @@
+From 71630f053c8da3b7d8e52c99ff2592f44dd28979 Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Mon, 29 Oct 2012 11:01:42 -0700
+Subject: libceph: fix osdmap decode error paths
+
+
+From: Sage Weil <sage@inktank.com>
+
+(cherry picked from commit 0ed7285e0001b960c888e5455ae982025210ed3d)
+
+Ensure that we set the err value correctly so that we do not pass a 0
+value to ERR_PTR and confuse the calling code.  (In particular,
+osd_client.c handle_map() will BUG(!newmap)).
+
+Signed-off-by: Sage Weil <sage@inktank.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/osdmap.c |   31 ++++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 11 deletions(-)
+
+--- a/net/ceph/osdmap.c
++++ b/net/ceph/osdmap.c
+@@ -645,10 +645,12 @@ struct ceph_osdmap *osdmap_decode(void *
+       ceph_decode_32_safe(p, end, max, bad);
+       while (max--) {
+               ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad);
++              err = -ENOMEM;
+               pi = kzalloc(sizeof(*pi), GFP_NOFS);
+               if (!pi)
+                       goto bad;
+               pi->id = ceph_decode_32(p);
++              err = -EINVAL;
+               ev = ceph_decode_8(p); /* encoding version */
+               if (ev > CEPH_PG_POOL_VERSION) {
+                       pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
+@@ -664,8 +666,13 @@ struct ceph_osdmap *osdmap_decode(void *
+               __insert_pg_pool(&map->pg_pools, pi);
+       }
+-      if (version >= 5 && __decode_pool_names(p, end, map) < 0)
+-              goto bad;
++      if (version >= 5) {
++              err = __decode_pool_names(p, end, map);
++              if (err < 0) {
++                      dout("fail to decode pool names");
++                      goto bad;
++              }
++      }
+       ceph_decode_32_safe(p, end, map->pool_max, bad);
+@@ -745,7 +752,7 @@ struct ceph_osdmap *osdmap_decode(void *
+       return map;
+ bad:
+-      dout("osdmap_decode fail\n");
++      dout("osdmap_decode fail err %d\n", err);
+       ceph_osdmap_destroy(map);
+       return ERR_PTR(err);
+ }
+@@ -839,6 +846,7 @@ struct ceph_osdmap *osdmap_apply_increme
+               if (ev > CEPH_PG_POOL_VERSION) {
+                       pr_warning("got unknown v %d > %d of ceph_pg_pool\n",
+                                  ev, CEPH_PG_POOL_VERSION);
++                      err = -EINVAL;
+                       goto bad;
+               }
+               pi = __lookup_pg_pool(&map->pg_pools, pool);
+@@ -855,8 +863,11 @@ struct ceph_osdmap *osdmap_apply_increme
+               if (err < 0)
+                       goto bad;
+       }
+-      if (version >= 5 && __decode_pool_names(p, end, map) < 0)
+-              goto bad;
++      if (version >= 5) {
++              err = __decode_pool_names(p, end, map);
++              if (err < 0)
++                      goto bad;
++      }
+       /* old_pool */
+       ceph_decode_32_safe(p, end, len, bad);
+@@ -932,15 +943,13 @@ struct ceph_osdmap *osdmap_apply_increme
+                       (void) __remove_pg_mapping(&map->pg_temp, pgid);
+                       /* insert */
+-                      if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) {
+-                              err = -EINVAL;
++                      err = -EINVAL;
++                      if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32))
+                               goto bad;
+-                      }
++                      err = -ENOMEM;
+                       pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS);
+-                      if (!pg) {
+-                              err = -ENOMEM;
++                      if (!pg)
+                               goto bad;
+-                      }
+                       pg->pgid = pgid;
+                       pg->len = pglen;
+                       for (j = 0; j < pglen; j++)
diff --git a/queue-3.7/libceph-fix-protocol-feature-mismatch-failure-path.patch b/queue-3.7/libceph-fix-protocol-feature-mismatch-failure-path.patch
new file mode 100644 (file)
index 0000000..a056609
--- /dev/null
@@ -0,0 +1,75 @@
+From f10a18433a1b3192e71eecffeaeca5f5f1694016 Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Thu, 27 Dec 2012 20:27:04 -0600
+Subject: libceph: fix protocol feature mismatch failure path
+
+
+From: Sage Weil <sage@inktank.com>
+
+(cherry picked from commit 0fa6ebc600bc8e830551aee47a0e929e818a1868)
+
+We should not set con->state to CLOSED here; that happens in
+ceph_fault() in the caller, where it first asserts that the state
+is not yet CLOSED.  Avoids a BUG when the features don't match.
+
+Since the fail_protocol() has become a trivial wrapper, replace
+calls to it with direct calls to reset_connection().
+
+Signed-off-by: Sage Weil <sage@inktank.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/messenger.c |   14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -506,6 +506,7 @@ static void reset_connection(struct ceph
+ {
+       /* reset connection, out_queue, msg_ and connect_seq */
+       /* discard existing out_queue and msg_seq */
++      dout("reset_connection %p\n", con);
+       ceph_msg_remove_list(&con->out_queue);
+       ceph_msg_remove_list(&con->out_sent);
+@@ -1506,13 +1507,6 @@ static int process_banner(struct ceph_co
+       return 0;
+ }
+-static void fail_protocol(struct ceph_connection *con)
+-{
+-      reset_connection(con);
+-      WARN_ON(con->state != CON_STATE_NEGOTIATING);
+-      con->state = CON_STATE_CLOSED;
+-}
+-
+ static int process_connect(struct ceph_connection *con)
+ {
+       u64 sup_feat = con->msgr->supported_features;
+@@ -1530,7 +1524,7 @@ static int process_connect(struct ceph_c
+                      ceph_pr_addr(&con->peer_addr.in_addr),
+                      sup_feat, server_feat, server_feat & ~sup_feat);
+               con->error_msg = "missing required protocol features";
+-              fail_protocol(con);
++              reset_connection(con);
+               return -1;
+       case CEPH_MSGR_TAG_BADPROTOVER:
+@@ -1541,7 +1535,7 @@ static int process_connect(struct ceph_c
+                      le32_to_cpu(con->out_connect.protocol_version),
+                      le32_to_cpu(con->in_reply.protocol_version));
+               con->error_msg = "protocol version mismatch";
+-              fail_protocol(con);
++              reset_connection(con);
+               return -1;
+       case CEPH_MSGR_TAG_BADAUTHORIZER:
+@@ -1631,7 +1625,7 @@ static int process_connect(struct ceph_c
+                              ceph_pr_addr(&con->peer_addr.in_addr),
+                              req_feat, server_feat, req_feat & ~server_feat);
+                       con->error_msg = "missing required protocol features";
+-                      fail_protocol(con);
++                      reset_connection(con);
+                       return -1;
+               }
diff --git a/queue-3.7/libceph-remove-osdtimeout-option.patch b/queue-3.7/libceph-remove-osdtimeout-option.patch
new file mode 100644 (file)
index 0000000..13f62ac
--- /dev/null
@@ -0,0 +1,161 @@
+From aa852ff17166b53b1d29388af472bb9c32297f05 Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Wed, 28 Nov 2012 12:28:24 -0800
+Subject: libceph: remove 'osdtimeout' option
+
+
+From: Sage Weil <sage@inktank.com>
+
+(cherry picked from commit 83aff95eb9d60aff5497e9f44a2ae906b86d8e88)
+
+This would reset a connection with any OSD that had an outstanding
+request that was taking more than N seconds.  The idea was that if the
+OSD was buggy, the client could compensate by resending the request.
+
+In reality, this only served to hide server bugs, and we haven't
+actually seen such a bug in quite a while.  Moreover, the userspace
+client code never did this.
+
+More importantly, often the request is taking a long time because the
+OSD is trying to recover, or overloaded, and killing the connection
+and retrying would only make the situation worse by giving the OSD
+more work to do.
+
+Signed-off-by: Sage Weil <sage@inktank.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/super.c              |    2 -
+ include/linux/ceph/libceph.h |    2 -
+ net/ceph/ceph_common.c       |    3 --
+ net/ceph/osd_client.c        |   47 +++----------------------------------------
+ 4 files changed, 5 insertions(+), 49 deletions(-)
+
+--- a/fs/ceph/super.c
++++ b/fs/ceph/super.c
+@@ -403,8 +403,6 @@ static int ceph_show_options(struct seq_
+               seq_printf(m, ",mount_timeout=%d", opt->mount_timeout);
+       if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
+               seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl);
+-      if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT)
+-              seq_printf(m, ",osdtimeout=%d", opt->osd_timeout);
+       if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
+               seq_printf(m, ",osdkeepalivetimeout=%d",
+                          opt->osd_keepalive_timeout);
+--- a/include/linux/ceph/libceph.h
++++ b/include/linux/ceph/libceph.h
+@@ -43,7 +43,6 @@ struct ceph_options {
+       struct ceph_entity_addr my_addr;
+       int mount_timeout;
+       int osd_idle_ttl;
+-      int osd_timeout;
+       int osd_keepalive_timeout;
+       /*
+@@ -63,7 +62,6 @@ struct ceph_options {
+  * defaults
+  */
+ #define CEPH_MOUNT_TIMEOUT_DEFAULT  60
+-#define CEPH_OSD_TIMEOUT_DEFAULT    60  /* seconds */
+ #define CEPH_OSD_KEEPALIVE_DEFAULT  5
+ #define CEPH_OSD_IDLE_TTL_DEFAULT    60
+--- a/net/ceph/ceph_common.c
++++ b/net/ceph/ceph_common.c
+@@ -305,7 +305,6 @@ ceph_parse_options(char *options, const
+       /* start with defaults */
+       opt->flags = CEPH_OPT_DEFAULT;
+-      opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT;
+       opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
+       opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */
+       opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;   /* seconds */
+@@ -391,7 +390,7 @@ ceph_parse_options(char *options, const
+                       /* misc */
+               case Opt_osdtimeout:
+-                      opt->osd_timeout = intval;
++                      pr_warning("ignoring deprecated osdtimeout option\n");
+                       break;
+               case Opt_osdkeepalivetimeout:
+                       opt->osd_keepalive_timeout = intval;
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -608,14 +608,6 @@ static void __kick_osd_requests(struct c
+       }
+ }
+-static void kick_osd_requests(struct ceph_osd_client *osdc,
+-                            struct ceph_osd *kickosd)
+-{
+-      mutex_lock(&osdc->request_mutex);
+-      __kick_osd_requests(osdc, kickosd);
+-      mutex_unlock(&osdc->request_mutex);
+-}
+-
+ /*
+  * If the osd connection drops, we need to resubmit all requests.
+  */
+@@ -629,7 +621,9 @@ static void osd_reset(struct ceph_connec
+       dout("osd_reset osd%d\n", osd->o_osd);
+       osdc = osd->o_osdc;
+       down_read(&osdc->map_sem);
+-      kick_osd_requests(osdc, osd);
++      mutex_lock(&osdc->request_mutex);
++      __kick_osd_requests(osdc, osd);
++      mutex_unlock(&osdc->request_mutex);
+       send_queued(osdc);
+       up_read(&osdc->map_sem);
+ }
+@@ -1093,12 +1087,10 @@ static void handle_timeout(struct work_s
+ {
+       struct ceph_osd_client *osdc =
+               container_of(work, struct ceph_osd_client, timeout_work.work);
+-      struct ceph_osd_request *req, *last_req = NULL;
++      struct ceph_osd_request *req;
+       struct ceph_osd *osd;
+-      unsigned long timeout = osdc->client->options->osd_timeout * HZ;
+       unsigned long keepalive =
+               osdc->client->options->osd_keepalive_timeout * HZ;
+-      unsigned long last_stamp = 0;
+       struct list_head slow_osds;
+       dout("timeout\n");
+       down_read(&osdc->map_sem);
+@@ -1108,37 +1100,6 @@ static void handle_timeout(struct work_s
+       mutex_lock(&osdc->request_mutex);
+       /*
+-       * reset osds that appear to be _really_ unresponsive.  this
+-       * is a failsafe measure.. we really shouldn't be getting to
+-       * this point if the system is working properly.  the monitors
+-       * should mark the osd as failed and we should find out about
+-       * it from an updated osd map.
+-       */
+-      while (timeout && !list_empty(&osdc->req_lru)) {
+-              req = list_entry(osdc->req_lru.next, struct ceph_osd_request,
+-                               r_req_lru_item);
+-
+-              /* hasn't been long enough since we sent it? */
+-              if (time_before(jiffies, req->r_stamp + timeout))
+-                      break;
+-
+-              /* hasn't been long enough since it was acked? */
+-              if (req->r_request->ack_stamp == 0 ||
+-                  time_before(jiffies, req->r_request->ack_stamp + timeout))
+-                      break;
+-
+-              BUG_ON(req == last_req && req->r_stamp == last_stamp);
+-              last_req = req;
+-              last_stamp = req->r_stamp;
+-
+-              osd = req->r_osd;
+-              BUG_ON(!osd);
+-              pr_warning(" tid %llu timed out on osd%d, will reset osd\n",
+-                         req->r_tid, osd->o_osd);
+-              __kick_osd_requests(osdc, osd);
+-      }
+-
+-      /*
+        * ping osds that are a bit slow.  this ensures that if there
+        * is a break in the TCP connection we will notice, and reopen
+        * a connection with that osd (from the fault callback).
diff --git a/queue-3.7/libceph-unlock-unprocessed-pages-in-start_read-error-path.patch b/queue-3.7/libceph-unlock-unprocessed-pages-in-start_read-error-path.patch
new file mode 100644 (file)
index 0000000..76d9b41
--- /dev/null
@@ -0,0 +1,47 @@
+From 9fa5ba96f32fbea354457fc7ece06b2ee81b1b71 Mon Sep 17 00:00:00 2001
+From: David Zafman <david.zafman@inktank.com>
+Date: Mon, 3 Dec 2012 19:14:05 -0800
+Subject: libceph: Unlock unprocessed pages in start_read() error path
+
+
+From: David Zafman <david.zafman@inktank.com>
+
+(cherry picked from commit 8884d53dd63b1d9315b343564fcbe1ede004a99e)
+
+Function start_read() can get an error before processing all pages.
+It must not only release the remaining pages, but unlock them too.
+
+This fixes http://tracker.newdream.net/issues/3370
+
+Signed-off-by: David Zafman <david.zafman@inktank.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/addr.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/fs/ceph/addr.c
++++ b/fs/ceph/addr.c
+@@ -267,6 +267,14 @@ static void finish_read(struct ceph_osd_
+       kfree(req->r_pages);
+ }
++static void ceph_unlock_page_vector(struct page **pages, int num_pages)
++{
++      int i;
++
++      for (i = 0; i < num_pages; i++)
++              unlock_page(pages[i]);
++}
++
+ /*
+  * start an async read(ahead) operation.  return nr_pages we submitted
+  * a read for on success, or negative error code.
+@@ -347,6 +355,7 @@ static int start_read(struct inode *inod
+       return nr_pages;
+ out_pages:
++      ceph_unlock_page_vector(pages, nr_pages);
+       ceph_release_page_vector(pages, nr_pages);
+ out:
+       ceph_osdc_put_request(req);
diff --git a/queue-3.7/rbd-do-not-allow-remove-of-mounted-on-image.patch b/queue-3.7/rbd-do-not-allow-remove-of-mounted-on-image.patch
new file mode 100644 (file)
index 0000000..64bea18
--- /dev/null
@@ -0,0 +1,74 @@
+From 730406993ec6d044a81115fc19091ba6abfcbb15 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Fri, 16 Nov 2012 09:29:16 -0600
+Subject: rbd: do not allow remove of mounted-on image
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 42382b709bd1d143b9f0fa93e0a3a1f2f4210707)
+
+There is no check in rbd_remove() to see if anybody holds open the
+image being removed.  That's not cool.
+
+Add a simple open count that goes up and down with opens and closes
+(releases) of the device, and don't allow an rbd image to be removed
+if the count is non-zero.
+
+Protect the updates of the open count value with ctl_mutex to ensure
+the underlying rbd device doesn't get removed while concurrently
+being opened.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c |   13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -207,6 +207,7 @@ struct rbd_device {
+       /* sysfs related */
+       struct device           dev;
++      unsigned long           open_count;
+ };
+ static DEFINE_MUTEX(ctl_mutex);         /* Serialize open/close/setup/teardown */
+@@ -280,8 +281,11 @@ static int rbd_open(struct block_device
+       if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only)
+               return -EROFS;
++      mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+       rbd_get_dev(rbd_dev);
+       set_device_ro(bdev, rbd_dev->mapping.read_only);
++      rbd_dev->open_count++;
++      mutex_unlock(&ctl_mutex);
+       return 0;
+ }
+@@ -290,7 +294,11 @@ static int rbd_release(struct gendisk *d
+ {
+       struct rbd_device *rbd_dev = disk->private_data;
++      mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
++      rbd_assert(rbd_dev->open_count > 0);
++      rbd_dev->open_count--;
+       rbd_put_dev(rbd_dev);
++      mutex_unlock(&ctl_mutex);
+       return 0;
+ }
+@@ -3221,6 +3229,11 @@ static ssize_t rbd_remove(struct bus_typ
+               goto done;
+       }
++      if (rbd_dev->open_count) {
++              ret = -EBUSY;
++              goto done;
++      }
++
+       rbd_remove_all_snaps(rbd_dev);
+       rbd_bus_del_dev(rbd_dev);
diff --git a/queue-3.7/rbd-fix-bug-in-rbd_dev_id_put.patch b/queue-3.7/rbd-fix-bug-in-rbd_dev_id_put.patch
new file mode 100644 (file)
index 0000000..eaa7cc0
--- /dev/null
@@ -0,0 +1,37 @@
+From 8824d0eb9dee3bad29e9dba796d5d7953cab6719 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Wed, 10 Oct 2012 21:19:13 -0700
+Subject: rbd: fix bug in rbd_dev_id_put()
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit b213e0b1a62637b2a9395a34349b13d73ca2b90a)
+
+In rbd_dev_id_put(), there's a loop that's intended to determine
+the maximum device id in use.  But it isn't doing that at all,
+the effect of how it's written is to simply use the just-put id
+number, which ignores whole purpose of this function.
+
+Fix the bug.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -2621,8 +2621,8 @@ static void rbd_dev_id_put(struct rbd_de
+               struct rbd_device *rbd_dev;
+               rbd_dev = list_entry(tmp, struct rbd_device, node);
+-              if (rbd_id > max_id)
+-                      max_id = rbd_id;
++              if (rbd_dev->dev_id > max_id)
++                      max_id = rbd_dev->dev_id;
+       }
+       spin_unlock(&rbd_dev_list_lock);
diff --git a/queue-3.7/rbd-fix-read-only-option-name.patch b/queue-3.7/rbd-fix-read-only-option-name.patch
new file mode 100644 (file)
index 0000000..9d63019
--- /dev/null
@@ -0,0 +1,36 @@
+From 9aca7b487cf1c996a13ff5abf0ea4ac560ea1dd4 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Mon, 22 Oct 2012 11:31:26 -0500
+Subject: rbd: fix read-only option name
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit be466c1cc36621590ef17b05a6d342dfd33f7280)
+
+The name of the "read-only" mapping option was inadvertently changed
+in this commit:
+
+    f84344f3 rbd: separate mapping info in rbd_dev
+
+Revert that hunk to return it to what it should be.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Dan Mick <dan.mick@inktank.com>
+Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -388,7 +388,7 @@ enum {
+ static match_table_t rbd_opts_tokens = {
+       /* int args above */
+       /* string args above */
+-      {Opt_read_only, "mapping.read_only"},
++      {Opt_read_only, "read_only"},
+       {Opt_read_only, "ro"},          /* Alternate spelling */
+       {Opt_read_write, "read_write"},
+       {Opt_read_write, "rw"},         /* Alternate spelling */
diff --git a/queue-3.7/rbd-get-rid-of-rbd_max_seg_name_len.patch b/queue-3.7/rbd-get-rid-of-rbd_max_seg_name_len.patch
new file mode 100644 (file)
index 0000000..1aba138
--- /dev/null
@@ -0,0 +1,62 @@
+From 965f03ad3d796d03ec16f9809cb0096a64f6523d Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Fri, 9 Nov 2012 15:05:54 -0600
+Subject: rbd: get rid of RBD_MAX_SEG_NAME_LEN
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 2fd82b9e92c2a718ae81fc987b4468ceeee6979b)
+
+RBD_MAX_SEG_NAME_LEN represents the maximum length of an rbd object
+name (i.e., one of the objects providing storage backing an rbd
+image).
+
+Another symbol, MAX_OBJ_NAME_SIZE, is used in the osd client code to
+define the maximum length of any object name in an osd request.
+
+Right now they disagree, with RBD_MAX_SEG_NAME_LEN being too big.
+
+There's no real benefit at this point to defining the rbd object
+name length limit separate from any other object name, so just
+get rid of RBD_MAX_SEG_NAME_LEN and use MAX_OBJ_NAME_SIZE in its
+place.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c       |    6 +++---
+ drivers/block/rbd_types.h |    2 --
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -706,13 +706,13 @@ static char *rbd_segment_name(struct rbd
+       u64 segment;
+       int ret;
+-      name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
++      name = kmalloc(MAX_OBJ_NAME_SIZE + 1, GFP_NOIO);
+       if (!name)
+               return NULL;
+       segment = offset >> rbd_dev->header.obj_order;
+-      ret = snprintf(name, RBD_MAX_SEG_NAME_LEN, "%s.%012llx",
++      ret = snprintf(name, MAX_OBJ_NAME_SIZE + 1, "%s.%012llx",
+                       rbd_dev->header.object_prefix, segment);
+-      if (ret < 0 || ret >= RBD_MAX_SEG_NAME_LEN) {
++      if (ret < 0 || ret > MAX_OBJ_NAME_SIZE) {
+               pr_err("error formatting segment name for #%llu (%d)\n",
+                       segment, ret);
+               kfree(name);
+--- a/drivers/block/rbd_types.h
++++ b/drivers/block/rbd_types.h
+@@ -46,8 +46,6 @@
+ #define RBD_MIN_OBJ_ORDER       16
+ #define RBD_MAX_OBJ_ORDER       30
+-#define RBD_MAX_SEG_NAME_LEN  128
+-
+ #define RBD_COMP_NONE         0
+ #define RBD_CRYPT_NONE                0
diff --git a/queue-3.7/rbd-increase-maximum-snapshot-name-length.patch b/queue-3.7/rbd-increase-maximum-snapshot-name-length.patch
new file mode 100644 (file)
index 0000000..f704b39
--- /dev/null
@@ -0,0 +1,77 @@
+From 1306be442fda1b7a92b879ab18a535f56da5ab0a Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Tue, 3 Jul 2012 16:01:19 -0500
+Subject: rbd: increase maximum snapshot name length
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit d4b125e9eb43babd14538ba61718e3db71a98d29)
+
+Change RBD_MAX_SNAP_NAME_LEN to be based on NAME_MAX.  That is a
+practical limit for the length of a snapshot name (based on the
+presence of a directory using the name under /sys/bus/rbd to
+represent the snapshot).
+
+The /sys entry is created by prefixing it with "snap_"; define that
+prefix symbolically, and take its length into account in defining
+the snapshot name length limit.
+
+Enforce the limit in rbd_add_parse_args().  Also delete a dout()
+call in that function that was not meant to be committed.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Dan Mick <dan.mick@inktank.com>
+Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c |   16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -61,7 +61,10 @@
+ #define RBD_MINORS_PER_MAJOR  256             /* max minors per blkdev */
+-#define RBD_MAX_SNAP_NAME_LEN 32
++#define RBD_SNAP_DEV_NAME_PREFIX      "snap_"
++#define RBD_MAX_SNAP_NAME_LEN \
++                      (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1))
++
+ #define RBD_MAX_SNAP_COUNT    510     /* allows max snapc to fit in 4KB */
+ #define RBD_MAX_OPT_LEN               1024
+@@ -2073,7 +2076,7 @@ static int rbd_register_snap_dev(struct
+       dev->type = &rbd_snap_device_type;
+       dev->parent = parent;
+       dev->release = rbd_snap_dev_release;
+-      dev_set_name(dev, "snap_%s", snap->name);
++      dev_set_name(dev, "%s%s", RBD_SNAP_DEV_NAME_PREFIX, snap->name);
+       dout("%s: registering device for snapshot %s\n", __func__, snap->name);
+       ret = device_register(dev);
+@@ -2766,8 +2769,13 @@ static char *rbd_add_parse_args(struct r
+       if (!rbd_dev->image_name)
+               goto out_err;
+-      /* Snapshot name is optional */
++      /* Snapshot name is optional; default is to use "head" */
++
+       len = next_token(&buf);
++      if (len > RBD_MAX_SNAP_NAME_LEN) {
++              err_ptr = ERR_PTR(-ENAMETOOLONG);
++              goto out_err;
++      }
+       if (!len) {
+               buf = RBD_SNAP_HEAD_NAME; /* No snapshot supplied */
+               len = sizeof (RBD_SNAP_HEAD_NAME) - 1;
+@@ -2778,8 +2786,6 @@ static char *rbd_add_parse_args(struct r
+       memcpy(snap_name, buf, len);
+       *(snap_name + len) = '\0';
+-dout("    SNAP_NAME is <%s>, len is %zd\n", snap_name, len);
+-
+       return snap_name;
+ out_err:
diff --git a/queue-3.7/rbd-remove-linger-unconditionally.patch b/queue-3.7/rbd-remove-linger-unconditionally.patch
new file mode 100644 (file)
index 0000000..c6727ca
--- /dev/null
@@ -0,0 +1,37 @@
+From 942784e7a6e2ef8f861043f65b054eb3ef10b2fd Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Thu, 6 Dec 2012 09:37:23 -0600
+Subject: rbd: remove linger unconditionally
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 61c74035626beb25a39b0273ccf7d75510bc36a1)
+
+In __unregister_linger_request(), the request is being removed
+from the osd client's req_linger list only when the request
+has a non-null osd pointer.  It should be done whether or not
+the request currently has an osd.
+
+This is most likely a non-issue because I believe the request
+will always have an osd when this function is called.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/osd_client.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -907,8 +907,8 @@ static void __unregister_linger_request(
+                                       struct ceph_osd_request *req)
+ {
+       dout("__unregister_linger_request %p\n", req);
++      list_del_init(&req->r_linger_item);
+       if (req->r_osd) {
+-              list_del_init(&req->r_linger_item);
+               list_del_init(&req->r_linger_osd);
+               if (list_empty(&req->r_osd->o_requests) &&
diff --git a/queue-3.7/rbd-remove-snapshots-on-error-in-rbd_add.patch b/queue-3.7/rbd-remove-snapshots-on-error-in-rbd_add.patch
new file mode 100644 (file)
index 0000000..5f45bfa
--- /dev/null
@@ -0,0 +1,110 @@
+From 21bc037520c252304c04d3bb8131fb3d4ba5b2c5 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Thu, 25 Oct 2012 23:34:40 -0500
+Subject: rbd: remove snapshots on error in rbd_add()
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit 41f38c2b2f8b66b176a0e548ef06294343a7bfa2)
+
+If rbd_dev_snaps_update() has ever been called for an rbd device
+structure there could be snapshot structures on its snaps list.
+In rbd_add(), this function is called but a subsequent error
+path neglected to clean up any of these snapshots.
+
+Add a call to rbd_remove_all_snaps() in the appropriate spot to
+remedy this.  Change a couple of error labels to be a little
+clearer while there.
+
+Drop the leading underscores from the function name; there's nothing
+special about that function that they might signify.  As suggested
+in review, the leading underscores in __rbd_remove_snap_dev() have
+been removed as well.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c |   20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -221,7 +221,7 @@ static int rbd_dev_snaps_update(struct r
+ static int rbd_dev_snaps_register(struct rbd_device *rbd_dev);
+ static void rbd_dev_release(struct device *dev);
+-static void __rbd_remove_snap_dev(struct rbd_snap *snap);
++static void rbd_remove_snap_dev(struct rbd_snap *snap);
+ static ssize_t rbd_add(struct bus_type *bus, const char *buf,
+                      size_t count);
+@@ -1710,13 +1710,13 @@ static int rbd_read_header(struct rbd_de
+       return ret;
+ }
+-static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev)
++static void rbd_remove_all_snaps(struct rbd_device *rbd_dev)
+ {
+       struct rbd_snap *snap;
+       struct rbd_snap *next;
+       list_for_each_entry_safe(snap, next, &rbd_dev->snaps, node)
+-              __rbd_remove_snap_dev(snap);
++              rbd_remove_snap_dev(snap);
+ }
+ /*
+@@ -2060,7 +2060,7 @@ static bool rbd_snap_registered(struct r
+       return ret;
+ }
+-static void __rbd_remove_snap_dev(struct rbd_snap *snap)
++static void rbd_remove_snap_dev(struct rbd_snap *snap)
+ {
+       list_del(&snap->node);
+       if (device_is_registered(&snap->dev))
+@@ -2442,7 +2442,7 @@ static int rbd_dev_snaps_update(struct r
+                       if (rbd_dev->mapping.snap_id == snap->id)
+                               rbd_dev->mapping.snap_exists = false;
+-                      __rbd_remove_snap_dev(snap);
++                      rbd_remove_snap_dev(snap);
+                       dout("%ssnap id %llu has been removed\n",
+                               rbd_dev->mapping.snap_id == snap->id ?
+                                                               "mapped " : "",
+@@ -3053,11 +3053,11 @@ static ssize_t rbd_add(struct bus_type *
+       /* no need to lock here, as rbd_dev is not registered yet */
+       rc = rbd_dev_snaps_update(rbd_dev);
+       if (rc)
+-              goto err_out_header;
++              goto err_out_probe;
+       rc = rbd_dev_set_mapping(rbd_dev, snap_name);
+       if (rc)
+-              goto err_out_header;
++              goto err_out_snaps;
+       /* generate unique id: find highest unique id, add one */
+       rbd_dev_id_get(rbd_dev);
+@@ -3121,7 +3121,9 @@ err_out_blkdev:
+       unregister_blkdev(rbd_dev->major, rbd_dev->name);
+ err_out_id:
+       rbd_dev_id_put(rbd_dev);
+-err_out_header:
++err_out_snaps:
++      rbd_remove_all_snaps(rbd_dev);
++err_out_probe:
+       rbd_header_free(&rbd_dev->header);
+ err_out_client:
+       kfree(rbd_dev->header_name);
+@@ -3219,7 +3221,7 @@ static ssize_t rbd_remove(struct bus_typ
+               goto done;
+       }
+-      __rbd_remove_all_snaps(rbd_dev);
++      rbd_remove_all_snaps(rbd_dev);
+       rbd_bus_del_dev(rbd_dev);
+ done:
diff --git a/queue-3.7/rbd-zero-return-code-in-rbd_dev_image_id.patch b/queue-3.7/rbd-zero-return-code-in-rbd_dev_image_id.patch
new file mode 100644 (file)
index 0000000..e9b2b05
--- /dev/null
@@ -0,0 +1,47 @@
+From cc8b5fcd343b3c99468fc9f0b4c3e03a7eafa7fc Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Wed, 10 Oct 2012 21:19:13 -0700
+Subject: rbd: zero return code in rbd_dev_image_id()
+
+
+From: Alex Elder <elder@inktank.com>
+
+(cherry picked from commit a0ea3a40fd20b8c66381f747c454f89d6d1f50d4)
+
+When rbd_dev_probe() calls rbd_dev_image_id() it expects to get
+a 0 return code if successful, but it is getting a positive value.
+
+The reason is that rbd_dev_image_id() returns the value it gets from
+rbd_req_sync_exec(), which returns the number of bytes read in as a
+result of the request.  (This ultimately comes from
+ceph_copy_from_page_vector() in rbd_req_sync_op()).
+
+Force the return value to 0 when successful in rbd_dev_image_id().
+Do the same in rbd_dev_v2_object_prefix().
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
+Reviewed-by: Dan Mick <dan.mick@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -2189,6 +2189,7 @@ static int rbd_dev_v2_object_prefix(stru
+       dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
+       if (ret < 0)
+               goto out;
++      ret = 0;    /* rbd_req_sync_exec() can return positive */
+       p = reply_buf;
+       rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p,
+@@ -2841,6 +2842,7 @@ static int rbd_dev_image_id(struct rbd_d
+       dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
+       if (ret < 0)
+               goto out;
++      ret = 0;    /* rbd_req_sync_exec() can return positive */
+       p = response;
+       rbd_dev->image_id = ceph_extract_encoded_string(&p,
index 3e99311f93e7caf4ccf0d7d305b5f44ae859dd5e..7e0314ea89d3e27035a3269d5c911fd76888168a 100644 (file)
@@ -197,3 +197,22 @@ kvm-ppc-44x-fix-dcr-read-write.patch
 0008-libceph-always-reset-osds-when-kicking.patch
 0009-libceph-WARN-don-t-BUG-on-unexpected-connection-stat.patch
 revert-drm-i915-no-lvds-quirk-for-zotac-zdbox-sd-id12-id13.patch
+libceph-fix-protocol-feature-mismatch-failure-path.patch
+libceph-fix-osdmap-decode-error-paths.patch
+libceph-avoid-using-freed-osd-in-__kick_osd_requests.patch
+libceph-remove-osdtimeout-option.patch
+ceph-don-t-reference-req-after-put.patch
+rbd-fix-bug-in-rbd_dev_id_put.patch
+rbd-zero-return-code-in-rbd_dev_image_id.patch
+rbd-fix-read-only-option-name.patch
+rbd-increase-maximum-snapshot-name-length.patch
+rbd-remove-snapshots-on-error-in-rbd_add.patch
+rbd-do-not-allow-remove-of-mounted-on-image.patch
+rbd-get-rid-of-rbd_max_seg_name_len.patch
+rbd-remove-linger-unconditionally.patch
+ceph-don-t-update-i_max_size-when-handling-non-auth-cap.patch
+ceph-fix-infinite-loop-in-__wake_requests.patch
+ceph-don-t-add-dirty-inode-to-dirty-list-if-caps-is-in-migration.patch
+ceph-fix-__ceph_do_pending_vmtruncate.patch
+ceph-call-handle_cap_grant-for-cap-import-message.patch
+libceph-unlock-unprocessed-pages-in-start_read-error-path.patch