- /* if write_conf is true, the registration must succeed */
- writeconf = !!(ldd->ldd_flags & (LDD_F_NEED_INDEX | LDD_F_UPDATE));
- mti->mti_flags |= LDD_F_OPC_REG;
-
- /* Register the target */
- /* FIXME use mgc_process_config instead */
- rc = obd_set_info_async(mgc->u.cli.cl_mgc_mgsexp,
- sizeof(KEY_REGISTER_TARGET), KEY_REGISTER_TARGET,
- sizeof(*mti), mti, NULL);
- if (rc) {
- if (mti->mti_flags & LDD_F_ERROR) {
- LCONSOLE_ERROR_MSG(0x160,
- "The MGS is refusing to allow this "
- "server (%s) to start. Please see messages"
- " on the MGS node.\n", ldd->ldd_svname);
- } else if (writeconf) {
- LCONSOLE_ERROR_MSG(0x15f,
- "Communication to the MGS return error %d. "
- "Is the MGS running?\n", rc);
- } else {
- CERROR("Cannot talk to the MGS: %d, not fatal\n", rc);
- /* reset the error code for non-fatal error. */
- rc = 0;
- }
- GOTO(out, rc);
- }
-
- /* Always update our flags */
- ldd->ldd_flags = mti->mti_flags & LDD_F_ONDISK_MASK;
-
- /* If this flag is set, it means the MGS wants us to change our
- on-disk data. (So far this means just the index.) */
- if (mti->mti_flags & LDD_F_REWRITE_LDD) {
- char *label;
- int err;
- CDEBUG(D_MOUNT, "Changing on-disk index from %#x to %#x "
- "for %s\n", ldd->ldd_svindex, mti->mti_stripe_index,
- mti->mti_svname);
- ldd->ldd_svindex = mti->mti_stripe_index;
- strncpy(ldd->ldd_svname, mti->mti_svname,
- sizeof(ldd->ldd_svname));
- /* or ldd_make_sv_name(ldd); */
- ldd_write(&mgc->obd_lvfs_ctxt, ldd);
- err = fsfilt_set_label(mgc, lsi->lsi_srv_mnt->mnt_sb,
- mti->mti_svname);
- if (err)
- CERROR("Label set error %d\n", err);
- label = fsfilt_get_label(mgc, lsi->lsi_srv_mnt->mnt_sb);
- if (label)
- CDEBUG(D_MOUNT, "Disk label changed to %s\n", label);
-
- /* Flush the new ldd to disk */
- fsfilt_sync(mgc, lsi->lsi_srv_mnt->mnt_sb);
- }
-
-out:
- if (mti)
- OBD_FREE_PTR(mti);
- RETURN(rc);
-}
-
-/**
- * Notify the MGS that this target is ready.
- * Used by IR - if the MGS receives this message, it will notify clients.
- */
-static int server_notify_target(struct super_block *sb, struct obd_device *obd)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct obd_device *mgc = lsi->lsi_mgc;
- struct mgs_target_info *mti = NULL;
- int rc;
- ENTRY;
-
- LASSERT(mgc);
-
- if (!(lsi->lsi_flags & LSI_SERVER))
- RETURN(-EINVAL);
-
- OBD_ALLOC_PTR(mti);
- if (!mti)
- RETURN(-ENOMEM);
- rc = server_sb2mti(sb, mti);
- if (rc)
- GOTO(out, rc);
-
- mti->mti_instance = obd->u.obt.obt_instance;
- mti->mti_flags |= LDD_F_OPC_READY;
-
- /* FIXME use mgc_process_config instead */
- rc = obd_set_info_async(mgc->u.cli.cl_mgc_mgsexp,
- sizeof(KEY_REGISTER_TARGET),
- KEY_REGISTER_TARGET,
- sizeof(*mti), mti, NULL);
-
- /* Imperative recovery: if the mgs informs us to use IR? */
- if (!rc && !(mti->mti_flags & LDD_F_ERROR) &&
- (mti->mti_flags & LDD_F_IR_CAPABLE))
- lsi->lsi_flags |= LSI_IR_CAPABLE;
-
-out:
- if (mti)
- OBD_FREE_PTR(mti);
- RETURN(rc);
-
-}
-
-/** Start server targets: MDTs and OSTs
- */
-static int server_start_targets(struct super_block *sb, struct vfsmount *mnt)
-{
- struct obd_device *obd;
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct config_llog_instance cfg;
- int rc;
- ENTRY;
-
- CDEBUG(D_MOUNT, "starting target %s\n", lsi->lsi_ldd->ldd_svname);
-
-#if 0
- /* If we're an MDT, make sure the global MDS is running */
- if (lsi->lsi_ldd->ldd_flags & LDD_F_SV_TYPE_MDT) {
- /* make sure the MDS is started */
- cfs_mutex_down(&server_start_lock);
- obd = class_name2obd(LUSTRE_MDS_OBDNAME);
- if (!obd) {
- rc = lustre_start_simple(LUSTRE_MDS_OBDNAME,
- /* FIXME pre-rename, should eventually be LUSTRE_MDS_NAME */
- LUSTRE_MDT_NAME,
- LUSTRE_MDS_OBDNAME"_uuid",
- 0, 0);
- if (rc) {
- cfs_mutex_up(&server_start_lock);
- CERROR("failed to start MDS: %d\n", rc);
- RETURN(rc);
- }
- }
- cfs_mutex_up(&server_start_lock);
- }
-#endif
-
- /* If we're an OST, make sure the global OSS is running */
- if (IS_OST(lsi->lsi_ldd)) {
- /* make sure OSS is started */
- cfs_mutex_down(&server_start_lock);
- obd = class_name2obd(LUSTRE_OSS_OBDNAME);
- if (!obd) {
- rc = lustre_start_simple(LUSTRE_OSS_OBDNAME,
- LUSTRE_OSS_NAME,
- LUSTRE_OSS_OBDNAME"_uuid",
- 0, 0);
- if (rc) {
- cfs_mutex_up(&server_start_lock);
- CERROR("failed to start OSS: %d\n", rc);
- RETURN(rc);
- }
- }
- cfs_mutex_up(&server_start_lock);
- }
-
- /* Set the mgc fs to our server disk. This allows the MGC to
- * read and write configs locally, in case it can't talk to the MGS. */
- rc = server_mgc_set_fs(lsi->lsi_mgc, sb);
- if (rc)
- RETURN(rc);
-
- /* Register with MGS */
- rc = server_register_target(sb);
- if (rc)
- GOTO(out_mgc, rc);
-
- /* 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_mgc, rc);
-
- /* Start targets using the llog named for the target */
- memset(&cfg, 0, sizeof(cfg));
- rc = lustre_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);
- /* Do NOT call server_deregister_mount() here. This makes it
- * impossible to find mount later in cleanup time and leaves
- * @lsi and othder stuff leaked. -umka */
- GOTO(out_mgc, rc);
- }
-
-out_mgc:
- /* Release the mgc fs for others to use */
- server_mgc_clear_fs(lsi->lsi_mgc);
-
- if (!rc) {
- obd = class_name2obd(lsi->lsi_ldd->ldd_svname);
- if (!obd) {
- CERROR("no server named %s was started\n",
- lsi->lsi_ldd->ldd_svname);
- RETURN(-ENXIO);
- }
-
- if ((lsi->lsi_lmd->lmd_flags & LMD_FLG_ABORT_RECOV) &&
- (OBP(obd, iocontrol))) {
- obd_iocontrol(OBD_IOC_ABORT_RECOVERY,
- obd->obd_self_export, 0, NULL, NULL);
- }
-
- server_notify_target(sb, obd);
-
- /* calculate recovery timeout, do it after lustre_process_log */
- server_calc_timeout(lsi, obd);
-
- /* log has been fully processed */
- obd_notify(obd, NULL, OBD_NOTIFY_CONFIG, (void *)CONFIG_LOG);
- }
-
- RETURN(rc);
-}
-
-/***************** lustre superblock **************/
-
-struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
-{
- struct lustre_sb_info *lsi;
- ENTRY;
-
- OBD_ALLOC_PTR(lsi);
- if (!lsi)
- RETURN(NULL);
- OBD_ALLOC_PTR(lsi->lsi_lmd);
- if (!lsi->lsi_lmd) {
- OBD_FREE_PTR(lsi);
- RETURN(NULL);
- }
-
- lsi->lsi_lmd->lmd_exclude_count = 0;
- lsi->lsi_lmd->lmd_recovery_time_soft = 0;
- lsi->lsi_lmd->lmd_recovery_time_hard = 0;
- s2lsi_nocast(sb) = lsi;
- /* we take 1 extra ref for our setup */
- cfs_atomic_set(&lsi->lsi_mounts, 1);
-
- /* Default umount style */
- lsi->lsi_flags = LSI_UMOUNT_FAILOVER;
-
- RETURN(lsi);
-}
-
-static int lustre_free_lsi(struct super_block *sb)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
- ENTRY;
-
- LASSERT(lsi != NULL);
- CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi);
-
- /* someone didn't call server_put_mount. */
- LASSERT(cfs_atomic_read(&lsi->lsi_mounts) == 0);
-
- if (lsi->lsi_ldd != NULL)
- OBD_FREE(lsi->lsi_ldd, sizeof(*lsi->lsi_ldd));
-
- if (lsi->lsi_lmd != NULL) {
- if (lsi->lsi_lmd->lmd_dev != NULL)
- OBD_FREE(lsi->lsi_lmd->lmd_dev,
- strlen(lsi->lsi_lmd->lmd_dev) + 1);
- if (lsi->lsi_lmd->lmd_profile != NULL)
- OBD_FREE(lsi->lsi_lmd->lmd_profile,
- strlen(lsi->lsi_lmd->lmd_profile) + 1);
- if (lsi->lsi_lmd->lmd_mgssec != NULL)
- OBD_FREE(lsi->lsi_lmd->lmd_mgssec,
- strlen(lsi->lsi_lmd->lmd_mgssec) + 1);
- if (lsi->lsi_lmd->lmd_opts != NULL)
- OBD_FREE(lsi->lsi_lmd->lmd_opts,
- strlen(lsi->lsi_lmd->lmd_opts) + 1);
- if (lsi->lsi_lmd->lmd_exclude_count)
- OBD_FREE(lsi->lsi_lmd->lmd_exclude,
- sizeof(lsi->lsi_lmd->lmd_exclude[0]) *
- lsi->lsi_lmd->lmd_exclude_count);
- OBD_FREE(lsi->lsi_lmd, sizeof(*lsi->lsi_lmd));
- }
-
- LASSERT(lsi->lsi_llsbi == NULL);
- OBD_FREE(lsi, sizeof(*lsi));
- s2lsi_nocast(sb) = NULL;
-
- RETURN(0);
-}
-
-/* The lsi has one reference for every server that is using the disk -
- e.g. MDT, MGS, and potentially MGC */
-static int lustre_put_lsi(struct super_block *sb)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
- ENTRY;
-
- LASSERT(lsi != NULL);
-
- CDEBUG(D_MOUNT, "put %p %d\n", sb, cfs_atomic_read(&lsi->lsi_mounts));
- if (cfs_atomic_dec_and_test(&lsi->lsi_mounts)) {
- lustre_free_lsi(sb);
- RETURN(1);
- }
- RETURN(0);
-}
-
-/*************** server mount ******************/
-
-/** Kernel mount using mount options in MOUNT_DATA_FILE.
- * Since this file lives on the disk, we pre-mount using a common
- * type, read the file, then re-mount using the type specified in the
- * file.
- */
-static struct vfsmount *server_kernel_mount(struct super_block *sb)
-{
- struct lvfs_run_ctxt mount_ctxt;
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct lustre_disk_data *ldd;
- struct lustre_mount_data *lmd = lsi->lsi_lmd;
- struct vfsmount *mnt;
- char *options = NULL;
- unsigned long page, s_flags;
- struct page *__page;
- int len;
- int rc;
- ENTRY;
-
- OBD_ALLOC(ldd, sizeof(*ldd));
- if (!ldd)
- RETURN(ERR_PTR(-ENOMEM));
-
- /* In the past, we have always used flags = 0.
- Note ext3/ldiskfs can't be mounted ro. */
- s_flags = sb->s_flags;
-
- /* allocate memory for options */
- OBD_PAGE_ALLOC(__page, CFS_ALLOC_STD);
- if (!__page)
- GOTO(out_free, rc = -ENOMEM);
- page = (unsigned long)cfs_page_address(__page);
- options = (char *)page;
- memset(options, 0, CFS_PAGE_SIZE);
-
- /* mount-line options must be added for pre-mount because it may
- * contain mount options such as journal_dev which are required
- * to mount successfuly the underlying filesystem */
- if (lmd->lmd_opts && (*(lmd->lmd_opts) != 0))
- strncat(options, lmd->lmd_opts, CFS_PAGE_SIZE - 1);
-
- /* Pre-mount ldiskfs to read the MOUNT_DATA_FILE */
- CDEBUG(D_MOUNT, "Pre-mount ldiskfs %s\n", lmd->lmd_dev);
- mnt = ll_kern_mount("ldiskfs", s_flags, lmd->lmd_dev, (void *)options);
- if (IS_ERR(mnt)) {
- rc = PTR_ERR(mnt);
- CERROR("premount %s:%#lx ldiskfs failed: %d "
- "Is the ldiskfs module available?\n",
- lmd->lmd_dev, s_flags, rc );
- GOTO(out_free, rc);
- }
-
- OBD_SET_CTXT_MAGIC(&mount_ctxt);
- mount_ctxt.pwdmnt = mnt;
- mount_ctxt.pwd = mnt->mnt_root;
- mount_ctxt.fs = get_ds();
-
- rc = ldd_parse(&mount_ctxt, ldd);
- unlock_mntput(mnt);
-
- if (rc) {
- CERROR("premount parse options failed: rc = %d\n", rc);
- GOTO(out_free, rc);
- }
-
- /* Done with our pre-mount, now do the real mount. */
-
- /* Glom up mount options */
- memset(options, 0, CFS_PAGE_SIZE);
- strncpy(options, ldd->ldd_mount_opts, CFS_PAGE_SIZE - 2);
-
- len = CFS_PAGE_SIZE - strlen(options) - 2;
- if (*options != 0)
- strcat(options, ",");
- strncat(options, "no_mbcache", len);
-
- /* Add in any mount-line options */
- if (lmd->lmd_opts && (*(lmd->lmd_opts) != 0)) {
- len = CFS_PAGE_SIZE - strlen(options) - 2;
- strcat(options, ",");
- strncat(options, lmd->lmd_opts, len);
- }
-
- /* Special permanent mount flags */
- if (IS_OST(ldd))
- s_flags |= MS_NOATIME | MS_NODIRATIME;
-
- CDEBUG(D_MOUNT, "kern_mount: %s %s %s\n",
- MT_STR(ldd), lmd->lmd_dev, options);
- mnt = ll_kern_mount(MT_STR(ldd), s_flags, lmd->lmd_dev,
- (void *)options);
- if (IS_ERR(mnt)) {
- rc = PTR_ERR(mnt);
- CERROR("ll_kern_mount failed: rc = %d\n", rc);
- GOTO(out_free, rc);
- }
-
- if (lmd->lmd_flags & LMD_FLG_ABORT_RECOV)
- simple_truncate(mnt->mnt_sb->s_root, mnt, LAST_RCVD,
- LR_CLIENT_START);
-
- OBD_PAGE_FREE(__page);
- lsi->lsi_ldd = ldd; /* freed at lsi cleanup */
- CDEBUG(D_SUPER, "%s: mnt = %p\n", lmd->lmd_dev, mnt);
- RETURN(mnt);
-
-out_free:
- if (__page)
- OBD_PAGE_FREE(__page);
- OBD_FREE(ldd, sizeof(*ldd));
- lsi->lsi_ldd = NULL;
- RETURN(ERR_PTR(rc));
-}
-
-/** Wait here forever until the mount refcount is 0 before completing umount,
- * else we risk dereferencing a null pointer.
- * LNET may take e.g. 165s before killing zombies.
- */
-static void server_wait_finished(struct vfsmount *mnt)
-{
- cfs_waitq_t waitq;
- int rc, waited = 0;
- cfs_sigset_t blocked;
-
- cfs_waitq_init(&waitq);
-
- while (mnt_get_count(mnt) > 1) {
- if (waited && (waited % 30 == 0))
- LCONSOLE_WARN("Mount still busy with %d refs after "
- "%d secs.\n",
- mnt_get_count(mnt),
- waited);
- /* Cannot use l_event_wait() for an interruptible sleep. */
- waited += 3;
- blocked = cfs_block_sigsinv(sigmask(SIGKILL));
- cfs_waitq_wait_event_interruptible_timeout(
- waitq,
- (mnt_get_count(mnt) == 1),
- cfs_time_seconds(3),
- rc);
- cfs_block_sigs(blocked);
- if (rc < 0) {
- LCONSOLE_EMERG("Danger: interrupted umount %s with "
- "%d refs!\n", mnt->mnt_devname,
- mnt_get_count(mnt));
- break;
- }
-
- }
-}
-
-/** Start the shutdown of servers at umount.
- */
-static void server_put_super(struct super_block *sb)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct obd_device *obd;
- struct vfsmount *mnt = lsi->lsi_srv_mnt;
- char *tmpname, *extraname = NULL;
- int tmpname_sz;
- int lddflags = lsi->lsi_ldd->ldd_flags;
- int lsiflags = lsi->lsi_flags;
- ENTRY;
-
- LASSERT(lsiflags & LSI_SERVER);
-
- tmpname_sz = strlen(lsi->lsi_ldd->ldd_svname) + 1;
- OBD_ALLOC(tmpname, tmpname_sz);
- memcpy(tmpname, lsi->lsi_ldd->ldd_svname, tmpname_sz);
- CDEBUG(D_MOUNT, "server put_super %s\n", tmpname);
- if (IS_MDT(lsi->lsi_ldd) && (lsi->lsi_lmd->lmd_flags & LMD_FLG_NOSVC))
- snprintf(tmpname, tmpname_sz, "MGS");
-
- /* Stop the target */
- if (!(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOSVC) &&
- (IS_MDT(lsi->lsi_ldd) || IS_OST(lsi->lsi_ldd))) {
- struct lustre_profile *lprof = NULL;
-
- /* tell the mgc to drop the config log */
- lustre_end_log(sb, lsi->lsi_ldd->ldd_svname, NULL);
-
- /* COMPAT_146 - profile may get deleted in mgc_cleanup.
- If there are any setup/cleanup errors, save the lov
- name for safety cleanup later. */
- lprof = class_get_profile(lsi->lsi_ldd->ldd_svname);
- if (lprof && lprof->lp_dt) {
- OBD_ALLOC(extraname, strlen(lprof->lp_dt) + 1);
- strcpy(extraname, lprof->lp_dt);
- }
-
- obd = class_name2obd(lsi->lsi_ldd->ldd_svname);
- if (obd) {
- CDEBUG(D_MOUNT, "stopping %s\n", obd->obd_name);
- if (lsi->lsi_flags & LSI_UMOUNT_FAILOVER)
- obd->obd_fail = 1;
- /* We can't seem to give an error return code
- * to .put_super, so we better make sure we clean up! */
- obd->obd_force = 1;
- class_manual_cleanup(obd);
- } else {
- CERROR("no obd %s\n", lsi->lsi_ldd->ldd_svname);
- server_deregister_mount(lsi->lsi_ldd->ldd_svname);
- }
- }
-
- /* If they wanted the mgs to stop separately from the mdt, they
- should have put it on a different device. */
- if (IS_MGS(lsi->lsi_ldd)) {
- /* if MDS start with --nomgs, don't stop MGS then */
- if (!(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOMGS)) {
- char *logname;
-
- OBD_ALLOC(logname, MGS_PARAM_MAXLEN);
- if (!logname) {
- LCONSOLE_WARN("Stopping mgs failed %d, please "
- "try again.", -ENOMEM);
- return;
- }
- strcpy(logname, lsi->lsi_ldd->ldd_fsname);
- strcat(logname, "-params");
- /* tell the mgc to drop parameter config log */
- lustre_end_log(sb, logname, NULL);
- OBD_FREE(logname, MGS_PARAM_MAXLEN);
-
- server_stop_mgs(sb);
- }
- }
-
- /* Clean the mgc and sb */
- lustre_common_put_super(sb);
-
- /* Wait for the targets to really clean up - can't exit (and let the
- sb get destroyed) while the mount is still in use */
- server_wait_finished(mnt);
-
- /* drop the One True Mount */
- unlock_mntput(mnt);
-
- /* Stop the servers (MDS, OSS) if no longer needed. We must wait
- until the target is really gone so that our type refcount check
- is right. */
- server_stop_servers(lddflags, lsiflags);
-
- /* In case of startup or cleanup err, stop related obds */
- if (extraname) {
- obd = class_name2obd(extraname);
- if (obd) {
- CWARN("Cleaning orphaned obd %s\n", extraname);
- obd->obd_force = 1;
- class_manual_cleanup(obd);
- }
- OBD_FREE(extraname, strlen(extraname) + 1);
- }
-
- LCONSOLE_WARN("server umount %s complete\n", tmpname);
- OBD_FREE(tmpname, tmpname_sz);
- EXIT;
-}
-
-/** Called only for 'umount -f'
- */
-#ifdef HAVE_UMOUNTBEGIN_VFSMOUNT
-static void server_umount_begin(struct vfsmount *vfsmnt, int flags)
-{
- struct super_block *sb = vfsmnt->mnt_sb;
-#else
-static void server_umount_begin(struct super_block *sb)
-{
-#endif
- struct lustre_sb_info *lsi = s2lsi(sb);
- ENTRY;
-
-#ifdef HAVE_UMOUNTBEGIN_VFSMOUNT
- if (!(flags & MNT_FORCE)) {
- EXIT;
- return;
- }
-#endif
-
- CDEBUG(D_MOUNT, "umount -f\n");
- /* umount = failover
- umount -f = force
- no third way to do non-force, non-failover */
- lsi->lsi_flags &= ~LSI_UMOUNT_FAILOVER;
- lsi->lsi_flags |= LSI_UMOUNT_FORCE;
- EXIT;
-}
-
-#ifndef HAVE_STATFS_DENTRY_PARAM
-static int server_statfs (struct super_block *sb, cfs_kstatfs_t *buf)
-{
-#else
-static int server_statfs (struct dentry *dentry, cfs_kstatfs_t *buf)
-{
- struct super_block *sb = dentry->d_sb;
-#endif
- struct vfsmount *mnt = s2lsi(sb)->lsi_srv_mnt;
- ENTRY;
-
- if (mnt && mnt->mnt_sb && mnt->mnt_sb->s_op->statfs) {
-#ifdef HAVE_STATFS_DENTRY_PARAM
- int rc = mnt->mnt_sb->s_op->statfs(mnt->mnt_root, buf);
-#else
- int rc = mnt->mnt_sb->s_op->statfs(mnt->mnt_sb, buf);
-#endif
- 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);
-}
-
-/** The operations we support directly on the superblock:
- * mount, umount, and df.
- */
-static struct super_operations server_ops =
-{
- .put_super = server_put_super,
- .umount_begin = server_umount_begin, /* umount -f */
- .statfs = server_statfs,
-};
-
-#define log2(n) cfs_ffz(~(n))
-#define LUSTRE_SUPER_MAGIC 0x0BD00BD1
-
-static int server_fill_super_common(struct super_block *sb)
-{
- struct inode *root = 0;
- ENTRY;
-
- CDEBUG(D_MOUNT, "Server sb, dev=%d\n", (int)sb->s_dev);
-
- sb->s_blocksize = 4096;
- sb->s_blocksize_bits = log2(sb->s_blocksize);
- sb->s_magic = LUSTRE_SUPER_MAGIC;
- sb->s_maxbytes = 0; //PAGE_CACHE_MAXBYTES;
- sb->s_flags |= MS_RDONLY;
- sb->s_op = &server_ops;
-
- root = new_inode(sb);
- if (!root) {
- CERROR("Can't make root inode\n");
- RETURN(-EIO);
- }
-
- /* returns -EIO for every operation */
- /* make_bad_inode(root); -- badness - can't umount */
- /* apparently we need to be a directory for the mount to finish */
- root->i_mode = S_IFDIR;
-
- sb->s_root = d_alloc_root(root);
- if (!sb->s_root) {
- CERROR("Can't make root dentry\n");
- iput(root);
- RETURN(-EIO);
- }
-
- RETURN(0);
-}
-
-/** Fill in the superblock info for a Lustre server.
- * Mount the device with the correct options.
- * Read the on-disk config file.
- * Start the services.
- */
-static int server_fill_super(struct super_block *sb)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct vfsmount *mnt;
- int rc;
- ENTRY;
-
- /* the One True Mount */
- mnt = server_kernel_mount(sb);
- if (IS_ERR(mnt)) {
- rc = PTR_ERR(mnt);
- CERROR("Unable to mount device %s: %d\n",
- lsi->lsi_lmd->lmd_dev, rc);
- lustre_put_lsi(sb);
- RETURN(rc);
- }
- lsi->lsi_srv_mnt = mnt;
-
- LASSERT(lsi->lsi_ldd);
- CDEBUG(D_MOUNT, "Found service %s for fs '%s' on device %s\n",
- lsi->lsi_ldd->ldd_svname, lsi->lsi_ldd->ldd_fsname,
- lsi->lsi_lmd->lmd_dev);
-
- if (class_name2obd(lsi->lsi_ldd->ldd_svname)) {
- LCONSOLE_ERROR_MSG(0x161, "The target named %s is already "
- "running. Double-mount may have compromised"
- " the disk journal.\n",
- lsi->lsi_ldd->ldd_svname);
- lustre_put_lsi(sb);
- unlock_mntput(mnt);
- RETURN(-EALREADY);
- }
-
- /* Start MGS before MGC */
- if (IS_MGS(lsi->lsi_ldd) && !(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOMGS)){
- rc = server_start_mgs(sb);
- if (rc)
- GOTO(out_mnt, rc);
- }
-
- /* Start MGC before servers */
- rc = lustre_start_mgc(sb);
- if (rc)
- GOTO(out_mnt, rc);
-
- /* Set up all obd devices for service */
- if (!(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOSVC) &&
- (IS_OST(lsi->lsi_ldd) || IS_MDT(lsi->lsi_ldd))) {
- rc = server_start_targets(sb, mnt);
- if (rc < 0) {
- CERROR("Unable to start targets: %d\n", rc);
- GOTO(out_mnt, rc);
- }
- /* FIXME overmount client here,
- or can we just start a client log and client_fill_super on this sb?
- We need to make sure server_put_super gets called too - ll_put_super
- 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.
- Note - MGS-only server does NOT get a client, since there is no
- lustre fs associated - the MGS is for all lustre fs's */
- } else if (IS_MGS(lsi->lsi_ldd) &&
- !(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOMGS)){
- struct config_llog_instance cfg;
- char *logname;
-
- OBD_ALLOC(logname, MGS_PARAM_MAXLEN);
- if (logname == NULL)
- GOTO(out_mnt, rc = -ENOMEM);
- strcpy(logname, lsi->lsi_ldd->ldd_fsname);
- strcat(logname, "-params");
-
- memset(&cfg, 0, sizeof(cfg));
- rc = lustre_process_log(sb, logname, &cfg);
- OBD_FREE(logname, MGS_PARAM_MAXLEN);
- if (rc) {
- CERROR("failed to process parameters %s: %d\n",
- logname, rc);
- GOTO(out_mnt, rc);
- }
- }
-
- rc = server_fill_super_common(sb);
- if (rc)
- GOTO(out_mnt, rc);
-
- RETURN(0);
-out_mnt:
- /* We jump here in case of failure while starting targets or MGS.
- * In this case we can't just put @mnt and have to do real cleanup
- * with stoping targets, etc. */
- server_put_super(sb);
- return rc;
-}