3.4.20-stable review
Subsystems (49)
Greg Kroah-Hartman
maintainerPATCH 158/171 libceph: avoid dropping con mutex before fault
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 8636ea672f0c5ab7478c42c5b6705ebd1db7eb6a)
The ceph_fault() function takes the con mutex, so we should avoid dropping it before calling it. This fixes a potential race with another thread calling ceph_con_close(), or _open(), or similar (we don't reverify con->state after retaking the lock).
Add annotation so that lockdep realizes we will drop the mutex before returning.
--- net/ceph/messenger.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
net/ceph/messenger.c +1 -3
@@ -2336,7 +2336,6 @@ done_unlocked:return ; fault: -mutex_unlock (&con->mutex);ceph_fault (con);/* error/fault path */ goto done_unlocked; }
@@ -2347,9 +2346,8 @@ fault:* exponential backoff */ static void ceph_fault (struct ceph_connection *con) + __releases(con->mutex) { -mutex_lock (&con->mutex); -pr_err ("%s%lld %s %s\n" ,ENTITY_NAME (con->peer_name),ceph_pr_addr (&con->peer_addr.in_addr), con->error_msg); dout("fault %p state %lu to peer %s\n",
Greg Kroah-Hartman
maintainerPATCH 159/171 libceph: change ceph_con_in_msg_alloc convention to be less weird
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 4740a623d20c51d167da7f752b63e2b8714b2543)
This function's calling convention is very limiting. In particular, we can't return any error other than ENOMEM (and only implicitly), which is a problem (see next patch).
Instead, return an normal 0 or error code, and make the skip a pointer output parameter. Drop the useless in_hdr argument (we have the con pointer).
--- net/ceph/messenger.c | 56 ++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 25 deletions(-)
net/ceph/messenger.c +31 -25
@@ -1733,9 +1733,7 @@ static int read_partial_message_section(return 1 ; } -static bool ceph_con_in_msg_alloc (struct ceph_connection *con, -struct ceph_msg_header *hdr); - +static int ceph_con_in_msg_alloc (struct ceph_connection *con,int *skip); static int read_partial_message_pages(struct ceph_connection *con, struct page **pages,
@@ -1864,9 +1862,14 @@ static int read_partial_message(struct c/* allocate message? */ if (!con->in_msg) { +int skip =0 ; +dout ("got hdr type %d front %d data %d\n" , con->in_hdr.type, con->in_hdr.front_len, con->in_hdr.data_len); -if (ceph_con_in_msg_alloc (con, &con->in_hdr)) { + ret =ceph_con_in_msg_alloc (con, &skip); +if (ret <0 ) +return ret; +if (skip) {/* skip this message */ dout ("alloc_msg said skip message\n" );BUG_ON (con->in_msg);
@@ -1876,12 +1879,8 @@ static int read_partial_message(struct c con->in_seq++;return 0 ; } -if (!con->in_msg) { - con->error_msg = -"error allocating memory for incoming message" ; -return -ENOMEM ; - } +BUG_ON (!con->in_msg);BUG_ON (con->in_msg->con != con); m = con->in_msg; m->front.iov_len =0 ;/* haven't read it yet */
@@ -2715,43 +2714,50 @@ static int ceph_alloc_middle(struct ceph* connection, and save the result in con->in_msg. Uses the * connection's private alloc_msg op if available. * -* Returns true if the message should be skipped, false otherwise. -* If true is returned (skip message), con->in_msg will be NULL. -* If false is returned, con->in_msg will contain a pointer to the -* newly-allocated message, or NULL in case of memory exhaustion. +* Returns 0 on success, or a negative error code. +* +* On success, if we set *skip = 1: +* - the next message should be skipped and ignored. +* - con->in_msg == NULL +* or if we set *skip = 0: +* - con->in_msg is non-null. +* On error (ENOMEM, EAGAIN, ...), +* - con->in_msg == NULL */ -static bool ceph_con_in_msg_alloc (struct ceph_connection *con, -struct ceph_msg_header *hdr) +static int ceph_con_in_msg_alloc (struct ceph_connection *con,int *skip) { +struct ceph_msg_header *hdr = &con->in_hdr;int type =le16_to_cpu (hdr->type);int front_len =le32_to_cpu (hdr->front_len);int middle_len =le32_to_cpu (hdr->middle_len); -int ret; +int ret =0 ;BUG_ON (con->in_msg !=NULL );if (con->ops->alloc_msg) { -int skip =0 ; -mutex_unlock (&con->mutex); - con->in_msg = con->ops->alloc_msg (con, hdr, &skip); + con->in_msg = con->ops->alloc_msg (con, hdr, skip);mutex_lock (&con->mutex);if (con->in_msg) { con->in_msg->con = con->ops->get (con);BUG_ON (con->in_msg->con ==NULL ); } -if (skip) +if (*skip) { con->in_msg =NULL ; - -if (!con->in_msg) -return skip !=0 ; +return 0 ; + } +if (!con->in_msg) { + con->error_msg = +"error allocating memory for incoming message" ; +return -ENOMEM ; + } }if (!con->in_msg) { con->in_msg =ceph_msg_new (type, front_len,GFP_NOFS , false);if (!con->in_msg) {pr_err ("unable to allocate msg type %d len %d\n" , type, front_len); -return false; +return -ENOMEM ; } con->in_msg->con = con->ops->get (con);BUG_ON (con->in_msg->con ==NULL );
@@ -2767,7 +2773,7 @@ static bool ceph_con_in_msg_alloc(struct } } -return false; +return ret; }
Greg Kroah-Hartman
maintainerPATCH 160/171 libceph: recheck con state after allocating incoming message
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 6139919133377652992a5fe134e22abce3e9c25e)
We drop the lock when calling the ->alloc_msg() con op, which means we need to (a) not clobber con->in_msg without the mutex held, and (b) we need to verify that we are still in the OPEN state when we retake it to avoid causing any mayhem. If the state does change, -EAGAIN will get us back to con_work() and loop.
--- net/ceph/messenger.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
net/ceph/messenger.c +8 -1
@@ -2735,9 +2735,16 @@ static int ceph_con_in_msg_alloc(structBUG_ON (con->in_msg !=NULL );if (con->ops->alloc_msg) { +struct ceph_msg *msg; +mutex_unlock (&con->mutex); - con->in_msg = con->ops->alloc_msg (con, hdr, skip); + msg = con->ops->alloc_msg (con, hdr, skip);mutex_lock (&con->mutex); +if (con->state !=CON_STATE_OPEN ) { +ceph_msg_put (msg); +return -EAGAIN ; + } + con->in_msg = msg;if (con->in_msg) { con->in_msg->con = con->ops->get (con);BUG_ON (con->in_msg->con ==NULL );
Greg Kroah-Hartman
maintainerPATCH 161/171 libceph: fix crypto key null deref, memory leak
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sylvain Munaut <[email protected]>
(cherry picked from commit f0666b1ac875ff32fe290219b150ec62eebbe10e)
Avoid crashing if the crypto key payload was NULL, as when it was not correctly allocated and initialized. Also, avoid leaking it.
--- net/ceph/crypto.c | 1 + net/ceph/crypto.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
net/ceph/crypto.c +1 -0
@@ -466,6 +466,7 @@ void ceph_key_destroy(struct key *key) {struct ceph_crypto_key *ckey = key->payload.data;ceph_crypto_key_destroy (ckey); +kfree (ckey); }struct key_type key_type_ceph = {
net/ceph/crypto.h +2 -1
@@ -16,7 +16,8 @@ struct ceph_crypto_key {static inline void ceph_crypto_key_destroy (struct ceph_crypto_key *key) { -kfree (key->key); +if (key) +kfree (key->key); } extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
Greg Kroah-Hartman
maintainerPATCH 162/171 libceph: delay debugfs initialization until we learn global_id
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit d1c338a509cea5378df59629ad47382810c38623)
The debugfs directory includes the cluster fsid and our unique global_id. We need to delay the initialization of the debug entry until we have learned both the fsid and our global_id from the monitor or else the second client can't create its debugfs entry and will fail (and multiple client instances aren't properly reflected in debugfs).
Reported by: Yan, Zheng <[email protected]>
--- fs/ceph/debugfs.c | 1 net/ceph/ceph_common.c | 1 net/ceph/debugfs.c | 4 +++ net/ceph/mon_client.c | 51 ++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 51 insertions(+), 6 deletions(-)
fs/ceph/debugfs.c +1 -0
@@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_int err = -ENOMEM ;dout ("ceph_fs_debugfs_init\n" ); +BUG_ON (!fsc->client->debugfs_dir); fsc->debugfs_congestion_kb = debugfs_create_file("writeback_congestion_kb", 0600,
net/ceph/ceph_common.c +0 -1
@@ -83,7 +83,6 @@ int ceph_check_fsid(struct ceph_client *return -1 ; } }else { -pr_info ("client%lld fsid %pU\n" ,ceph_client_id (client), fsid);memcpy (&client->fsid, fsid,sizeof (*fsid)); }return 0 ;
net/ceph/debugfs.c +4 -0
@@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct cephsnprintf (name,sizeof (name),"%pU.client%lld" , &client->fsid, client->monc.auth->global_id); +dout ("ceph_debugfs_client_init %p %s\n" , client, name); + +BUG_ON (client->debugfs_dir); client->debugfs_dir =debugfs_create_dir (name, ceph_debugfs_dir);if (!client->debugfs_dir) goto out;
@@ -234,6 +237,7 @@ out:void ceph_debugfs_client_cleanup (struct ceph_client *client) { +dout ("ceph_debugfs_client_cleanup %p\n" , client);debugfs_remove (client->debugfs_osdmap);debugfs_remove (client->debugfs_monmap);debugfs_remove (client->osdc.debugfs_file);
net/ceph/mon_client.c +46 -5
88 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 163/171 libceph: avoid truncation due to racing banners
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jim Schutt <[email protected]>
(cherry picked from commit 6d4221b53707486dfad3f5bfe568d2ce7f4c9863)
Because the Ceph client messenger uses a non-blocking connect, it is possible for the sending of the client banner to race with the arrival of the banner sent by the peer.
When ceph_sock_state_change() notices the connect has completed, it schedules work to process the socket via con_work(). During this time the peer is writing its banner, and arrival of the peer banner races with con_work().
If con_work() calls try_read() before the peer banner arrives, there is nothing for it to do, after which con_work() calls try_write() to send the client's banner. In this case Ceph's protocol negotiation can complete succesfully.
The server-side messenger immediately sends its banner and addresses after accepting a connect request, *before* actually attempting to read or verify the banner from the client. As a result, it is possible for the banner from the server to arrive before con_work() calls try_read(). If that happens, try_read() will read the banner and prepare protocol negotiation info via prepare_write_connect(). prepare_write_connect() calls con_out_kvec_reset(), which discards the as-yet-unsent client banner. Next, con_work() calls try_write(), which sends the protocol negotiation info rather than the banner that the peer is expecting.
The result is that the peer sees an invalid banner, and the client reports "negotiation failed".
Fix this by moving con_out_kvec_reset() out of prepare_write_connect() to its callers at all locations except the one where the banner might still need to be sent.
[[email protected]: added note about server-side behavior]
--- net/ceph/messenger.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
net/ceph/messenger.c +9 -2
@@ -911,7 +911,6 @@ static int prepare_write_connect(struct con->out_connect.authorizer_len = auth ?cpu_to_le32 (auth->authorizer_buf_len) :0 ; -con_out_kvec_reset (con);con_out_kvec_add (con,sizeof (con->out_connect), &con->out_connect);if (auth && auth->authorizer_buf_len)
@@ -1553,6 +1552,7 @@ static int process_connect(struct ceph_creturn -1 ; } con->auth_retry =1 ; +con_out_kvec_reset (con); ret =prepare_write_connect (con);if (ret <0 )return ret;
@@ -1573,6 +1573,7 @@ static int process_connect(struct ceph_cENTITY_NAME (con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr));reset_connection (con); +con_out_kvec_reset (con); ret =prepare_write_connect (con);if (ret <0 )return ret;
@@ -1597,6 +1598,7 @@ static int process_connect(struct ceph_cle32_to_cpu (con->out_connect.connect_seq), le32_to_cpu(con->in_reply.connect_seq)); con->connect_seq =le32_to_cpu (con->in_reply.connect_seq); +con_out_kvec_reset (con); ret =prepare_write_connect (con);if (ret <0 )return ret;
@@ -1613,6 +1615,7 @@ static int process_connect(struct ceph_c le32_to_cpu(con->in_reply.global_seq));get_global_seq (con->msgr,le32_to_cpu (con->in_reply.global_seq)); +con_out_kvec_reset (con); ret =prepare_write_connect (con);if (ret <0 )return ret;
@@ -2131,7 +2134,11 @@ more:BUG_ON (con->state !=CON_STATE_CONNECTING ); con->state =CON_STATE_NEGOTIATING ; -/* Banner is good, exchange connection info */ +/* +* Received banner is good, exchange connection info. +* Do not reset out_kvec, as sending our banner raced +* with receiving peer banner after connect completed. +*/ ret =prepare_write_connect (con);if (ret <0 ) goto out;
Greg Kroah-Hartman
maintainerPATCH 164/171 libceph: only kunmap kmapped pages
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 5ce765a540f34d1e2005e1210f49f67fdf11e997)
In write_partial_msg_pages(), pages need to be kmapped in order to perform a CRC-32c calculation on them. As an artifact of the way this code used to be structured, the kunmap() call was separated from the kmap() call and both were done conditionally. But the conditions under which the kmap() and kunmap() calls were made differed, so there was a chance a kunmap() call would be done on a page that had not been mapped.
The symptom of this was tripping a BUG() in kunmap_high() when pkmap_count[nr] became 0.
--- net/ceph/messenger.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
net/ceph/messenger.c +1 -4
@@ -1069,16 +1069,13 @@ static int write_partial_msg_pages(strucBUG_ON (kaddr ==NULL ); base = kaddr + con->out_msg_pos.page_pos + bio_offset; crc =crc32c (crc, base, len); +kunmap (page); msg->footer.data_crc =cpu_to_le32 (crc); con->out_msg_pos.did_page_crc = true; } ret =ceph_tcp_sendpage (con->sock, page, con->out_msg_pos.page_pos + bio_offset, len,1 ); - -if (do_datacrc) -kunmap (page); -if (ret <=0 ) goto out;
Greg Kroah-Hartman
maintainerPATCH 165/171 rbd: reset BACKOFF if unable to re-queue
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 588377d6199034c36d335e7df5818b731fea072c)
If ceph_fault() is unable to queue work after a delay, it sets the BACKOFF connection flag so con_work() will attempt to do so.
In con_work(), when BACKOFF is set, if queue_delayed_work() doesn't result in newly-queued work, it simply ignores this condition and proceeds as if no backoff delay were desired. There are two problems with this--one of which is a bug.
The first problem is simply that the intended behavior is to back off, and if we aren't able queue the work item to run after a delay we're not doing that.
The only reason queue_delayed_work() won't queue work is if the provided work item is already queued. In the messenger, this means that con_work() is already scheduled to be run again. So if we simply set the BACKOFF flag again when this occurs, we know the next con_work() call will again attempt to hold off activity on the connection until after the delay.
The second problem--the bug--is a leak of a reference count. If queue_delayed_work() returns 0 in con_work(), con->ops->put() drops the connection reference held on entry to con_work(). However, processing is (was) allowed to continue, and at the end of the function a second con->ops->put() is called.
This patch fixes both problems.
--- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ceph/messenger.c +2 -1
@@ -2296,10 +2296,11 @@ restart:mutex_unlock (&con->mutex);return ; }else { - con->ops->put (con);dout ("con_work %p FAILED to back off %lu\n" , con, con->delay); +set_bit (CON_FLAG_BACKOFF , &con->flags); } + goto done; }if (con->state ==CON_STATE_STANDBY ) {
Greg Kroah-Hartman
maintainerPATCH 166/171 libceph: avoid NULL kref_put when osd reset races with alloc_msg
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 9bd952615a42d7e2ce3fa2c632e808e804637a1a)
The ceph_on_in_msg_alloc() method drops con->mutex while it allocates a message. If that races with a timeout that resends a zillion messages and resets the connection, and the ->alloc_msg() method returns a NULL message, it will call ceph_msg_put(NULL) and BUG.
Fix by only calling put if msg is non-NULL.
Fixes http://tracker.newdream.net/issues/3142
--- net/ceph/messenger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ceph/messenger.c +2 -1
@@ -2746,7 +2746,8 @@ static int ceph_con_in_msg_alloc(struct msg = con->ops->alloc_msg (con, hdr, skip);mutex_lock (&con->mutex);if (con->state !=CON_STATE_OPEN ) { -ceph_msg_put (msg); +if (msg) +ceph_msg_put (msg);return -EAGAIN ; } con->in_msg = msg;
Greg Kroah-Hartman
maintainerPATCH 167/171 ceph: Fix oops when handling mdsmap that decreases max_mds
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Yan, Zheng" <[email protected]>
(cherry picked from commit 3e8f43a089f06279c5f76a9ccd42578eebf7bfa5)
When i >= newmap->m_max_mds, ceph_mdsmap_get_addr(newmap, i) return NULL. Passing NULL to memcmp() triggers oops.
--- fs/ceph/mds_client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ceph/mds_client.c +2 -1
@@ -2634,7 +2634,8 @@ static void check_new_map(struct ceph_mdceph_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 ) {
Greg Kroah-Hartman
maintainerPATCH 168/171 libceph: check for invalid mapping
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit d63b77f4c552cc3a20506871046ab0fcbc332609)
If we encounter an invalid (e.g., zeroed) mapping, return an error and avoid a divide by zero.
--- 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(-)
include/linux/ceph/osd_client.h +1 -1
@@ -207,7 +207,7 @@ extern void ceph_osdc_handle_reply(strucextern 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,
include/linux/ceph/osdmap.h +3 -3
@@ -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,
net/ceph/osd_client.c +20 -12
@@ -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_osstruct 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_osdout ("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; }/*
net/ceph/osdmap.c +16 -2
@@ -952,7 +952,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)
@@ -966,11 +966,17 @@ void ceph_calc_file_object_mapping(strucdout ("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);
@@ -998,6 +1004,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);
Greg Kroah-Hartman
maintainerPATCH 169/171 ceph: avoid 32-bit page index overflow
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 6285bc231277419255f3498d3eb5ddc9f8e7fe79)
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
--- fs/ceph/addr.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
fs/ceph/addr.c +5 -6
@@ -205,7 +205,7 @@ static int readpage_nounlock(struct filedout ("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 )
@@ -286,7 +286,7 @@ static int start_read(struct inode *inodint nr_pages =0 ;int ret; - off = page->index <<PAGE_CACHE_SHIFT ; + off = (u64 )page_offset (page);/* count pages */ next_index = page->index;
@@ -426,7 +426,7 @@ static int writepage_nounlock(struct pagstruct 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 ;
@@ -817,8 +817,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,
@@ -1180,7 +1179,7 @@ static int ceph_page_mkwrite(struct vm_astruct 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;
Greg Kroah-Hartman
maintainerPATCH 170/171 ACPI video: Ignore errors after _DOD evaluation.
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Igor Murzov <[email protected]>
commit fba4e087361605d1eed63343bb08811f097c83ee upstream.
There are systems where video module known to work fine regardless of broken _DOD and ignoring returned value here doesn't cause any issues later. This should fix brightness controls on some laptops.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47861
--- drivers/acpi/video.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/acpi/video.c +7 -4
@@ -1345,12 +1345,15 @@ static int acpi_video_bus_get_devices(struct acpi_video_bus *video, struct acpi_device *device) { - int status; + int status = 0;struct acpi_device *dev; - status =acpi_video_device_enumerate (video); -if (status) -return status; +/* +* There are systems where video module known to work fine regardless +* of broken _DOD and ignoring returned value here doesn't cause +* any issues later. +*/ +acpi_video_device_enumerate (video);list_for_each_entry (dev, &device->children, node) {
Greg Kroah-Hartman
maintainerPATCH 171/171 Revert "serial: omap: fix software flow control"
In reply to Greg Kroah-Hartman3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felipe Balbi <[email protected]>
commit a4f743851f74fc3e0cc40c13082e65c24139f481 upstream.
This reverts commit 957ee7270d632245b43f6feb0e70d9a5e9ea6cf6 (serial: omap: fix software flow control).
As Russell has pointed out, that commit isn't fixing Software Flow Control at all, and it actually makes it even more broken.
It was agreed to revert this commit and use Russell's latest UART patches instead.
--- arch/arm/plat-omap/include/plat/omap-serial.h | 4 ++-- drivers/tty/serial/omap-serial.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-)
arch/arm/plat-omap/include/plat/omap-serial.h +2 -2
@@ -42,10 +42,10 @@#define OMAP_UART_WER_MOD_WKUP 0X7F/* Enable XON/XOFF flow control on output */ -#define OMAP_UART_SW_TX 0x8 +#define OMAP_UART_SW_TX 0x04/* Enable XON/XOFF flow control on input */ -#define OMAP_UART_SW_RX 0x2 +#define OMAP_UART_SW_RX 0x04#define OMAP_UART_SYSC_RESET 0X07#define OMAP_UART_TCR_TRIG 0X0F
drivers/tty/serial/omap-serial.c +6 -6
@@ -649,19 +649,19 @@ serial_omap_configure_xonxoff/* * IXON Flag: -* Flow control for OMAP.TX -* OMAP.RX should listen for XON/XOFF +* Enable XON/XOFF flow control on output. +* Transmit XON1, XOFF1 */ if (termios->c_iflag &IXON ) - up->efr |=OMAP_UART_SW_RX ; + up->efr |=OMAP_UART_SW_TX ;/* * IXOFF Flag: -* Flow control for OMAP.RX -* OMAP.TX should send XON/XOFF +* Enable XON/XOFF flow control on input. +* Receiver compares XON1, XOFF1. */ if (termios->c_iflag &IXOFF ) - up->efr |=OMAP_UART_SW_TX ; + up->efr |=OMAP_UART_SW_RX ;serial_out (up,UART_EFR , up->efr |UART_EFR_ECB );serial_out (up,UART_LCR ,UART_LCR_CONF_MODE_A );