From f6ed61ea624a2783b37e3f22f6a98cabda419b1f Mon Sep 17 00:00:00 2001 From: yury <yury> Date: Mon, 22 Aug 2005 09:48:30 +0000 Subject: [PATCH] - fixes about cobd_switch() which caused issues with cleanup: - avoid double connections to choosen export due to using lctl on umounted client (1st connection) and after that mount the client (2nd connection). Avoid double EA init along with double connection. - disconnect correct export on cobd_disconnect() - avoid possible oops on double cobd_cleanup() due to freed cmobd->write_srv, but not zerod out after that. - in cobd_switch() set ->cache_on field into new value only if COBD_CONNECT or COBD_SWITCH bias is specified. - in LMV and LOV in lconf cleanup LMV and LOV first and after that cleanup all their targets. This is because LMV, etc. cleanup needs targets OBD attached, with correct obd_name, etc. This fixes prevents oops in disconnect time whrn using test45 configuration. --- lustre/cmobd/cm_obd.c | 4 +- lustre/cobd/cache_obd.c | 94 +++++++++++++++++++++++------------------ lustre/utils/lconf | 11 +++-- 3 files changed, 61 insertions(+), 48 deletions(-) diff --git a/lustre/cmobd/cm_obd.c b/lustre/cmobd/cm_obd.c index fe384a9565..25878671f4 100644 --- a/lustre/cmobd/cm_obd.c +++ b/lustre/cmobd/cm_obd.c @@ -247,8 +247,10 @@ static int cmobd_cleanup(struct obd_device *obd, int flags) int rc; ENTRY; - if (cmobd->write_srv) + if (cmobd->write_srv) { cmobd_cleanup_write_srv(obd); + cmobd->write_srv = NULL; + } rc = obd_disconnect(cmobd->master_exp, flags); if (rc) { diff --git a/lustre/cobd/cache_obd.c b/lustre/cobd/cache_obd.c index 073ff70231..a2b1d1733b 100644 --- a/lustre/cobd/cache_obd.c +++ b/lustre/cobd/cache_obd.c @@ -305,8 +305,8 @@ cobd_disconnect_client(struct obd_device *obd, } #define COBD_CONNECT (1 << 0) -#define COBD_DISCON (1 << 1) -#define COBD_BOTH (1 << 2) +#define COBD_DISCON (1 << 1) +#define COBD_SWITCH (1 << 2) /* magic function for switching cobd between two exports cache and master in * strong correspondence with passed @cache_on. It also may perform partial @@ -314,8 +314,9 @@ cobd_disconnect_client(struct obd_device *obd, * * bias == COBD_CONNECT only connect new export (used in cobd_connect()) * bias == COBD_DISCON only disconnect old export (used in cobd_disconnect()) - * bias == COBD_BOTH do both (disconnect old and connect new) (used in - * cobd_iocontrol()) + * + * bias == COBD_SWITCH do both (disconnect old and connect new). This will also + * set ->cache_on to passed @cache_on value. */ static int cobd_switch(struct obd_device *obd, int cache_on, int bias) @@ -337,7 +338,7 @@ static int cobd_switch(struct obd_device *obd, } /* disconnect old export */ - if (bias == COBD_BOTH || bias == COBD_DISCON) { + if (bias == COBD_SWITCH || bias == COBD_DISCON) { if (discon_exp) { rc = cobd_disconnect_client(obd, discon_exp, 0); if (rc) { @@ -353,43 +354,54 @@ static int cobd_switch(struct obd_device *obd, } /* connect new export */ - if (bias == COBD_BOTH || bias == COBD_CONNECT) { - rc = cobd_connect_client(obd, conn_exp, &conn, - NULL, OBD_OPT_REAL_CLIENT); - if (rc) { - CERROR("can't connect export %p, err %d\n", - conn_exp, rc); - RETURN(rc); - } + if (bias == COBD_SWITCH || bias == COBD_CONNECT) { + int connected; - if (cache_on) { - cobd->cache_real_exp = class_conn2export(&conn); - cli_obd = class_exp2obd(cobd->cache_exp); - } else { - cobd->master_real_exp = class_conn2export(&conn); - cli_obd = class_exp2obd(cobd->master_exp); - } - } + connected = cache_on ? (cobd->cache_real_exp != NULL) : + (cobd->master_real_exp != NULL); - cobd->cache_on = cache_on; - - if (bias == COBD_BOTH || bias == COBD_CONNECT) { - /* re-init EA size for new selected export. This should be done after - * assigining new state to @cobd->cache_on to not call not connened - * already old export. */ - if (obd_md_type(cli_obd)) { - rc = cobd_init_dt_desc(obd); - if (rc == 0) { - rc = cobd_init_ea_size(obd); - if (rc) { - CERROR("can't initialize EA size, " + /* correct export already may be connected */ + if (!connected) { + rc = cobd_connect_client(obd, conn_exp, &conn, + NULL, OBD_OPT_REAL_CLIENT); + if (rc) { + CERROR("can't connect export %p, err %d\n", + conn_exp, rc); + RETURN(rc); + } + + if (cache_on) { + cobd->cache_real_exp = class_conn2export(&conn); + cli_obd = class_exp2obd(cobd->cache_exp); + } else { + cobd->master_real_exp = class_conn2export(&conn); + cli_obd = class_exp2obd(cobd->master_exp); + } + + /* change flag only if connect is allowed to keep + * ->cache_on coherent with real export connected. */ + cobd->cache_on = cache_on; + + /* re-init EA size for new selected export. This should + * be done after assigining new state to @cobd->cache_on + * to not call disconnected old export. */ + if (obd_md_type(cli_obd)) { + rc = cobd_init_dt_desc(obd); + if (rc == 0) { + rc = cobd_init_ea_size(obd); + if (rc) { + CERROR("can't initialize EA size, " + "err %d\n", rc); + } + } else { + CERROR("can't initialize data lovdesc, " "err %d\n", rc); + /* ignore cases when we did not manage + * to init lovdesc. This is because some + * devices may not know "lovdesc" info + * command. */ + rc = 0; } - } else { - /* ignore cases when we di dnot manage to init - * lovdesc. This is because some devices may not know - * "lovdesc" info command. */ - rc = 0; } } } @@ -442,7 +454,7 @@ cobd_disconnect(struct obd_export *exp, unsigned long flags) * cache should be switched after client umount this is not needed. * --umka. */ cobd = &obd->u.cobd; - rc = cobd_switch(obd, cobd->cache_on, COBD_DISCON); + rc = cobd_switch(obd, !cobd->cache_on, COBD_DISCON); class_disconnect(exp, flags); RETURN(rc); @@ -520,11 +532,11 @@ static int cobd_iocontrol(unsigned int cmd, struct obd_export *exp, switch (cmd) { case OBD_IOC_COBD_CON: if (!cobd->cache_on) - rc = cobd_switch(obd, 1, COBD_BOTH); + rc = cobd_switch(obd, 1, COBD_SWITCH); break; case OBD_IOC_COBD_COFF: if (cobd->cache_on) - rc = cobd_switch(obd, 0, COBD_BOTH); + rc = cobd_switch(obd, 0, COBD_SWITCH); break; default: cobd_exp = cobd_get_exp(obd); diff --git a/lustre/utils/lconf b/lustre/utils/lconf index e69dbcb09c..53f19c777e 100755 --- a/lustre/utils/lconf +++ b/lustre/utils/lconf @@ -1659,11 +1659,11 @@ class LOV(Module): lctl.lov_add_osc(self.name, target_uuid, index, gen) def cleanup(self): + if is_prepared(self.name): + Module.cleanup(self) for (osc, index, gen, active) in self.osclist: target_uuid = osc.target_uuid osc.cleanup() - if is_prepared(self.name): - Module.cleanup(self) if self.config_only: panic("Can't clean up config_only LOV ", self.name) @@ -1719,10 +1719,10 @@ class LMV(Module): lctl.lmv_add_mdc(self.name, mdc.target_uuid) def cleanup(self): - for mdc in self.mdclist: - mdc.cleanup() if is_prepared(self.name): Module.cleanup(self) + for mdc in self.mdclist: + mdc.cleanup() def add_module(self, manager): for mdc in self.mdclist: @@ -2708,8 +2708,7 @@ class CMOBD(Module): def cleanup(self): if is_prepared(self.name): Module.cleanup(self) - if self.master: - self.master.cleanup() + self.master.cleanup() def add_module(self, manager): manager.add_lustre_module('smfs', 'smfs') -- GitLab