int mds_try_to_split_dir(struct obd_device *, struct dentry *, struct mea **,
int, int);
int mds_md_get_attr(struct obd_device *, struct inode *, struct mea **, int *);
-int mds_choose_mdsnum(struct obd_device *, const char *, int, int);
+int mds_choose_mdsnum(struct obd_device *, const char *, int, int, struct ptlrpc_peer *, struct inode *);
int mds_md_postsetup(struct obd_device *);
int mds_splitting_expected(struct obd_device *, struct dentry *);
int mds_lock_slave_objs(struct obd_device *, struct dentry *,
#include <linux/lustre_lib.h>
#include <linux/lustre_fsfilt.h>
#include <linux/lustre_lite.h>
+#include <asm/div64.h>
#include "mds_internal.h"
RETURN(rc);
}
-int mds_choose_mdsnum(struct obd_device *obd, const char *name, int len, int flags)
+int mds_choose_mdsnum(struct obd_device *obd, const char *name, int len, int flags,
+ struct ptlrpc_peer *peer, struct inode *parent)
{
- struct lmv_obd *lmv;
struct mds_obd *mds = &obd->u.mds;
+ struct lmv_obd *lmv;
int i = mds->mds_num;
-
+ char peer_str[PTL_NALFMT_SIZE];
if (flags & REC_REINT_CREATE) {
i = mds->mds_num;
+ } else if (mds->mds_md_exp != NULL && peer != NULL) {
+ LASSERT(parent != NULL);
+ /* distribute only at root level */
+ lmv = &mds->mds_md_exp->exp_obd->u.lmv;
+ if (parent->i_ino != id_ino(&mds->mds_rootid)) {
+ i = mds->mds_num;
+ } else {
+ __u64 nid = peer->peer_id.nid;
+ __u64 count = lmv->desc.ld_tgt_count;
+ i = do_div(nid, count);
+ CWARN("client from %s creates top dir %*s on mds #%d\n",
+ ptlrpc_peernid2str(peer, peer_str), len, name, i);
+ }
} else if (mds->mds_md_exp) {
lmv = &mds->mds_md_exp->exp_obd->u.lmv;
i = raw_name2idx(MEA_MAGIC_LAST_CHAR, lmv->desc.ld_tgt_count, name, len);
* new directory's inode in.
*/
i = mds_choose_mdsnum(obd, rec->ur_name, rec->ur_namelen - 1,
- rec->ur_flags);
+ rec->ur_flags, &req->rq_peer, dir);
if (i == mds->mds_num) {
/* inode will be created locally */
handle = fsfilt_start(obd, dir, FSFILT_OP_MKDIR, NULL);