From: Lai Siyao Date: Tue, 3 Mar 2015 12:36:31 +0000 (+0800) Subject: LU-28 fileset: add fileset mount support X-Git-Tag: 2.8.52~5 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=refs%2Fchanges%2F07%2F5007%2F39;p=fs%2Flustre-release.git LU-28 fileset: add fileset mount support 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 Signed-off-by: Kit Westneat Signed-off-by: Wang Shilong Change-Id: I947785de3b053907600d1090c80e8f57396e1e93 Reviewed-on: http://review.whamcloud.com/5007 Tested-by: Jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Li Xi Reviewed-by: Oleg Drokin --- diff --git a/lustre/contrib/wireshark/packet-lustre.c b/lustre/contrib/wireshark/packet-lustre.c index 27640f6..e07576b 100644 --- a/lustre/contrib/wireshark/packet-lustre.c +++ b/lustre/contrib/wireshark/packet-lustre.c @@ -205,7 +205,7 @@ typedef enum { 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, @@ -1162,7 +1162,7 @@ const value_string lustre_op_codes[] = { {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"}, @@ -8590,7 +8590,7 @@ lustre_mds_opcode_process(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo 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) ; diff --git a/lustre/doc/mount.lustre.8 b/lustre/doc/mount.lustre.8 index 027dc4e..c020ae2 100644 --- a/lustre/doc/mount.lustre.8 +++ b/lustre/doc/mount.lustre.8 @@ -25,10 +25,12 @@ There are two forms for the .I device option, depending on whether a client or a target service is started: .TP -.IR :/ +.IR :/ [/] 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 . @@ -150,6 +152,9 @@ Start a client for the Lustre filesystem 'testfs' at the mount point /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 diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index 9bff175..713f99d 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -1296,7 +1296,8 @@ struct ptlrpc_body_v2 { 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 | \ @@ -2005,7 +2006,7 @@ typedef enum { 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 */ @@ -3691,11 +3692,14 @@ struct link_ea_entry { /** 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 */ diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index 340bec5..e680b4e 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -266,6 +266,7 @@ extern int llapi_search_mounts(const char *pathname, int index, 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); diff --git a/lustre/include/lustre_disk.h b/lustre/include/lustre_disk.h index 653349d..b56385e5 100644 --- a/lustre/include/lustre_disk.h +++ b/lustre/include/lustre_disk.h @@ -219,21 +219,22 @@ static inline int server_make_name(__u32 flags, __u16 index, char *fs, /* 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 */ @@ -550,6 +551,7 @@ struct lustre_sb_info { #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__ */ diff --git a/lustre/include/lustre_req_layout.h b/lustre/include/lustre_req_layout.h index 5a124b4..134edba 100644 --- a/lustre/include/lustre_req_layout.h +++ b/lustre/include/lustre_req_layout.h @@ -155,7 +155,7 @@ extern struct req_format RQF_FLD_READ; 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; diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 7ed95ea..31232e4 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -1069,7 +1069,8 @@ struct md_ops { #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 *, diff --git a/lustre/include/obd_class.h b/lustre/include/obd_class.h index 9e4b99d..2941e10 100644 --- a/lustre/include/obd_class.h +++ b/lustre/include/obd_class.h @@ -1267,14 +1267,15 @@ static inline int obd_register_observer(struct obd_device *obd, } /* 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); } diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index ce28659..71b4792 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -183,8 +183,8 @@ extern char obd_jobid_var[]; #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 diff --git a/lustre/llite/file.c b/lustre/llite/file.c index ff1dd64..2eb5b75 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1838,6 +1838,10 @@ int ll_fid2path(struct inode *inode, void __user *arg) 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); @@ -3120,6 +3124,14 @@ int ll_migrate(struct inode *parent, struct file *file, int mdtidx, 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)) { @@ -3199,6 +3211,7 @@ out_close: 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); diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 7ecc93c..5674ca4 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -209,7 +209,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, 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) @@ -473,7 +474,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, 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); diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index 0198517..0b7a1f0 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -691,14 +691,18 @@ static int lmv_fid2path(struct obd_export *exp, int len, void *karg, 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) @@ -711,23 +715,24 @@ repeat_fid2path: 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) @@ -756,7 +761,8 @@ repeat_fid2path: 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; @@ -1492,18 +1498,20 @@ out_free_temp: 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); } diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 090d6fa..ef49a28 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -84,7 +84,22 @@ static inline int mdc_queue_wait(struct ptlrpc_request *req) 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; @@ -92,13 +107,29 @@ static int mdc_getstatus(struct obd_export *exp, struct lu_fid *rootfid) 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); @@ -1445,28 +1476,30 @@ output: 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; @@ -1482,9 +1515,9 @@ static int mdc_ioc_fid2path(struct obd_export *exp, struct getinfo_fid2path *gf) 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); @@ -2758,7 +2791,7 @@ static struct obd_ops mdc_obd_ops = { }; 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, diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 3f16666..7d7f052 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -65,6 +65,8 @@ #include #include +#include + #include "mdt_internal.h" @@ -266,11 +268,87 @@ static void mdt_lock_pdo_mode(struct mdt_thread_info *info, struct mdt_object *o 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; @@ -279,11 +357,21 @@ static int mdt_getstatus(struct tgt_session_info *tsi) 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; @@ -4241,7 +4329,7 @@ TGT_RPC_HANDLER(MDS_FIRST_OPC, 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), @@ -5347,6 +5435,7 @@ int mdt_links_read(struct mdt_thread_info *info, struct mdt_object *mdt_obj, * \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 @@ -5354,7 +5443,8 @@ int mdt_links_read(struct mdt_thread_info *info, struct mdt_object *mdt_obj, */ 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; @@ -5377,16 +5467,18 @@ static int mdt_path_current(struct mdt_thread_info *info, 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)); @@ -5447,7 +5539,7 @@ static int mdt_path_current(struct mdt_thread_info *info, /* 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) = '/'; @@ -5462,7 +5554,8 @@ static int mdt_path_current(struct mdt_thread_info *info, 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); @@ -5484,7 +5577,7 @@ out: * \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; @@ -5494,14 +5587,17 @@ static int mdt_path(struct mdt_thread_info *info, struct mdt_object *obj, 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); } @@ -5523,6 +5619,7 @@ static int mdt_path(struct mdt_thread_info *info, struct mdt_object *obj, * \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; @@ -5565,20 +5662,22 @@ static int mdt_fid2path(struct mdt_thread_info *info, 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)); @@ -5591,7 +5690,18 @@ static int mdt_rpc_fid2path(struct mdt_thread_info *info, void *key, 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); } @@ -5636,7 +5746,7 @@ int mdt_get_info(struct tgt_session_info *tsi) 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; diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 18f383b..cce0628 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -657,7 +657,7 @@ static const char *obd_connect_names[] = { "unlink_close", "multi_mod_rpcs", "dir_stripe", - "fileset_mount", + "subtree", "lock_ahead", "bulk_mbits", "compact_obdo", diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index 153986a..6b1ae94 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -593,32 +593,35 @@ static struct lustre_sb_info *lustre_init_lsi(struct super_block *sb) 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); @@ -628,14 +631,14 @@ static int lustre_free_lsi(struct super_block *sb) 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 - @@ -1298,18 +1301,39 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) 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); @@ -1381,28 +1405,28 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent) 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); @@ -1415,7 +1439,7 @@ static int lustre_fill_super(struct super_block *sb, void *data, int silent) "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. */ diff --git a/lustre/ptlrpc/layout.c b/lustre/ptlrpc/layout.c index 8a4933d..111d1d1 100644 --- a/lustre/ptlrpc/layout.c +++ b/lustre/ptlrpc/layout.c @@ -501,6 +501,12 @@ static const struct req_msg_field *ldlm_intent_getxattr_server[] = { &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, @@ -731,7 +737,7 @@ static struct req_format *req_formats[] = { &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, @@ -1328,9 +1334,9 @@ struct req_format RQF_LDLM_INTENT_QUOTA = 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); diff --git a/lustre/ptlrpc/lproc_ptlrpc.c b/lustre/ptlrpc/lproc_ptlrpc.c index 255c9f5..1920fc7 100644 --- a/lustre/ptlrpc/lproc_ptlrpc.c +++ b/lustre/ptlrpc/lproc_ptlrpc.c @@ -78,7 +78,7 @@ static struct ll_rpc_opcode { { 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" }, diff --git a/lustre/ptlrpc/wiretest.c b/lustre/ptlrpc/wiretest.c index a8f52f8..33ea7b1 100644 --- a/lustre/ptlrpc/wiretest.c +++ b/lustre/ptlrpc/wiretest.c @@ -134,8 +134,8 @@ void lustre_assert_wire_constants(void) (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", @@ -4068,10 +4068,10 @@ void lustre_assert_wire_constants(void) (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", diff --git a/lustre/tests/cfg/local.sh b/lustre/tests/cfg/local.sh index 85f6644..d9d0ce2 100644 --- a/lustre/tests/cfg/local.sh +++ b/lustre/tests/cfg/local.sh @@ -7,6 +7,10 @@ mgs_HOST=${mgs_HOST:-$mds_HOST} 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} diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh old mode 100755 new mode 100644 index 21b7f1e..8a96be6 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -105,7 +105,6 @@ check_swap_layouts_support() } check_and_setup_lustre - DIR=${DIR:-$MOUNT} assert_DIR @@ -2020,6 +2019,7 @@ run_test 27C "check full striping across all OSTs" 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)) @@ -9946,6 +9946,7 @@ test_154a() { [[ $(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 @@ -9972,6 +9973,7 @@ test_154b() { [ $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 @@ -10068,6 +10070,7 @@ test_154e() 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 @@ -10147,6 +10150,7 @@ test_154g() { [[ $(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 @@ -11435,6 +11439,7 @@ test_185() { # LU-2441 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" @@ -11449,8 +11454,10 @@ test_185() { # LU-2441 # 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 @@ -11501,6 +11508,7 @@ run_test 187b "Test data version change on volatile file" 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} @@ -13197,6 +13205,7 @@ run_test 232 "failed lock should not block umount" 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 || @@ -13207,6 +13216,7 @@ run_test 233a "checking that OBF of the FS root succeeds" 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 || @@ -13488,6 +13498,74 @@ test_246() { # LU-7371 } 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 diff --git a/lustre/tests/test-framework.sh b/lustre/tests/test-framework.sh index 24790da..c413a35 100755 --- a/lustre/tests/test-framework.sh +++ b/lustre/tests/test-framework.sh @@ -1499,25 +1499,37 @@ setup_quota(){ } 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() { @@ -1607,21 +1619,35 @@ sanity_mount_check () { # 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 @@ -1631,12 +1657,12 @@ 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() { diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 516af31..dd15d55 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -847,21 +847,21 @@ out: */ 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; @@ -873,58 +873,71 @@ int get_root_path(int want, char *fsname, int *outfd, char *path, int index) 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; } /* @@ -3889,9 +3902,6 @@ int root_ioctl(const char *mdtname, int opc, void *data, int *mdtidxp, 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; } @@ -4136,7 +4146,7 @@ int llapi_fid2path(const char *device, const char *fidstr, char *buf, 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'; diff --git a/lustre/utils/mount_lustre.c b/lustre/utils/mount_lustre.c index 66ddb21..dfa65f4 100644 --- a/lustre/utils/mount_lustre.c +++ b/lustre/utils/mount_lustre.c @@ -96,7 +96,7 @@ void usage(FILE *out) progname); fprintf(out, "\t: the disk device, or for a client:\n" - "\t\t[:...]:/-client\n" + "\t\t[:...]:/[/]\n" "\t: name of the Lustre filesystem (e.g. lustre1)\n" "\t: filesystem mountpoint (e.g. /mnt/lustre)\n" "\t-f|--fake: fake mount (updates /etc/mtab)\n" diff --git a/lustre/utils/wirecheck.c b/lustre/utils/wirecheck.c index eabca64..9b65370 100644 --- a/lustre/utils/wirecheck.c +++ b/lustre/utils/wirecheck.c @@ -446,6 +446,14 @@ check_ptlrpc_body(void) 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) { @@ -2442,7 +2450,7 @@ main(int argc, char **argv) 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); diff --git a/lustre/utils/wiretest.c b/lustre/utils/wiretest.c index fc031e4..f965bac 100644 --- a/lustre/utils/wiretest.c +++ b/lustre/utils/wiretest.c @@ -149,8 +149,8 @@ void lustre_assert_wire_constants(void) (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", @@ -4083,10 +4083,10 @@ void lustre_assert_wire_constants(void) (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",