diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c
index adfcf71efbda226db86b76a279ce4ad60176f5a2..457dd7e435de539c337e175063985812a1c0e1de 100644
--- a/lustre/lov/lov_obd.c
+++ b/lustre/lov/lov_obd.c
@@ -2361,7 +2361,7 @@ static int lov_get_info(struct obd_export *exp, __u32 keylen,
                 GOTO(out, rc = -ENXIO);
         } else if (KEY_IS("last_id")) {
                 obd_id *ids = val;
-                int size = sizeof(obd_id);
+                unsigned int size = sizeof(obd_id);
                 for (i = 0; i < lov->desc.ld_tgt_count; i++) {
                         if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
                                 continue;
diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c
index 76821e47f13a21c8dfbac7c0e350827ca7ff6d2c..450626e0ac77eae603660b263a49ddb0b7307435 100644
--- a/lustre/mds/handler.c
+++ b/lustre/mds/handler.c
@@ -1301,9 +1301,8 @@ static char *reint_names[] = {
 
 static int mds_set_info_rpc(struct obd_export *exp, struct ptlrpc_request *req)
 {
-        char *key;
-        __u32 *val;
-        int keylen, rc = 0;
+        void *key, *val;
+        int keylen, vallen, rc = 0;
         ENTRY;
 
         key = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, 1);
@@ -1313,25 +1312,27 @@ static int mds_set_info_rpc(struct obd_export *exp, struct ptlrpc_request *req)
         }
         keylen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF);
 
-        val = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1, sizeof(*val));
-        if (val == NULL) {
-                DEBUG_REQ(D_HA, req, "no set_info val");
-                RETURN(-EFAULT);
-        }
+        val = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1, 0);
+        vallen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF + 1);
 
         rc = lustre_pack_reply(req, 1, NULL, NULL);
         if (rc)
                 RETURN(rc);
         lustre_msg_set_status(req->rq_repmsg, 0);
 
-        if (keylen < strlen("read-only") ||
-            memcmp(key, "read-only", keylen) != 0)
-                RETURN(-EINVAL);
+        if (KEY_IS("read-only")) {
+                if (val == NULL || vallen < sizeof(__u32)) {
+                        DEBUG_REQ(D_HA, req, "no set_info val");
+                        RETURN(-EFAULT);
+                }
 
-        if (*val)
-                exp->exp_connect_flags |= OBD_CONNECT_RDONLY;
-        else
-                exp->exp_connect_flags &= ~OBD_CONNECT_RDONLY;
+                if (*(__u32 *)val)
+                        exp->exp_connect_flags |= OBD_CONNECT_RDONLY;
+                else
+                        exp->exp_connect_flags &= ~OBD_CONNECT_RDONLY;
+        } else {
+                RETURN(-EINVAL);
+        }
 
         RETURN(0);
 }
diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c
index bcdd5f539c3e512e63ac1dacffff81d41bf6ccd1..445e315fd2137a6a8c29e77314c8cfcb0259b1f3 100644
--- a/lustre/obdfilter/filter.c
+++ b/lustre/obdfilter/filter.c
@@ -3817,28 +3817,40 @@ static int filter_get_info(struct obd_export *exp, __u32 keylen,
                 RETURN(-EINVAL);
         }
 
-        if (keylen == strlen("blocksize") &&
-            memcmp(key, "blocksize", keylen) == 0) {
+        if (KEY_IS("blocksize")) {
                 __u32 *blocksize = val;
+                if (blocksize) {
+                        if (*vallen < sizeof(*blocksize))
+                                RETURN(-EOVERFLOW);
+                        *blocksize = obd->u.obt.obt_sb->s_blocksize;
+                }
                 *vallen = sizeof(*blocksize);
-                *blocksize = obd->u.obt.obt_sb->s_blocksize;
                 RETURN(0);
         }
 
-        if (keylen == strlen("blocksize_bits") &&
-            memcmp(key, "blocksize_bits", keylen) == 0) {
+        if (KEY_IS("blocksize_bits")) {
                 __u32 *blocksize_bits = val;
+                if (blocksize_bits) {
+                        if (*vallen < sizeof(*blocksize_bits))
+                                RETURN(-EOVERFLOW);
+                        *blocksize_bits = obd->u.obt.obt_sb->s_blocksize_bits;
+                }
                 *vallen = sizeof(*blocksize_bits);
-                *blocksize_bits = obd->u.obt.obt_sb->s_blocksize_bits;
                 RETURN(0);
         }
 
-        if (keylen >= strlen("last_id") && memcmp(key, "last_id", 7) == 0) {
+        if (KEY_IS("last_id")) {
                 obd_id *last_id = val;
                 /* FIXME: object groups */
-                *last_id = filter_last_id(&obd->u.filter, 0);
+                if (last_id) {
+                        if (*vallen < sizeof(*last_id))
+                                RETURN(-EOVERFLOW);
+                        *last_id = filter_last_id(&obd->u.filter, 0);
+                }
+                *vallen = sizeof(*last_id);
                 RETURN(0);
         }
+
         CDEBUG(D_IOCTL, "invalid key\n");
         RETURN(-EINVAL);
 }
@@ -3871,8 +3883,7 @@ static int filter_set_info_async(struct obd_export *exp, __u32 keylen,
                 RETURN(0);
         }
 
-        if (keylen < strlen(KEY_MDS_CONN) ||
-            memcmp(key, KEY_MDS_CONN, keylen) != 0)
+        if (!KEY_IS(KEY_MDS_CONN))
                 RETURN(-EINVAL);
 
         LCONSOLE_WARN("%s: received MDS connection from %s\n", obd->obd_name,
diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c
index bab0344ab2d82501222fe0b6ae4335307a193e64..d7bd9ded9d6b763f1e380adb48e871a9b3b6b5a9 100644
--- a/lustre/osc/osc_request.c
+++ b/lustre/osc/osc_request.c
@@ -3312,13 +3312,12 @@ static int osc_get_info(struct obd_export *exp, obd_count keylen,
         if (!vallen || !val)
                 RETURN(-EFAULT);
 
-        if (keylen > strlen("lock_to_stripe") &&
-            strcmp(key, "lock_to_stripe") == 0) {
+        if (KEY_IS("lock_to_stripe")) {
                 __u32 *stripe = val;
                 *vallen = sizeof(*stripe);
                 *stripe = 0;
                 RETURN(0);
-        } else if (keylen >= strlen("last_id") && strcmp(key, "last_id") == 0) {
+        } else if (KEY_IS("last_id")) {
                 struct ptlrpc_request *req;
                 obd_id *reply;
                 char *bufs[2] = { NULL, key };
diff --git a/lustre/ost/ost_handler.c b/lustre/ost/ost_handler.c
index 27e25bbd2f9a373fa33fbd97b54ac59aa7649520..4bb2054e7ee61fe653834cde9eae095fee2458ca 100644
--- a/lustre/ost/ost_handler.c
+++ b/lustre/ost/ost_handler.c
@@ -1268,10 +1268,9 @@ out:
 
 static int ost_get_info(struct obd_export *exp, struct ptlrpc_request *req)
 {
-        char *key;
+        void *key, *reply;
         int keylen, rc = 0;
-        int size[2] = { sizeof(struct ptlrpc_body), sizeof(obd_id) };
-        obd_id *reply;
+        int size[2] = { sizeof(struct ptlrpc_body), 0 };
         ENTRY;
 
         key = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, 1);
@@ -1281,16 +1280,20 @@ static int ost_get_info(struct obd_export *exp, struct ptlrpc_request *req)
         }
         keylen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF);
 
-        if (keylen < strlen("last_id") || memcmp(key, "last_id", 7) != 0)
-                RETURN(-EPROTO);
+        /* call once to get the size to allocate the reply buffer */
+        rc = obd_get_info(exp, keylen, key, &size[1], NULL);
+        if (rc)
+                RETURN(rc);
 
         rc = lustre_pack_reply(req, 2, size, NULL);
         if (rc)
                 RETURN(rc);
 
         reply = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*reply));
+        /* call again to fill in the reply buffer */
         rc = obd_get_info(exp, keylen, key, size, reply);
         lustre_msg_set_status(req->rq_repmsg, 0);
+
         RETURN(rc);
 }