Whamcloud - gitweb
Branch b1_4_mountconf
authornathan <nathan>
Thu, 29 Dec 2005 00:24:17 +0000 (00:24 +0000)
committernathan <nathan>
Thu, 29 Dec 2005 00:24:17 +0000 (00:24 +0000)
b=8192,9867
- move llog parsing into mgc
- track "used" logs to keep config generation info
- add statfs for df info on the server mounts - just report underlying disk
info (huanghua)
- more LCFG_MARKER processing

14 files changed:
lustre/include/linux/lustre_cfg.h
lustre/include/linux/lustre_disk.h
lustre/include/linux/lustre_log.h
lustre/include/linux/lustre_mgs.h
lustre/include/linux/obd_class.h
lustre/llite/llite_lib.c
lustre/lov/lov_log.c
lustre/mgc/mgc_request.c
lustre/mgs/mgs_llog.c
lustre/obdclass/genops.c
lustre/obdclass/llog.c
lustre/obdclass/obd_config.c
lustre/obdclass/obd_mount.c
lustre/utils/llog_reader.c

index 124141c..d6bb24a 100644 (file)
@@ -50,7 +50,8 @@ enum lcfg_command_type {
         LCFG_LOV_ADD_OBD    = 0x00cf00d,
         LCFG_LOV_DEL_OBD    = 0x00cf00e,
         LCFG_PARAM          = 0x00cf00f,
-        LCFG_MARKER         = 0x00cf010
+        LCFG_MARKER         = 0x00cf010,
+        LCFG_PARSE_LOG      = 0x00cf011,
 };
 
 struct lustre_cfg_bufs {
index a9e5a77..d035281 100644 (file)
@@ -192,11 +192,9 @@ struct ll_sb_info;
 
 struct lustre_sb_info {
         int                       lsi_flags;
-        //struct lvfs_run_ctxt      lsi_ctxt;    /* mount context */
         struct obd_device        *lsi_mgc;     /* mgc obd */
         struct lustre_mount_data *lsi_lmd;     /* mount command info */
         struct lustre_disk_data  *lsi_ldd;     /* mount info on-disk */
-        //struct fsfilt_operations *lsi_fsops;
         struct ll_sb_info        *lsi_llsbi;   /* add'l client sbi info */
         struct vfsmount          *lsi_srv_mnt; /* the one server mount */
         atomic_t                  lsi_mounts;  /* references to the srv_mnt */
@@ -236,8 +234,11 @@ void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb));
 int lustre_common_put_super(struct super_block *sb);
 struct lustre_mount_info *server_get_mount(char *name);
 int server_put_mount(char *name, struct vfsmount *mnt);
