📄 obd_mount.c
字号:
OBD_FREE(lsi, sizeof(*lsi)); RETURN(NULL); } lsi->lsi_lmd->lmd_exclude_count = 0; s2lsi_nocast(sb) = lsi; /* we take 1 extra ref for our setup */ 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; if (!lsi) RETURN(0); CDEBUG(D_MOUNT, "Freeing lsi\n"); /* someone didn't call server_put_mount. */ LASSERT(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_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); CDEBUG(D_MOUNT, "put %p %d\n", sb, atomic_read(&lsi->lsi_mounts)); if (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 */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 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; /* 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, 0); if (IS_ERR(mnt)) { rc = PTR_ERR(mnt);#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) /* 2.6 kernels: if ldiskfs fails, try ldiskfs2 */ mnt = ll_kern_mount("ldiskfs2", s_flags, lmd->lmd_dev, 0); if (IS_ERR(mnt)) { int rc2 = PTR_ERR(mnt); CERROR("premount %s:%#lx ldiskfs failed: %d, ldiskfs2 " "failed: %d. Is the ldiskfs module available?\n", lmd->lmd_dev, s_flags, rc, rc2); GOTO(out_free, rc); }#else /* 2.4 kernels: if ldiskfs fails, try ext3 */ mnt = ll_kern_mount("ext3", s_flags, lmd->lmd_dev, 0); if (IS_ERR(mnt)) { rc = PTR_ERR(mnt); CERROR("premount ext3 failed: rc = %d\n", rc); GOTO(out_free, rc); }#endif } 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 */ 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); strncpy(options, ldd->ldd_mount_opts, CFS_PAGE_SIZE - 2); /* Add in any mount-line options */ if (lmd->lmd_opts && (*(lmd->lmd_opts) != 0)) { int len = CFS_PAGE_SIZE - strlen(options) - 2; if (*options != 0) 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); OBD_PAGE_FREE(__page); if (IS_ERR(mnt)) { rc = PTR_ERR(mnt); CERROR("ll_kern_mount failed: rc = %d\n", rc); GOTO(out_free, rc); } lsi->lsi_ldd = ldd; /* freed at lsi cleanup */ CDEBUG(D_SUPER, "%s: mnt = %p\n", lmd->lmd_dev, mnt); RETURN(mnt);out_free: OBD_FREE(ldd, sizeof(*ldd)); lsi->lsi_ldd = NULL; RETURN(ERR_PTR(rc));}static void server_wait_finished(struct vfsmount *mnt){ wait_queue_head_t waitq; struct l_wait_info lwi; int retries = 330; init_waitqueue_head(&waitq); while ((atomic_read(&mnt->mnt_count) > 1) && (retries > 0)) { LCONSOLE_WARN("Mount still busy with %d refs, waiting for " "%d secs...\n", atomic_read(&mnt->mnt_count), retries); /* Wait for a bit */ retries -= 5; lwi = LWI_TIMEOUT(5 * HZ, NULL, NULL); l_wait_event(waitq, 0, &lwi); } if (atomic_read(&mnt->mnt_count) > 1) { CERROR("Mount %p is still busy (%d refs), giving up.\n", mnt, atomic_read(&mnt->mnt_count)); }}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; int rc; 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); /* Stop the target */ if (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_osc) { OBD_ALLOC(extraname, strlen(lprof->lp_osc) + 1); strcpy(extraname, lprof->lp_osc); } 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)) { /* stop the mgc before the mgs so the connection gets cleaned up */ lustre_stop_mgc(sb); server_stop_mgs(sb); } /* Clean the mgc and sb */ rc = lustre_common_put_super(sb); /* FIXME how can I report a failure to umount? */ /* 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;}#ifdef HAVE_UMOUNTBEGIN_VFSMOUNTstatic void server_umount_begin(struct vfsmount *vfsmnt, int flags){ struct super_block *sb = vfsmnt->mnt_sb;#elsestatic 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_PARAMstatic int server_statfs (struct super_block *sb, struct kstatfs *buf){#elsestatic int server_statfs (struct dentry *dentry, struct kstatfs *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);}static int server_show_options(struct seq_file *seq, struct vfsmount *vfsmnt){ struct vfsmount *mnt = s2lsi(vfsmnt->mnt_sb)->lsi_srv_mnt; ENTRY; if (mnt && mnt->mnt_sb && mnt->mnt_sb->s_op->show_options) { int rc = mnt->mnt_sb->s_op->show_options(seq, mnt); RETURN(rc); } RETURN(0);}static struct super_operations server_ops ={ .put_super = server_put_super, .umount_begin = server_umount_begin, /* umount -f */ .statfs = server_statfs, .show_options = server_show_options,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -