+++ /dev/null
-From 6285bc231277419255f3498d3eb5ddc9f8e7fe79 Mon Sep 17 00:00:00 2001
-From: Alex Elder <elder@inktank.com>
-Date: Tue, 2 Oct 2012 10:25:51 -0500
-Subject: ceph: avoid 32-bit page index overflow
-
-From: Alex Elder <elder@inktank.com>
-
-commit 6285bc231277419255f3498d3eb5ddc9f8e7fe79 upstream.
-
-A pgoff_t is defined (by default) to have type (unsigned long). On
-architectures such as i686 that's a 32-bit type. The ceph address
-space code was attempting to produce 64 bit offsets by shifting a
-page's index by PAGE_CACHE_SHIFT, but the result was not what was
-desired because the shift occurred before the result got promoted
-to 64 bits.
-
-Fix this by converting all uses of page->index used in this way to
-use the page_offset() macro, which ensures the 64-bit result has the
-intended value.
-
-This fixes http://tracker.newdream.net/issues/3112
-
-Reported-by: Mohamed Pakkeer <pakkeer.mohideen@realimage.com>
-Signed-off-by: Alex Elder <elder@inktank.com>
-Reviewed-by: Sage Weil <sage@inktank.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- fs/ceph/addr.c | 11 +++++------
- 1 file changed, 5 insertions(+), 6 deletions(-)
-
---- a/fs/ceph/addr.c
-+++ b/fs/ceph/addr.c
-@@ -202,7 +202,7 @@ static int readpage_nounlock(struct file
- dout("readpage inode %p file %p page %p index %lu\n",
- inode, filp, page, page->index);
- err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout,
-- page->index << PAGE_CACHE_SHIFT, &len,
-+ (u64) page_offset(page), &len,
- ci->i_truncate_seq, ci->i_truncate_size,
- &page, 1, 0);
- if (err == -ENOENT)
-@@ -283,7 +283,7 @@ static int start_read(struct inode *inod
- int nr_pages = 0;
- int ret;
-
-- off = page->index << PAGE_CACHE_SHIFT;
-+ off = (u64) page_offset(page);
-
- /* count pages */
- next_index = page->index;
-@@ -423,7 +423,7 @@ static int writepage_nounlock(struct pag
- struct ceph_inode_info *ci;
- struct ceph_fs_client *fsc;
- struct ceph_osd_client *osdc;
-- loff_t page_off = page->index << PAGE_CACHE_SHIFT;
-+ loff_t page_off = page_offset(page);
- int len = PAGE_CACHE_SIZE;
- loff_t i_size;
- int err = 0;
-@@ -814,8 +814,7 @@ get_more_pages:
- /* ok */
- if (locked_pages == 0) {
- /* prepare async write request */
-- offset = (unsigned long long)page->index
-- << PAGE_CACHE_SHIFT;
-+ offset = (u64) page_offset(page);
- len = wsize;
- req = ceph_osdc_new_request(&fsc->client->osdc,
- &ci->i_layout,
-@@ -1177,7 +1176,7 @@ static int ceph_page_mkwrite(struct vm_a
- struct inode *inode = vma->vm_file->f_dentry->d_inode;
- struct page *page = vmf->page;
- struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
-- loff_t off = page->index << PAGE_CACHE_SHIFT;
-+ loff_t off = page_offset(page);
- loff_t size, len;
- int ret;
-
+++ /dev/null
-From 3e8f43a089f06279c5f76a9ccd42578eebf7bfa5 Mon Sep 17 00:00:00 2001
-From: "Yan, Zheng" <zheng.z.yan@intel.com>
-Date: Thu, 20 Sep 2012 17:42:25 +0800
-Subject: ceph: Fix oops when handling mdsmap that decreases max_mds
-
-From: "Yan, Zheng" <zheng.z.yan@intel.com>
-
-commit 3e8f43a089f06279c5f76a9ccd42578eebf7bfa5 upstream.
-
-When i >= newmap->m_max_mds, ceph_mdsmap_get_addr(newmap, i) return
-NULL. Passing NULL to memcmp() triggers oops.
-
-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 | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/fs/ceph/mds_client.c
-+++ b/fs/ceph/mds_client.c
-@@ -2636,7 +2636,8 @@ static void check_new_map(struct ceph_md
- ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "",
- session_state_name(s->s_state));
-
-- if (memcmp(ceph_mdsmap_get_addr(oldmap, i),
-+ if (i >= newmap->m_max_mds ||
-+ memcmp(ceph_mdsmap_get_addr(oldmap, i),
- ceph_mdsmap_get_addr(newmap, i),
- sizeof(struct ceph_entity_addr))) {
- if (s->s_state == CEPH_MDS_SESSION_OPENING) {
+++ /dev/null
-From d63b77f4c552cc3a20506871046ab0fcbc332609 Mon Sep 17 00:00:00 2001
-From: Sage Weil <sage@inktank.com>
-Date: Mon, 24 Sep 2012 20:59:48 -0700
-Subject: libceph: check for invalid mapping
-
-From: Sage Weil <sage@inktank.com>
-
-commit d63b77f4c552cc3a20506871046ab0fcbc332609 upstream.
-
-If we encounter an invalid (e.g., zeroed) mapping, return an error
-and avoid a divide by zero.
-
-Signed-off-by: Sage Weil <sage@inktank.com>
-Reviewed-by: Alex Elder <elder@inktank.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- include/linux/ceph/osd_client.h | 2 +-
- include/linux/ceph/osdmap.h | 6 +++---
- net/ceph/osd_client.c | 32 ++++++++++++++++++++------------
- net/ceph/osdmap.c | 18 ++++++++++++++++--
- 4 files changed, 40 insertions(+), 18 deletions(-)
-
---- a/include/linux/ceph/osd_client.h
-+++ b/include/linux/ceph/osd_client.h
-@@ -208,7 +208,7 @@ extern void ceph_osdc_handle_reply(struc
- extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc,
- struct ceph_msg *msg);
-
--extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
-+extern int ceph_calc_raw_layout(struct ceph_osd_client *osdc,
- struct ceph_file_layout *layout,
- u64 snapid,
- u64 off, u64 *plen, u64 *bno,
---- a/include/linux/ceph/osdmap.h
-+++ b/include/linux/ceph/osdmap.h
-@@ -111,9 +111,9 @@ extern struct ceph_osdmap *osdmap_apply_
- extern void ceph_osdmap_destroy(struct ceph_osdmap *map);
-
- /* calculate mapping of a file extent to an object */
--extern void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
-- u64 off, u64 *plen,
-- u64 *bno, u64 *oxoff, u64 *oxlen);
-+extern int ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
-+ u64 off, u64 *plen,
-+ u64 *bno, u64 *oxoff, u64 *oxlen);
-
- /* calculate mapping of object to a placement group */
- extern int ceph_calc_object_layout(struct ceph_object_layout *ol,
---- a/net/ceph/osd_client.c
-+++ b/net/ceph/osd_client.c
-@@ -52,7 +52,7 @@ static int op_has_extent(int op)
- op == CEPH_OSD_OP_WRITE);
- }
-
--void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
-+int ceph_calc_raw_layout(struct ceph_osd_client *osdc,
- struct ceph_file_layout *layout,
- u64 snapid,
- u64 off, u64 *plen, u64 *bno,
-@@ -62,12 +62,15 @@ void ceph_calc_raw_layout(struct ceph_os
- struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
- u64 orig_len = *plen;
- u64 objoff, objlen; /* extent in object */
-+ int r;
-
- reqhead->snapid = cpu_to_le64(snapid);
-
- /* object extent? */
-- ceph_calc_file_object_mapping(layout, off, plen, bno,
-- &objoff, &objlen);
-+ r = ceph_calc_file_object_mapping(layout, off, plen, bno,
-+ &objoff, &objlen);
-+ if (r < 0)
-+ return r;
- if (*plen < orig_len)
- dout(" skipping last %llu, final file extent %llu~%llu\n",
- orig_len - *plen, off, *plen);
-@@ -83,7 +86,7 @@ void ceph_calc_raw_layout(struct ceph_os
-
- dout("calc_layout bno=%llx %llu~%llu (%d pages)\n",
- *bno, objoff, objlen, req->r_num_pages);
--
-+ return 0;
- }
- EXPORT_SYMBOL(ceph_calc_raw_layout);
-
-@@ -112,20 +115,25 @@ EXPORT_SYMBOL(ceph_calc_raw_layout);
- *
- * fill osd op in request message.
- */
--static void calc_layout(struct ceph_osd_client *osdc,
-- struct ceph_vino vino,
-- struct ceph_file_layout *layout,
-- u64 off, u64 *plen,
-- struct ceph_osd_request *req,
-- struct ceph_osd_req_op *op)
-+static int calc_layout(struct ceph_osd_client *osdc,
-+ struct ceph_vino vino,
-+ struct ceph_file_layout *layout,
-+ u64 off, u64 *plen,
-+ struct ceph_osd_request *req,
-+ struct ceph_osd_req_op *op)
- {
- u64 bno;
-+ int r;
-
-- ceph_calc_raw_layout(osdc, layout, vino.snap, off,
-- plen, &bno, req, op);
-+ r = ceph_calc_raw_layout(osdc, layout, vino.snap, off,
-+ plen, &bno, req, op);
-+ if (r < 0)
-+ return r;
-
- snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno);
- req->r_oid_len = strlen(req->r_oid);
-+
-+ return r;
- }
-
- /*
---- a/net/ceph/osdmap.c
-+++ b/net/ceph/osdmap.c
-@@ -940,7 +940,7 @@ bad:
- * for now, we write only a single su, until we can
- * pass a stride back to the caller.
- */
--void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
-+int ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
- u64 off, u64 *plen,
- u64 *ono,
- u64 *oxoff, u64 *oxlen)
-@@ -954,11 +954,17 @@ void ceph_calc_file_object_mapping(struc
-
- dout("mapping %llu~%llu osize %u fl_su %u\n", off, *plen,
- osize, su);
-+ if (su == 0 || sc == 0)
-+ goto invalid;
- su_per_object = osize / su;
-+ if (su_per_object == 0)
-+ goto invalid;
- dout("osize %u / su %u = su_per_object %u\n", osize, su,
- su_per_object);
-
-- BUG_ON((su & ~PAGE_MASK) != 0);
-+ if ((su & ~PAGE_MASK) != 0)
-+ goto invalid;
-+
- /* bl = *off / su; */
- t = off;
- do_div(t, su);
-@@ -986,6 +992,14 @@ void ceph_calc_file_object_mapping(struc
- *plen = *oxlen;
-
- dout(" obj extent %llu~%llu\n", *oxoff, *oxlen);
-+ return 0;
-+
-+invalid:
-+ dout(" invalid layout\n");
-+ *ono = 0;
-+ *oxoff = 0;
-+ *oxlen = 0;
-+ return -EINVAL;
- }
- EXPORT_SYMBOL(ceph_calc_file_object_mapping);
-