This patch enables client to mount subdirectory as fileset.
usage: mount -t lustre mgsname:/fsname/subdir /mount/point
* mdt lookup fileset fid and return to client during mount.
* `lfs fid2path` support for fileset.
Test-Parameters: envdefinitions=FILESET=/somedir testlist=sanity
Signed-off-by: Lai Siyao <lai.siyao@intel.com>
Signed-off-by: Kit Westneat <kwestneat@ddn.com>
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Change-Id: I947785de3b053907600d1090c80e8f57396e1e93
Reviewed-on: http://review.whamcloud.com/5007
Tested-by: Jenkins
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
MDS_READPAGE = 37,
MDS_CONNECT = 38,
MDS_DISCONNECT = 39,
- MDS_GETSTATUS = 40,
+ MDS_GET_ROOT = 40,
MDS_STATFS = 41,
MDS_PIN = 42,
MDS_UNPIN = 43,
{37 , "MDS_READPAGE"},
{38 , "MDS_CONNECT"},
{39 , "MDS_DISCONNECT"},
- {40 , "MDS_GETSTATUS"},
+ {40 , "MDS_GET_ROOT"},
{41 , "MDS_STATFS"},
{42 , "MDS_PIN"},
{43 , "MDS_UNPIN"},
case MDS_DISCONNECT:
/*[nothing]*/
break;
- case MDS_GETSTATUS:
+ case MDS_GET_ROOT:
/*request: [mds body]*/
/*reply: [mds body][capa] */
offset=lustre_dissect_struct_mdt_body(tvb, offset, pinfo, tree, hf_lustre_mdt_body) ;
.I device
option, depending on whether a client or a target service is started:
.TP
-.IR <mgsspec> :/ <fsname>
+.IR <mgsspec> :/ <fsname>[/<subdir>]
mounts the Lustre filesystem named
.I fsname
-on the client by contacting the Management Service at
+(under subdirectory
+.I subdir
+if specified) on the client by contacting the Management Service at
.IR mgsspec
on the pathname given by
.IR directory .
/mnt/myfilesystem. The Management Service is running on a node reachable
from this client via the nid cfs21@tcp0.
.TP
+.B mount -t lustre cfs21@tcp0:/testfs/dir /mnt/myfilesystem
+Like above example, but mount subdirectory 'dir' as fileset.
+.TP
.B mount -t lustre /dev/sda1 /mnt/test/mdt
Start the Lustre metadata target service from /dev/sda1 on mountpoint /mnt/test/mdt.
.TP
OBD_CONNECT_OPEN_BY_FID | \
OBD_CONNECT_DIR_STRIPE | \
OBD_CONNECT_BULK_MBITS | \
- OBD_CONNECT_MULTIMODRPCS)
+ OBD_CONNECT_MULTIMODRPCS | \
+ OBD_CONNECT_SUBTREE)
#define OST_CONNECT_SUPPORTED (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
MDS_READPAGE = 37,
MDS_CONNECT = 38,
MDS_DISCONNECT = 39,
- MDS_GETSTATUS = 40,
+ MDS_GET_ROOT = 40,
MDS_STATFS = 41,
MDS_PIN = 42, /* obsolete, never used in a release */
MDS_UNPIN = 43, /* obsolete, never used in a release */
/** fid2path request/reply structure */
struct getinfo_fid2path {
- struct lu_fid gf_fid;
- __u64 gf_recno;
- __u32 gf_linkno;
- __u32 gf_pathlen;
- char gf_path[0];
+ struct lu_fid gf_fid;
+ __u64 gf_recno;
+ __u32 gf_linkno;
+ __u32 gf_pathlen;
+ union {
+ char gf_path[0];
+ struct lu_fid gf_root_fid[0];
+ } gf_u;
} __attribute__((packed));
/** path2parent request/reply structures */
char *mntdir, char *fsname);
extern int llapi_search_fsname(const char *pathname, char *fsname);
extern int llapi_getname(const char *path, char *buf, size_t size);
+extern int llapi_search_fileset(const char *pathname, char *fileset);
extern int llapi_search_rootpath(char *pathname, const char *fsname);
extern int llapi_nodemap_exists(const char *name);
/* gleaned from the mount command - no persistent info here */
struct lustre_mount_data {
- __u32 lmd_magic;
- __u32 lmd_flags; /* lustre mount flags */
- int lmd_mgs_failnodes; /* mgs failover node count */
- int lmd_exclude_count;
- int lmd_recovery_time_soft;
- int lmd_recovery_time_hard;
- char *lmd_dev; /* device name */
- char *lmd_profile; /* client only */
- char *lmd_mgssec; /* sptlrpc flavor to mgs */
- char *lmd_opts; /* lustre mount options (as opposed to
- _device_ mount options) */
- char *lmd_params; /* lustre params */
- __u32 *lmd_exclude; /* array of OSTs to ignore */
- char *lmd_mgs; /* MGS nid */
- char *lmd_osd_type; /* OSD type */
+ __u32 lmd_magic;
+ __u32 lmd_flags; /* lustre mount flags */
+ int lmd_mgs_failnodes; /* mgs failover node count */
+ int lmd_exclude_count;
+ int lmd_recovery_time_soft;
+ int lmd_recovery_time_hard;
+ char *lmd_dev; /* device name */
+ char *lmd_profile; /* client only */
+ char *lmd_fileset; /* mount fileset */
+ char *lmd_mgssec; /* sptlrpc flavor to mgs */
+ char *lmd_opts; /* lustre mount options (as opposed to
+ * device_ mount options) */
+ char *lmd_params; /* lustre params */
+ __u32 *lmd_exclude; /* array of OSTs to ignore */
+ char *lmd_mgs; /* MGS nid */
+ char *lmd_osd_type; /* OSD type */
};
#define LMD_FLG_SERVER 0x0001 /* Mounting a server */
#define get_profile_name(sb) (s2lsi(sb)->lsi_lmd->lmd_profile)
#define get_mount_flags(sb) (s2lsi(sb)->lsi_lmd->lmd_flags)
#define get_mntdev_name(sb) (s2lsi(sb)->lsi_lmd->lmd_dev)
+#define get_mount_fileset(sb) (s2lsi(sb)->lsi_lmd->lmd_fileset)
#endif /* __KERNEL__ */
extern struct req_format RQF_MDS_CONNECT;
extern struct req_format RQF_MDS_DISCONNECT;
extern struct req_format RQF_MDS_STATFS;
-extern struct req_format RQF_MDS_GETSTATUS;
+extern struct req_format RQF_MDS_GET_ROOT;
extern struct req_format RQF_MDS_SYNC;
extern struct req_format RQF_MDS_GETXATTR;
extern struct req_format RQF_MDS_GETATTR;
#define MD_STATS_LAST_OP m_revalidate_lock
- int (*m_getstatus)(struct obd_export *, struct lu_fid *);
+ int (*m_getstatus)(struct obd_export *, const char *fileset,
+ struct lu_fid *);
int (*m_null_inode)(struct obd_export *, const struct lu_fid *);
int (*m_getattr_name)(struct obd_export *, struct md_op_data *,
}
/* metadata helpers */
-static inline int md_getstatus(struct obd_export *exp, struct lu_fid *fid)
+static inline int md_get_root(struct obd_export *exp, const char *fileset,
+ struct lu_fid *fid)
{
int rc;
ENTRY;
EXP_CHECK_MD_OP(exp, getstatus);
EXP_MD_COUNTER_INCREMENT(exp, getstatus);
- rc = MDP(exp->exp_obd, getstatus)(exp, fid);
+ rc = MDP(exp->exp_obd, getstatus)(exp, fileset, fid);
RETURN(rc);
}
#define OBD_FAIL_MDS_CONNECT_PACK 0x118
#define OBD_FAIL_MDS_REINT_NET_REP 0x119
#define OBD_FAIL_MDS_DISCONNECT_NET 0x11a
-#define OBD_FAIL_MDS_GETSTATUS_NET 0x11b
-#define OBD_FAIL_MDS_GETSTATUS_PACK 0x11c
+#define OBD_FAIL_MDS_GET_ROOT_NET 0x11b
+#define OBD_FAIL_MDS_GET_ROOT_PACK 0x11c
#define OBD_FAIL_MDS_STATFS_PACK 0x11d
#define OBD_FAIL_MDS_STATFS_NET 0x11e
#define OBD_FAIL_MDS_GETATTR_NAME_NET 0x11f
if (copy_from_user(gfout, arg, sizeof(*gfout)))
GOTO(gf_free, rc = -EFAULT);
+ /* append root FID after gfout to let MDT know the root FID so that it
+ * can lookup the correct path, this is mainly for fileset.
+ * old server without fileset mount support will ignore this. */
+ *gfout->gf_u.gf_root_fid = *ll_inode2fid(inode);
/* Call mdc_iocontrol */
rc = obd_iocontrol(OBD_IOC_FID2PATH, exp, outsize, gfout, NULL);
if (child_inode == NULL)
GOTO(out_free, rc = -EINVAL);
+ /*
+ * lfs migrate command needs to be blocked on the client
+ * by checking the migrate FID against the FID of the
+ * filesystem root.
+ */
+ if (child_inode == parent->i_sb->s_root->d_inode)
+ GOTO(out_iput, rc = -EINVAL);
+
mutex_lock(&child_inode->i_mutex);
op_data->op_fid3 = *ll_inode2fid(child_inode);
if (!fid_is_sane(&op_data->op_fid3)) {
clear_nlink(child_inode);
out_unlock:
mutex_unlock(&child_inode->i_mutex);
+out_iput:
iput(child_inode);
out_free:
ll_finish_md_op_data(op_data);
OBD_CONNECT_DISP_STRIPE | OBD_CONNECT_LFSCK |
OBD_CONNECT_OPEN_BY_FID |
OBD_CONNECT_DIR_STRIPE |
- OBD_CONNECT_BULK_MBITS;
+ OBD_CONNECT_BULK_MBITS |
+ OBD_CONNECT_SUBTREE;
#ifdef HAVE_LRU_RESIZE_SUPPORT
if (sbi->ll_flags & LL_SBI_LRU_RESIZE)
mutex_unlock(&sbi->ll_lco.lco_lock);
fid_zero(&sbi->ll_root_fid);
- err = md_getstatus(sbi->ll_md_exp, &sbi->ll_root_fid);
+ err = md_get_root(sbi->ll_md_exp, get_mount_fileset(sb),
+ &sbi->ll_root_fid);
if (err) {
CERROR("cannot mds_connect: rc = %d\n", err);
GOTO(out_lock_cn_cb, err);
struct getinfo_fid2path *gf;
struct lmv_tgt_desc *tgt;
struct getinfo_fid2path *remote_gf = NULL;
+ struct lu_fid root_fid;
int remote_gf_size = 0;
int rc;
- gf = (struct getinfo_fid2path *)karg;
+ gf = karg;
tgt = lmv_find_target(lmv, &gf->gf_fid);
if (IS_ERR(tgt))
RETURN(PTR_ERR(tgt));
+ root_fid = *gf->gf_u.gf_root_fid;
+ LASSERT(fid_is_sane(&root_fid));
+
repeat_fid2path:
rc = obd_iocontrol(OBD_IOC_FID2PATH, tgt->ltd_exp, len, gf, uarg);
if (rc != 0 && rc != -EREMOTE)
char *ptr;
ori_gf = (struct getinfo_fid2path *)karg;
- if (strlen(ori_gf->gf_path) +
- strlen(gf->gf_path) > ori_gf->gf_pathlen)
+ if (strlen(ori_gf->gf_u.gf_path) +
+ strlen(gf->gf_u.gf_path) > ori_gf->gf_pathlen)
GOTO(out_fid2path, rc = -EOVERFLOW);
- ptr = ori_gf->gf_path;
+ ptr = ori_gf->gf_u.gf_path;
- memmove(ptr + strlen(gf->gf_path) + 1, ptr,
- strlen(ori_gf->gf_path));
+ memmove(ptr + strlen(gf->gf_u.gf_path) + 1, ptr,
+ strlen(ori_gf->gf_u.gf_path));
- strncpy(ptr, gf->gf_path, strlen(gf->gf_path));
- ptr += strlen(gf->gf_path);
+ strncpy(ptr, gf->gf_u.gf_path,
+ strlen(gf->gf_u.gf_path));
+ ptr += strlen(gf->gf_u.gf_path);
*ptr = '/';
}
CDEBUG(D_INFO, "%s: get path %s "DFID" rec: "LPU64" ln: %u\n",
tgt->ltd_exp->exp_obd->obd_name,
- gf->gf_path, PFID(&gf->gf_fid), gf->gf_recno,
+ gf->gf_u.gf_path, PFID(&gf->gf_fid), gf->gf_recno,
gf->gf_linkno);
if (rc == 0)
remote_gf->gf_fid = gf->gf_fid;
remote_gf->gf_recno = -1;
remote_gf->gf_linkno = -1;
- memset(remote_gf->gf_path, 0, remote_gf->gf_pathlen);
+ memset(remote_gf->gf_u.gf_path, 0, remote_gf->gf_pathlen);
+ *remote_gf->gf_u.gf_root_fid = root_fid;
gf = remote_gf;
goto repeat_fid2path;
return rc;
}
-static int lmv_getstatus(struct obd_export *exp, struct lu_fid *fid)
+static int lmv_getstatus(struct obd_export *exp,
+ const char *fileset,
+ struct lu_fid *fid)
{
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
int rc;
ENTRY;
- rc = lmv_check_connect(obd);
- if (rc)
- RETURN(rc);
+ rc = lmv_check_connect(obd);
+ if (rc)
+ RETURN(rc);
- rc = md_getstatus(lmv->tgts[0]->ltd_exp, fid);
+ rc = md_get_root(lmv->tgts[0]->ltd_exp, fileset, fid);
RETURN(rc);
}
return rc;
}
-static int mdc_getstatus(struct obd_export *exp, struct lu_fid *rootfid)
+/*
+ * Send MDS_GET_ROOT RPC to fetch root FID.
+ *
+ * If \a fileset is not NULL it should contain a subdirectory off
+ * the ROOT/ directory to be mounted on the client. Return the FID
+ * of the subdirectory to the client to mount onto its mountpoint.
+ *
+ * \param[in] imp MDC import
+ * \param[in] fileset fileset name, which could be NULL
+ * \param[out] rootfid root FID of this mountpoint
+ * \param[out] pc root capa will be unpacked and saved in this pointer
+ *
+ * \retval 0 on success, negative errno on failure
+ */
+static int mdc_get_root(struct obd_export *exp, const char *fileset,
+ struct lu_fid *rootfid)
{
struct ptlrpc_request *req;
struct mdt_body *body;
ENTRY;
- req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
- &RQF_MDS_GETSTATUS,
- LUSTRE_MDS_VERSION, MDS_GETSTATUS);
+ if (fileset && !(exp_connect_flags(exp) & OBD_CONNECT_SUBTREE))
+ RETURN(-ENOTSUPP);
+
+ req = ptlrpc_request_alloc(class_exp2cliimp(exp),
+ &RQF_MDS_GET_ROOT);
if (req == NULL)
RETURN(-ENOMEM);
+ if (fileset != NULL)
+ req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
+ strlen(fileset) + 1);
+ rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_GET_ROOT);
+ if (rc) {
+ ptlrpc_request_free(req);
+ RETURN(rc);
+ }
mdc_pack_body(req, NULL, 0, 0, -1, 0);
+ if (fileset != NULL) {
+ char *name = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
+
+ memcpy(name, fileset, strlen(fileset));
+ }
+ lustre_msg_add_flags(req->rq_reqmsg, LUSTRE_IMP_FULL);
req->rq_send_state = LUSTRE_IMP_FULL;
ptlrpc_request_set_replen(req);
static int mdc_ioc_fid2path(struct obd_export *exp, struct getinfo_fid2path *gf)
{
- __u32 keylen, vallen;
- void *key;
- int rc;
-
- if (gf->gf_pathlen > PATH_MAX)
- RETURN(-ENAMETOOLONG);
- if (gf->gf_pathlen < 2)
- RETURN(-EOVERFLOW);
+ __u32 keylen, vallen;
+ void *key;
+ int rc;
- /* Key is KEY_FID2PATH + getinfo_fid2path description */
- keylen = cfs_size_round(sizeof(KEY_FID2PATH)) + sizeof(*gf);
- OBD_ALLOC(key, keylen);
- if (key == NULL)
- RETURN(-ENOMEM);
- memcpy(key, KEY_FID2PATH, sizeof(KEY_FID2PATH));
- memcpy(key + cfs_size_round(sizeof(KEY_FID2PATH)), gf, sizeof(*gf));
+ if (gf->gf_pathlen > PATH_MAX)
+ RETURN(-ENAMETOOLONG);
+ if (gf->gf_pathlen < 2)
+ RETURN(-EOVERFLOW);
- CDEBUG(D_IOCTL, "path get "DFID" from "LPU64" #%d\n",
- PFID(&gf->gf_fid), gf->gf_recno, gf->gf_linkno);
+ /* Key is KEY_FID2PATH + getinfo_fid2path description */
+ keylen = cfs_size_round(sizeof(KEY_FID2PATH) + sizeof(*gf) +
+ sizeof(struct lu_fid));
+ OBD_ALLOC(key, keylen);
+ if (key == NULL)
+ RETURN(-ENOMEM);
+ memcpy(key, KEY_FID2PATH, sizeof(KEY_FID2PATH));
+ memcpy(key + cfs_size_round(sizeof(KEY_FID2PATH)), gf, sizeof(*gf));
+ memcpy(key + cfs_size_round(sizeof(KEY_FID2PATH)) + sizeof(*gf),
+ gf->gf_u.gf_root_fid, sizeof(struct lu_fid));
+ CDEBUG(D_IOCTL, "path get "DFID" from "LPU64" #%d\n",
+ PFID(&gf->gf_fid), gf->gf_recno, gf->gf_linkno);
- if (!fid_is_sane(&gf->gf_fid))
- GOTO(out, rc = -EINVAL);
+ if (!fid_is_sane(&gf->gf_fid))
+ GOTO(out, rc = -EINVAL);
/* Val is struct getinfo_fid2path result plus path */
vallen = sizeof(*gf) + gf->gf_pathlen;
CDEBUG(D_IOCTL, "path got "DFID" from "LPU64" #%d: %s\n",
PFID(&gf->gf_fid), gf->gf_recno, gf->gf_linkno,
- gf->gf_pathlen < 512 ? gf->gf_path :
+ gf->gf_pathlen < 512 ? gf->gf_u.gf_path :
/* only log the last 512 characters of the path */
- gf->gf_path + gf->gf_pathlen - 512);
+ gf->gf_u.gf_path + gf->gf_pathlen - 512);
out:
OBD_FREE(key, keylen);
};
static struct md_ops mdc_md_ops = {
- .m_getstatus = mdc_getstatus,
+ .m_getstatus = mdc_get_root,
.m_null_inode = mdc_null_inode,
.m_close = mdc_close,
.m_create = mdc_create,
#include <obd.h>
#include <obd_support.h>
+#include <llog_swab.h>
+
#include "mdt_internal.h"
EXIT;
}
-static int mdt_getstatus(struct tgt_session_info *tsi)
+static int mdt_lookup_fileset(struct mdt_thread_info *info, const char *fileset,
+ struct lu_fid *fid)
+{
+ struct mdt_device *mdt = info->mti_mdt;
+ struct lu_name *lname = &info->mti_name;
+ char *name = NULL;
+ struct mdt_object *parent;
+ u32 mode;
+ int rc = 0;
+
+ LASSERT(!info->mti_cross_ref);
+
+ OBD_ALLOC(name, NAME_MAX + 1);
+ if (name == NULL)
+ return -ENOMEM;
+ lname->ln_name = name;
+
+ /*
+ * We may want to allow this to mount a completely separate
+ * fileset from the MDT in the future, but keeping it to
+ * ROOT/ only for now avoid potential security issues.
+ */
+ *fid = mdt->mdt_md_root_fid;
+
+ while (rc == 0 && fileset != NULL && *fileset != '\0') {
+ const char *s1 = fileset;
+ const char *s2;
+
+ while (*++s1 == '/')
+ ;
+ s2 = s1;
+ while (*s2 != '/' && *s2 != '\0')
+ s2++;
+
+ if (s2 == s1)
+ break;
+
+ fileset = s2;
+
+ lname->ln_namelen = s2 - s1;
+ if (lname->ln_namelen > NAME_MAX) {
+ rc = -EINVAL;
+ break;
+ }
+ strncpy(name, s1, lname->ln_namelen);
+ name[lname->ln_namelen] = '\0';
+
+ parent = mdt_object_find(info->mti_env, mdt, fid);
+ if (IS_ERR(parent)) {
+ rc = PTR_ERR(parent);
+ break;
+ }
+ /* Only got the fid of this obj by name */
+ fid_zero(fid);
+ rc = mdo_lookup(info->mti_env, mdt_object_child(parent), lname,
+ fid, &info->mti_spec);
+ mdt_object_put(info->mti_env, parent);
+ }
+ if (!rc) {
+ parent = mdt_object_find(info->mti_env, mdt, fid);
+ if (IS_ERR(parent))
+ rc = PTR_ERR(parent);
+ else {
+ mode = lu_object_attr(&parent->mot_obj);
+ mdt_object_put(info->mti_env, parent);
+ if (!S_ISDIR(mode))
+ rc = -ENOTDIR;
+ }
+ }
+
+ OBD_FREE(name, NAME_MAX + 1);
+
+ return rc;
+}
+
+static int mdt_get_root(struct tgt_session_info *tsi)
{
struct mdt_thread_info *info = tsi2mdt_info(tsi);
struct mdt_device *mdt = info->mti_mdt;
struct mdt_body *repbody;
+ char *fileset;
int rc;
ENTRY;
if (rc)
GOTO(out, rc = err_serious(rc));
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETSTATUS_PACK))
+ if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GET_ROOT_PACK))
GOTO(out, rc = err_serious(-ENOMEM));
repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
- repbody->mbo_fid1 = mdt->mdt_md_root_fid;
+ if (req_capsule_get_size(info->mti_pill, &RMF_NAME, RCL_CLIENT) > 0) {
+ fileset = req_capsule_client_get(info->mti_pill, &RMF_NAME);
+ if (fileset == NULL)
+ GOTO(out, rc = err_serious(-EFAULT));
+
+ rc = mdt_lookup_fileset(info, fileset, &repbody->mbo_fid1);
+ if (rc < 0)
+ GOTO(out, rc = err_serious(rc));
+ } else {
+ repbody->mbo_fid1 = mdt->mdt_md_root_fid;
+ }
repbody->mbo_valid |= OBD_MD_FLID;
EXIT;
HABEO_REFERO, MDS_SET_INFO, mdt_set_info,
&RQF_OBD_SET_INFO, LUSTRE_MDS_VERSION),
TGT_MDT_HDL(0, MDS_GET_INFO, mdt_get_info),
-TGT_MDT_HDL(0 | HABEO_REFERO, MDS_GETSTATUS, mdt_getstatus),
+TGT_MDT_HDL(0 | HABEO_REFERO, MDS_GET_ROOT, mdt_get_root),
TGT_MDT_HDL(HABEO_CORPUS, MDS_GETATTR, mdt_getattr),
TGT_MDT_HDL(HABEO_CORPUS| HABEO_REFERO, MDS_GETATTR_NAME,
mdt_getattr_name),
* \param[in] info Per-thread common data shared by MDT level handlers.
* \param[in] obj Object to do path lookup of
* \param[in,out] fp User-provided struct to store path information
+ * \param[in] root_fid Root FID of current path should reach
*
* \retval 0 Lookup successful, path information stored in fp
* \retval -EAGAIN Lookup failed, usually because object is being moved
*/
static int mdt_path_current(struct mdt_thread_info *info,
struct mdt_object *obj,
- struct getinfo_fid2path *fp)
+ struct getinfo_fid2path *fp,
+ struct lu_fid *root_fid)
{
struct mdt_device *mdt = info->mti_mdt;
struct mdt_object *mdt_obj;
RETURN(-ENOMEM);
ldata.ld_buf = buf;
- ptr = fp->gf_path + fp->gf_pathlen - 1;
+ ptr = fp->gf_u.gf_path + fp->gf_pathlen - 1;
*ptr = 0;
--ptr;
*tmpfid = fp->gf_fid = *mdt_object_fid(obj);
- /* root FID only exists on MDT0, and fid2path should also ends at MDT0,
- * so checking root_fid can only happen on MDT0. */
- while (!lu_fid_eq(&mdt->mdt_md_root_fid, &fp->gf_fid)) {
+ while (!lu_fid_eq(root_fid, &fp->gf_fid)) {
struct lu_buf lmv_buf;
+ if (!lu_fid_eq(root_fid, &mdt->mdt_md_root_fid) &&
+ lu_fid_eq(&mdt->mdt_md_root_fid, &fp->gf_fid))
+ GOTO(out, rc = -ENOENT);
+
mdt_obj = mdt_object_find(info->mti_env, mdt, tmpfid);
if (IS_ERR(mdt_obj))
GOTO(out, rc = PTR_ERR(mdt_obj));
/* Pack the name in the end of the buffer */
ptr -= tmpname->ln_namelen;
- if (ptr - 1 <= fp->gf_path)
+ if (ptr - 1 <= fp->gf_u.gf_path)
GOTO(out, rc = -EOVERFLOW);
strncpy(ptr, tmpname->ln_name, tmpname->ln_namelen);
*(--ptr) = '/';
remote_out:
ptr++; /* skip leading / */
- memmove(fp->gf_path, ptr, fp->gf_path + fp->gf_pathlen - ptr);
+ memmove(fp->gf_u.gf_path, ptr,
+ fp->gf_u.gf_path + fp->gf_pathlen - ptr);
out:
RETURN(rc);
* \retval negative errno if there was a problem
*/
static int mdt_path(struct mdt_thread_info *info, struct mdt_object *obj,
- struct getinfo_fid2path *fp)
+ struct getinfo_fid2path *fp, struct lu_fid *root_fid)
{
struct mdt_device *mdt = info->mti_mdt;
int tries = 3;
if (fp->gf_pathlen < 3)
RETURN(-EOVERFLOW);
- if (lu_fid_eq(&mdt->mdt_md_root_fid, mdt_object_fid(obj))) {
- fp->gf_path[0] = '\0';
+ if (root_fid == NULL)
+ root_fid = &mdt->mdt_md_root_fid;
+
+ if (lu_fid_eq(root_fid, mdt_object_fid(obj))) {
+ fp->gf_u.gf_path[0] = '\0';
RETURN(0);
}
/* Retry multiple times in case file is being moved */
while (tries-- && rc == -EAGAIN)
- rc = mdt_path_current(info, obj, fp);
+ rc = mdt_path_current(info, obj, fp, root_fid);
RETURN(rc);
}
* \retval negative errno if there was a problem
*/
static int mdt_fid2path(struct mdt_thread_info *info,
+ struct lu_fid *root_fid,
struct getinfo_fid2path *fp)
{
struct mdt_device *mdt = info->mti_mdt;
RETURN(rc);
}
- rc = mdt_path(info, obj, fp);
+ rc = mdt_path(info, obj, fp, root_fid);
CDEBUG(D_INFO, "fid "DFID", path %s recno "LPX64" linkno %u\n",
- PFID(&fp->gf_fid), fp->gf_path, fp->gf_recno, fp->gf_linkno);
+ PFID(&fp->gf_fid), fp->gf_u.gf_path,
+ fp->gf_recno, fp->gf_linkno);
mdt_object_put(info->mti_env, obj);
RETURN(rc);
}
-static int mdt_rpc_fid2path(struct mdt_thread_info *info, void *key,
+static int mdt_rpc_fid2path(struct mdt_thread_info *info, void *key, int keylen,
void *val, int vallen)
{
struct getinfo_fid2path *fpout, *fpin;
+ struct lu_fid *root_fid = NULL;
int rc = 0;
fpin = key + cfs_size_round(sizeof(KEY_FID2PATH));
if (fpout->gf_pathlen != vallen - sizeof(*fpin))
RETURN(-EINVAL);
- rc = mdt_fid2path(info, fpout);
+ if (keylen >= cfs_size_round(sizeof(KEY_FID2PATH)) + sizeof(*fpin) +
+ sizeof(struct lu_fid)) {
+ /* client sent its root FID, which is normally fileset FID */
+ root_fid = fpin->gf_u.gf_root_fid;
+ if (ptlrpc_req_need_swab(info->mti_pill->rc_req))
+ lustre_swab_lu_fid(root_fid);
+
+ if (root_fid != NULL && !fid_is_sane(root_fid))
+ RETURN(-EINVAL);
+ }
+
+ rc = mdt_fid2path(info, root_fid, fpout);
RETURN(rc);
}
if (KEY_IS(KEY_FID2PATH)) {
struct mdt_thread_info *info = tsi2mdt_info(tsi);
- rc = mdt_rpc_fid2path(info, key, valout, *vallen);
+ rc = mdt_rpc_fid2path(info, key, keylen, valout, *vallen);
mdt_thread_info_fini(info);
} else {
rc = -EINVAL;
"unlink_close",
"multi_mod_rpcs",
"dir_stripe",
- "fileset_mount",
+ "subtree",
"lock_ahead",
"bulk_mbits",
"compact_obdo",
static int lustre_free_lsi(struct super_block *sb)
{
- struct lustre_sb_info *lsi = s2lsi(sb);
- ENTRY;
+ struct lustre_sb_info *lsi = s2lsi(sb);
+ ENTRY;
- LASSERT(lsi != NULL);
- CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi);
+ LASSERT(lsi != NULL);
+ CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi);
- /* someone didn't call server_put_mount. */
+ /* someone didn't call server_put_mount. */
LASSERT(atomic_read(&lsi->lsi_mounts) == 0);
- 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);
+ 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_fileset != NULL)
+ OBD_FREE(lsi->lsi_lmd->lmd_fileset,
+ strlen(lsi->lsi_lmd->lmd_fileset) + 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);
if (lsi->lsi_lmd->lmd_mgs != NULL)
OBD_FREE(lsi->lsi_lmd->lmd_mgs,
strlen(lsi->lsi_lmd->lmd_mgs) + 1);
if (lsi->lsi_lmd->lmd_params != NULL)
OBD_FREE(lsi->lsi_lmd->lmd_params, 4096);
- OBD_FREE(lsi->lsi_lmd, sizeof(*lsi->lsi_lmd));
- }
+ OBD_FREE_PTR(lsi->lsi_lmd);
+ }
- LASSERT(lsi->lsi_llsbi == NULL);
- OBD_FREE(lsi, sizeof(*lsi));
- s2lsi_nocast(sb) = NULL;
+ LASSERT(lsi->lsi_llsbi == NULL);
+ OBD_FREE_PTR(lsi);
+ s2lsi_nocast(sb) = NULL;
- RETURN(0);
+ RETURN(0);
}
/* The lsi has one reference for every server that is using the disk -
goto invalid;
}
- s1 = strstr(devname, ":/");
- if (s1) {
- ++s1;
- lmd->lmd_flags |= LMD_FLG_CLIENT;
- /* Remove leading /s from fsname */
- while (*++s1 == '/') ;
- /* Freed in lustre_free_lsi */
- OBD_ALLOC(lmd->lmd_profile, strlen(s1) + 8);
- if (!lmd->lmd_profile)
- RETURN(-ENOMEM);
- sprintf(lmd->lmd_profile, "%s-client", s1);
- }
+ s1 = strstr(devname, ":/");
+ if (s1) {
+ ++s1;
+ lmd->lmd_flags |= LMD_FLG_CLIENT;
+ /* Remove leading /s from fsname */
+ while (*++s1 == '/')
+ ;
+ s2 = s1;
+ while (*s2 != '/' && *s2 != '\0')
+ s2++;
+ /* Freed in lustre_free_lsi */
+ OBD_ALLOC(lmd->lmd_profile, s2 - s1 + 8);
+ if (!lmd->lmd_profile)
+ RETURN(-ENOMEM);
+
+ strncat(lmd->lmd_profile, s1, s2 - s1);
+ strncat(lmd->lmd_profile, "-client", 7);
+
+ s1 = s2;
+ s2 = s1 + strlen(s1) - 1;
+ /* Remove padding /s from fileset */
+ while (*s2 == '/')
+ s2--;
+ if (s2 > s1) {
+ OBD_ALLOC(lmd->lmd_fileset, s2 - s1 + 2);
+ if (lmd->lmd_fileset == NULL) {
+ OBD_FREE(lmd->lmd_profile,
+ strlen(lmd->lmd_profile) + 1);
+ RETURN(-ENOMEM);
+ }
+ strncat(lmd->lmd_fileset, s1, s2 - s1 + 1);
+ }
+ }
/* Freed in lustre_free_lsi */
OBD_ALLOC(lmd->lmd_dev, strlen(devname) + 1);
GOTO(out, rc = -EINVAL);
}
- if (lmd_is_client(lmd)) {
- CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
+ if (lmd_is_client(lmd)) {
+ CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
if (client_fill_super == NULL)
request_module("lustre");
if (client_fill_super == NULL) {
- LCONSOLE_ERROR_MSG(0x165, "Nothing registered for "
- "client mount! Is the 'lustre' "
- "module loaded?\n");
- lustre_put_lsi(sb);
- rc = -ENODEV;
- } else {
- rc = lustre_start_mgc(sb);
- if (rc) {
- lustre_put_lsi(sb);
- GOTO(out, rc);
- }
- /* Connect and start */
- /* (should always be ll_fill_super) */
- rc = (*client_fill_super)(sb, lmd2->lmd2_mnt);
- /* c_f_s will call lustre_common_put_super on failure */
- }
- } else {
+ LCONSOLE_ERROR_MSG(0x165, "Nothing registered for "
+ "client mount! Is the 'lustre' "
+ "module loaded?\n");
+ lustre_put_lsi(sb);
+ rc = -ENODEV;
+ } else {
+ rc = lustre_start_mgc(sb);
+ if (rc) {
+ lustre_put_lsi(sb);
+ GOTO(out, rc);
+ }
+ /* Connect and start */
+ /* (should always be ll_fill_super) */
+ rc = (*client_fill_super)(sb, lmd2->lmd2_mnt);
+ /* c_f_s will call lustre_common_put_super on failure */
+ }
+ } else {
#ifdef HAVE_SERVER_SUPPORT
CDEBUG(D_MOUNT, "Mounting server from %s\n", lmd->lmd_dev);
rc = server_fill_super(sb);
"cannot handle server mount.\n");
rc = -EINVAL;
#endif
- }
+ }
/* If error happens in fill_super() call, @lsi will be killed there.
* This is why we do not put it here. */
&RMF_EAVALS_LENS
};
+static const struct req_msg_field *mds_get_root_client[] = {
+ &RMF_PTLRPC_BODY,
+ &RMF_MDT_BODY,
+ &RMF_NAME
+};
+
static const struct req_msg_field *mds_getxattr_client[] = {
&RMF_PTLRPC_BODY,
&RMF_MDT_BODY,
&RQF_MDS_CONNECT,
&RQF_MDS_DISCONNECT,
&RQF_MDS_GET_INFO,
- &RQF_MDS_GETSTATUS,
+ &RQF_MDS_GET_ROOT,
&RQF_MDS_STATFS,
&RQF_MDS_GETATTR,
&RQF_MDS_GETATTR_NAME,
ldlm_intent_quota_server);
EXPORT_SYMBOL(RQF_LDLM_INTENT_QUOTA);
-struct req_format RQF_MDS_GETSTATUS =
- DEFINE_REQ_FMT0("MDS_GETSTATUS", mdt_body_only, mdt_body_capa);
-EXPORT_SYMBOL(RQF_MDS_GETSTATUS);
+struct req_format RQF_MDS_GET_ROOT =
+ DEFINE_REQ_FMT0("MDS_GET_ROOT", mds_get_root_client, mdt_body_capa);
+EXPORT_SYMBOL(RQF_MDS_GET_ROOT);
struct req_format RQF_MDS_STATFS =
DEFINE_REQ_FMT0("MDS_STATFS", empty, obd_statfs_server);
{ MDS_READPAGE, "mds_readpage" },
{ MDS_CONNECT, "mds_connect" },
{ MDS_DISCONNECT, "mds_disconnect" },
- { MDS_GETSTATUS, "mds_getstatus" },
+ { MDS_GET_ROOT, "mds_get_root" },
{ MDS_STATFS, "mds_statfs" },
{ MDS_PIN, "mds_pin" },
{ MDS_UNPIN, "mds_unpin" },
(long long)MDS_CONNECT);
LASSERTF(MDS_DISCONNECT == 39, "found %lld\n",
(long long)MDS_DISCONNECT);
- LASSERTF(MDS_GETSTATUS == 40, "found %lld\n",
- (long long)MDS_GETSTATUS);
+ LASSERTF(MDS_GET_ROOT == 40, "found %lld\n",
+ (long long)MDS_GET_ROOT);
LASSERTF(MDS_STATFS == 41, "found %lld\n",
(long long)MDS_STATFS);
LASSERTF(MDS_PIN == 42, "found %lld\n",
(long long)(int)offsetof(struct getinfo_fid2path, gf_pathlen));
LASSERTF((int)sizeof(((struct getinfo_fid2path *)0)->gf_pathlen) == 4, "found %lld\n",
(long long)(int)sizeof(((struct getinfo_fid2path *)0)->gf_pathlen));
- LASSERTF((int)offsetof(struct getinfo_fid2path, gf_path[0]) == 32, "found %lld\n",
- (long long)(int)offsetof(struct getinfo_fid2path, gf_path[0]));
- LASSERTF((int)sizeof(((struct getinfo_fid2path *)0)->gf_path[0]) == 1, "found %lld\n",
- (long long)(int)sizeof(((struct getinfo_fid2path *)0)->gf_path[0]));
+ LASSERTF((int)offsetof(struct getinfo_fid2path, gf_u.gf_path[0]) == 32, "found %lld\n",
+ (long long)(int)offsetof(struct getinfo_fid2path, gf_u.gf_path[0]));
+ LASSERTF((int)sizeof(((struct getinfo_fid2path *)0)->gf_u.gf_path[0]) == 1, "found %lld\n",
+ (long long)(int)sizeof(((struct getinfo_fid2path *)0)->gf_u.gf_path[0]));
/* Checks for struct fiemap */
LASSERTF((int)sizeof(struct fiemap) == 32, "found %lld\n",
ost_HOST=${ost_HOST:-$(hostname)}
ostfailover_HOST=${ostfailover_HOST}
CLIENTS=""
+# FILESET variable is used by sanity.sh to verify fileset
+# feature, tests should pass even under subdirectory namespace.
+FILESET=${FILESET:-""}
+[[ -z "$FILESET" ]] || [[ "${FILESET:0:1}" = "/" ]] || FILESET="/$FILESET"
TMP=${TMP:-/tmp}
}
check_and_setup_lustre
-
DIR=${DIR:-$MOUNT}
assert_DIR
test_27D() {
[ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs" && return
+ [ -n "$FILESET" ] && skip "SKIP due to FILESET set" && return
local POOL=${POOL:-testpool}
local first_ost=0
local last_ost=$(($OSTCOUNT - 1))
[[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.2.51) ]] ||
{ skip "Need MDS version at least 2.2.51"; return 0; }
[ -z "$(which setfacl)" ] && skip "must have setfacl tool" && return
+ [ -n "$FILESET" ] && skip "SKIP due to FILESET set" && return
cp /etc/hosts $DIR/$tfile
[ $PARALLEL == "yes" ] && skip "skip parallel run" && return
[[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.2.51) ]] ||
{ skip "Need MDS version at least 2.2.51"; return 0; }
+ [ -n "$FILESET" ] && skip "SKIP due to FILESET set" && return
[ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
run_test 154e ".lustre is not returned by readdir"
test_154f() {
+ [ -n "$FILESET" ] && skip "SKIP due to FILESET set" && return
# create parent directory on a single MDT to avoid cross-MDT hardlinks
test_mkdir -p -c1 $DIR/$tdir/d
# test dirs inherit from its stripe
{
[[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.6.92) ]] ||
{ skip "Need MDS version at least 2.6.92"; return 0; }
+ [ -n "$FILESET" ] && skip "SKIP due to FILESET set" && return
mkdir -p $DIR/$tdir
llapi_fid_test -d $DIR/$tdir
local mtime1=$(stat -c "%Y" $DIR/$tdir)
local fid=$($MULTIOP $DIR/$tdir VFw4096c) ||
error "cannot create/write a volatile file"
+ [ "$FILESET" == "" ] &&
$CHECKSTAT -t file $MOUNT/.lustre/fid/$fid 2>/dev/null &&
error "FID is still valid after close"
# is unfortunately eaten by multiop_bg_pause
local n=$((${fidv[1]} + 1))
local next_fid="${fidv[0]}:$(printf "0x%x" $n):${fidv[2]}"
- $CHECKSTAT -t file $MOUNT/.lustre/fid/$next_fid ||
- error "FID is missing before close"
+ if [ "$FILESET" == "" ]; then
+ $CHECKSTAT -t file $MOUNT/.lustre/fid/$next_fid ||
+ error "FID is missing before close"
+ fi
kill -USR1 $multi_pid
# 1 second delay, so if mtime change we will see it
sleep 1
test_200() {
[ $PARALLEL == "yes" ] && skip "skip parallel run" && return
remote_mgs_nodsh && skip "remote MGS with nodsh" && return
+ [ -n "$FILESET" ] && skip "SKIP due to FILESET set" && return
local POOL=${POOL:-cea1}
local POOL_ROOT=${POOL_ROOT:-$DIR/d200.pools}
test_233a() {
[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.3.64) ] ||
{ skip "Need MDS version at least 2.3.64"; return; }
+ [ -n "$FILESET" ] && skip "SKIP due to FILESET set" && return
local fid=$($LFS path2fid $MOUNT)
stat $MOUNT/.lustre/fid/$fid > /dev/null ||
test_233b() {
[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.5.90) ] ||
{ skip "Need MDS version at least 2.5.90"; return; }
+ [ -n "$FILESET" ] && skip "SKIP due to FILESET set" && return
local fid=$($LFS path2fid $MOUNT/.lustre)
stat $MOUNT/.lustre/fid/$fid > /dev/null ||
}
run_test 246 "Read file of size 4095 should return right length"
+test_247a() {
+ lctl get_param -n mdc.$FSNAME-MDT0000*.import |
+ grep -q subtree ||
+ { skip "Fileset feature is not supported"; return; }
+
+ local submount=${MOUNT}_$tdir
+
+ mkdir $MOUNT/$tdir
+ mkdir -p $submount || error "mkdir $submount failed"
+ FILESET="$FILESET/$tdir" mount_client $submount ||
+ error "mount $submount failed"
+ echo foo > $submount/$tfile || error "write $submount/$tfile failed"
+ [ $(cat $MOUNT/$tdir/$tfile) = "foo" ] ||
+ error "read $MOUNT/$tdir/$tfile failed"
+ umount_client $submount || error "umount $submount failed"
+ rmdir $submount
+}
+run_test 247a "mount subdir as fileset"
+
+test_247b() {
+ lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
+ { skip "Fileset feature is not supported"; return; }
+
+ local submount=${MOUNT}_$tdir
+
+ rm -rf $MOUNT/$tdir
+ mkdir -p $submount || error "mkdir $submount failed"
+ SKIP_FILESET=1
+ FILESET="$FILESET/$tdir" mount_client $submount &&
+ error "mount $submount should fail"
+ rmdir $submount
+}
+run_test 247b "mount subdir that dose not exist"
+
+test_247c() {
+ lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
+ { skip "Fileset feature is not supported"; return; }
+
+ local submount=${MOUNT}_$tdir
+
+ mkdir -p $MOUNT/$tdir/dir1
+ mkdir -p $submount || error "mkdir $submount failed"
+ FILESET="$FILESET/$tdir" mount_client $submount ||
+ error "mount $submount failed"
+ local fid=$($LFS path2fid $MOUNT/)
+ $LFS fid2path $submount $fid && error "fid2path should fail"
+ umount_client $submount || error "umount $submount failed"
+ rmdir $submount
+}
+run_test 247c "running fid2path outside root"
+
+test_247d() {
+ lctl get_param -n mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
+ { skip "Fileset feature is not supported"; return; }
+
+ local submount=${MOUNT}_$tdir
+
+ mkdir -p $MOUNT/$tdir/dir1
+ mkdir -p $submount || error "mkdir $submount failed"
+ FILESET="$FILESET/$tdir" mount_client $submount ||
+ error "mount $submount failed"
+ local fid=$($LFS path2fid $submount/dir1)
+ $LFS fid2path $submount $fid || error "fid2path should succeed"
+ umount_client $submount || error "umount $submount failed"
+ rmdir $submount
+}
+run_test 247d "running fid2path inside root"
+
test_250() {
[ "$(facet_fstype ost$(($($GETSTRIPE -i $DIR/$tfile) + 1)))" = "zfs" ] \
&& skip "no 16TB file size limit on ZFS" && return
}
zconf_mount() {
- local client=$1
- local mnt=$2
- local opts=${3:-$MOUNT_OPTS}
- opts=${opts:+-o $opts}
- local flags=${4:-$MOUNT_FLAGS}
-
- local device=$MGSNID:/$FSNAME
- if [ -z "$mnt" -o -z "$FSNAME" ]; then
- echo Bad zconf mount command: opt=$flags $opts dev=$device mnt=$mnt
- exit 1
- fi
+ local client=$1
+ local mnt=$2
+ local opts=${3:-$MOUNT_OPTS}
+ opts=${opts:+-o $opts}
+ local flags=${4:-$MOUNT_FLAGS}
+
+ local device=$MGSNID:/$FSNAME$FILESET
+ if [ -z "$mnt" -o -z "$FSNAME" ]; then
+ echo "Bad mount command: opt=$flags $opts dev=$device " \
+ "mnt=$mnt"
+ exit 1
+ fi
+
+ echo "Starting client: $client: $flags $opts $device $mnt"
+ do_node $client mkdir -p $mnt
+ if [ -n "$FILESET" -a -z "$SKIP_FILESET" ];then
+ do_node $client $MOUNT_CMD $flags $opts $MGSNID:/$FSNAME \
+ $mnt || return 1
+ #disable FILESET if not supported
+ do_nodes $client lctl get_param -n \
+ mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
+ device=$MGSNID:/$FSNAME
+ do_node $client mkdir -p $mnt/$FILESET
+ do_node $client "! grep -q $mnt' ' /proc/mounts ||
+ umount $mnt"
+ fi
+ do_node $client $MOUNT_CMD $flags $opts $device $mnt || return 1
+
+ set_default_debug_nodes $client
- echo "Starting client: $client: $flags $opts $device $mnt"
- do_node $client mkdir -p $mnt
- do_node $client $MOUNT_CMD $flags $opts $device $mnt || return 1
-
- set_default_debug_nodes $client
-
- return 0
+ return 0
}
zconf_umount() {
# mount clients if not mouted
zconf_mount_clients() {
- local clients=$1
- local mnt=$2
- local opts=${3:-$MOUNT_OPTS}
- opts=${opts:+-o $opts}
- local flags=${4:-$MOUNT_FLAGS}
-
- local device=$MGSNID:/$FSNAME
- if [ -z "$mnt" -o -z "$FSNAME" ]; then
- echo Bad zconf mount command: opt=$flags $opts dev=$device mnt=$mnt
- exit 1
- fi
-
- echo "Starting client $clients: $flags $opts $device $mnt"
-
- do_nodes $clients "
+ local clients=$1
+ local mnt=$2
+ local opts=${3:-$MOUNT_OPTS}
+ opts=${opts:+-o $opts}
+ local flags=${4:-$MOUNT_FLAGS}
+
+ local device=$MGSNID:/$FSNAME$FILESET
+ if [ -z "$mnt" -o -z "$FSNAME" ]; then
+ echo "Bad conf mount command: opt=$flags $opts dev=$device " \
+ "mnt=$mnt"
+ exit 1
+ fi
+
+ echo "Starting client $clients: $flags $opts $device $mnt"
+ if [ -n "$FILESET" -a ! -n "$SKIP_FILESET" ]; then
+ do_nodes $clients "! grep -q $mnt' ' /proc/mounts ||
+ umount $mnt"
+ do_nodes $clients $MOUNT_CMD $flags $opts $MGSNID:/$FSNAME \
+ $mnt || return 1
+ #disable FILESET if not supported
+ do_nodes $clients lctl get_param -n \
+ mdc.$FSNAME-MDT0000*.import | grep -q subtree ||
+ device=$MGSNID:/$FSNAME
+ do_nodes $clients mkdir -p $mnt/$FILESET
+ do_nodes $clients "! grep -q $mnt' ' /proc/mounts ||
+ umount $mnt"
+ fi
+
+ do_nodes $clients "
running=\\\$(mount | grep -c $mnt' ');
rc=0;
if [ \\\$running -eq 0 ] ; then
fi;
exit \\\$rc" || return ${PIPESTATUS[0]}
- echo "Started clients $clients: "
- do_nodes $clients "mount | grep $mnt' '"
+ echo "Started clients $clients: "
+ do_nodes $clients "mount | grep $mnt' '"
- set_default_debug_nodes $clients
+ set_default_debug_nodes $clients
- return 0
+ return 0
}
zconf_umount_clients() {
*/
int get_root_path(int want, char *fsname, int *outfd, char *path, int index)
{
- struct mntent mnt;
- char buf[PATH_MAX], mntdir[PATH_MAX];
- char *ptr;
- FILE *fp;
- int idx = 0, len = 0, mntlen, fd;
- int rc = -ENODEV;
+ struct mntent mnt;
+ char buf[PATH_MAX], mntdir[PATH_MAX];
+ char *ptr, *ptr_end;
+ FILE *fp;
+ int idx = 0, len = 0, mntlen, fd;
+ int rc = -ENODEV;
/* get the mount point */
- fp = setmntent(PROC_MOUNTS, "r");
- if (fp == NULL) {
- rc = -EIO;
- llapi_error(LLAPI_MSG_ERROR, rc,
+ fp = setmntent(PROC_MOUNTS, "r");
+ if (fp == NULL) {
+ rc = -EIO;
+ llapi_error(LLAPI_MSG_ERROR, rc,
"setmntent(%s) failed", PROC_MOUNTS);
- return rc;
- }
+ return rc;
+ }
while (1) {
if (getmntent_r(fp, &mnt, buf, sizeof(buf)) == NULL)
break;
continue;
mntlen = strlen(mnt.mnt_dir);
- ptr = strrchr(mnt.mnt_fsname, '/');
+ ptr = strchr(mnt.mnt_fsname, '/');
+ while (ptr && *ptr == '/')
+ ptr++;
/* thanks to the call to llapi_is_lustre_mnt() above,
* we are sure that mnt.mnt_fsname contains ":/",
* so ptr should never be NULL */
if (ptr == NULL)
continue;
- ptr++;
+ ptr_end = ptr;
+ while (*ptr_end != '/' && *ptr_end != '\0')
+ ptr_end++;
- /* Check the fsname for a match, if given */
+ /* Check the fsname for a match, if given */
if (!(want & WANT_FSNAME) && fsname != NULL &&
- (strlen(fsname) > 0) && (strcmp(ptr, fsname) != 0))
+ (strlen(fsname) > 0) &&
+ (strncmp(ptr, fsname, ptr_end - ptr) != 0))
continue;
/* If the path isn't set return the first one we find */
- if (path == NULL || strlen(path) == 0) {
- strcpy(mntdir, mnt.mnt_dir);
- if ((want & WANT_FSNAME) && fsname != NULL)
- strcpy(fsname, ptr);
- rc = 0;
- break;
- /* Otherwise find the longest matching path */
- } else if ((strlen(path) >= mntlen) && (mntlen >= len) &&
- (strncmp(mnt.mnt_dir, path, mntlen) == 0)) {
- strcpy(mntdir, mnt.mnt_dir);
- len = mntlen;
- if ((want & WANT_FSNAME) && fsname != NULL)
- strcpy(fsname, ptr);
- rc = 0;
- }
- }
- endmntent(fp);
+ if (path == NULL || strlen(path) == 0) {
+ strncpy(mntdir, mnt.mnt_dir, strlen(mnt.mnt_dir));
+ mntdir[strlen(mnt.mnt_dir)] = '\0';
+ if ((want & WANT_FSNAME) && fsname != NULL) {
+ strncpy(fsname, ptr, ptr_end - ptr);
+ fsname[ptr_end - ptr] = '\0';
+ }
+ rc = 0;
+ break;
+ /* Otherwise find the longest matching path */
+ } else if ((strlen(path) >= mntlen) && (mntlen >= len) &&
+ (strncmp(mnt.mnt_dir, path, mntlen) == 0)) {
+ strncpy(mntdir, mnt.mnt_dir, strlen(mnt.mnt_dir));
+ mntdir[strlen(mnt.mnt_dir)] = '\0';
+ len = mntlen;
+ if ((want & WANT_FSNAME) && fsname != NULL) {
+ strncpy(fsname, ptr, ptr_end - ptr);
+ fsname[ptr_end - ptr] = '\0';
+ }
+ rc = 0;
+ }
+ }
+ endmntent(fp);
- /* Found it */
- if (rc == 0) {
- if ((want & WANT_PATH) && path != NULL)
- strcpy(path, mntdir);
- if (want & WANT_FD) {
- fd = open(mntdir, O_RDONLY | O_DIRECTORY | O_NONBLOCK);
- if (fd < 0) {
- rc = -errno;
- llapi_error(LLAPI_MSG_ERROR, rc,
- "error opening '%s'", mntdir);
+ /* Found it */
+ if (rc == 0) {
+ if ((want & WANT_PATH) && path != NULL) {
+ strncpy(path, mntdir, strlen(mntdir));
+ path[strlen(mntdir)] = '\0';
+ }
+ if (want & WANT_FD) {
+ fd = open(mntdir, O_RDONLY | O_DIRECTORY | O_NONBLOCK);
+ if (fd < 0) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc,
+ "error opening '%s'", mntdir);
- } else {
- *outfd = fd;
- }
- }
- } else if (want & WANT_ERROR)
- llapi_err_noerrno(LLAPI_MSG_ERROR,
- "can't find fs root for '%s': %d",
- (want & WANT_PATH) ? fsname : path, rc);
- return rc;
+ } else {
+ *outfd = fd;
+ }
+ }
+ } else if (want & WANT_ERROR)
+ llapi_err_noerrno(LLAPI_MSG_ERROR,
+ "can't find fs root for '%s': %d",
+ (want & WANT_PATH) ? fsname : path, rc);
+ return rc;
}
/*
rc = -errno;
else
rc = 0;
- if (rc && want_error)
- llapi_error(LLAPI_MSG_ERROR, rc, "ioctl %d err %d", opc, rc);
-
close(fd);
return rc;
}
if (rc != -ENOENT)
llapi_error(LLAPI_MSG_ERROR, rc, "ioctl err %d", rc);
} else {
- memcpy(buf, gf->gf_path, gf->gf_pathlen);
+ memcpy(buf, gf->gf_u.gf_path, gf->gf_pathlen);
if (buf[0] == '\0') { /* ROOT path */
buf[0] = '/';
buf[1] = '\0';
progname);
fprintf(out,
"\t<device>: the disk device, or for a client:\n"
- "\t\t<mgmtnid>[:<altmgtnid>...]:/<filesystem>-client\n"
+ "\t\t<mgsnid>[:<altmgsnid>...]:/<filesystem>[/<subdir>]\n"
"\t<filesystem>: name of the Lustre filesystem (e.g. lustre1)\n"
"\t<mountpt>: filesystem mountpoint (e.g. /mnt/lustre)\n"
"\t-f|--fake: fake mount (updates /etc/mtab)\n"
CHECK_VALUE_X(MSG_CONNECT_TRANSNO);
}
+/* XXX README XXX:
+ * Please DO NOT add flag values here before first ensuring that this same
+ * flag value is not in use on some other branch. Please clear any such
+ * changes with senior engineers before starting to use a new flag. Then,
+ * submit a small patch against EVERY branch that ONLY adds the new flag,
+ * updates obd_connect_names[] for lprocfs_rd_connect_flags(), adds the
+ * flag to check_obd_connect_data(), and updates wiretests accordingly, so it
+ * can be approved and landed easily to reserve the flag for future use. */
static void
check_obd_connect_data(void)
{
CHECK_VALUE(MDS_READPAGE);
CHECK_VALUE(MDS_CONNECT);
CHECK_VALUE(MDS_DISCONNECT);
- CHECK_VALUE(MDS_GETSTATUS);
+ CHECK_VALUE(MDS_GET_ROOT);
CHECK_VALUE(MDS_STATFS);
CHECK_VALUE(MDS_PIN);
CHECK_VALUE(MDS_UNPIN);
(long long)MDS_CONNECT);
LASSERTF(MDS_DISCONNECT == 39, "found %lld\n",
(long long)MDS_DISCONNECT);
- LASSERTF(MDS_GETSTATUS == 40, "found %lld\n",
- (long long)MDS_GETSTATUS);
+ LASSERTF(MDS_GET_ROOT == 40, "found %lld\n",
+ (long long)MDS_GET_ROOT);
LASSERTF(MDS_STATFS == 41, "found %lld\n",
(long long)MDS_STATFS);
LASSERTF(MDS_PIN == 42, "found %lld\n",
(long long)(int)offsetof(struct getinfo_fid2path, gf_pathlen));
LASSERTF((int)sizeof(((struct getinfo_fid2path *)0)->gf_pathlen) == 4, "found %lld\n",
(long long)(int)sizeof(((struct getinfo_fid2path *)0)->gf_pathlen));
- LASSERTF((int)offsetof(struct getinfo_fid2path, gf_path[0]) == 32, "found %lld\n",
- (long long)(int)offsetof(struct getinfo_fid2path, gf_path[0]));
- LASSERTF((int)sizeof(((struct getinfo_fid2path *)0)->gf_path[0]) == 1, "found %lld\n",
- (long long)(int)sizeof(((struct getinfo_fid2path *)0)->gf_path[0]));
+ LASSERTF((int)offsetof(struct getinfo_fid2path, gf_u.gf_path[0]) == 32, "found %lld\n",
+ (long long)(int)offsetof(struct getinfo_fid2path, gf_u.gf_path[0]));
+ LASSERTF((int)sizeof(((struct getinfo_fid2path *)0)->gf_u.gf_path[0]) == 1, "found %lld\n",
+ (long long)(int)sizeof(((struct getinfo_fid2path *)0)->gf_u.gf_path[0]));
/* Checks for struct fiemap */
LASSERTF((int)sizeof(struct fiemap) == 32, "found %lld\n",