📄 obd_mount.c
字号:
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * lustre/obdclass/obd_mount.c * Client/server mount routines * * Copyright (c) 2006 Cluster File Systems, Inc. * Author: Nathan Rutman <nathan@clusterfs.com> * * This file is part of Lustre, http://www.lustre.org/ * * Lustre is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * Lustre is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Lustre; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#define DEBUG_SUBSYSTEM S_CLASS#define D_MOUNT D_SUPER|D_CONFIG /*|D_WARNING */#define PRINT_CMD CDEBUG#define PRINT_MASK D_SUPER|D_CONFIG#include <obd.h>#include <lvfs.h>#include <lustre_fsfilt.h>#include <obd_class.h>#include <lustre/lustre_user.h>#include <linux/version.h>#include <lustre_log.h>#include <lustre_disk.h>#include <lustre_param.h>static int (*client_fill_super)(struct super_block *sb) = NULL;static void (*kill_super_cb)(struct super_block *sb) = NULL;/*********** mount lookup *********/DECLARE_MUTEX(lustre_mount_info_lock);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; ENTRY; 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) RETURN(lmi); } RETURN(NULL);}/* we must register an obd for a mount before we call the setup routine. *_setup will call lustre_get_mount to get the mnt struct by obd_name, since we can't pass the pointer to setup. */static int server_register_mount(char *name, struct super_block *sb, struct vfsmount *mnt){ struct lustre_mount_info *lmi; char *name_cp; ENTRY; LASSERT(mnt); LASSERT(sb); OBD_ALLOC(lmi, sizeof(*lmi)); if (!lmi) RETURN(-ENOMEM); OBD_ALLOC(name_cp, strlen(name) + 1); if (!name_cp) { OBD_FREE(lmi, sizeof(*lmi)); RETURN(-ENOMEM); } strcpy(name_cp, name); down(&lustre_mount_info_lock); if (server_find_mount(name)) { up(&lustre_mount_info_lock); OBD_FREE(lmi, sizeof(*lmi)); OBD_FREE(name_cp, strlen(name) + 1); CERROR("Already registered %s\n", name); RETURN(-EEXIST); } lmi->lmi_name = name_cp; lmi->lmi_sb = sb; lmi->lmi_mnt = mnt; list_add(&lmi->lmi_list_chain, &server_mount_info_list); up(&lustre_mount_info_lock); CDEBUG(D_MOUNT, "reg_mnt %p from %s, vfscount=%d\n", lmi->lmi_mnt, name, atomic_read(&lmi->lmi_mnt->mnt_count)); RETURN(0);}/* when an obd no longer needs a mount */static int server_deregister_mount(char *name){ struct lustre_mount_info *lmi; ENTRY; down(&lustre_mount_info_lock); lmi = server_find_mount(name); if (!lmi) { up(&lustre_mount_info_lock); CERROR("%s not registered\n", name); RETURN(-ENOENT); } CDEBUG(D_MOUNT, "dereg_mnt %p from %s, vfscount=%d\n", lmi->lmi_mnt, name, atomic_read(&lmi->lmi_mnt->mnt_count)); OBD_FREE(lmi->lmi_name, strlen(lmi->lmi_name) + 1); list_del(&lmi->lmi_list_chain); OBD_FREE(lmi, sizeof(*lmi)); up(&lustre_mount_info_lock); RETURN(0);}/* obd's look up a registered mount using their obdname. This is just for initial obd setup to find the mount struct. It should not be called every time you want to mntget. */struct lustre_mount_info *server_get_mount(char *name){ struct lustre_mount_info *lmi; struct lustre_sb_info *lsi; ENTRY; down(&lustre_mount_info_lock); lmi = server_find_mount(name); up(&lustre_mount_info_lock); if (!lmi) { CERROR("Can't find mount for %s\n", name); RETURN(NULL); } lsi = s2lsi(lmi->lmi_sb); mntget(lmi->lmi_mnt); atomic_inc(&lsi->lsi_mounts); CDEBUG(D_MOUNT, "get_mnt %p from %s, refs=%d, vfscount=%d\n", lmi->lmi_mnt, name, atomic_read(&lsi->lsi_mounts), atomic_read(&lmi->lmi_mnt->mnt_count)); RETURN(lmi);}static void unlock_mntput(struct vfsmount *mnt){ if (kernel_locked()) { unlock_kernel(); mntput(mnt); lock_kernel(); } else { mntput(mnt); }}static int lustre_put_lsi(struct super_block *sb);/* to be called from obd_cleanup methods */int server_put_mount(char *name, struct vfsmount *mnt){ struct lustre_mount_info *lmi; struct lustre_sb_info *lsi; int count = atomic_read(&mnt->mnt_count) - 1; ENTRY; /* This might be the last one, can't deref after this */ unlock_mntput(mnt); down(&lustre_mount_info_lock); lmi = server_find_mount(name); up(&lustre_mount_info_lock); if (!lmi) { CERROR("Can't find mount for %s\n", name); RETURN(-ENOENT); } LASSERT(lmi->lmi_mnt == mnt); /* Note if lsi is poisoned, it's probably because server_wait_finished didn't wait long enough and the sb was freed at the umount. */ lsi = s2lsi(lmi->lmi_sb); CDEBUG(D_MOUNT, "put_mnt %p from %s, refs=%d, vfscount=%d\n", lmi->lmi_mnt, name, atomic_read(&lsi->lsi_mounts), count); if (lustre_put_lsi(lmi->lmi_sb)) { CDEBUG(D_MOUNT, "Last put of mnt %p from %s, vfscount=%d\n", lmi->lmi_mnt, name, count); /* last mount is the One True Mount */ if (count > 1) CERROR("%s: mount busy, vfscount=%d!\n", name, count); } /* this obd should never need the mount again */ server_deregister_mount(name); RETURN(0);}/******* mount helper utilities *********/static void ldd_print(struct lustre_disk_data *ldd){ PRINT_CMD(PRINT_MASK, " disk data:\n"); PRINT_CMD(PRINT_MASK, "server: %s\n", ldd->ldd_svname); PRINT_CMD(PRINT_MASK, "uuid: %s\n", (char *)ldd->ldd_uuid); PRINT_CMD(PRINT_MASK, "fs: %s\n", ldd->ldd_fsname); PRINT_CMD(PRINT_MASK, "index: %04x\n", ldd->ldd_svindex); PRINT_CMD(PRINT_MASK, "config: %d\n", ldd->ldd_config_ver); PRINT_CMD(PRINT_MASK, "flags: %#x\n", ldd->ldd_flags); PRINT_CMD(PRINT_MASK, "diskfs: %s\n", MT_STR(ldd)); PRINT_CMD(PRINT_MASK, "options: %s\n", ldd->ldd_mount_opts); PRINT_CMD(PRINT_MASK, "params: %s\n", ldd->ldd_params); PRINT_CMD(PRINT_MASK, "comment: %s\n", ldd->ldd_userdata);}static int ldd_parse(struct lvfs_run_ctxt *mount_ctxt, struct lustre_disk_data *ldd){ struct lvfs_run_ctxt saved; struct file *file; loff_t off = 0; unsigned long len; int rc; ENTRY; push_ctxt(&saved, mount_ctxt, NULL); file = filp_open(MOUNT_DATA_FILE, O_RDONLY, 0644); if (IS_ERR(file)) { rc = PTR_ERR(file); CERROR("cannot open %s: rc = %d\n", MOUNT_DATA_FILE, rc); GOTO(out, rc); } len = i_size_read(file->f_dentry->d_inode); CDEBUG(D_MOUNT, "Have %s, size %lu\n", MOUNT_DATA_FILE, len); if (len != sizeof(*ldd)) { CERROR("disk data size does not match: see %lu expect "LPSZ"\n", len, sizeof(*ldd)); GOTO(out_close, rc = -EINVAL); } rc = lustre_fread(file, ldd, len, &off); if (rc != len) { CERROR("error reading %s: read %d of %lu\n", MOUNT_DATA_FILE, rc, len); GOTO(out_close, rc = -EINVAL); } rc = 0; if (ldd->ldd_magic != LDD_MAGIC) { /* FIXME add swabbing support */ CERROR("Bad magic in %s: %x!=%x\n", MOUNT_DATA_FILE, ldd->ldd_magic, LDD_MAGIC); GOTO(out_close, rc = -EINVAL); } if (ldd->ldd_feature_incompat & ~LDD_INCOMPAT_SUPP) { CERROR("%s: unsupported incompat filesystem feature(s) %x\n", ldd->ldd_svname, ldd->ldd_feature_incompat & ~LDD_INCOMPAT_SUPP); GOTO(out_close, rc = -EINVAL); } if (ldd->ldd_feature_rocompat & ~LDD_ROCOMPAT_SUPP) { CERROR("%s: unsupported read-only filesystem feature(s) %x\n", ldd->ldd_svname, ldd->ldd_feature_rocompat & ~LDD_ROCOMPAT_SUPP); /* Do something like remount filesystem read-only */ GOTO(out_close, rc = -EINVAL); } ldd_print(ldd);out_close: filp_close(file, 0);out: pop_ctxt(&saved, mount_ctxt, NULL); RETURN(rc);}static int ldd_write(struct lvfs_run_ctxt *mount_ctxt, struct lustre_disk_data *ldd){ struct lvfs_run_ctxt saved; struct file *file; loff_t off = 0; unsigned long len = sizeof(struct lustre_disk_data); int rc = 0; ENTRY; LASSERT(ldd->ldd_magic == LDD_MAGIC); ldd->ldd_config_ver++; push_ctxt(&saved, mount_ctxt, NULL); file = filp_open(MOUNT_DATA_FILE, O_RDWR, 0644); if (IS_ERR(file)) { rc = PTR_ERR(file); CERROR("cannot open %s: rc = %d\n", MOUNT_DATA_FILE, rc); GOTO(out, rc); } rc = lustre_fwrite(file, ldd, len, &off); if (rc != len) { CERROR("error writing %s: read %d of %lu\n", MOUNT_DATA_FILE, rc, len); GOTO(out_close, rc = -EINVAL); } rc = 0; ldd_print(ldd);out_close: filp_close(file, 0);out: pop_ctxt(&saved, mount_ctxt, NULL); RETURN(rc);}/**************** config llog ********************//* Get a config log from the MGS and process it. This func is called for both clients and servers. Continue to process new statements appended to the logs (whenever the config lock is revoked) until lustre_end_log is called. */int lustre_process_log(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; int rc; ENTRY; LASSERT(mgc); LASSERT(cfg); /* mgc_process_config */ 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)); lustre_cfg_bufs_set(&bufs, 3, &sb, sizeof(sb)); lcfg = lustre_cfg_new(LCFG_LOG_START, &bufs); rc = obd_process_config(mgc, sizeof(*lcfg), lcfg); lustre_cfg_free(lcfg); if (rc == -EINVAL) LCONSOLE_ERROR_MSG(0x15b, "%s: The configuration from log '%s' " "failed (%d). Make sure this client and " "the MGS are running compatible versions of " "Lustre.\n", mgc->obd_name, logname, rc); if (rc) LCONSOLE_ERROR_MSG(0x15c, "%s: The configuration from log '%s' " "failed (%d). This may be the result of " "communication errors between this node and "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -