/* obd_mount.c */
void lustre_register_client_fill_super(int (*cfs)(struct super_block *sb));
-void lustre_common_put_super(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 *,
struct vfsmount *mgs_vfsmnt;
struct super_block *mgs_sb;
struct dentry *mgs_configs_dir;
+ struct dentry *mgs_fid_de;
struct llog_handle *mgs_cfg_llh;
spinlock_t mgs_system_db_lock;
struct list_head mgs_system_db_list;
void class_fail_export(struct obd_export *exp);
void class_disconnect_exports(struct obd_device *obddev);
void class_disconnect_stale_exports(struct obd_device *obddev);
-void class_manual_cleanup(struct obd_device *obd);
+int class_manual_cleanup(struct obd_device *obd);
/* obdo.c */
#ifdef __KERNEL__
if (rc)
RETURN(rc);
+ //FIXME remove D_ERROR
+ CDEBUG(D_CONFIG | D_ERROR, "llog init with %d targets\n", count);
LASSERT(lov->desc.ld_tgt_count == count);
for (i = 0, ctgt = lov->tgts; i < lov->desc.ld_tgt_count; i++, ctgt++) {
struct obd_device *child;
{
struct mgs_obd *mgs = &obd->u.mgs;
struct lvfs_run_ctxt saved;
- struct dentry *logs_dentry;
+ struct dentry *dentry;
int rc;
ENTRY;
obd->obd_lvfs_ctxt.fs = get_ds();
obd->obd_lvfs_ctxt.cb_ops = mgs_lvfs_ops;
- /* setup the directory tree */
push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- logs_dentry = simple_mkdir(current->fs->pwd, MOUNT_CONFIGS_DIR, 0777, 1);
- if (IS_ERR(logs_dentry)) {
- rc = PTR_ERR(logs_dentry);
+ /* Setup the configs dir */
+ dentry = simple_mkdir(current->fs->pwd, MOUNT_CONFIGS_DIR, 0777, 1);
+ if (IS_ERR(dentry)) {
+ rc = PTR_ERR(dentry);
CERROR("cannot create %s directory: rc = %d\n",
MOUNT_CONFIGS_DIR, rc);
GOTO(err_pop, rc);
}
-
- mgs->mgs_configs_dir = logs_dentry;
+ mgs->mgs_configs_dir = dentry;
+
+ /* Need the iopen dir for fid2dentry, required by
+ LLOG_ORIGIN_HANDLE_READ_HEADER */
+ dentry = lookup_one_len("__iopen__", current->fs->pwd,
+ strlen("__iopen__"));
+ if (IS_ERR(dentry)) {
+ rc = PTR_ERR(dentry);
+ CERROR("cannot lookup __iopen__ directory: rc = %d\n", rc);
+ GOTO(err_configs, rc);
+ }
+ mgs->mgs_fid_de = dentry;
+ if (!dentry->d_inode || is_bad_inode(dentry->d_inode)) {
+ rc = -ENOENT;
+ CERROR("__iopen__ directory has no inode? rc = %d\n", rc);
+ GOTO(err_fid, rc);
+ }
err_pop:
pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
return rc;
+err_fid:
+ dput(mgs->mgs_fid_de);
+err_configs:
+ dput(mgs->mgs_configs_dir);
+ goto err_pop;
}
int mgs_fs_cleanup(struct obd_device *obd)
struct lvfs_run_ctxt saved;
int rc = 0;
- if (obd->obd_fail)
- CERROR("%s: shutting down for failover; client state will"
- " be preserved.\n", obd->obd_name);
-
class_disconnect_exports(obd); /* cleans up client info too */
push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (mgs->mgs_configs_dir) {
+ CERROR("configs dir dcount=%d\n",
+ atomic_read(&mgs->mgs_configs_dir->d_count));
l_dput(mgs->mgs_configs_dir);
mgs->mgs_configs_dir = NULL;
}
+ shrink_dcache_parent(mgs->mgs_fid_de);
+ CERROR("fid dir dcount=%d\n",
+ atomic_read(&mgs->mgs_fid_de->d_count));
+ dput(mgs->mgs_fid_de);
+
pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
return rc;
int fail = OBD_FAIL_MGMT_ALL_REPLY_NET;
int rc = 0;
ENTRY;
-
- CDEBUG(D_MGS, "MGS handle\n");
OBD_FAIL_RETURN(OBD_FAIL_MGMT_ALL_REQUEST_NET | OBD_FAIL_ONCE, 0);
break;
case OBD_LOG_CANCEL:
- CDEBUG(D_MGS, "log cancel\n");
+ DEBUG_REQ(D_MGS, req, "log cancel\n");
OBD_FAIL_RETURN(OBD_FAIL_OBD_LOG_CANCEL_NET, 0);
rc = -ENOTSUPP; /* la la la */
break;
}
LASSERT(current->journal_info == NULL);
+
+ CDEBUG(D_MGS, "MGS handle cmd=%d rc=%d\n", req->rq_reqmsg->opc, rc);
out:
target_send_reply(req, rc, fail);
RETURN(0);
}
+/* Same as mds_fid2dentry */
+/* Look up an entry by inode number. */
+/* this function ONLY returns valid dget'd dentries with an initialized inode
+ or errors */
+struct dentry *mgs_fid2dentry(struct mgs_obd *mgs, struct ll_fid *fid)
+{
+ char fid_name[32];
+ unsigned long ino = fid->id;
+ __u32 generation = fid->generation;
+ struct inode *inode;
+ struct dentry *result;
+
+ CDEBUG(D_DENTRY|D_ERROR, "--> mgs_fid2dentry: ino/gen %lu/%u, sb %p\n",
+ ino, generation, mgs->mgs_sb);
+
+ if (ino == 0)
+ RETURN(ERR_PTR(-ESTALE));
+
+ snprintf(fid_name, sizeof(fid_name), "0x%lx", ino);
+
+ /* under ext3 this is neither supposed to return bad inodes
+ nor NULL inodes. */
+ result = ll_lookup_one_len(fid_name, mgs->mgs_fid_de, strlen(fid_name));
+ if (IS_ERR(result))
+ RETURN(result);
+
+ inode = result->d_inode;
+ if (!inode)
+ RETURN(ERR_PTR(-ENOENT));
+
+ if (inode->i_generation == 0 || inode->i_nlink == 0) {
+ LCONSOLE_WARN("Found inode with zero generation or link -- this"
+ " may indicate disk corruption (inode: %lu, link:"
+ " %lu, count: %d)\n", inode->i_ino,
+ (unsigned long)inode->i_nlink,
+ atomic_read(&inode->i_count));
+ l_dput(result);
+ RETURN(ERR_PTR(-ENOENT));
+ }
+
+ if (generation && inode->i_generation != generation) {
+ /* we didn't find the right inode.. */
+ CDEBUG(D_INODE, "found wrong generation: inode %lu, link: %lu, "
+ "count: %d, generation %u/%u\n", inode->i_ino,
+ (unsigned long)inode->i_nlink,
+ atomic_read(&inode->i_count), inode->i_generation,
+ generation);
+ l_dput(result);
+ RETURN(ERR_PTR(-ENOENT));
+ }
+
+ RETURN(result);
+}
+
static struct dentry *mgs_lvfs_fid2dentry(__u64 id, __u32 gen, __u64 gr,
- void *data)
+ void *data)
{
- CERROR("Help!\n");
- return NULL;
+ struct obd_device *obd = data;
+ struct ll_fid fid;
+ fid.id = id;
+ fid.generation = gen;
+ return mgs_fid2dentry(&obd->u.mgs, &fid);
}
struct lvfs_callback_ops mgs_lvfs_ops = {
if (lovdesc == NULL)
RETURN(-ENOMEM);
/* Use defaults here, will fix them later with LCFG_PARAM */
+ lovdesc->ld_magic = LOV_DESC_MAGIC;
+ lovdesc->ld_tgt_count = 0;
lovdesc->ld_pattern = 0;
+ lovdesc->ld_default_stripe_count = 1;
lovdesc->ld_default_stripe_size = 1024*1024;
lovdesc->ld_default_stripe_offset = 0;
sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
int rc;
ENTRY;
+ // FIXME remove
+ CDEBUG(D_ERROR, "Closing file=%p\n", handle->lgh_file);
rc = filp_close(handle->lgh_file, 0);
if (rc)
CERROR("error closing log: rc %d\n", rc);
int size = sizeof(*idarray) * count;
loff_t off = 0;
- LASSERT(count);
+ if (!count)
+ return (0);
push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
file = filp_open(name, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
int size = sizeof(*idarray) * count;
loff_t off = 0;
- LASSERT(count);
+ if (!count)
+ return (0);
push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
file = filp_open(name, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
{
int cfg_len = rec->lrh_len;
char *cfg_buf = (char*) (rec + 1);
+ char *outstr, *ptr, *end;
int rc = 0;
ENTRY;
+
+ OBD_ALLOC(outstr, 256);
+ end = outstr + 256;
+ ptr = outstr;
+ if (!outstr) {
+ RETURN(-ENOMEM);
+ }
if (rec->lrh_type == OBD_CFG_REC) {
struct lustre_cfg *lcfg;
int i;
GOTO(out, rc);
lcfg = (struct lustre_cfg *)cfg_buf;
- CDEBUG(D_DUMP, "lcfg command: %x\n", lcfg->lcfg_command);
- if (LUSTRE_CFG_BUFLEN(lcfg, 0) > 0)
- CDEBUG(D_DUMP, " devname: %s\n",
- lustre_cfg_string(lcfg, 0));
- if (lcfg->lcfg_flags)
- CDEBUG(D_DUMP, " flags: %x\n", lcfg->lcfg_flags);
- if (lcfg->lcfg_nid)
- CDEBUG(D_DUMP, " nid: %s\n",
- libcfs_nid2str(lcfg->lcfg_nid));
- if (lcfg->lcfg_nal)
- CDEBUG(D_DUMP, " nal: %x (obsolete)\n", lcfg->lcfg_nal);
- if (lcfg->lcfg_num)
- CDEBUG(D_DUMP, " num: %x\n", lcfg->lcfg_num);
- for (i = 1; i < lcfg->lcfg_bufcount; i++)
- if (LUSTRE_CFG_BUFLEN(lcfg, i) > 0)
- CDEBUG(D_DUMP, " inlbuf%d: %s\n", i,
- lustre_cfg_string(lcfg, i));
+ ptr += snprintf(ptr, end-ptr, "\n cmd=%05x ",
+ lcfg->lcfg_command);
+ if (lcfg->lcfg_flags) {
+ ptr += snprintf(ptr, end-ptr, "flags=%#08x ",
+ lcfg->lcfg_flags);
+ }
+ if (lcfg->lcfg_num) {
+ ptr += snprintf(ptr, end-ptr, "num=%#08x ",
+ lcfg->lcfg_num);
+ }
+ if (lcfg->lcfg_nid) {
+ 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));
+ }
+ CDEBUG(D_DUMP, "%s\n", outstr);
} else if (rec->lrh_type == PTL_CFG_REC) {
CDEBUG(D_DUMP, "Obsolete pcfg command\n");
} else {
rc = -EINVAL;
}
out:
+ OBD_FREE(outstr, end - outstr);
RETURN(rc);
}
int rc, rc2;
ENTRY;
+ CDEBUG(D_DUMP, "Dumping config log %s\n", name);
+
rc = llog_create(ctxt, &llh, NULL, name);
if (rc)
RETURN(rc);
if (rc == 0)
rc = rc2;
+ CDEBUG(D_DUMP, "End config log %s\n", name);
RETURN(rc);
}
/* Cleanup and detach */
-void class_manual_cleanup(struct obd_device *obd)
+int class_manual_cleanup(struct obd_device *obd)
{
struct lustre_cfg *lcfg;
struct lustre_cfg_bufs bufs;
- int err;
+ int rc;
char flags[3]="";
ENTRY;
if (!obd) {
CERROR("empty cleanup\n");
- EXIT;
- return;
+ RETURN(-EALREADY);
}
if (obd->obd_force)
lustre_cfg_bufs_set_string(&bufs, 1, flags);
lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
- err = class_process_config(lcfg);
- if (err)
- CERROR("cleanup failed %d: %s\n", err, obd->obd_name);
+ rc = class_process_config(lcfg);
+ if (rc) {
+ CERROR("cleanup failed %d: %s\n", rc, obd->obd_name);
+ GOTO(out, rc);
+ }
/* the lcfg is almost the same for both ops */
lcfg->lcfg_command = LCFG_DETACH;
- err = class_process_config(lcfg);
+ rc = class_process_config(lcfg);
+ if (rc)
+ CERROR("detach failed %d: %s\n", rc, obd->obd_name);
+out:
lustre_cfg_free(lcfg);
- if (err)
- CERROR("detach failed %d: %s\n", err, obd->obd_name);
- EXIT;
+ RETURN(rc);
}
LASSERT(lmi->lmi_mnt == mnt);
unlock_mntput(lmi->lmi_mnt);
if (atomic_dec_and_test(&lsi->lsi_mounts)) {
- CDEBUG(D_MOUNT, "Last put of mnt %p from %s, mount count %d\n",
+ CDEBUG(D_MOUNT, "Last put of mnt %p from %s, vfscount=%d\n",
lmi->lmi_mnt, name,
atomic_read(&lmi->lmi_mnt->mnt_count));
/* last mount is the One True Mount */
if (atomic_read(&lmi->lmi_mnt->mnt_count) > 1)
- CERROR("%s: mount busy, mnt_count %d\n", name,
+ CERROR("%s: mount busy, vfscount=%d\n", name,
atomic_read(&lmi->lmi_mnt->mnt_count));
}
up(&lustre_mount_info_lock);
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);
return(-EINVAL);
}
- /* FIXME set up local llog originator with mgc_fs_setup
- could use ioctl (can't call directly because of layering). */
-
rc = obd_connect(&mgc_conn, mgc, &(mgc->obd_uuid), NULL);
if (rc) {
CERROR("connect failed %d\n", rc);
rc = class_config_parse_llog(rctxt, logname, cfg);
obd_disconnect(exp);
if (rc) {
+ int rc2;
LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
"from the MGS (%d). Trying local log.\n",
mgc->obd_name, logname, rc);
/* If we couldn't connect to the MGS, try reading a copy
of the config log stored locally on disk */
- rc = class_config_parse_llog(lctxt, logname, cfg);
- if (rc) {
+ rc2 = class_config_parse_llog(lctxt, logname, cfg);
+ if (rc2) {
LCONSOLE_ERROR("%s: Can't read the local config (%d)\n",
- mgc->obd_name, rc);
+ mgc->obd_name, rc2);
+ } else {
+ rc = 0;
}
}
out:
- //FIXME cleanup local originator with mgc_fs_cleanup
return (rc);
}
{
struct obd_device *obd;
char mgsname[] = "MGS";
+ int rc;
CDEBUG(D_MOUNT, "Stop MGS service %s\n", mgsname);
+ /* There better be only one MGS */
obd = class_name2obd(mgsname);
if (!obd) {
CDEBUG(D_CONFIG, "mgs %s not running\n", mgsname);
return;
}
+ /* The MGS should always stop when we say so */
+ obd->obd_force = 1;
class_manual_cleanup(obd);
}
return rc;
}
-static void lustre_stop_mgc(struct super_block *sb)
+static int lustre_stop_mgc(struct super_block *sb)
{
struct lustre_sb_info *lsi = s2lsi(sb);
struct obd_device *obd;
obd = lsi->lsi_mgc;
if (!obd)
- return;
+ return -ENOENT;
lsi->lsi_mgc = NULL;
if (!atomic_dec_and_test(&obd->u.cli.cl_mgc_refcount)) {
CDEBUG(D_MOUNT, "mgc still has %d references.\n",
atomic_read(&obd->u.cli.cl_mgc_refcount));
- return;
+ return -EBUSY;
}
- class_manual_cleanup(obd);
+ rc = class_manual_cleanup(obd);
+ if (rc)
+ return(rc);
/* class_add_uuid adds a nid even if the same uuid exists; we might
delete any copy here. So they all better match. */
libcfs_nid2str(nid), rc);
}
/* class_import_put will get rid of the additional connections */
+ return 0;
}
/* Since there's only one mgc per node, we have to change it's fs to get
ldd->ldd_svindex, mti->mti_stripe_index,
mti->mti_svname);
ldd->ldd_flags &= ~(LDD_F_NEED_INDEX | LDD_F_NEED_REGISTER);
- ldd->ldd_config_ver = 666; // FIXME
+ /* This server has never been started, so has no config */
+ ldd->ldd_config_ver = 0;
ldd->ldd_svindex = mti->mti_stripe_index;
- //ldd_make_sv_name(ldd);
+ strncpy(ldd->ldd_svname, mti->mti_svname,
+ sizeof(ldd->ldd_svname));
+ /* or ldd_make_sv_name(ldd); */
ldd_write(&mgc->obd_lvfs_ctxt, ldd);
/* FIXME write last_rcvd?, disk label? */
}
/* The MGC starts targets using the svname llog */
cfg.cfg_instance = NULL;
cfg.cfg_uuid = lsi->lsi_mgc->obd_uuid;
- lustre_get_process_log(sb, lsi->lsi_ldd->ldd_svname, &cfg);
+ rc = lustre_get_process_log(sb, lsi->lsi_ldd->ldd_svname, &cfg);
if (rc) {
CERROR("failed to start server %s: %d\n",
lsi->lsi_ldd->ldd_svname, rc);
return(lsi);
}
-void lustre_free_lsi(struct super_block *sb)
+static int lustre_free_lsi(struct super_block *sb)
{
struct lustre_sb_info *lsi = s2lsi(sb);
ENTRY;
if (lsi != NULL) {
+ if (atomic_read(&lsi->lsi_mounts) > 0) {
+ /* someone didn't call server_put_mount */
+ /* FIXME this should assert */
+ CERROR("There are still mounts on this sb!\n");
+ RETURN(-EBUSY);
+ }
if (lsi->lsi_ldd != NULL)
OBD_FREE(lsi->lsi_ldd, sizeof(*lsi->lsi_ldd));
s2lsi_nocast(sb) = NULL;
}
- EXIT;
+ RETURN(0);
}
struct lustre_sb_info *lsi = s2lsi(sb);
struct obd_device *obd;
struct vfsmount *mnt = lsi->lsi_srv_mnt;
+ int rc;
CDEBUG(D_MOUNT, "server put_super %s\n", lsi->lsi_ldd->ldd_svname);
server_stop_mgs(sb);
/* clean the mgc and sb */
- lustre_common_put_super(sb);
-
+ rc = lustre_common_put_super(sb);
+ // FIXME how do I return a failure?
+
/* drop the One True Mount */
unlock_mntput(mnt);
}
calls lustre_common_put_super; check there for LSI_SERVER flag,
call s_p_s if so.
Probably should start client from new thread so we can return.
- Client will not finish until all servers are connected. */
+ Client will not finish until all servers are connected.
+ Note - MGMT-only server does NOT get a client, since there is no
+ lustre fs associated - the MGMT is for all lustre fs's */
}
rc = server_fill_super_common(sb);
/*************** mount common betweeen server and client ***************/
/* Common umount */
-void lustre_common_put_super(struct super_block *sb)
+int lustre_common_put_super(struct super_block *sb)
{
+ int rc;
CDEBUG(D_MOUNT, "dropping sb %p\n", sb);
- lustre_stop_mgc(sb);
- lustre_free_lsi(sb);
+ rc = lustre_stop_mgc(sb);
+ rc = lustre_free_lsi(sb);
+ return rc;
}
static void lmd_print(struct lustre_mount_data *lmd)
static int llog_client_close(struct llog_handle *handle)
{
int rc = 0;
-
+ /* this doesn't call LLOG_ORIGIN_HANDLE_CLOSE because
+ the servers all close the file at the end of every
+ other LLOG_ RPC. */
RETURN(rc);
}
fwrite(&mop->mo_ldd, sizeof(mop->mo_ldd), 1, filep);
fclose(filep);
+#if 0
+ /* servers create their own last_rcvd if nonexistent - why do it here?*/
/* Create the inital last_rcvd file */
vprint("Writing %s\n", LAST_RCVD);
sprintf(filepnm, "%s/%s", mntpt, LAST_RCVD);
fwrite(&lsd, sizeof(lsd), 1, filep);
ret = 0;
fclose(filep);
+#endif
+
out_umnt:
vprint("unmounting backing device\n");
umount(mntpt);
case LDD_MT_EXT3:
case LDD_MT_LDISKFS: {
sprintf(mop.mo_ldd.ldd_mount_opts, "errors=remount-ro");
- if (IS_MDT(&mop.mo_ldd))
+ if (IS_MDT(&mop.mo_ldd) || IS_MGMT(&mop.mo_ldd))
strcat(mop.mo_ldd.ldd_mount_opts,
",iopen_nopriv,user_xattr");
if ((get_os_version() == 24) && IS_OST(&mop.mo_ldd))
#!/bin/sh
-rmmod llite
-rmmod mdc
-rmmod lov
-rmmod osc
-rmmod obdfilter
-rmmod fsfilt_ext3
-rmmod fsfilt_ldiskfs
-rmmod ldiskfs
-rmmod mgc
-rmmod mgs
-rmmod ost
-rmmod mds
-rmmod ptlrpc
-rmmod obdclass
-rmmod lvfs
-rmmod ksocknal
-rmmod portals
-rmmod libcfs
+./lctl modules | awk '{ print $2 }' | xargs rmmod
+# do it again, in case we tried to unload ksocklnd too early
+./lctl modules | awk '{ print $2 }' | xargs rmmod