-int lustre_get_process_log(struct super_block *, char *,
+int config_log_start(struct super_block *, char *,
                            struct config_llog_instance *cfg);
+int config_log_end(char *instance);
+struct config_llog_data *config_log_get(char *name);
+void config_log_put(void);
 
 #endif
 
index 96cd5d0..52ad5c1 100644 (file)
@@ -73,6 +73,7 @@ struct llog_fill_rec_data {
         obd_count       lfd_ogen;       /* object group */
 };
 
+
 /* llog.c  -  general API */
 typedef int (*llog_cb_t)(struct llog_handle *, struct llog_rec_hdr *, void *);
 typedef int (*llog_fill_rec_cb_t)(struct llog_rec_hdr *rec, void *data);
@@ -106,6 +107,14 @@ int llog_cat_cancel_records(struct llog_handle *cathandle, int count,
 int llog_cat_process(struct llog_handle *cat_llh, llog_cb_t cb, void *data);
 int llog_cat_set_first_idx(struct llog_handle *cathandle, int index);
 
+/* list of configuration llogs we are watching */
+struct config_llog_data {
+        char               *cld_name;
+        __u32               cld_gen;
+        struct ldlm_res_id  cld_res_id;
+        struct list_head    cld_list_chain;
+};
+
 /* llog_obd.c */
 int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
                int count,  struct llog_logid *logid,struct llog_operations *op);
index 26ba68b..fc01dd6 100644 (file)
@@ -27,7 +27,7 @@ struct fs_db {
         struct list_head  fd_list;
         void*             fd_index_map;
         __u32             fd_flags;
-        __u32             fd_last_step;
+        __u32             fd_gen;
         //FIXME add a semaphore for locking the fs_db (and logs)
 };
 
index 9064072..078ee34 100644 (file)
@@ -106,8 +106,9 @@ void class_decref(struct obd_device *obd);
 
 /* Passed as data param to class_config_parse_llog */
 struct config_llog_instance {
-        char * cfg_instance;
+        char *          cfg_instance;
         struct obd_uuid cfg_uuid;
+        int             cfg_last_idx; /* for partial llog processing */
 };
 int class_config_parse_llog(struct llog_ctxt *ctxt, char *name,
                             struct config_llog_instance *cfg);
index 89af4ff..c4ab3b8 100644 (file)
@@ -521,7 +521,7 @@ int ll_fill_super(struct super_block *sb)
         cfg.cfg_uuid = lsi->lsi_llsbi->ll_sb_uuid;
         
         /* set up client obds */
-        err = lustre_get_process_log(sb, profilenm, &cfg);
+        err = config_log_start(sb, profilenm, &cfg);
         if (err < 0) {
                 CERROR("Unable to process log: %d\n", err);
                 GOTO(out_free, err);
@@ -573,6 +573,7 @@ out_free:
 
 void ll_put_super(struct super_block *sb)
 {
+        char   ll_instance[sizeof(sb) * 2 + 1];
         struct obd_device *obd;
         struct lustre_sb_info *lsi = s2lsi(sb);
         struct ll_sb_info *sbi = ll_s2sbi(sb);
@@ -581,6 +582,10 @@ void ll_put_super(struct super_block *sb)
         ENTRY;
 
         CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm);
+        
+        sprintf(ll_instance, "%p", sb);
+        config_log_end(ll_instance);
+        
         obd = class_exp2obd(sbi->ll_mdc_exp);
         if (obd) {
                 int next = 0;
@@ -601,7 +606,7 @@ void ll_put_super(struct super_block *sb)
         
         if (profilenm) 
                 class_del_profile(profilenm);
-        
+
         ll_free_sbi(sb);
         lsi->lsi_llsbi = NULL;
 
index 61088d6..587a8c9 100644 (file)
@@ -101,7 +101,9 @@ static int lov_llog_origin_connect(struct llog_ctxt *ctxt, int count,
         int i, rc = 0;
         ENTRY;
 
-        LASSERT(lov->desc.ld_tgt_count  == count);
+        if (lov->desc.ld_tgt_count != count)
+                CERROR("Origin connect %d != %d\n",
+                       lov->desc.ld_tgt_count, count);
         for (i = 0, tgt = lov->tgts; i < lov->desc.ld_tgt_count; i++, tgt++) {
                 struct obd_device *child;
                 struct llog_ctxt *cctxt;
index 5cd9a56..8b1dc1c 100644 (file)
@@ -49,7 +49,7 @@
 
 #include "mgc_internal.h"
 
-
+/********************** class fns **********************/
 
 static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb, 
                         struct vfsmount *mnt)
@@ -549,7 +549,136 @@ static int mgc_llog_finish(struct obd_device *obd, int count)
         RETURN(rc);
 }
 
-/* reuse the client_import_[add/del]_conn*/
+/* Get the client export to the MGS */
+static struct obd_export *get_mgs_export(struct obd_device *mgc)
+{
+        struct obd_export *exp, *n;
+
+        /* FIXME is this a Bad Idea?  Should I just store this export 
+           somewhere in the u.cli? */
+
+        /* There should be exactly 2 exports in the mgc, the mgs export and 
+           the mgc self-export, in that order. So just return the list head. */
+        LASSERT(!list_empty(&mgc->obd_exports));
+        LASSERT(mgc->obd_num_exports == 2);
+        list_for_each_entry_safe(exp, n, &mgc->obd_exports, exp_obd_chain) {
+                LASSERT(exp != mgc->obd_self_export);
+                break;
+        }
+        /*FIXME there's clearly a better way, but I'm too confused to sort it 
+          out now...
+        exp = &list_entry(&mgc->obd_exports->head, export_obd, exp_obd_chain);
+        */
+        return exp;
+}
+
+/* Get a config log from the MGS and process it.
+   This func is called for both clients and servers. */
+static int mgc_process_log(struct obd_device *mgc, char *logname, 
+                           struct config_llog_instance *cfg)
+{
+        struct llog_ctxt *rctxt;
+        struct config_llog_data *cld;
+        struct lustre_handle lockh;
+        int rc, rcl, flags = 0;
+        ENTRY;
+
+        CDEBUG(D_MGC, "parsing config log %s\n", logname);
+
+        rctxt = llog_get_context(mgc, LLOG_CONFIG_REPL_CTXT);
+        if (!rctxt) {
+                CERROR("missing llog context\n");
+                RETURN(-EINVAL);
+        }
+
+        /* Remember where we last stopped in this log. 
+           hmm - hold global config lock over the entire llog parse?
+           I could just 'get' it again after the parse.  */
+        if (cfg && cfg->cfg_instance) 
+                cld = config_log_get(cfg->cfg_instance);
+        else
+                cld = config_log_get(logname);
+        if (cld && cfg) {
+                cfg->cfg_last_idx = cld->cld_gen;
+                CDEBUG(D_MGC, "parsing log %s from %d\n", logname, 
+                       cfg->cfg_last_idx);
+        }
+
+        /* Get the cfg lock on the llog */
+        rcl = mgc_enqueue(get_mgs_export(mgc), NULL, LDLM_PLAIN, NULL, 
+                          LCK_CR, &flags, NULL, NULL, NULL, 
+                          logname, 0, NULL, &lockh);
+        if (rcl) {
+                CERROR("Can't get cfg lock: %d\n", rcl);
+                config_log_put();
+                RETURN(rcl);
+        }
+        
+        //FIXME Copy the mgs remote log to the local disk
+
+        rc = class_config_parse_llog(rctxt, logname, cfg);
+        
+        /* Now drop the lock so MGS can revoke it */ 
+        rcl = mgc_cancel(get_mgs_export(mgc), NULL, LCK_CR, &lockh);
+        if (rcl) {
+                CERROR("Can't drop cfg lock: %d\n", rcl);
+        }
+        
+        /* Remember our gen */
+        if (!rc && cld && cfg)
+                cld->cld_gen = cfg->cfg_last_idx;
+        config_log_put();
+
+        if (rc) {
+                LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
+                               "(%d) from the MGS.\n",
+                               mgc->obd_name, logname, rc);
+        }
+
+        RETURN(rc);
+}
+
+static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf)
+{
+        struct lustre_cfg *lcfg = buf;
+        int cmd;
+        int rc = 0;
+        ENTRY;
+
+        switch(cmd = lcfg->lcfg_command) {
+        case LCFG_LOV_ADD_OBD:
+        case LCFG_LOV_DEL_OBD: {
+                struct mgmt_target_info *mti;
+
+                if (LUSTRE_CFG_BUFLEN(lcfg, 1) != 
+                    sizeof(struct mgmt_target_info))
+                        GOTO(out, rc = -EINVAL);
+
+                mti = (struct mgmt_target_info *)lustre_cfg_buf(lcfg, 1);
+                CDEBUG(D_MGC, "add_target %s %#x\n",    
+                       mti->mti_svname, mti->mti_flags);
+                rc = mgc_target_add(get_mgs_export(obd), mti);
+                GOTO(out, rc);
+        }
+        case LCFG_PARSE_LOG: {
+                char *logname = lustre_cfg_string(lcfg, 1);
+                struct config_llog_instance *cfg;
+                cfg = (struct config_llog_instance *)lustre_cfg_buf(lcfg, 2);
+                CDEBUG(D_MGC, "parse_log %s from %d\n", logname, 
+                       cfg->cfg_last_idx);
+                mgc_process_log(obd, logname, cfg);
+                GOTO(out, rc);
+        }
+        default: {
+                CERROR("Unknown command: %d\n", lcfg->lcfg_command);
+                GOTO(out, rc = -EINVAL);
+
+        }
+        }
+out:
+        RETURN(rc);
+}
+
 struct obd_ops mgc_obd_ops = {
         .o_owner        = THIS_MODULE,
         .o_setup        = mgc_setup,
@@ -565,6 +694,7 @@ struct obd_ops mgc_obd_ops = {
         .o_import_event = mgc_import_event,
         .o_llog_init    = mgc_llog_init,
         .o_llog_finish  = mgc_llog_finish,
+        .o_process_config = mgc_process_config,
 };
 
 int __init mgc_init(void)
index 80c4ee7..45c69ff 100644 (file)
@@ -83,8 +83,7 @@ static int db_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
                 if (lcfg->lcfg_command == LCFG_MARKER) {
                         struct cfg_marker *marker;
                         marker = lustre_cfg_buf(lcfg, 1);
-                        db->fd_last_step = 
-                                max(db->fd_last_step, marker->cm_step);
+                        db->fd_gen = max(db->fd_gen, marker->cm_step);
                         CDEBUG(D_MGS, "marker %d %s\n", marker->cm_step, 
                                marker->cm_comment);
                 }
@@ -431,8 +430,8 @@ static int record_marker(struct obd_device *obd, struct llog_handle *llh,
         CDEBUG(D_MGS, "lcfg marker\n");
 
         if (flags & CM_START) 
-                db->fd_last_step++;
-        marker.cm_step = db->fd_last_step;
+                db->fd_gen++;
+        marker.cm_step = db->fd_gen;
         marker.cm_flags = flags;
         strncpy(marker.cm_comment, comment, sizeof(marker.cm_comment)); 
         lustre_cfg_bufs_reset(&bufs, NULL);
@@ -632,6 +631,7 @@ static int mgs_write_log_lov(struct obd_device *obd, struct fs_db *db,
         rc = record_marker(obd, llh, db, CM_END, "lov setup"); 
         rc = record_end_log(obd, &llh);
         
+        OBD_FREE(lovdesc, sizeof(*lovdesc));
         RETURN(rc);
 }
 
index 616a02f..cc5337d 100644 (file)
@@ -310,10 +310,10 @@ void class_obd_list(void)
                         status = "AT";
                 else
                         status = "--";
-                CDEBUG(D_WARNING, "%3d %s %s %s %s %d\n",
-                       i, status, obd->obd_type->typ_name,
-                       obd->obd_name, obd->obd_uuid.uuid,
-                       atomic_read(&obd->obd_refcount));
+                LCONSOLE_WARN("%3d %s %s %s %s %d\n",
+                              i, status, obd->obd_type->typ_name,
+                              obd->obd_name, obd->obd_uuid.uuid,
+                              atomic_read(&obd->obd_refcount));
         }
         spin_unlock(&obd_dev_lock);
         return;
index 2a4297f..2ad2e1e 100644 (file)
@@ -211,7 +211,7 @@ int llog_process(struct llog_handle *loghandle, llog_cb_t cb,
         char *buf;
         __u64 cur_offset = LLOG_CHUNK_SIZE;
         int rc = 0, index = 1, last_index;
-        int saved_index = 0;
+        int saved_index = 0, last_called_index = 0;
         ENTRY;
 
         LASSERT(llh);
@@ -289,6 +289,7 @@ int llog_process(struct llog_handle *loghandle, llog_cb_t cb,
                         /* if set, process the callback on this record */
                         if (ext2_test_bit(index, llh->llh_bitmap)) {
                                 rc = cb(loghandle, rec, data);
+                                last_called_index = index;
                                 if (rc == LLOG_PROC_BREAK) {
                                         CWARN("recovery from log: "LPX64":%x"
                                               " stopped\n",
@@ -310,6 +311,8 @@ int llog_process(struct llog_handle *loghandle, llog_cb_t cb,
         }
 
  out:
+        if (cd != NULL)
+                cd->last_idx = last_called_index;
         if (buf)
                 OBD_FREE(buf, LLOG_CHUNK_SIZE);
         RETURN(rc);
index 7614797..d3e5a34 100644 (file)
@@ -43,6 +43,8 @@
 #include <libcfs/list.h>
 
 
+/********************** class fns **********************/
+
 /* Create a new device and set the type, name and uuid.  If
  * successful, the new device can be accessed by either name or uuid.
  */
@@ -628,8 +630,6 @@ int class_process_config(struct lustre_cfg *lcfg)
         case LCFG_DEL_MOUNTOPT: {
                 CDEBUG(D_IOCTL, "mountopt: profile %s\n",
                        lustre_cfg_string(lcfg, 1));
-                /* set these mount options somewhere, so ll_fill_super
-                 * can find them. */
                 class_del_profile(lustre_cfg_string(lcfg, 1));
                 GOTO(out, err = 0);
         }
@@ -652,9 +652,8 @@ int class_process_config(struct lustre_cfg *lcfg)
         }
         case LCFG_MARKER: {
                 struct cfg_marker *marker;
-                LCONSOLE_WARN("LCFG_MARKER not yet implemented.\n");
                 marker = lustre_cfg_buf(lcfg, 1);
-                CDEBUG(D_WARNING, "%d (%x) %s\n", marker->cm_step,
+                CDEBUG(D_IOCTL, "marker %d (%#x) %s\n", marker->cm_step,
                        marker->cm_flags, marker->cm_comment);
                 GOTO(out, err = 0);
         }
@@ -734,6 +733,13 @@ static int class_config_llog_handler(struct llog_handle * handle,
                 if (rc)
                         GOTO(out, rc);
 
+                /* FIXME check cm_flags for skip - must save state,
+                   probably in handle 
+                if (lcfg->lcfg_command == LCFG_MARKER) {
+                        struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
+                }
+                */
+
                 lustre_cfg_bufs_init(&bufs, lcfg);
 
                 if (cfg && cfg->cfg_instance && LUSTRE_CFG_BUFLEN(lcfg, 0) > 0) {
@@ -755,7 +761,8 @@ static int class_config_llog_handler(struct llog_handle * handle,
                 are unique */
                 if (cfg && cfg->cfg_instance && 
                     lcfg->lcfg_command == LCFG_ATTACH) {
-                        lustre_cfg_bufs_set_string(&bufs, 2, cfg->cfg_uuid.uuid);
+                        lustre_cfg_bufs_set_string(&bufs, 2,
+                                                   cfg->cfg_uuid.uuid);
                 }
 
                 lcfg_new = lustre_cfg_new(lcfg->lcfg_command, &bufs);
@@ -779,7 +786,7 @@ static int class_config_llog_handler(struct llog_handle * handle,
                 }
 
                 lcfg_new->lcfg_nal = 0; /* illegal value for obsolete field */
-
+                
                 rc = class_process_config(lcfg_new);
                 lustre_cfg_free(lcfg_new);
 
@@ -803,6 +810,7 @@ out:
 int class_config_parse_llog(struct llog_ctxt *ctxt, char *name,
                             struct config_llog_instance *cfg)
 {
+        struct llog_process_cat_data cd = {0, 0};
         struct llog_handle *llh;
         int rc, rc2;
         ENTRY;
@@ -816,7 +824,16 @@ int class_config_parse_llog(struct llog_ctxt *ctxt, char *name,
         if (rc)
                 GOTO(parse_out, rc);
 
-        rc = llog_process(llh, class_config_llog_handler, cfg, NULL);
+        /* continue processing from where we last stopped to end-of-log */
+        if (cfg)
+                cd.first_idx = cfg->cfg_last_idx;
+        cd.last_idx = 0;
+
+        rc = llog_process(llh, class_config_llog_handler, cfg, &cd);
+
+        CERROR("Processed %d-%d\n", cd.first_idx, cd.last_idx);
+        cfg->cfg_last_idx = cd.last_idx;
+
 parse_out:
         rc2 = llog_close(llh);
         if (rc == 0)
@@ -825,7 +842,6 @@ parse_out:
         RETURN(rc);
 }
 
-#define D_DUMP D_INFO|D_WARNING
 int class_config_dump_handler(struct llog_handle * handle,
                               struct llog_rec_hdr *rec, void *data)
 {
@@ -850,7 +866,7 @@ int class_config_dump_handler(struct llog_handle * handle,
                         GOTO(out, rc);
                 lcfg = (struct lustre_cfg *)cfg_buf;
 
-                ptr += snprintf(ptr, end-ptr, "\n   cmd=%05x ",
+                ptr += snprintf(ptr, end-ptr, "cmd=%05x ",
                                 lcfg->lcfg_command);
                 if (lcfg->lcfg_flags) {
                         ptr += snprintf(ptr, end-ptr, "flags=%#08x ",
@@ -861,19 +877,26 @@ int class_config_dump_handler(struct llog_handle * handle,
                                         lcfg->lcfg_num);
                 }
                 if (lcfg->lcfg_nid) {
-                        ptr += snprintf(ptr, end-ptr, "nid=%s("LPX64")\n",
+                        ptr += snprintf(ptr, end-ptr, "nid=%s("LPX64")\n     ",
                                         libcfs_nid2str(lcfg->lcfg_nid),
                                         lcfg->lcfg_nid);
                 }
-                for (i = 0; i <  lcfg->lcfg_bufcount; i++) {
-                        ptr += snprintf(ptr, end-ptr, "%d:%s  ", i,
-                                        lustre_cfg_string(lcfg, i));
+                if (lcfg->lcfg_command == LCFG_MARKER) {
+                        struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
+                        ptr += snprintf(ptr, end-ptr, "marker=%d(%#x)'%s'",
+                                        marker->cm_step, marker->cm_flags, 
+                                        marker->cm_comment);
+                } else {
+                        for (i = 0; i <  lcfg->lcfg_bufcount; i++) {
+                                ptr += snprintf(ptr, end-ptr, "%d:%s  ", i,
+                                                lustre_cfg_string(lcfg, i));
+                        }
                 }
-                CDEBUG(D_DUMP, "%s\n", outstr);
+                LCONSOLE_INFO("   %s\n", outstr);
         } else if (rec->lrh_type == PTL_CFG_REC) {
-                CDEBUG(D_DUMP, "Obsolete pcfg command\n");
+                LCONSOLE_INFO("Obsolete pcfg command\n");
         } else {
-                CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
+                LCONSOLE_INFO("unhandled lrh_type: %#x\n", rec->lrh_type);
                 rc = -EINVAL;
         }
 out:
@@ -888,7 +911,7 @@ int class_config_dump_llog(struct llog_ctxt *ctxt, char *name,
         int rc, rc2;
         ENTRY;
 
-        CDEBUG(D_DUMP, "Dumping config log %s\n", name);
+        LCONSOLE_INFO("Dumping config log %s\n", name);
 
         rc = llog_create(ctxt, &llh, NULL, name);
         if (rc)
@@ -904,7 +927,7 @@ parse_out:
         if (rc == 0)
                 rc = rc2;
 
-        CDEBUG(D_DUMP, "End config log %s\n", name);
+        LCONSOLE_INFO("End config log %s\n", name);
         RETURN(rc);
 
 }
index 5e3c26a..11161f8 100644 (file)
                       
 static int (*client_fill_super)(struct super_block *sb) = NULL;
 
+
 /*********** mount lookup *********/
+
 DECLARE_MUTEX(lustre_mount_info_lock);
-struct list_head lustre_mount_info_list = LIST_HEAD_INIT(lustre_mount_info_list);
+struct list_head server_mount_info_list = LIST_HEAD_INIT(server_mount_info_list);
 
 static struct lustre_mount_info *server_find_mount(char *name)
 {
         struct list_head *tmp;
         struct lustre_mount_info *lmi;
-        int found = 0;
-        list_for_each(tmp, &lustre_mount_info_list) {
+        
+        list_for_each(tmp, &server_mount_info_list) {
                 lmi = list_entry(tmp, struct lustre_mount_info, lmi_list_chain);
-                if (strcmp(name, lmi->lmi_name) == 0) {
-                        found++;
-                        break;
-                }
+                if (strcmp(name, lmi->lmi_name) == 0) 
+                        return(lmi);
         }
-        if (found)
-                return(lmi);
         return(NULL);
 }
 
@@ -93,7 +91,7 @@ static int server_register_mount(char *name, struct super_block *sb,
         lmi->lmi_name = name_cp;
         lmi->lmi_sb = sb;
         lmi->lmi_mnt = mnt;
-        list_add(&lmi->lmi_list_chain, &lustre_mount_info_list);
+        list_add(&lmi->lmi_list_chain, &server_mount_info_list);
          
         up(&lustre_mount_info_lock);
         return 0;
@@ -129,7 +127,7 @@ static void server_deregister_mount_all(struct vfsmount *mnt)
                 return;
 
         down(&lustre_mount_info_lock);
-        list_for_each_safe(tmp, n, &lustre_mount_info_list) {
+        list_for_each_safe(tmp, n, &server_mount_info_list) {
                 lmi = list_entry(tmp, struct lustre_mount_info, lmi_list_chain);
                 if (lmi->lmi_mnt == mnt) {
                         CERROR("Deregister failsafe %s\n", lmi->lmi_name);
@@ -224,18 +222,18 @@ static void ldd_print(struct lustre_disk_data *ldd)
 {
         int i;
 
-        CDEBUG(D_MOUNT, "disk data\n"); 
-        CDEBUG(D_MOUNT, "config:  %d\n", ldd->ldd_config_ver);
-        CDEBUG(D_MOUNT, "fs:      %s\n", ldd->ldd_fsname);
-        CDEBUG(D_MOUNT, "server:  %s\n", ldd->ldd_svname);
-        CDEBUG(D_MOUNT, "index:   %04x\n", ldd->ldd_svindex);
-        CDEBUG(D_MOUNT, "flags:   %#x\n", ldd->ldd_flags);
-        CDEBUG(D_MOUNT, "diskfs:  %s\n", MT_STR(ldd));
-        CDEBUG(D_MOUNT, "options: %s\n", ldd->ldd_mount_opts);
+        LCONSOLE_WARN("  disk data:\n"); 
+        LCONSOLE_WARN("config:  %d\n", ldd->ldd_config_ver);
+        LCONSOLE_WARN("fs:      %s\n", ldd->ldd_fsname);
+        LCONSOLE_WARN("server:  %s\n", ldd->ldd_svname);
+        LCONSOLE_WARN("index:   %04x\n", ldd->ldd_svindex);
+        LCONSOLE_WARN("flags:   %#x\n", ldd->ldd_flags);
+        LCONSOLE_WARN("diskfs:  %s\n", MT_STR(ldd));
+        LCONSOLE_WARN("options: %s\n", ldd->ldd_mount_opts);
         if (!ldd->ldd_mgsnid_count) 
-                CDEBUG(D_MOUNT, "no MGS nids\n");
+                LCONSOLE_WARN("no MGS nids\n");
         else for (i = 0; i < ldd->ldd_mgsnid_count; i++) {
-                CDEBUG(D_MOUNT, "mgs nid %d:  %s\n", i, 
+                LCONSOLE_WARN("mgs nid %d:  %s\n", i, 
                        libcfs_nid2str(ldd->ldd_mgsnid[i]));
         }
 }
@@ -374,77 +372,136 @@ out:
 }
 #endif
 
-/**************** config llog ********************/
 
-/* Get the client export to the MGS */
-static struct obd_export *get_mgs_export(struct obd_device *mgc)
+/********************** config llog list **********************/
+DECLARE_MUTEX(config_llog_lock);
+struct list_head config_llog_list = LIST_HEAD_INIT(config_llog_list);
+
+/* Find log and take the global lock (whether found or not) */
+struct config_llog_data *config_log_get(char *name)
 {
-        struct obd_export *exp, *n;
+        struct list_head *tmp;
+        struct config_llog_data *cld;
+        down(&config_llog_lock);
+        list_for_each(tmp, &config_llog_list) {
+                cld = list_entry(tmp, struct config_llog_data, cld_list_chain);
+                if (strcmp(name, cld->cld_name) == 0) {
+                        return(cld);
+                }
+        }
+        CERROR("can't get log %s\n", name);
+        return(NULL);
+}
 
-        /* FIXME is this a Bad Idea?  Should I just store this export 
-           somewhere in the u.cli? Slightly annoying because of layering */
+void config_log_put(void)
+{
+        up(&config_llog_lock);
+}
 
-        /* There should be exactly 2 exports in the mgc, the mgs export and 
-           the mgc self-export, in that order. So just return the list head. */
-        LASSERT(!list_empty(&mgc->obd_exports));
-        LASSERT(mgc->obd_num_exports == 2);
-        list_for_each_entry_safe(exp, n, &mgc->obd_exports, exp_obd_chain) {
-                LASSERT(exp != mgc->obd_self_export);
-                break;
+static int config_log_add(char *name)
+{
+        struct config_llog_data *cld;
+        char *name_cp;
+        int rc;
+        ENTRY;
+
+        CDEBUG(D_MOUNT, "adding config llog %s\n", name);
+        if (config_log_get(name)) {
+                GOTO(out, rc = -EEXIST);
         }
-        /*FIXME there's clearly a better way, but I'm too confused to sort it 
-          out now...
-        exp = &list_entry(&mgc->obd_exports->head, export_obd, exp_obd_chain);
-        */
-        return exp;
+
+        OBD_ALLOC(cld, sizeof(*cld));
+        if (!cld) 
+                GOTO(out, rc = -ENOMEM);
+        OBD_ALLOC(name_cp, strlen(name) + 1);
+        if (!name_cp) { 
+                OBD_FREE(cld, sizeof(*cld));
+                GOTO(out, rc = -ENOMEM);
+        }
+        strcpy(name_cp, name);
+
+        cld->cld_name = name_cp;
+        cld->cld_gen = 0;
+        list_add(&cld->cld_list_chain, &config_llog_list);
+out:
+        config_log_put();
+        RETURN(rc);
+}
+
+
+/* Stop watching for updates on this log. 2 clients on the same node
+   may be at different gens, so we need different log info (eg. 
+   already mounted client is at gen 10, but must start a new client
+   from gen 0.)*/
+int config_log_end(char *name)
+{       
+        struct config_llog_data *cld;
+        int rc = 0;
+        ENTRY;
+                                       
+        cld = config_log_get(name);
+        if (!cld) 
+                GOTO(out, rc = -ENOENT);
+        OBD_FREE(cld->cld_name, strlen(cld->cld_name) + 1);
+        list_del(&cld->cld_list_chain);
+        OBD_FREE(cld, sizeof(*cld));
+out:
+        config_log_put();
+        CDEBUG(D_MOUNT, "removed config llog %s %d\n", name, rc);
+        RETURN(rc);
+}
+
+static void config_log_end_all(void)
+{
+        struct list_head *tmp, *n;
+        struct config_llog_data *cld;
+        
+        down(&config_llog_lock);
+        list_for_each_safe(tmp, n, &config_llog_list) {
+                cld = list_entry(tmp, struct config_llog_data, cld_list_chain);
+                CERROR("conflog failsafe %s\n", cld->cld_name);
+                OBD_FREE(cld->cld_name, strlen(cld->cld_name) + 1);
+                list_del(&cld->cld_list_chain);
+                OBD_FREE(cld, sizeof(*cld));
+        }
+        up(&config_llog_lock);
 }
 
+/**************** config llog ********************/
+
 /* Get a config log from the MGS and process it.
    This func is called for both clients and servers. */
-/* FIXME maybe it makes more sense for this to be a mgc func, not
-   a mount func.  We could make this mgc_process_config */ 
-int lustre_get_process_log(struct super_block *sb, char *logname, 
+int config_log_start(struct super_block *sb, char *logname, 
                            struct config_llog_instance *cfg)
 {
+        struct lustre_cfg *lcfg;
+        struct lustre_cfg_bufs bufs;
         struct lustre_sb_info *lsi = s2lsi(sb);
         struct obd_device *mgc = lsi->lsi_mgc;
-        struct llog_ctxt *rctxt, *lctxt;
-        struct lustre_handle lockh;
-        int rc, rcl, flags = 0;
+        struct llog_ctxt *lctxt;
+        int rc;
+        ENTRY;
+
         LASSERT(mgc);
 
-        CDEBUG(D_MOUNT, "parsing config log %s\n", logname);
+        if (cfg && cfg->cfg_instance) 
+                config_log_add(cfg->cfg_instance);
+        else
+                config_log_add(logname);
 
-        rctxt = llog_get_context(mgc, LLOG_CONFIG_REPL_CTXT);
         lctxt = llog_get_context(mgc, LLOG_CONFIG_ORIG_CTXT);
-        if (!lctxt || !rctxt) {
+        if (!lctxt) {
                 CERROR("missing llog context\n");
                 return(-EINVAL);
         }
 
-        /* Get the cfg lock */
-        rcl = obd_enqueue(get_mgs_export(mgc), NULL, LDLM_PLAIN, NULL, 
-                          LCK_CR, &flags, NULL, NULL, NULL, 
-                          logname, 0, NULL, &lockh);
-        if (rcl) {
-                CERROR("Can't get cfg lock: %d\n", rcl);
-                return (rcl);
-        }
-        
-        //FIXME Copy the mgs remote log to the local disk
+        lustre_cfg_bufs_reset(&bufs, mgc->obd_name);
+        lustre_cfg_bufs_set_string(&bufs, 1, logname);
+        lustre_cfg_bufs_set(&bufs, 2, cfg, sizeof(*cfg));
+        lcfg = lustre_cfg_new(LCFG_PARSE_LOG, &bufs);
+        rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
+        lustre_cfg_free(lcfg);
 
-#if 0
-        /* For debugging, it's useful to just dump the log */
-        class_config_dump_llog(rctxt, logname, cfg);
-#endif
-        rc = class_config_parse_llog(rctxt, logname, cfg);
-        
-        /* Now drop the lock so MGS can revoke it */ 
-        rcl = obd_cancel(get_mgs_export(mgc), NULL, LCK_CR, &lockh);
-        if (rcl) {
-                CERROR("Can't drop cfg lock: %d\n", rcl);
-        }
-        
         if (rc && !lmd_is_client(lsi->lsi_lmd)) {
                 int rc2;
                 LCONSOLE_INFO("%s: The configuration '%s' could not be read "
@@ -466,10 +523,8 @@ int lustre_get_process_log(struct super_block *sb, char *logname,
                                mgc->obd_name, logname, rc);
         }
 
-        CDEBUG(D_MOUNT, "after lustre_get_process_log %s\n", logname);
         class_obd_list();
-
-        return (rc);
+        RETURN(rc);
 }
 
 /**************** obd start *******************/
@@ -576,6 +631,8 @@ static int server_stop_mgs(struct super_block *sb)
         return rc;
 }
 
+static struct obd_export *mgc_mgs_export = NULL;
+
 /* Set up a mgcobd to process startup logs */
 static int lustre_start_mgc(struct super_block *sb)
 {
@@ -617,8 +674,12 @@ static int lustre_start_mgc(struct super_block *sb)
                 return rc;
 
         /* Generate a unique uuid for each MGC - use the 1st non-loopback nid */
-        /* FIXME if no loopback? Use lustre_generate_random_uuid? */
-        rc = LNetGetId(1, &id);  
+        i = 0;
+        while ((rc = LNetGetId(i++, &id)) != -ENOENT) {
+                if (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND) 
+                        continue;
+                break;
+        }
         OBD_ALLOC(uuid, sizeof(struct obd_uuid));
         sprintf(uuid, "mgc_"LPX64, id.nid);
         /* Start the MGC */
@@ -667,8 +728,10 @@ static int lustre_start_mgc(struct super_block *sb)
                 CERROR("connect failed %d\n", rc);
                 goto out;
         }
+        
         exp = class_conn2export(&mgc_conn);
-        LASSERT(exp == get_mgs_export(obd));
+        /* only 1 mgc, only 1 connection to the mgs */
+        mgc_mgs_export = exp;
 
         /* And keep a refcount of servers/clients who started with "mount",
            so we know when we can get rid of the mgc. */
@@ -701,7 +764,9 @@ static int lustre_stop_mgc(struct super_block *sb)
                 return -EBUSY; 
         }
 
-        obd_disconnect(get_mgs_export(obd));
+        if (mgc_mgs_export) 
+                obd_disconnect(mgc_mgs_export);
+        mgc_mgs_export = NULL;
 
         rc = class_manual_cleanup(obd);
         if (rc)
@@ -718,6 +783,9 @@ static int lustre_stop_mgc(struct super_block *sb)
                                libcfs_nid2str(nid), rc);
         }
         /* class_import_put will get rid of the additional connections */
+
+        config_log_end_all();
+
         return 0;
 }
           
@@ -836,15 +904,8 @@ static int server_add_target(struct super_block *sb, struct vfsmount *mnt)
                libcfs_nid2str(mti->mti_nid), mti->mti_stripe_index);
 
         /* Register the target */
-        /* FIXME use ioctl instead? eg 
-        struct obd_ioctl_data ioc_data = { 0 };
-        ioc_data.ioc_inllen1 = strlen(ldd->ldd_svname) + 1;
-        ioc_data.ioc_inlbuf1 = ldd->ldd_svname;
-        
-        rc = obd_iocontrol(OBD_IOC_START, obd->obd_self_export,
-                            sizeof ioc_data, &ioc_data, NULL);
-        */
-        rc = obd_set_info(get_mgs_export(mgc),
+        /* FIXME use mdc_process_config instead */
+        rc = obd_set_info(mgc_mgs_export,
                           strlen("add_target"), "add_target",
                           sizeof(*mti), mti);
         CDEBUG(D_MOUNT, "disconnect");
@@ -921,7 +982,8 @@ static int server_start_targets(struct super_block *sb, struct vfsmount *mnt)
         server_mgc_set_fs(lsi->lsi_mgc, sb);
 
         /* Get a new index if needed */
-        if (lsi->lsi_ldd->ldd_flags & (LDD_F_NEED_INDEX | LDD_F_NEED_REGISTER)) {
+        if (lsi->lsi_ldd->ldd_flags & 
+            (LDD_F_NEED_INDEX | LDD_F_NEED_REGISTER)) {
                 CDEBUG(D_MOUNT, "Need new target index from MGS\n");
                 rc = server_add_target(sb, mnt);
                 if (rc) {
@@ -931,14 +993,15 @@ static int server_start_targets(struct super_block *sb, struct vfsmount *mnt)
                 }
         }
 
-        /* Let the target look up the mount using the target's name. */
+        /* Let the target look up the mount using the target's name 
+           (we can't pass the sb or mnt through class_process_config.) */
         rc = server_register_mount(lsi->lsi_ldd->ldd_svname, sb, mnt);
         if (rc) 
                 goto out;
 
-        /* The MGC starts targets using the llog named with the target name */
+        /* Start targets using the llog named for the target */
         cfg.cfg_instance = NULL;
-        rc = lustre_get_process_log(sb, lsi->lsi_ldd->ldd_svname, &cfg);
+        rc = config_log_start(sb, lsi->lsi_ldd->ldd_svname, &cfg);
         if (rc) {
                 CERROR("failed to start server %s: %d\n",
                        lsi->lsi_ldd->ldd_svname, rc);
@@ -1117,6 +1180,8 @@ static void server_put_super(struct super_block *sb)
                                                                                        
         CDEBUG(D_MOUNT, "server put_super %s\n", lsi->lsi_ldd->ldd_svname);
                                                                                        
+        config_log_end(lsi->lsi_ldd->ldd_svname);
+
         obd = class_name2obd(lsi->lsi_ldd->ldd_svname);
         if (obd) {
                 CDEBUG(D_MOUNT, "stopping %s\n", obd->obd_name);
@@ -1163,16 +1228,40 @@ static void server_umount_begin(struct super_block *sb)
         lsi->lsi_flags |= LSI_UMOUNT_FAILOVER;
 }
 
-#define log2(n) ffz(~(n))
-#define LUSTRE_SUPER_MAGIC 0x0BD00BD1
+static int server_statfs (struct super_block *sb, struct kstatfs *buf)
+{
+        struct vfsmount *mnt = s2lsi(sb)->lsi_srv_mnt;
+        
+        if (mnt && mnt->mnt_sb && mnt->mnt_sb->s_op->statfs) {
+                int rc = mnt->mnt_sb->s_op->statfs(mnt->mnt_sb, buf);
+                if (!rc) {
+                        buf->f_type = sb->s_magic;
+                        return 0;
+                }
+        }
+        
+        /* just return 0 */
+        buf->f_type = sb->s_magic;
+        buf->f_bsize = sb->s_blocksize;
+        buf->f_blocks = 1;
+        buf->f_bfree = 0;
+        buf->f_bavail = 0;
+        buf->f_files = 1;
+        buf->f_ffree = 0;
+        buf->f_namelen = NAME_MAX;
+        return 0;
+}
 
 static struct super_operations server_ops =
 {
-        //.statfs         = NULL,
         .put_super      = server_put_super,
         .umount_begin   = server_umount_begin, /* umount -f */
+        .statfs         = server_statfs,
 };
 
+#define log2(n) ffz(~(n))
+#define LUSTRE_SUPER_MAGIC 0x0BD00BD1
+
 static int server_fill_super_common(struct super_block *sb)
 {
         struct inode *root = 0;
@@ -1317,20 +1406,20 @@ static void lmd_print(struct lustre_mount_data *lmd)
 {
         int i;
 
-        CDEBUG(D_MOUNT, "mount data\n"); 
+        LCONSOLE_WARN("  mount data:\n"); 
         if (!lmd->lmd_mgsnid_count) 
-                CDEBUG(D_MOUNT, "no MGS nids\n");
+                LCONSOLE_WARN("no MGS nids\n");
         else for (i = 0; i < lmd->lmd_mgsnid_count; i++) {
-                CDEBUG(D_MOUNT, "nid %d:  %s\n", i, 
+                LCONSOLE_WARN("nid %d:  %s\n", i, 
                        libcfs_nid2str(lmd->lmd_mgsnid[i]));
         }
         if (lmd_is_client(lmd)) 
-                CDEBUG(D_MOUNT, "fsname:  %s\n", lmd->lmd_dev);
+                LCONSOLE_WARN("fsname:  %s\n", lmd->lmd_dev);
         else
-                CDEBUG(D_MOUNT, "device:  %s\n", lmd->lmd_dev);
-        CDEBUG(D_MOUNT, "flags:   %x\n", lmd->lmd_flags);
+                LCONSOLE_WARN("device:  %s\n", lmd->lmd_dev);
+        LCONSOLE_WARN("flags:   %x\n", lmd->lmd_flags);
         if (lmd->lmd_opts)
-                CDEBUG(D_MOUNT, "options: %s\n", lmd->lmd_opts);
+                LCONSOLE_WARN("options: %s\n", lmd->lmd_opts);
 }
 
 static int lmd_parse(char *options, struct lustre_mount_data *lmd)
@@ -1570,8 +1659,10 @@ int lustre_unregister_fs(void)
 
 EXPORT_SYMBOL(lustre_register_client_fill_super);
 EXPORT_SYMBOL(lustre_common_put_super);
-EXPORT_SYMBOL(lustre_get_process_log);
+EXPORT_SYMBOL(config_log_start);
+EXPORT_SYMBOL(config_log_end);
+EXPORT_SYMBOL(config_log_get);
+EXPORT_SYMBOL(config_log_put);
 EXPORT_SYMBOL(server_get_mount);
 EXPORT_SYMBOL(server_put_mount);
 
-
index 4ea9996..7141919 100644 (file)
@@ -325,8 +325,9 @@ void print_lustre_cfg(struct lustre_cfg *lcfg)
                 break;
         }
         case(LCFG_MARKER):{
-                printf("marker ");
-                print_1_cfg(lcfg);
+                struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
+                printf("marker %d (flags=%#x) '%s'", marker->cm_step,
+                       marker->cm_flags, marker->cm_comment);
                 break;
         }
         default: