int nodemap_set_squash_projid(const char *name, projid_t projid);
int nodemap_set_audit_mode(const char *name, bool enable_audit);
int nodemap_set_forbid_encryption(const char *name, bool forbid_encryption);
-bool nodemap_can_setquota(const struct lu_nodemap *nodemap);
+bool nodemap_can_setquota(struct lu_nodemap *nodemap, __u32 qc_type, __u32 id);
int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
const __u32 map[2]);
int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
b->mbo_nlink = attr->la_nlink;
b->mbo_valid |= OBD_MD_FLNLINK;
}
- if (attr->la_valid & (LA_UID|LA_GID)) {
+ if (attr->la_valid & (LA_UID|LA_GID|LA_PROJID)) {
nodemap = nodemap_get_from_exp(exp);
if (IS_ERR(nodemap))
goto out;
}
if (attr->la_valid & LA_PROJID) {
- /* TODO, nodemap for project id */
- b->mbo_projid = attr->la_projid;
+ b->mbo_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_FS_TO_CLIENT,
+ attr->la_projid);
b->mbo_valid |= OBD_MD_FLPROJID;
}
case LUSTRE_Q_SETQUOTAPOOL:
case LUSTRE_Q_SETINFOPOOL:
case LUSTRE_Q_SETDEFAULT_POOL:
- if (!nodemap_can_setquota(nodemap))
+ if (!nodemap_can_setquota(nodemap, oqctl->qc_type,
+ oqctl->qc_id))
GOTO(out_nodemap, rc = -EPERM);
/* fallthrough */
case Q_GETINFO:
NODEMAP_CLIENT_TO_FS, id);
break;
case PRJQUOTA:
- /* todo: check/map project id */
- id = oqctl->qc_id;
+ id = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_CLIENT_TO_FS, id);
break;
default:
GOTO(out_nodemap, rc = -EOPNOTSUPP);
if (cmd == OBD_BRW_WRITE) {
struct lu_nodemap *nodemap;
- __u32 mapped_uid, mapped_gid;
+ __u32 mapped_uid, mapped_gid, mapped_projid;
nodemap = nodemap_get_from_exp(exp);
if (IS_ERR(nodemap))
mapped_gid = nodemap_map_id(nodemap, NODEMAP_GID,
NODEMAP_FS_TO_CLIENT,
oa->o_gid);
+ mapped_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_FS_TO_CLIENT,
+ oa->o_projid);
if (!IS_ERR_OR_NULL(nodemap)) {
/* do not bypass quota enforcement if squashed uid */
if (unlikely(mapped_uid == nodemap->nm_squash_uid)) {
*/
oa->o_uid = mapped_uid;
oa->o_gid = mapped_gid;
+ oa->o_projid = mapped_projid;
} else if (cmd == OBD_BRW_READ) {
/* If oa != NULL then mdt_preprw_read updated the inode
* atime and we should update the lvb so that other glimpses
if (IS_ERR(nodemap))
RETURN(PTR_ERR(nodemap));
- la->la_uid = nodemap_map_id(nodemap, NODEMAP_UID,
- NODEMAP_CLIENT_TO_FS, rec->sa_uid);
- la->la_gid = nodemap_map_id(nodemap, NODEMAP_GID,
- NODEMAP_CLIENT_TO_FS, rec->sa_gid);
- la->la_projid = rec->sa_projid;
+ la->la_uid = nodemap_map_id(nodemap, NODEMAP_UID,
+ NODEMAP_CLIENT_TO_FS, rec->sa_uid);
+ la->la_gid = nodemap_map_id(nodemap, NODEMAP_GID,
+ NODEMAP_CLIENT_TO_FS, rec->sa_gid);
+ la->la_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_CLIENT_TO_FS, rec->sa_projid);
nodemap_putref(nodemap);
la->la_size = rec->sa_size;
id = nodemap_map_id(nodemap, NODEMAP_GID,
NODEMAP_CLIENT_TO_FS,
repoqc->qc_id);
+ else if (oqctl->qc_type == PRJQUOTA)
+ id = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_CLIENT_TO_FS,
+ repoqc->qc_id);
nodemap_putref(nodemap);
if (cmd == OBD_BRW_WRITE) {
struct lu_nodemap *nodemap;
- __u32 mapped_uid, mapped_gid;
+ __u32 mapped_uid, mapped_gid, mapped_projid;
nodemap = nodemap_get_from_exp(exp);
if (IS_ERR(nodemap))
mapped_gid = nodemap_map_id(nodemap, NODEMAP_GID,
NODEMAP_FS_TO_CLIENT,
oa->o_gid);
+ mapped_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_FS_TO_CLIENT,
+ oa->o_projid);
if (!IS_ERR_OR_NULL(nodemap)) {
/* do not bypass quota enforcement if squashed uid */
* server ID will be returned back to client in that case. */
oa->o_uid = mapped_uid;
oa->o_gid = mapped_gid;
+ oa->o_projid = mapped_projid;
} else if (cmd == OBD_BRW_READ) {
rc = ofd_commitrw_read(env, ofd, fid, objcount,
npages, lnb);
EXPORT_SYMBOL(nodemap_set_squash_projid);
/**
- * Returns true if this nodemap has root user access. Always returns true if
- * nodemaps are not active.
+ * Check if nodemap allows setting quota.
+ *
+ * If nodemap is not active, always allow.
+ * For user and group quota, allow if the nodemap allows root access.
+ * For project quota, allow if project id is not squashed or deny_unknown
+ * is not set.
*
* \param nodemap nodemap to check access for
+ * \param qc_type quota type
+ * \param id client id to map
+ * \retval true is setquota is allowed, false otherwise
*/
-bool nodemap_can_setquota(const struct lu_nodemap *nodemap)
+bool nodemap_can_setquota(struct lu_nodemap *nodemap, __u32 qc_type, __u32 id)
{
- return !nodemap_active || (nodemap && nodemap->nmf_allow_root_access);
+ if (!nodemap_active)
+ return true;
+
+ if (!nodemap || !nodemap->nmf_allow_root_access)
+ return false;
+
+ if (qc_type == PRJQUOTA) {
+ id = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_CLIENT_TO_FS, id);
+
+ if (id == nodemap->nm_squash_projid &&
+ nodemap->nmf_deny_unknown)
+ return false;
+ }
+
+ return true;
}
EXPORT_SYMBOL(nodemap_can_setquota);
body->oa.o_gid = nodemap_map_id(nodemap, NODEMAP_GID,
NODEMAP_CLIENT_TO_FS,
body->oa.o_gid);
+ body->oa.o_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_CLIENT_TO_FS,
+ body->oa.o_projid);
nodemap_putref(nodemap);
tsi->tsi_ost_body = body;
rc=$?
[[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
+ for (( i = 0; i < NODEMAP_COUNT; i++ )); do
+ local csum=${HOSTNAME_CHECKSUM}_${i}
+
+ if ! do_facet mgs $LCTL nodemap_modify --name $csum \
+ --property admin --value 0; then
+ rc=$((rc + 1))
+ fi
+ if ! do_facet mgs $LCTL nodemap_modify --name $csum \
+ --property trusted --value 0; then
+ rc=$((rc + 1))
+ fi
+ done
+ [[ $rc != 0 ]] && error "nodemap_modify failed with $rc" && return 1
+
rc=0
for ((i = 0; i < NODEMAP_COUNT; i++)); do
if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
nodemap_exercise_fileset() {
local nm="$1"
local loop=0
+ local check_proj=true
+
+ (( $MDS1_VERSION >= $(version_code 2.14.52) )) || check_proj=false
# setup
if [ "$nm" == "default" ]; then
do_facet mgs $LCTL nodemap_activate 1
wait_nm_sync active
+ check_proj=false
else
nodemap_test_setup
fi
error "unable to add fileset info to $nm nodemap for servers"
wait_nm_sync $nm fileset "nodemap.${nm}.fileset=/$subdir"
+ if $check_proj; then
+ do_facet mgs $LCTL nodemap_modify --name $nm \
+ --property admin --value 1
+ wait_nm_sync $nm admin_nodemap
+ do_facet mgs $LCTL nodemap_modify --name $nm \
+ --property trusted --value 0
+ wait_nm_sync $nm trusted_nodemap
+ do_facet mgs $LCTL nodemap_modify --name $nm \
+ --property map_mode --value projid
+ wait_nm_sync $nm map_mode
+ do_facet mgs $LCTL nodemap_add_idmap --name $nm \
+ --idtype projid --idmap 1:1
+ do_facet mgs $LCTL nodemap_modify --name $nm \
+ --property deny_unknown --value 1
+ wait_nm_sync $nm deny_unknown
+ fi
+
# re-mount client
zconf_umount_clients ${clients_arr[0]} $MOUNT ||
error "unable to umount client ${clients_arr[0]}"
do_node ${clients_arr[0]} test -f $MOUNT/this_is_$subdir ||
error "fileset not taken into account"
+ if $check_proj; then
+ $LFS setquota -p 1 -b 10000 -B 11000 -i 0 -I 0 $MOUNT ||
+ error "setquota -p 1 failed"
+ $LFS setquota -p 2 -b 10000 -B 11000 -i 0 -I 0 $MOUNT &&
+ error "setquota -p 2 should have failed"
+ fi
+
# re-mount client with sub-subdir
zconf_umount_clients ${clients_arr[0]} $MOUNT ||
error "unable to umount client ${clients_arr[0]}"
if (rc) {
if (*obd_type)
fprintf(stderr,
- "%s setquota: cannot quotactl '%s' '%s': %s",
+ "%s setquota: cannot quotactl '%s' '%s': %s\n",
progname, obd_type,
obd_uuid2str(&qctl->obd_uuid), strerror(-rc));
+ else
+ fprintf(stderr,
+ "%s setquota: quotactl failed: %s\n",
+ progname, strerror(-rc));
}
out:
if (rc)
}
rc = nodemap_cmd(LCFG_NODEMAP_TEST_ID, &rawbuf, sizeof(rawbuf),
- argv[0], nidstr, typestr, idstr);
+ argv[0], nidstr, typestr, idstr, NULL);
if (rc == 0)
printf("%s\n", (char *)rawbuf);