- return e;
-}
-
-void idmap_free_entry(struct mds_idmap_entry *e)
-{
- if (!list_empty(&e->rmt_hash))
- list_del(&e->rmt_hash);
- if (!list_empty(&e->lcl_hash))
- list_del(&e->lcl_hash);
- OBD_FREE(e, sizeof(*e));
-}
-
-static
-int idmap_insert_entry(struct list_head *rmt_hash, struct list_head *lcl_hash,
- struct mds_idmap_entry *new, const char *warn_msg)
-{
- struct list_head *rmt_head = &rmt_hash[MDS_IDMAP_HASHFUNC(new->rmt_id)];
- struct list_head *lcl_head = &lcl_hash[MDS_IDMAP_HASHFUNC(new->lcl_id)];
- struct mds_idmap_entry *e;
-
- list_for_each_entry(e, rmt_head, rmt_hash) {
- if (e->rmt_id == new->rmt_id &&
- e->lcl_id == new->lcl_id) {
- atomic_inc(&e->refcount);
- return 1;
- }
- if (e->rmt_id == new->rmt_id && warn_msg)
- CWARN("%s: rmt id %u already map to %u (new %u)\n",
- warn_msg, e->rmt_id, e->lcl_id, new->lcl_id);
- if (e->lcl_id == new->lcl_id && warn_msg)
- CWARN("%s: lcl id %u already be mapped from %u "
- "(new %u)\n", warn_msg,
- e->lcl_id, e->rmt_id, new->rmt_id);
- }
-
- list_add_tail(rmt_head, &new->rmt_hash);
- list_add_tail(lcl_head, &new->lcl_hash);
- return 0;
-}
-
-static
-int idmap_remove_entry(struct list_head *rmt_hash, struct list_head *lcl_hash,
- __u32 rmt_id, __u32 lcl_id)
-{
- struct list_head *rmt_head = &rmt_hash[MDS_IDMAP_HASHFUNC(rmt_id)];
- struct mds_idmap_entry *e;
-
- list_for_each_entry(e, rmt_head, rmt_hash) {
- if (e->rmt_id == rmt_id && e->lcl_id == lcl_id) {
- if (atomic_dec_and_test(&e->refcount)) {
- list_del(&e->rmt_hash);
- list_del(&e->lcl_hash);
- OBD_FREE(e, sizeof(*e));
- return 0;
- } else
- return 1;
- }
- }
- return -ENOENT;
-}
-
-int mds_idmap_add(struct mds_idmap_table *tbl,
- uid_t rmt_uid, uid_t lcl_uid,
- gid_t rmt_gid, gid_t lcl_gid)
-{
- struct mds_idmap_entry *ue, *ge;
- ENTRY;
-
- if (!tbl)
- RETURN(-EPERM);
-
- ue = idmap_alloc_entry(rmt_uid, lcl_uid);
- if (!ue)
- RETURN(-ENOMEM);
- ge = idmap_alloc_entry(rmt_gid, lcl_gid);
- if (!ge) {
- idmap_free_entry(ue);
- RETURN(-ENOMEM);
- }
-
- spin_lock(&tbl->mit_lock);
-
- if (idmap_insert_entry(tbl->mit_idmaps[MDS_RMT_UIDMAP_IDX],
- tbl->mit_idmaps[MDS_LCL_UIDMAP_IDX],
- ue, "UID mapping")) {
- idmap_free_entry(ue);
- }
-
- if (idmap_insert_entry(tbl->mit_idmaps[MDS_RMT_GIDMAP_IDX],
- tbl->mit_idmaps[MDS_LCL_GIDMAP_IDX],
- ge, "GID mapping")) {
- idmap_free_entry(ge);
- }
-
- spin_unlock(&tbl->mit_lock);
- RETURN(0);
-}
-
-int mds_idmap_del(struct mds_idmap_table *tbl,
- uid_t rmt_uid, uid_t lcl_uid,
- gid_t rmt_gid, gid_t lcl_gid)
-{
- ENTRY;
-
- if (!tbl)
- RETURN(0);
-
- spin_lock(&tbl->mit_lock);
- idmap_remove_entry(tbl->mit_idmaps[MDS_RMT_UIDMAP_IDX],
- tbl->mit_idmaps[MDS_LCL_UIDMAP_IDX],
- rmt_uid, lcl_uid);
- idmap_remove_entry(tbl->mit_idmaps[MDS_RMT_GIDMAP_IDX],
- tbl->mit_idmaps[MDS_LCL_GIDMAP_IDX],
- rmt_gid, lcl_gid);
- spin_unlock(&tbl->mit_lock);
- RETURN(0);
-}
-
-static
-__u32 idmap_lookup_id(struct list_head *hash, int reverse, __u32 id)
-{
- struct list_head *head = &hash[MDS_IDMAP_HASHFUNC(id)];
- struct mds_idmap_entry *e;
-
- if (!reverse) {
- list_for_each_entry(e, head, rmt_hash) {
- if (e->rmt_id == id)
- return e->lcl_id;
- }
- return MDS_IDMAP_NOTFOUND;
- } else {
- list_for_each_entry(e, head, lcl_hash) {
- if (e->lcl_id == id)
- return e->rmt_id;
- }
- return MDS_IDMAP_NOTFOUND;
- }
-}
-
-int mds_idmap_lookup_uid(struct mds_idmap_table *tbl, int reverse, uid_t uid)
-{
- struct list_head *hash;
-
- if (!tbl)
- return MDS_IDMAP_NOTFOUND;
-
- if (!reverse)
- hash = tbl->mit_idmaps[MDS_RMT_UIDMAP_IDX];
- else
- hash = tbl->mit_idmaps[MDS_LCL_UIDMAP_IDX];
-
- spin_lock(&tbl->mit_lock);
- uid = idmap_lookup_id(hash, reverse, uid);
- spin_unlock(&tbl->mit_lock);
-
- return uid;
-}
-
-int mds_idmap_lookup_gid(struct mds_idmap_table *tbl, int reverse, gid_t gid)
-{
- struct list_head *hash;
-
- if (!tbl)
- return MDS_IDMAP_NOTFOUND;
-
- if (!reverse)
- hash = tbl->mit_idmaps[MDS_RMT_GIDMAP_IDX];
- else
- hash = tbl->mit_idmaps[MDS_LCL_GIDMAP_IDX];
-
- spin_lock(&tbl->mit_lock);
- gid = idmap_lookup_id(hash, reverse, gid);
- spin_unlock(&tbl->mit_lock);
-
- return gid;
-}
-
-struct mds_idmap_table *mds_idmap_alloc()
-{
- struct mds_idmap_table *tbl;
- int i, j;
-
- OBD_ALLOC(tbl, sizeof(*tbl));
- if (!tbl)
- return NULL;
-
- spin_lock_init(&tbl->mit_lock);
- for (i = 0; i < MDS_IDMAP_N_HASHES; i++)
- for (j = 0; j < MDS_IDMAP_HASHSIZE; j++)
- INIT_LIST_HEAD(&tbl->mit_idmaps[i][j]);
-
- return tbl;
-}
-
-static void idmap_clear_rmt_hash(struct list_head *list)
-{
- struct mds_idmap_entry *e;
- int i;
-
- for (i = 0; i < MDS_IDMAP_HASHSIZE; i++) {
- while (!list_empty(&list[i])) {
- e = list_entry(list[i].next, struct mds_idmap_entry,
- rmt_hash);
- idmap_free_entry(e);
- }
- }
-}
-
-void mds_idmap_free(struct mds_idmap_table *tbl)
-{
- int i;
-
- spin_lock(&tbl->mit_lock);
- idmap_clear_rmt_hash(tbl->mit_idmaps[MDS_RMT_UIDMAP_IDX]);
- idmap_clear_rmt_hash(tbl->mit_idmaps[MDS_RMT_GIDMAP_IDX]);
-
- /* paranoid checking */
- for (i = 0; i < MDS_IDMAP_HASHSIZE; i++) {
- LASSERT(list_empty(&tbl->mit_idmaps[MDS_LCL_UIDMAP_IDX][i]));
- LASSERT(list_empty(&tbl->mit_idmaps[MDS_LCL_GIDMAP_IDX][i]));
- }
- spin_unlock(&tbl->mit_lock);
-
- OBD_FREE(tbl, sizeof(*tbl));
-}
-
-/*********************************
- * helpers doing mapping for MDS *
- *********************************/
-
-/*
- * we allow remote setuid/setgid to an "authencated" one,
- * this policy probably change later.
- */
-static
-int mds_req_secdesc_do_map(struct mds_export_data *med,
- struct mds_req_sec_desc *rsd)
-{
- struct mds_idmap_table *idmap = med->med_idmap;
- uid_t uid, fsuid;
- gid_t gid, fsgid;
-
- uid = mds_idmap_lookup_uid(idmap, 0, rsd->rsd_uid);
- if (uid == MDS_IDMAP_NOTFOUND) {
- CERROR("can't find map for uid %u\n", rsd->rsd_uid);
- return -EPERM;
- }
-
- if (rsd->rsd_uid == rsd->rsd_fsuid)
- fsuid = uid;
- else {
- fsuid = mds_idmap_lookup_uid(idmap, 0, rsd->rsd_fsuid);
- if (fsuid == MDS_IDMAP_NOTFOUND) {
- CERROR("can't find map for fsuid %u\n", rsd->rsd_fsuid);
- return -EPERM;
- }
- }
-
- gid = mds_idmap_lookup_gid(idmap, 0, rsd->rsd_gid);
- if (gid == MDS_IDMAP_NOTFOUND) {
- CERROR("can't find map for gid %u\n", rsd->rsd_gid);
- return -EPERM;
- }
-
- if (rsd->rsd_gid == rsd->rsd_fsgid)
- fsgid = gid;
- else {
- fsgid = mds_idmap_lookup_gid(idmap, 0, rsd->rsd_fsgid);
- if (fsgid == MDS_IDMAP_NOTFOUND) {
- CERROR("can't find map for fsgid %u\n", rsd->rsd_fsgid);
- return -EPERM;
- }
- }
-
- rsd->rsd_uid = uid;
- rsd->rsd_gid = gid;
- rsd->rsd_fsuid = fsuid;
- rsd->rsd_fsgid = fsgid;
-
- return 0;
-}
-
-void mds_body_do_reverse_map(struct mds_export_data *med,
- struct mds_body *body)
-{
- uid_t uid;
- gid_t gid;
-
- if (!med->med_remote)
- return;
-
- ENTRY;
- if (body->valid & OBD_MD_FLUID) {
- uid = mds_idmap_lookup_uid(med->med_idmap, 1, body->uid);
- if (uid == MDS_IDMAP_NOTFOUND) {
- uid = med->med_nllu;
- if (body->valid & OBD_MD_FLMODE) {
- body->mode = (body->mode & ~S_IRWXU) |
- ((body->mode & S_IRWXO) << 6);
- }
- }
- body->uid = uid;
- }
- if (body->valid & OBD_MD_FLGID) {
- gid = mds_idmap_lookup_gid(med->med_idmap, 1, body->gid);
- if (gid == MDS_IDMAP_NOTFOUND) {
- gid = med->med_nllg;
- if (body->valid & OBD_MD_FLMODE) {
- body->mode = (body->mode & ~S_IRWXG) |
- ((body->mode & S_IRWXO) << 3);
- }
- }
- body->gid = gid;
- }
-
- EXIT;