From 862de19a12438b248e0aa7bd7e0354ef94a947ca Mon Sep 17 00:00:00 2001
From: shadow <shadow>
Date: Thu, 8 May 2008 10:18:09 +0000
Subject: [PATCH] don't panic with use echo client b=14949 i=johan i=deen

---
 lustre/ChangeLog                 |  6 ++++++
 lustre/include/lprocfs_status.h  |  5 +++--
 lustre/ldlm/ldlm_lib.c           |  6 +++---
 lustre/mds/handler.c             |  3 +--
 lustre/mds/mds_fs.c              | 12 ++++++------
 lustre/mds/mds_internal.h        |  2 +-
 lustre/mgs/mgs_fs.c              |  4 ++--
 lustre/obdclass/lprocfs_status.c | 20 ++++++++++++--------
 lustre/obdfilter/filter.c        | 15 +++++++--------
 9 files changed, 41 insertions(+), 32 deletions(-)

diff --git a/lustre/ChangeLog b/lustre/ChangeLog
index cb5df0aeaa..7c9826709c 100644
--- a/lustre/ChangeLog
+++ b/lustre/ChangeLog
@@ -25,6 +25,12 @@ tbd Sun Microsystems, Inc.
 	  	'tunefs.lustre --param="mdt.quota_type=ug1" $MDTDEV'.
 	  For more information, please refer to bugzilla 13904.
 
+Severity   : minor
+Bugzilla   : 14949
+Description: don't panic with use echo client
+Details    : echo client pass NULL as client nid pointer and this produce null
+             pointer dereference.
+
 Severity   : major
 Bugzilla   : 15575
 Description: Stack overflow during MDS log replay
diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h
index cceec77bf2..eadf96db40 100644
--- a/lustre/include/lprocfs_status.h
+++ b/lustre/include/lprocfs_status.h
@@ -345,7 +345,7 @@ struct obd_export;
 extern int lprocfs_add_clear_entry(struct obd_device * obd,
                                    cfs_proc_dir_entry_t *entry);
 extern int lprocfs_exp_setup(struct obd_export *exp,
-                             lnet_nid_t peer_nid, int *newnid);
+                             lnet_nid_t *peer_nid, int *newnid);
 extern int lprocfs_exp_cleanup(struct obd_export *exp);
 extern int lprocfs_add_simple(struct proc_dir_entry *root,
                               char *name, read_proc_t *read_proc,
@@ -586,7 +586,8 @@ static inline void lprocfs_free_obd_stats(struct obd_device *obddev)
 struct obd_export;
 static inline int lprocfs_add_clear_entry(struct obd_export *exp)
 { return 0; }
-static inline int lprocfs_exp_setup(struct obd_export *exp)
+static inline int lprocfs_exp_setup(struct obd_export *exp,
+                             	    lnet_nid_t *peer_nid, int *newnid)
 { return 0; }
 static inline int lprocfs_exp_cleanup(struct obd_export *exp)
 { return 0; }
diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c
index 5f7a7a4c0a..50e769ffb4 100644
--- a/lustre/ldlm/ldlm_lib.c
+++ b/lustre/ldlm/ldlm_lib.c
@@ -582,7 +582,7 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         int rc = 0, abort_recovery;
         struct obd_connect_data *data;
         int size[2] = { sizeof(struct ptlrpc_body), sizeof(*data) };
-        lnet_nid_t client_nid = 0;
+        lnet_nid_t *client_nid = NULL;
         ENTRY;
 
         OBD_RACE(OBD_FAIL_TGT_CONN_RACE);
@@ -794,7 +794,7 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         /* Tell the client if we support replayable requests */
         if (target->obd_replayable)
                 lustre_msg_add_op_flags(req->rq_repmsg, MSG_CONNECT_REPLAYABLE);
-        client_nid = req->rq_peer.nid;
+        client_nid = &req->rq_peer.nid;
 
         if (export == NULL) {
                 if (target->obd_recovering) {
@@ -809,7 +809,7 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
                 } else {
  dont_check_exports:
                         rc = obd_connect(&conn, target, &cluuid, data,
-                                         &client_nid);
+                                         client_nid);
                 }
         } else {
                 rc = obd_reconnect(export, target, &cluuid, data);
diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c
index 655cac4c5b..334208becd 100644
--- a/lustre/mds/handler.c
+++ b/lustre/mds/handler.c
@@ -328,7 +328,6 @@ static int mds_connect(struct lustre_handle *conn, struct obd_device *obd,
         struct obd_export *exp;
         struct mds_export_data *med;
         struct mds_client_data *mcd = NULL;
-        lnet_nid_t *client_nid = (lnet_nid_t *)localdata;
         int rc, abort_recovery;
         ENTRY;
 
@@ -370,7 +369,7 @@ static int mds_connect(struct lustre_handle *conn, struct obd_device *obd,
         memcpy(mcd->mcd_uuid, cluuid, sizeof(mcd->mcd_uuid));
         med->med_mcd = mcd;
 
-        rc = mds_client_add(obd, exp, -1, *client_nid);
+        rc = mds_client_add(obd, exp, -1, localdata);
         GOTO(out, rc);
 
 out:
diff --git a/lustre/mds/mds_fs.c b/lustre/mds/mds_fs.c
index ce27d6acc1..3bef1cb6ac 100644
--- a/lustre/mds/mds_fs.c
+++ b/lustre/mds/mds_fs.c
@@ -52,15 +52,15 @@
 
 static int mds_export_stats_init(struct obd_device *obd,
                                  struct obd_export *exp,
-                                 lnet_nid_t client_nid)
+                                 void *client_nid)
   {
-        int rc, num_stats, newnid;
+        int rc, num_stats, newnid = 0;
 
         rc = lprocfs_exp_setup(exp, client_nid, &newnid);
         if (rc)
                 return rc;
 
-        if (client_nid && newnid) {
+        if (newnid) {
                 struct nid_stat *tmp = exp->exp_nid_stats;
                 LASSERT(tmp != NULL);
 
@@ -92,7 +92,7 @@ static int mds_export_stats_init(struct obd_device *obd,
  * mds_init_server_data() callsite needs to be fixed.
  */
 int mds_client_add(struct obd_device *obd, struct obd_export *exp,
-                   int cl_idx, lnet_nid_t client_nid)
+                   int cl_idx, void *localdata)
 {
         struct mds_obd *mds = &obd->u.mds;
         struct mds_export_data *med = &exp->exp_mds_data;
@@ -140,7 +140,7 @@ int mds_client_add(struct obd_device *obd, struct obd_export *exp,
         med->med_lr_off = le32_to_cpu(mds->mds_server_data->lsd_client_start) +
                 (cl_idx * le16_to_cpu(mds->mds_server_data->lsd_client_size));
         LASSERTF(med->med_lr_off > 0, "med_lr_off = %llu\n", med->med_lr_off);
-        mds_export_stats_init(obd, exp, client_nid);
+        mds_export_stats_init(obd, exp, localdata);
 
         if (new_client) {
                 struct lvfs_run_ctxt saved;
@@ -425,7 +425,7 @@ static int mds_init_server_data(struct obd_device *obd, struct file *file)
                 } else {
                         med = &exp->exp_mds_data;
                         med->med_mcd = mcd;
-                        rc = mds_client_add(obd, exp, cl_idx, 0);
+                        rc = mds_client_add(obd, exp, cl_idx, NULL);
                         /* can't fail for existing client */
                         LASSERTF(rc == 0, "rc = %d\n", rc);
 
diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h
index 6041da6980..f0817ef771 100644
--- a/lustre/mds/mds_internal.h
+++ b/lustre/mds/mds_internal.h
@@ -235,7 +235,7 @@ int mds_join_file(struct mds_update_record *rec, struct ptlrpc_request *req,
 
 /* mds/mds_fs.c */
 int mds_client_add(struct obd_device *obd, struct obd_export *exp,
-                   int cl_off, lnet_nid_t client_nid);
+                   int cl_off, void *localdata);
 int mds_client_free(struct obd_export *exp);
 int mds_obd_create(struct obd_export *exp, struct obdo *oa,
                    struct lov_stripe_md **ea, struct obd_trans_info *oti);
diff --git a/lustre/mgs/mgs_fs.c b/lustre/mgs/mgs_fs.c
index 51abb0e03f..4e8033d6f5 100644
--- a/lustre/mgs/mgs_fs.c
+++ b/lustre/mgs/mgs_fs.c
@@ -45,9 +45,9 @@
 
 static int mgs_export_stats_init(struct obd_device *obd, struct obd_export *exp)
 {
-        int rc, num_stats, newnid;
+        int rc, num_stats, newnid = 0;
 
-        rc = lprocfs_exp_setup(exp, 0, &newnid);
+        rc = lprocfs_exp_setup(exp, NULL, &newnid);
         if (rc)
                 return rc;
 
diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c
index 99edb9d51a..44cdf07d11 100644
--- a/lustre/obdclass/lprocfs_status.c
+++ b/lustre/obdclass/lprocfs_status.c
@@ -1283,7 +1283,7 @@ int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
 }
 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
 
-int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t nid, int *newnid)
+int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
 {
         int rc = 0;
         struct nid_stat *tmp = NULL, *tmp1;
@@ -1296,7 +1296,10 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t nid, int *newnid)
             !exp->exp_obd->obd_nid_stats_hash_body)
                 RETURN(-EINVAL);
 
-        if (!nid)
+	/* not test against zero because eric say:
+	 * You may only test nid against another nid, or LNET_NID_ANY.  Anything else is
+	 * nonsense.*/
+        if (!nid || *nid == LNET_NID_ANY)
                 RETURN(0);
 
         obd = exp->exp_obd;
@@ -1307,26 +1310,26 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t nid, int *newnid)
         if (tmp == NULL)
                 RETURN(-ENOMEM);
 
-        tmp->nid = nid;
+        tmp->nid = *nid;
         tmp->nid_obd = exp->exp_obd;
         tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */
 
-        tmp1= lustre_hash_findadd_unique(obd->obd_nid_stats_hash_body, &nid,
+        tmp1= lustre_hash_findadd_unique(obd->obd_nid_stats_hash_body, nid,
                                          &tmp->nid_hash);
         CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
-               tmp1, libcfs_nid2str(nid), tmp->nid_exp_ref_count);
+               tmp1, libcfs_nid2str(*nid), tmp->nid_exp_ref_count);
 
         if (tmp1 != tmp) {
                 exp->exp_nid_stats = tmp1;
                 GOTO(destroy_new, rc = 0);
         }
         /* not found - create */
-        tmp->nid_proc = proc_mkdir(libcfs_nid2str(nid),
+        tmp->nid_proc = proc_mkdir(libcfs_nid2str(*nid),
                                    obd->obd_proc_exports_entry);
         if (!tmp->nid_proc) {
                 CERROR("Error making export directory for"
-                       " nid %s\n", libcfs_nid2str(nid));
-                lustre_hash_delitem(obd->obd_nid_stats_hash_body, &nid,
+                       " nid %s\n", libcfs_nid2str(*nid));
+                lustre_hash_delitem(obd->obd_nid_stats_hash_body, nid,
                                     &tmp->nid_hash);
                 GOTO(destroy_new, rc = -ENOMEM);
         }
@@ -1349,6 +1352,7 @@ destroy_new:
         OBD_FREE(tmp, sizeof(struct nid_stat));
         RETURN(rc);
 }
+
 int lprocfs_exp_cleanup(struct obd_export *exp)
 {
         struct nid_stat *stat = exp->exp_nid_stats;
diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c
index 2f82325ca9..0590bf49dd 100644
--- a/lustre/obdfilter/filter.c
+++ b/lustre/obdfilter/filter.c
@@ -182,7 +182,7 @@ static int lprocfs_init_rw_stats(struct obd_device *obd,
    plus the procfs overhead :( */
 static int filter_export_stats_init(struct obd_device *obd,
                                     struct obd_export *exp,
-                                    lnet_nid_t client_nid)
+                                    void *client_nid)
 {
         struct filter_export_data *fed = &exp->exp_filter_data;
         struct proc_dir_entry *brw_entry;
@@ -198,7 +198,7 @@ static int filter_export_stats_init(struct obd_device *obd,
         if (rc)
                 RETURN(rc);
 
-        if (client_nid && newnid) {
+        if (newnid) {
                 struct nid_stat *tmp = exp->exp_nid_stats;
                 LASSERT(tmp != NULL);
 
@@ -234,7 +234,7 @@ static int filter_export_stats_init(struct obd_device *obd,
  * Otherwise, we have just read the data from the last_rcvd file and
  * we know its offset. */
 static int filter_client_add(struct obd_device *obd, struct obd_export *exp,
-                             int cl_idx, lnet_nid_t client_nid)
+                             int cl_idx)
 {
         struct filter_obd *filter = &obd->u.filter;
         struct filter_export_data *fed = &exp->exp_filter_data;
@@ -796,8 +796,8 @@ static int filter_init_server_data(struct obd_device *obd, struct file * filp)
                 } else {
                         fed = &exp->exp_filter_data;
                         fed->fed_fcd = fcd;
-                        filter_export_stats_init(obd, exp, 0);
-                        rc = filter_client_add(obd, exp, cl_idx, 0);
+                        filter_export_stats_init(obd, exp, NULL);
+                        rc = filter_client_add(obd, exp, cl_idx);
                         /* can't fail for existing client */
                         LASSERTF(rc == 0, "rc = %d\n", rc);
 
@@ -2160,7 +2160,6 @@ static int filter_connect(struct lustre_handle *conn, struct obd_device *obd,
         struct obd_export *exp;
         struct filter_export_data *fed;
         struct filter_client_data *fcd = NULL;
-        lnet_nid_t *client_nid = (lnet_nid_t *)localdata;
         int rc;
         ENTRY;
 
@@ -2179,7 +2178,7 @@ static int filter_connect(struct lustre_handle *conn, struct obd_device *obd,
         if (rc)
                 GOTO(cleanup, rc);
 
-        filter_export_stats_init(obd, exp, *client_nid);
+        filter_export_stats_init(obd, exp, localdata);
 
         if (!obd->obd_replayable)
                 GOTO(cleanup, rc = 0);
@@ -2193,7 +2192,7 @@ static int filter_connect(struct lustre_handle *conn, struct obd_device *obd,
         memcpy(fcd->fcd_uuid, cluuid, sizeof(fcd->fcd_uuid));
         fed->fed_fcd = fcd;
 
-        rc = filter_client_add(obd, exp, -1, *client_nid);
+        rc = filter_client_add(obd, exp, -1);
 
         GOTO(cleanup, rc);
 
-- 
GitLab