X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fmdt%2Fmdt_lib.c;h=051421bbd0303bbd4134808e95b1e28e9a7e3d58;hp=36c235e5ae767768fc35440bdb2492d8c2c07448;hb=f4547f0569774eb794fb143362e201f658415f4c;hpb=6869932b552ac705f411de3362f01bd50c1f6f7d diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index 36c235e..051421bb 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,8 +24,10 @@ * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2011, 2012, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -46,13 +46,10 @@ * Author: Fan Yong */ - -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif #define DEBUG_SUBSYSTEM S_MDS #include "mdt_internal.h" +#include typedef enum ucred_init_type { @@ -63,41 +60,80 @@ typedef enum ucred_init_type { void mdt_exit_ucred(struct mdt_thread_info *info) { - struct md_ucred *uc = mdt_ucred(info); - struct mdt_device *mdt = info->mti_mdt; - - if (uc->mu_valid != UCRED_INIT) { - uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1; - if (uc->mu_ginfo) { - groups_free(uc->mu_ginfo); - uc->mu_ginfo = NULL; - } - if (uc->mu_identity) { - mdt_identity_put(mdt->mdt_identity_cache, - uc->mu_identity); - uc->mu_identity = NULL; - } - uc->mu_valid = UCRED_INIT; - } + struct lu_ucred *uc = mdt_ucred(info); + struct mdt_device *mdt = info->mti_mdt; + + LASSERT(uc != NULL); + if (uc->uc_valid != UCRED_INIT) { + uc->uc_suppgids[0] = uc->uc_suppgids[1] = -1; + if (uc->uc_ginfo) { + cfs_put_group_info(uc->uc_ginfo); + uc->uc_ginfo = NULL; + } + if (uc->uc_identity) { + mdt_identity_put(mdt->mdt_identity_cache, + uc->uc_identity); + uc->uc_identity = NULL; + } + uc->uc_valid = UCRED_INIT; + } } -/* XXX: root_squash will be redesigned in Lustre 1.7. - * Do not root_squash for inter-MDS operations */ -static int mdt_root_squash(struct mdt_thread_info *info) +static int match_nosquash_list(struct rw_semaphore *sem, + cfs_list_t *nidlist, + lnet_nid_t peernid) { - return 0; + int rc; + ENTRY; + down_read(sem); + rc = cfs_match_nid(peernid, nidlist); + up_read(sem); + RETURN(rc); +} + +/* root_squash for inter-MDS operations */ +static int mdt_root_squash(struct mdt_thread_info *info, lnet_nid_t peernid) +{ + struct lu_ucred *ucred = mdt_ucred(info); + ENTRY; + + LASSERT(ucred != NULL); + if (!info->mti_mdt->mdt_squash_uid || ucred->uc_fsuid) + RETURN(0); + + if (match_nosquash_list(&info->mti_mdt->mdt_squash_sem, + &info->mti_mdt->mdt_nosquash_nids, + peernid)) { + CDEBUG(D_OTHER, "%s is in nosquash_nids list\n", + libcfs_nid2str(peernid)); + RETURN(0); + } + + CDEBUG(D_OTHER, "squash req from %s, (%d:%d/%x)=>(%d:%d/%x)\n", + libcfs_nid2str(peernid), + ucred->uc_fsuid, ucred->uc_fsgid, ucred->uc_cap, + info->mti_mdt->mdt_squash_uid, info->mti_mdt->mdt_squash_gid, + 0); + + ucred->uc_fsuid = info->mti_mdt->mdt_squash_uid; + ucred->uc_fsgid = info->mti_mdt->mdt_squash_gid; + ucred->uc_cap = 0; + ucred->uc_suppgids[0] = -1; + ucred->uc_suppgids[1] = -1; + + RETURN(0); } static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, void *buf) { struct ptlrpc_request *req = mdt_info_req(info); - struct mdt_export_data *med = mdt_req2med(req); struct mdt_device *mdt = info->mti_mdt; struct ptlrpc_user_desc *pud = req->rq_user_desc; - struct md_ucred *ucred = mdt_ucred(info); + struct lu_ucred *ucred = mdt_ucred(info); lnet_nid_t peernid = req->rq_peer.nid; __u32 perm = 0; + __u32 remote = exp_connect_rmtclient(info->mti_exp); int setuid; int setgid; int rc = 0; @@ -107,23 +143,24 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, LASSERT(req->rq_auth_gss); LASSERT(!req->rq_auth_usr_mdt); LASSERT(req->rq_user_desc); - - ucred->mu_valid = UCRED_INVALID; + LASSERT(ucred != NULL); - ucred->mu_o_uid = pud->pud_uid; - ucred->mu_o_gid = pud->pud_gid; - ucred->mu_o_fsuid = pud->pud_fsuid; - ucred->mu_o_fsgid = pud->pud_fsgid; + ucred->uc_valid = UCRED_INVALID; - if (type == BODY_INIT) { - struct mdt_body *body = (struct mdt_body *)buf; + ucred->uc_o_uid = pud->pud_uid; + ucred->uc_o_gid = pud->pud_gid; + ucred->uc_o_fsuid = pud->pud_fsuid; + ucred->uc_o_fsgid = pud->pud_fsgid; - ucred->mu_suppgids[0] = body->suppgid; - ucred->mu_suppgids[1] = -1; - } + if (type == BODY_INIT) { + struct mdt_body *body = (struct mdt_body *)buf; + + ucred->uc_suppgids[0] = body->suppgid; + ucred->uc_suppgids[1] = -1; + } /* sanity check: we expect the uid which client claimed is true */ - if (med->med_rmtclient) { + if (remote) { if (req->rq_auth_mapped_uid == INVALID_UID) { CDEBUG(D_SEC, "remote user not mapped, deny access!\n"); RETURN(-EACCES); @@ -153,12 +190,12 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, } if (is_identity_get_disabled(mdt->mdt_identity_cache)) { - if (med->med_rmtclient) { + if (remote) { CDEBUG(D_SEC, "remote client must run with identity_get " "enabled!\n"); RETURN(-EACCES); } else { - ucred->mu_identity = NULL; + ucred->uc_identity = NULL; perm = CFS_SETUID_PERM | CFS_SETGID_PERM | CFS_SETGRP_PERM; } @@ -169,8 +206,8 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, pud->pud_uid); if (IS_ERR(identity)) { if (unlikely(PTR_ERR(identity) == -EREMCHG && - !med->med_rmtclient)) { - ucred->mu_identity = NULL; + !remote)) { + ucred->uc_identity = NULL; perm = CFS_SETUID_PERM | CFS_SETGID_PERM | CFS_SETGRP_PERM; } else { @@ -179,18 +216,17 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, RETURN(-EACCES); } } else { - ucred->mu_identity = identity; - perm = mdt_identity_get_perm(ucred->mu_identity, - med->med_rmtclient, - peernid); + ucred->uc_identity = identity; + perm = mdt_identity_get_perm(ucred->uc_identity, + remote, peernid); } } /* find out the setuid/setgid attempt */ setuid = (pud->pud_uid != pud->pud_fsuid); - setgid = ((pud->pud_gid != pud->pud_fsgid) || - (ucred->mu_identity && - (pud->pud_gid != ucred->mu_identity->mi_gid))); + setgid = ((pud->pud_gid != pud->pud_fsgid) || + (ucred->uc_identity && + (pud->pud_gid != ucred->uc_identity->mi_gid))); /* check permission of setuid */ if (setuid && !(perm & CFS_SETUID_PERM)) { @@ -201,96 +237,100 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, /* check permission of setgid */ if (setgid && !(perm & CFS_SETGID_PERM)) { - CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) " - "from %s\n", pud->pud_uid, pud->pud_gid, - pud->pud_fsuid, pud->pud_fsgid, - ucred->mu_identity->mi_gid, libcfs_nid2str(peernid)); - GOTO(out, rc = -EACCES); + CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) " + "from %s\n", pud->pud_uid, pud->pud_gid, + pud->pud_fsuid, pud->pud_fsgid, + ucred->uc_identity->mi_gid, libcfs_nid2str(peernid)); + GOTO(out, rc = -EACCES); } /* * NB: remote client not allowed to setgroups anyway. */ - if (!med->med_rmtclient && perm & CFS_SETGRP_PERM) { - if (pud->pud_ngroups) { - /* setgroups for local client */ - ucred->mu_ginfo = groups_alloc(pud->pud_ngroups); - if (!ucred->mu_ginfo) { - CERROR("failed to alloc %d groups\n", - pud->pud_ngroups); - GOTO(out, rc = -ENOMEM); - } - - lustre_groups_from_list(ucred->mu_ginfo, - pud->pud_groups); - lustre_groups_sort(ucred->mu_ginfo); - } else { - ucred->mu_ginfo = NULL; - } - } else { - ucred->mu_suppgids[0] = -1; - ucred->mu_suppgids[1] = -1; - ucred->mu_ginfo = NULL; - } - - ucred->mu_uid = pud->pud_uid; - ucred->mu_gid = pud->pud_gid; - ucred->mu_fsuid = pud->pud_fsuid; - ucred->mu_fsgid = pud->pud_fsgid; - - /* XXX: need to process root_squash here. */ - mdt_root_squash(info); - - /* remove fs privilege for non-root user */ - if (ucred->mu_fsuid) - ucred->mu_cap = pud->pud_cap & ~CAP_FS_MASK; - else - ucred->mu_cap = pud->pud_cap; - ucred->mu_valid = UCRED_NEW; - - EXIT; + if (!remote && perm & CFS_SETGRP_PERM) { + if (pud->pud_ngroups) { + /* setgroups for local client */ + ucred->uc_ginfo = cfs_groups_alloc(pud->pud_ngroups); + if (!ucred->uc_ginfo) { + CERROR("failed to alloc %d groups\n", + pud->pud_ngroups); + GOTO(out, rc = -ENOMEM); + } + + lustre_groups_from_list(ucred->uc_ginfo, + pud->pud_groups); + lustre_groups_sort(ucred->uc_ginfo); + } else { + ucred->uc_ginfo = NULL; + } + } else { + ucred->uc_suppgids[0] = -1; + ucred->uc_suppgids[1] = -1; + ucred->uc_ginfo = NULL; + } + + ucred->uc_uid = pud->pud_uid; + ucred->uc_gid = pud->pud_gid; + ucred->uc_fsuid = pud->pud_fsuid; + ucred->uc_fsgid = pud->pud_fsgid; + + /* process root_squash here. */ + mdt_root_squash(info, peernid); + + /* remove fs privilege for non-root user. */ + if (ucred->uc_fsuid) + ucred->uc_cap = pud->pud_cap & ~CFS_CAP_FS_MASK; + else + ucred->uc_cap = pud->pud_cap; + if (remote && !(perm & CFS_RMTOWN_PERM)) + ucred->uc_cap &= ~(CFS_CAP_SYS_RESOURCE_MASK | + CFS_CAP_CHOWN_MASK); + ucred->uc_valid = UCRED_NEW; + + EXIT; out: - if (rc) { - if (ucred->mu_ginfo) { - groups_free(ucred->mu_ginfo); - ucred->mu_ginfo = NULL; - } - if (ucred->mu_identity) { - mdt_identity_put(mdt->mdt_identity_cache, - ucred->mu_identity); - ucred->mu_identity = NULL; - } - } - - return rc; + if (rc) { + if (ucred->uc_ginfo) { + cfs_put_group_info(ucred->uc_ginfo); + ucred->uc_ginfo = NULL; + } + if (ucred->uc_identity) { + mdt_identity_put(mdt->mdt_identity_cache, + ucred->uc_identity); + ucred->uc_identity = NULL; + } + } + + return rc; } int mdt_check_ucred(struct mdt_thread_info *info) { struct ptlrpc_request *req = mdt_info_req(info); - struct mdt_export_data *med = mdt_req2med(req); struct mdt_device *mdt = info->mti_mdt; struct ptlrpc_user_desc *pud = req->rq_user_desc; - struct md_ucred *ucred = mdt_ucred(info); + struct lu_ucred *ucred = mdt_ucred(info); struct md_identity *identity = NULL; lnet_nid_t peernid = req->rq_peer.nid; __u32 perm = 0; + __u32 remote = exp_connect_rmtclient(info->mti_exp); int setuid; int setgid; int rc = 0; ENTRY; - if ((ucred->mu_valid == UCRED_OLD) || (ucred->mu_valid == UCRED_NEW)) - RETURN(0); + LASSERT(ucred != NULL); + if ((ucred->uc_valid == UCRED_OLD) || (ucred->uc_valid == UCRED_NEW)) + RETURN(0); if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc) RETURN(0); /* sanity check: if we use strong authentication, we expect the * uid which client claimed is true */ - if (med->med_rmtclient) { + if (remote) { if (req->rq_auth_mapped_uid == INVALID_UID) { CDEBUG(D_SEC, "remote user not mapped, deny access!\n"); RETURN(-EACCES); @@ -320,7 +360,7 @@ int mdt_check_ucred(struct mdt_thread_info *info) } if (is_identity_get_disabled(mdt->mdt_identity_cache)) { - if (med->med_rmtclient) { + if (remote) { CDEBUG(D_SEC, "remote client must run with identity_get " "enabled!\n"); RETURN(-EACCES); @@ -331,7 +371,7 @@ int mdt_check_ucred(struct mdt_thread_info *info) identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid); if (IS_ERR(identity)) { if (unlikely(PTR_ERR(identity) == -EREMCHG && - !med->med_rmtclient)) { + !remote)) { RETURN(0); } else { CDEBUG(D_SEC, "Deny access without identity: uid %u\n", @@ -340,7 +380,7 @@ int mdt_check_ucred(struct mdt_thread_info *info) } } - perm = mdt_identity_get_perm(identity, med->med_rmtclient, peernid); + perm = mdt_identity_get_perm(identity, remote, peernid); /* find out the setuid/setgid attempt */ setuid = (pud->pud_uid != pud->pud_fsuid); setgid = (pud->pud_gid != pud->pud_fsgid || @@ -370,95 +410,98 @@ out: } static int old_init_ucred(struct mdt_thread_info *info, - struct mdt_body *body) + struct mdt_body *body) { - struct md_ucred *uc = mdt_ucred(info); - struct mdt_device *mdt = info->mti_mdt; - struct md_identity *identity = NULL; - - ENTRY; - - uc->mu_valid = UCRED_INVALID; - uc->mu_o_uid = uc->mu_uid = body->uid; - uc->mu_o_gid = uc->mu_gid = body->gid; - uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid; - uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid; - uc->mu_suppgids[0] = body->suppgid; - uc->mu_suppgids[1] = -1; - uc->mu_ginfo = NULL; - if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { - identity = mdt_identity_get(mdt->mdt_identity_cache, - uc->mu_fsuid); - if (IS_ERR(identity)) { - if (unlikely(PTR_ERR(identity) == -EREMCHG)) { - identity = NULL; - } else { - CDEBUG(D_SEC, "Deny access without identity: " - "uid %u\n", uc->mu_fsuid); - RETURN(-EACCES); - } - } - } - uc->mu_identity = identity; - - /* XXX: need to process root_squash here. */ - mdt_root_squash(info); - - /* remove fs privilege for non-root user */ - if (uc->mu_fsuid) - uc->mu_cap = body->capability & ~CAP_FS_MASK; - else - uc->mu_cap = body->capability; - uc->mu_valid = UCRED_OLD; - - RETURN(0); + struct lu_ucred *uc = mdt_ucred(info); + struct mdt_device *mdt = info->mti_mdt; + struct md_identity *identity = NULL; + + ENTRY; + + LASSERT(uc != NULL); + uc->uc_valid = UCRED_INVALID; + uc->uc_o_uid = uc->uc_uid = body->uid; + uc->uc_o_gid = uc->uc_gid = body->gid; + uc->uc_o_fsuid = uc->uc_fsuid = body->fsuid; + uc->uc_o_fsgid = uc->uc_fsgid = body->fsgid; + uc->uc_suppgids[0] = body->suppgid; + uc->uc_suppgids[1] = -1; + uc->uc_ginfo = NULL; + if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { + identity = mdt_identity_get(mdt->mdt_identity_cache, + uc->uc_fsuid); + if (IS_ERR(identity)) { + if (unlikely(PTR_ERR(identity) == -EREMCHG)) { + identity = NULL; + } else { + CDEBUG(D_SEC, "Deny access without identity: " + "uid %u\n", uc->uc_fsuid); + RETURN(-EACCES); + } + } + } + uc->uc_identity = identity; + + /* process root_squash here. */ + mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); + + /* remove fs privilege for non-root user. */ + if (uc->uc_fsuid) + uc->uc_cap = body->capability & ~CFS_CAP_FS_MASK; + else + uc->uc_cap = body->capability; + uc->uc_valid = UCRED_OLD; + + RETURN(0); } static int old_init_ucred_reint(struct mdt_thread_info *info) { - struct md_ucred *uc = mdt_ucred(info); - struct mdt_device *mdt = info->mti_mdt; - struct md_identity *identity = NULL; - - ENTRY; - - uc->mu_valid = UCRED_INVALID; - uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid; - uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid; - uc->mu_ginfo = NULL; - if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { - identity = mdt_identity_get(mdt->mdt_identity_cache, - uc->mu_fsuid); - if (IS_ERR(identity)) { - if (unlikely(PTR_ERR(identity) == -EREMCHG)) { - identity = NULL; - } else { - CDEBUG(D_SEC, "Deny access without identity: " - "uid %u\n", uc->mu_fsuid); - RETURN(-EACCES); - } - } - } - uc->mu_identity = identity; - - /* XXX: need to process root_squash here. */ - mdt_root_squash(info); - - /* remove fs privilege for non-root user */ - if (uc->mu_fsuid) - uc->mu_cap &= ~CAP_FS_MASK; - uc->mu_valid = UCRED_OLD; - - RETURN(0); + struct lu_ucred *uc = mdt_ucred(info); + struct mdt_device *mdt = info->mti_mdt; + struct md_identity *identity = NULL; + + ENTRY; + + LASSERT(uc != NULL); + uc->uc_valid = UCRED_INVALID; + uc->uc_o_uid = uc->uc_o_fsuid = uc->uc_uid = uc->uc_fsuid; + uc->uc_o_gid = uc->uc_o_fsgid = uc->uc_gid = uc->uc_fsgid; + uc->uc_ginfo = NULL; + if (!is_identity_get_disabled(mdt->mdt_identity_cache)) { + identity = mdt_identity_get(mdt->mdt_identity_cache, + uc->uc_fsuid); + if (IS_ERR(identity)) { + if (unlikely(PTR_ERR(identity) == -EREMCHG)) { + identity = NULL; + } else { + CDEBUG(D_SEC, "Deny access without identity: " + "uid %u\n", uc->uc_fsuid); + RETURN(-EACCES); + } + } + } + uc->uc_identity = identity; + + /* process root_squash here. */ + mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid); + + /* remove fs privilege for non-root user. */ + if (uc->uc_fsuid) + uc->uc_cap &= ~CFS_CAP_FS_MASK; + uc->uc_valid = UCRED_OLD; + + RETURN(0); } int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body) { struct ptlrpc_request *req = mdt_info_req(info); - struct md_ucred *uc = mdt_ucred(info); + struct lu_ucred *uc = mdt_ucred(info); - if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW)) - return 0; + LASSERT(uc != NULL); + if ((uc->uc_valid == UCRED_OLD) || (uc->uc_valid == UCRED_NEW)) + return 0; mdt_exit_ucred(info); @@ -471,10 +514,11 @@ int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body) int mdt_init_ucred_reint(struct mdt_thread_info *info) { struct ptlrpc_request *req = mdt_info_req(info); - struct md_ucred *uc = mdt_ucred(info); + struct lu_ucred *uc = mdt_ucred(info); - if ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW)) - return 0; + LASSERT(uc != NULL); + if ((uc->uc_valid == UCRED_OLD) || (uc->uc_valid == UCRED_NEW)) + return 0; mdt_exit_ucred(info); @@ -488,31 +532,34 @@ int mdt_init_ucred_reint(struct mdt_thread_info *info) void mdt_dump_lmm(int level, const struct lov_mds_md *lmm) { const struct lov_ost_data_v1 *lod; - int i; - __s16 stripe_count = - le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count); + int i; + __u16 count; + + count = le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count); CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n", le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic), le32_to_cpu(lmm->lmm_pattern)); CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n", - le32_to_cpu(lmm->lmm_stripe_size), - le32_to_cpu(lmm->lmm_stripe_count)); - LASSERT(stripe_count <= (__s16)LOV_MAX_STRIPE_COUNT); - for (i = 0, lod = lmm->lmm_objects; i < stripe_count; i++, lod++) { + le32_to_cpu(lmm->lmm_stripe_size), count); + if (count == LOV_ALL_STRIPES) + return; + LASSERT(count <= LOV_MAX_STRIPE_COUNT); + for (i = 0, lod = lmm->lmm_objects; i < count; i++, lod++) CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n", i, le32_to_cpu(lod->l_ost_idx), - le64_to_cpu(lod->l_object_gr), + le64_to_cpu(lod->l_object_seq), le64_to_cpu(lod->l_object_id)); - } } -void mdt_shrink_reply(struct mdt_thread_info *info) +/* Shrink and/or grow reply buffers */ +int mdt_fix_reply(struct mdt_thread_info *info) { struct req_capsule *pill = info->mti_pill; struct mdt_body *body; - int md_size; + int md_size, md_packed = 0; int acl_size; + int rc = 0; ENTRY; body = req_capsule_server_get(pill, &RMF_MDT_BODY); @@ -525,11 +572,17 @@ void mdt_shrink_reply(struct mdt_thread_info *info) acl_size = body->aclsize; - CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d" - " MDSCAPA = "LPX64", OSSCAPA = "LPX64"\n", + /* this replay - not send info to client */ + if (info->mti_spec.no_create) { + md_size = 0; + acl_size = 0; + } + + CDEBUG(D_INFO, "Shrink to md_size = %d cookie/acl_size = %d" + " MDSCAPA = %llx, OSSCAPA = %llx\n", md_size, acl_size, - body->valid & OBD_MD_FLMDSCAPA, - body->valid & OBD_MD_FLOSSCAPA); + (unsigned long long)(body->valid & OBD_MD_FLMDSCAPA), + (unsigned long long)(body->valid & OBD_MD_FLOSSCAPA)); /* &RMF_MDT_BODY, &RMF_MDT_MD, @@ -539,28 +592,74 @@ void mdt_shrink_reply(struct mdt_thread_info *info) (optional) something else */ - if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER)) - req_capsule_shrink(pill, &RMF_MDT_MD, md_size, - RCL_SERVER); + /* MDT_MD buffer may be bigger than packed value, let's shrink all + * buffers before growing it */ + if (info->mti_big_lmm_used) { + LASSERT(req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER)); + md_packed = req_capsule_get_size(pill, &RMF_MDT_MD, + RCL_SERVER); + LASSERT(md_packed > 0); + /* buffer must be allocated separately */ + LASSERT(info->mti_attr.ma_lmm != + req_capsule_server_get(pill, &RMF_MDT_MD)); + req_capsule_shrink(pill, &RMF_MDT_MD, 0, RCL_SERVER); + /* free big lmm if md_size is not needed */ + if (md_size == 0) + info->mti_big_lmm_used = 0; + } else if (req_capsule_has_field(pill, &RMF_MDT_MD, RCL_SERVER)) { + req_capsule_shrink(pill, &RMF_MDT_MD, md_size, RCL_SERVER); + } + if (req_capsule_has_field(pill, &RMF_ACL, RCL_SERVER)) req_capsule_shrink(pill, &RMF_ACL, acl_size, RCL_SERVER); else if (req_capsule_has_field(pill, &RMF_LOGCOOKIES, RCL_SERVER)) req_capsule_shrink(pill, &RMF_LOGCOOKIES, - acl_size, RCL_SERVER); + acl_size, RCL_SERVER); if (req_capsule_has_field(pill, &RMF_CAPA1, RCL_SERVER) && - !(body->valid & OBD_MD_FLMDSCAPA)) + !(body->valid & OBD_MD_FLMDSCAPA)) req_capsule_shrink(pill, &RMF_CAPA1, 0, RCL_SERVER); if (req_capsule_has_field(pill, &RMF_CAPA2, RCL_SERVER) && - !(body->valid & OBD_MD_FLOSSCAPA)) + !(body->valid & OBD_MD_FLOSSCAPA)) req_capsule_shrink(pill, &RMF_CAPA2, 0, RCL_SERVER); /* * Some more field should be shrinked if needed. * This should be done by those who added fields to reply message. */ - EXIT; + + /* Grow MD buffer if needed finally */ + if (info->mti_big_lmm_used) { + void *lmm; + + LASSERT(md_size > md_packed); + CDEBUG(D_INFO, "Enlarge reply buffer, need extra %d bytes\n", + md_size - md_packed); + rc = req_capsule_server_grow(pill, &RMF_MDT_MD, md_size); + if (rc) { + /* we can't answer with proper LOV EA, drop flags, + * the rc is also returned so this request is + * considered as failed */ + body->valid &= ~(OBD_MD_FLDIREA | OBD_MD_FLEASIZE); + /* don't return transno along with error */ + lustre_msg_set_transno(pill->rc_req->rq_repmsg, 0); + } else { + /* now we need to pack right LOV EA */ + lmm = req_capsule_server_get(pill, &RMF_MDT_MD); + LASSERT(req_capsule_get_size(pill, &RMF_MDT_MD, + RCL_SERVER) == + info->mti_attr.ma_lmm_size); + memcpy(lmm, info->mti_attr.ma_lmm, + info->mti_attr.ma_lmm_size); + } + /* update mdt_max_mdsize so clients will be aware about that */ + if (info->mti_mdt->mdt_max_mdsize < info->mti_attr.ma_lmm_size) + info->mti_mdt->mdt_max_mdsize = + info->mti_attr.ma_lmm_size; + info->mti_big_lmm_used = 0; + } + RETURN(rc); } @@ -571,6 +670,7 @@ int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo, { struct mdt_body *repbody; const struct lu_attr *la = &ma->ma_attr; + int rc; ENTRY; repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY); @@ -580,31 +680,31 @@ int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo, mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo)); if (ma->ma_valid & MA_LOV) { - __u32 mode; - - if (mdt_object_exists(mo) < 0) - /* If it is a remote object, and we do not retrieve - * EA back unlink reg file*/ - mode = S_IFREG; - else - mode = lu_object_attr(&mo->mot_obj.mo_lu); - - LASSERT(ma->ma_lmm_size); - mdt_dump_lmm(D_INFO, ma->ma_lmm); - repbody->eadatasize = ma->ma_lmm_size; - if (S_ISREG(mode)) - repbody->valid |= OBD_MD_FLEASIZE; - else if (S_ISDIR(mode)) - repbody->valid |= OBD_MD_FLDIREA; - else - LBUG(); + CERROR("No need in LOV EA upon unlink\n"); + dump_stack(); } + repbody->eadatasize = 0; if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) { repbody->aclsize = ma->ma_cookie_size; repbody->valid |= OBD_MD_FLCOOKIE; } + if (info->mti_mdt->mdt_opts.mo_oss_capa && + info->mti_exp->exp_connect_flags & OBD_CONNECT_OSS_CAPA && + repbody->valid & OBD_MD_FLEASIZE) { + struct lustre_capa *capa; + + capa = req_capsule_server_get(info->mti_pill, &RMF_CAPA2); + LASSERT(capa); + capa->lc_opc = CAPA_OPC_OSS_DESTROY; + rc = mo_capa_get(info->mti_env, mdt_object_child(mo), capa, 0); + if (rc) + RETURN(rc); + + repbody->valid |= OBD_MD_FLOSSCAPA; + } + RETURN(0); } @@ -666,7 +766,7 @@ static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr, out |= LA_BLOCKS; if (in & ATTR_FROM_OPEN) - rr->rr_flags |= MRF_SETATTR_LOCKED; + rr->rr_flags |= MRF_OPEN_TRUNC; if (in & ATTR_ATIME_SET) out |= LA_ATIME; @@ -680,23 +780,33 @@ static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr, if (in & ATTR_ATTR_FLAG) out |= LA_FLAGS; - if (in & MDS_OPEN_OWNEROVERRIDE) - ma->ma_attr_flags |= MDS_OPEN_OWNEROVERRIDE; + if (in & ATTR_KILL_SUID) + out |= LA_KILL_SUID; + + if (in & ATTR_KILL_SGID) + out |= LA_KILL_SGID; + + if (in & MDS_OPEN_OWNEROVERRIDE) + ma->ma_attr_flags |= MDS_OWNEROVERRIDE; + + if (in & ATTR_FORCE) + ma->ma_attr_flags |= MDS_PERM_BYPASS; /*XXX need ATTR_RAW?*/ in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS| ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN| ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET| - ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE); + ATTR_ATTR_FLAG|ATTR_RAW|MDS_OPEN_OWNEROVERRIDE| + ATTR_FORCE|ATTR_KILL_SUID|ATTR_KILL_SGID); if (in != 0) - CERROR("Unknown attr bits: %#llx\n", in); + CERROR("Unknown attr bits: "LPX64"\n", in); return out; } /* unpacking */ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) { - struct md_ucred *uc = mdt_ucred(info); + struct lu_ucred *uc = mdt_ucred(info); struct md_attr *ma = &info->mti_attr; struct lu_attr *la = &ma->ma_attr; struct req_capsule *pill = info->mti_pill; @@ -709,11 +819,12 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) if (rec == NULL) RETURN(-EFAULT); - uc->mu_fsuid = rec->sa_fsuid; - uc->mu_fsgid = rec->sa_fsgid; - uc->mu_cap = rec->sa_cap; - uc->mu_suppgids[0] = rec->sa_suppgid; - uc->mu_suppgids[1] = -1; + /* This prior initialization is needed for old_init_ucred_reint() */ + uc->uc_fsuid = rec->sa_fsuid; + uc->uc_fsgid = rec->sa_fsgid; + uc->uc_cap = rec->sa_cap; + uc->uc_suppgids[0] = rec->sa_suppgid; + uc->uc_suppgids[1] = -1; rr->rr_fid1 = &rec->sa_fid; la->la_valid = mdt_attr_valid_xlate(attr_unpack(rec->sa_valid), rr, ma); @@ -728,6 +839,11 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) la->la_mtime = rec->sa_mtime; ma->ma_valid = MA_INODE; + if (rec->sa_bias & MDS_DATA_MODIFIED) + ma->ma_attr_flags |= MDS_DATA_MODIFIED; + else + ma->ma_attr_flags &= ~MDS_DATA_MODIFIED; + if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) mdt_set_capainfo(info, 0, rr->rr_fid1, req_capsule_client_get(pill, &RMF_CAPA1)); @@ -735,16 +851,17 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info) RETURN(0); } -static int mdt_epoch_unpack(struct mdt_thread_info *info) +static int mdt_ioepoch_unpack(struct mdt_thread_info *info) { struct req_capsule *pill = info->mti_pill; ENTRY; if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT)) - info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH); + info->mti_ioepoch = + req_capsule_client_get(pill, &RMF_MDT_EPOCH); else - info->mti_epoch = NULL; - RETURN(info->mti_epoch == NULL ? -EFAULT : 0); + info->mti_ioepoch = NULL; + RETURN(info->mti_ioepoch == NULL ? -EFAULT : 0); } static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) { @@ -755,12 +872,13 @@ static inline int mdt_dlmreq_unpack(struct mdt_thread_info *info) { if (info->mti_dlm_req == NULL) RETURN(-EFAULT); } - + RETURN(0); } static int mdt_setattr_unpack(struct mdt_thread_info *info) { + struct mdt_reint_record *rr = &info->mti_rr; struct md_attr *ma = &info->mti_attr; struct req_capsule *pill = info->mti_pill; int rc; @@ -771,19 +889,17 @@ static int mdt_setattr_unpack(struct mdt_thread_info *info) RETURN(rc); /* Epoch may be absent */ - mdt_epoch_unpack(info); + mdt_ioepoch_unpack(info); - ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); - if (ma->ma_lmm_size) { - ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA); - ma->ma_valid |= MA_LOV; - } - - ma->ma_cookie_size = req_capsule_get_size(pill, &RMF_LOGCOOKIES, - RCL_CLIENT); - if (ma->ma_cookie_size) { - ma->ma_cookie = req_capsule_client_get(pill, &RMF_LOGCOOKIES); - ma->ma_valid |= MA_COOKIE; + if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) { + rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA); + rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, + RCL_CLIENT); + ma->ma_lmm_size = rr->rr_eadatalen; + if (ma->ma_lmm_size > 0) { + ma->ma_lmm = (void *)rr->rr_eadata; + ma->ma_valid |= MA_LOV; + } } rc = mdt_dlmreq_unpack(info); @@ -795,16 +911,19 @@ int mdt_close_unpack(struct mdt_thread_info *info) int rc; ENTRY; - rc = mdt_epoch_unpack(info); + rc = mdt_ioepoch_unpack(info); if (rc) RETURN(rc); - RETURN(mdt_setattr_unpack_rec(info)); + rc = mdt_setattr_unpack_rec(info); + if (rc) + RETURN(rc); + RETURN(mdt_init_ucred_reint(info)); } static int mdt_create_unpack(struct mdt_thread_info *info) { - struct md_ucred *uc = mdt_ucred(info); + struct lu_ucred *uc = mdt_ucred(info); struct mdt_rec_create *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; @@ -818,11 +937,13 @@ static int mdt_create_unpack(struct mdt_thread_info *info) if (rec == NULL) RETURN(-EFAULT); - uc->mu_fsuid = rec->cr_fsuid; - uc->mu_fsgid = rec->cr_fsgid; - uc->mu_cap = rec->cr_cap; - uc->mu_suppgids[0] = rec->cr_suppgid1; - uc->mu_suppgids[1] = -1; + /* This prior initialization is needed for old_init_ucred_reint() */ + uc->uc_fsuid = rec->cr_fsuid; + uc->uc_fsgid = rec->cr_fsgid; + uc->uc_cap = rec->cr_cap; + uc->uc_suppgids[0] = rec->cr_suppgid1; + uc->uc_suppgids[1] = -1; + uc->uc_umask = rec->cr_umask; rr->rr_fid1 = &rec->cr_fid1; rr->rr_fid2 = &rec->cr_fid2; @@ -833,56 +954,22 @@ static int mdt_create_unpack(struct mdt_thread_info *info) attr->la_ctime = rec->cr_time; attr->la_mtime = rec->cr_time; attr->la_atime = rec->cr_time; - attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID | - LA_CTIME | LA_MTIME | LA_ATIME; + attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID | LA_TYPE | + LA_CTIME | LA_MTIME | LA_ATIME; memset(&sp->u, 0, sizeof(sp->u)); - sp->sp_cr_flags = rec->cr_flags; - sp->sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT); - info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF); + sp->sp_cr_flags = get_mrc_cr_flags(rec); if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) mdt_set_capainfo(info, 0, rr->rr_fid1, req_capsule_client_get(pill, &RMF_CAPA1)); mdt_set_capainfo(info, 1, rr->rr_fid2, BYPASS_CAPA); - rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); - rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; - LASSERT(rr->rr_name && rr->rr_namelen > 0); - -#ifdef CONFIG_FS_POSIX_ACL - if (sp->sp_cr_flags & MDS_CREATE_RMT_ACL) { - if (S_ISDIR(attr->la_mode)) - sp->u.sp_pfid = rr->rr_fid1; - req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL); - LASSERT(req_capsule_field_present(pill, &RMF_EADATA, - RCL_CLIENT)); - sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA); - sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA, - RCL_CLIENT); - sp->u.sp_ea.fid = rr->rr_fid1; - RETURN(0); - } -#endif - if (S_ISDIR(attr->la_mode)) { - /* pass parent fid for cross-ref cases */ - sp->u.sp_pfid = rr->rr_fid1; - if (sp->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) { - /* create salve object req, need - * unpack split ea here - */ - req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SLAVE); - LASSERT(req_capsule_field_present(pill, &RMF_EADATA, - RCL_CLIENT)); - sp->u.sp_ea.eadata = req_capsule_client_get(pill, - &RMF_EADATA); - sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, - &RMF_EADATA, - RCL_CLIENT); - sp->u.sp_ea.fid = rr->rr_fid1; - RETURN(0); - } - req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL); - } else if (S_ISLNK(attr->la_mode)) { + rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); + rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, + RCL_CLIENT) - 1; + LASSERT(rr->rr_name && rr->rr_namelen > 0); + + if (S_ISLNK(attr->la_mode)) { const char *tgt = NULL; req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM); @@ -895,13 +982,14 @@ static int mdt_create_unpack(struct mdt_thread_info *info) } else { req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL); } + rc = mdt_dlmreq_unpack(info); RETURN(rc); } static int mdt_link_unpack(struct mdt_thread_info *info) { - struct md_ucred *uc = mdt_ucred(info); + struct lu_ucred *uc = mdt_ucred(info); struct mdt_rec_link *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct mdt_reint_record *rr = &info->mti_rr; @@ -914,11 +1002,12 @@ static int mdt_link_unpack(struct mdt_thread_info *info) if (rec == NULL) RETURN(-EFAULT); - uc->mu_fsuid = rec->lk_fsuid; - uc->mu_fsgid = rec->lk_fsgid; - uc->mu_cap = rec->lk_cap; - uc->mu_suppgids[0] = rec->lk_suppgid1; - uc->mu_suppgids[1] = rec->lk_suppgid2; + /* This prior initialization is needed for old_init_ucred_reint() */ + uc->uc_fsuid = rec->lk_fsuid; + uc->uc_fsgid = rec->lk_fsgid; + uc->uc_cap = rec->lk_cap; + uc->uc_suppgids[0] = rec->lk_suppgid1; + uc->uc_suppgids[1] = rec->lk_suppgid2; attr->la_uid = rec->lk_fsuid; attr->la_gid = rec->lk_fsgid; @@ -939,9 +1028,8 @@ static int mdt_link_unpack(struct mdt_thread_info *info) if (rr->rr_name == NULL) RETURN(-EFAULT); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; - LASSERT(rr->rr_namelen > 0); - info->mti_spec.sp_ck_split = !!(rec->lk_bias & MDS_CHECK_SPLIT); - info->mti_cross_ref = !!(rec->lk_bias & MDS_CROSS_REF); + + LASSERT(rr->rr_namelen > 0); rc = mdt_dlmreq_unpack(info); RETURN(rc); @@ -949,7 +1037,7 @@ static int mdt_link_unpack(struct mdt_thread_info *info) static int mdt_unlink_unpack(struct mdt_thread_info *info) { - struct md_ucred *uc = mdt_ucred(info); + struct lu_ucred *uc = mdt_ucred(info); struct mdt_rec_unlink *rec; struct md_attr *ma = &info->mti_attr; struct lu_attr *attr = &info->mti_attr.ma_attr; @@ -963,11 +1051,12 @@ static int mdt_unlink_unpack(struct mdt_thread_info *info) if (rec == NULL) RETURN(-EFAULT); - uc->mu_fsuid = rec->ul_fsuid; - uc->mu_fsgid = rec->ul_fsgid; - uc->mu_cap = rec->ul_cap; - uc->mu_suppgids[0] = rec->ul_suppgid1; - uc->mu_suppgids[1] = -1; + /* This prior initialization is needed for old_init_ucred_reint() */ + uc->uc_fsuid = rec->ul_fsuid; + uc->uc_fsgid = rec->ul_fsgid; + uc->uc_cap = rec->ul_cap; + uc->uc_suppgids[0] = rec->ul_suppgid1; + uc->uc_suppgids[1] = -1; attr->la_uid = rec->ul_fsuid; attr->la_gid = rec->ul_fsgid; @@ -982,25 +1071,25 @@ static int mdt_unlink_unpack(struct mdt_thread_info *info) mdt_set_capainfo(info, 0, rr->rr_fid1, req_capsule_client_get(pill, &RMF_CAPA1)); - rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); - if (rr->rr_name == NULL) - RETURN(-EFAULT); - rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; - LASSERT(rr->rr_namelen > 0); - info->mti_spec.sp_ck_split = !!(rec->ul_bias & MDS_CHECK_SPLIT); - info->mti_cross_ref = !!(rec->ul_bias & MDS_CROSS_REF); + rr->rr_name = req_capsule_client_get(pill, &RMF_NAME); + rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; + if (rr->rr_name == NULL || rr->rr_namelen == 0) + RETURN(-EFAULT); + if (rec->ul_bias & MDS_VTX_BYPASS) ma->ma_attr_flags |= MDS_VTX_BYPASS; else ma->ma_attr_flags &= ~MDS_VTX_BYPASS; + info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info)); + rc = mdt_dlmreq_unpack(info); RETURN(rc); } static int mdt_rename_unpack(struct mdt_thread_info *info) { - struct md_ucred *uc = mdt_ucred(info); + struct lu_ucred *uc = mdt_ucred(info); struct mdt_rec_rename *rec; struct md_attr *ma = &info->mti_attr; struct lu_attr *attr = &info->mti_attr.ma_attr; @@ -1014,11 +1103,12 @@ static int mdt_rename_unpack(struct mdt_thread_info *info) if (rec == NULL) RETURN(-EFAULT); - uc->mu_fsuid = rec->rn_fsuid; - uc->mu_fsgid = rec->rn_fsgid; - uc->mu_cap = rec->rn_cap; - uc->mu_suppgids[0] = rec->rn_suppgid1; - uc->mu_suppgids[1] = rec->rn_suppgid2; + /* This prior initialization is needed for old_init_ucred_reint() */ + uc->uc_fsuid = rec->rn_fsuid; + uc->uc_fsgid = rec->rn_fsgid; + uc->uc_cap = rec->rn_cap; + uc->uc_suppgids[0] = rec->rn_suppgid1; + uc->uc_suppgids[1] = rec->rn_suppgid2; attr->la_uid = rec->rn_fsuid; attr->la_gid = rec->rn_fsgid; @@ -1042,23 +1132,47 @@ static int mdt_rename_unpack(struct mdt_thread_info *info) if (rr->rr_name == NULL || rr->rr_tgt == NULL) RETURN(-EFAULT); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; - LASSERT(rr->rr_namelen > 0); rr->rr_tgtlen = req_capsule_get_size(pill, &RMF_SYMTGT, RCL_CLIENT) - 1; - LASSERT(rr->rr_tgtlen > 0); - info->mti_spec.sp_ck_split = !!(rec->rn_bias & MDS_CHECK_SPLIT); - info->mti_cross_ref = !!(rec->rn_bias & MDS_CROSS_REF); + LASSERT(rr->rr_namelen > 0 && rr->rr_tgtlen > 0); + if (rec->rn_bias & MDS_VTX_BYPASS) ma->ma_attr_flags |= MDS_VTX_BYPASS; else ma->ma_attr_flags &= ~MDS_VTX_BYPASS; + info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info)); + rc = mdt_dlmreq_unpack(info); RETURN(rc); } +/* + * please see comment above LOV_MAGIC_V1_DEF + */ +static void mdt_fix_lov_magic(struct mdt_thread_info *info) +{ + struct mdt_reint_record *rr = &info->mti_rr; + struct lov_user_md_v1 *v1; + + v1 = (void *)rr->rr_eadata; + LASSERT(v1); + + if (unlikely(req_is_replay(mdt_info_req(info)))) { + if (v1->lmm_magic == LOV_USER_MAGIC_V1) { + v1->lmm_magic = LOV_MAGIC_V1_DEF; + } else if (v1->lmm_magic == __swab32(LOV_USER_MAGIC_V1)) { + v1->lmm_magic = __swab32(LOV_MAGIC_V1_DEF); + } else if (v1->lmm_magic == LOV_USER_MAGIC_V3) { + v1->lmm_magic = LOV_MAGIC_V3_DEF; + } else if (v1->lmm_magic == __swab32(LOV_USER_MAGIC_V3)) { + v1->lmm_magic = __swab32(LOV_MAGIC_V3_DEF); + } + } +} + static int mdt_open_unpack(struct mdt_thread_info *info) { - struct md_ucred *uc = mdt_ucred(info); + struct lu_ucred *uc = mdt_ucred(info); struct mdt_rec_create *rec; struct lu_attr *attr = &info->mti_attr.ma_attr; struct req_capsule *pill = info->mti_pill; @@ -1072,11 +1186,13 @@ static int mdt_open_unpack(struct mdt_thread_info *info) if (rec == NULL) RETURN(-EFAULT); - uc->mu_fsuid = rec->cr_fsuid; - uc->mu_fsgid = rec->cr_fsgid; - uc->mu_cap = rec->cr_cap; - uc->mu_suppgids[0] = rec->cr_suppgid1; - uc->mu_suppgids[1] = rec->cr_suppgid2; + /* This prior initialization is needed for old_init_ucred_reint() */ + uc->uc_fsuid = rec->cr_fsuid; + uc->uc_fsgid = rec->cr_fsgid; + uc->uc_cap = rec->cr_cap; + uc->uc_suppgids[0] = rec->cr_suppgid1; + uc->uc_suppgids[1] = rec->cr_suppgid2; + uc->uc_umask = rec->cr_umask; rr->rr_fid1 = &rec->cr_fid1; rr->rr_fid2 = &rec->cr_fid2; @@ -1091,17 +1207,19 @@ static int mdt_open_unpack(struct mdt_thread_info *info) attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID | LA_CTIME | LA_MTIME | LA_ATIME; memset(&info->mti_spec.u, 0, sizeof(info->mti_spec.u)); - info->mti_spec.sp_cr_flags = rec->cr_flags; + info->mti_spec.sp_cr_flags = get_mrc_cr_flags(rec); + /* Do not trigger ASSERTION if client miss to set such flags. */ + if (unlikely(info->mti_spec.sp_cr_flags == 0)) + RETURN(-EPROTO); info->mti_replayepoch = rec->cr_ioepoch; - info->mti_spec.sp_ck_split = !!(rec->cr_bias & MDS_CHECK_SPLIT); info->mti_cross_ref = !!(rec->cr_bias & MDS_CROSS_REF); if (req_capsule_get_size(pill, &RMF_CAPA1, RCL_CLIENT)) mdt_set_capainfo(info, 0, rr->rr_fid1, req_capsule_client_get(pill, &RMF_CAPA1)); - if ((lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) && - (req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT))) { + if (req_is_replay(req) && + req_capsule_get_size(pill, &RMF_CAPA2, RCL_CLIENT)) { #if 0 mdt_set_capainfo(info, 1, rr->rr_fid2, req_capsule_client_get(pill, &RMF_CAPA2)); @@ -1120,13 +1238,27 @@ static int mdt_open_unpack(struct mdt_thread_info *info) RETURN(-EFAULT); rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; - sp->u.sp_ea.eadatalen = req_capsule_get_size(pill, &RMF_EADATA, - RCL_CLIENT); - if (sp->u.sp_ea.eadatalen) { - sp->u.sp_ea.eadata = req_capsule_client_get(pill, &RMF_EADATA); - if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) - sp->u.sp_ea.no_lov_create = 1; - } + if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) { + rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, + RCL_CLIENT); + if (rr->rr_eadatalen > 0) { + rr->rr_eadata = req_capsule_client_get(pill, + &RMF_EADATA); + sp->u.sp_ea.eadatalen = rr->rr_eadatalen; + sp->u.sp_ea.eadata = rr->rr_eadata; + sp->no_create = !!req_is_replay(req); + mdt_fix_lov_magic(info); + } + + /* + * Client default md_size may be 0 right after client start, + * until all osc are connected, set here just some reasonable + * value to prevent misbehavior. + */ + if (rr->rr_eadatalen == 0 && + !(info->mti_spec.sp_cr_flags & MDS_OPEN_DELAY_CREATE)) + rr->rr_eadatalen = MIN_MD_SIZE; + } RETURN(0); } @@ -1134,7 +1266,7 @@ static int mdt_open_unpack(struct mdt_thread_info *info) static int mdt_setxattr_unpack(struct mdt_thread_info *info) { struct mdt_reint_record *rr = &info->mti_rr; - struct md_ucred *uc = mdt_ucred(info); + struct lu_ucred *uc = mdt_ucred(info); struct lu_attr *attr = &info->mti_attr.ma_attr; struct req_capsule *pill = info->mti_pill; struct mdt_rec_setxattr *rec; @@ -1148,11 +1280,12 @@ static int mdt_setxattr_unpack(struct mdt_thread_info *info) if (rec == NULL) RETURN(-EFAULT); - uc->mu_fsuid = rec->sx_fsuid; - uc->mu_fsgid = rec->sx_fsgid; - uc->mu_cap = rec->sx_cap; - uc->mu_suppgids[0] = rec->sx_suppgid1; - uc->mu_suppgids[1] = -1; + /* This prior initialization is needed for old_init_ucred_reint() */ + uc->uc_fsuid = rec->sx_fsuid; + uc->uc_fsgid = rec->sx_fsgid; + uc->uc_cap = rec->sx_cap; + uc->uc_suppgids[0] = rec->sx_suppgid1; + uc->uc_suppgids[1] = -1; rr->rr_opcode = rec->sx_opcode; rr->rr_fid1 = &rec->sx_fid; @@ -1173,11 +1306,20 @@ static int mdt_setxattr_unpack(struct mdt_thread_info *info) rr->rr_namelen = req_capsule_get_size(pill, &RMF_NAME, RCL_CLIENT) - 1; LASSERT(rr->rr_namelen > 0); - rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT); - if (rr->rr_eadatalen > 0) { - rr->rr_eadata = req_capsule_client_get(pill, &RMF_EADATA); - if (rr->rr_eadata == NULL) - RETURN(-EFAULT); + if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) { + rr->rr_eadatalen = req_capsule_get_size(pill, &RMF_EADATA, + RCL_CLIENT); + if (rr->rr_eadatalen > 0) { + rr->rr_eadata = req_capsule_client_get(pill, + &RMF_EADATA); + if (rr->rr_eadata == NULL) + RETURN(-EFAULT); + } else { + rr->rr_eadata = NULL; + } + } else if (!(attr->la_valid & OBD_MD_FLXATTRRM)) { + CDEBUG(D_INFO, "no xattr data supplied\n"); + RETURN(-EFAULT); } RETURN(0);