return (__u32)__kgid_val(INVALID_GID);
}
+static bool failed_it_can_retry(int retval, struct lookup_intent *it)
+{
+ int rc = 0;
+
+ if (!retval && (it->it_op & IT_OPEN_CREAT) == IT_OPEN_CREAT &&
+ it_disposition(it, DISP_OPEN_CREATE)) {
+ rc = it_open_error(DISP_OPEN_CREATE, it);
+ } else {
+ rc = retval;
+ }
+
+ return (rc == -EACCES);
+}
+
/* This function implements a retry mechanism on top of md_intent_lock().
* This is useful because the client can provide at most 2 supplementary
* groups in the request sent to the MDS, but sometimes it does not know
"intent lock %d on i1 "DFID" suppgids %d %d: rc %d\n",
it->it_op, PFID(&op_data->op_fid1),
op_data->op_suppgids[0], op_data->op_suppgids[1], rc);
- if (rc == -EACCES && tryagain && it->it_op & IT_OPEN &&
- it_disposition(it, DISP_OPEN_DENY) && *reqp) {
+ if (tryagain && *reqp && failed_it_can_retry(rc, it)) {
struct mdt_body *body;
__u32 new_suppgid;
return (result == 0) ? LCK_PR : LCK_PW;
}
+static void mdt_pack_attr_acl(struct mdt_thread_info *info,
+ struct mdt_object *o)
+{
+ struct ptlrpc_request *req = mdt_info_req(info);
+ struct md_attr *ma = &info->mti_attr;
+ struct lu_nodemap *nodemap;
+ struct mdt_body *repbody;
+ int rc;
+
+ repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
+
+ rc = mdt_attr_get_complex(info, o, ma);
+ if (!rc)
+ mdt_pack_attr2body(info, repbody, &ma->ma_attr,
+ mdt_object_fid(o));
+
+#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
+ if (exp_connect_flags(req->rq_export) & OBD_CONNECT_ACL) {
+ nodemap = nodemap_get_from_exp(req->rq_export);
+ if (IS_ERR(nodemap))
+ return;
+
+ (void)mdt_pack_acl2body(info, repbody, o, nodemap);
+ nodemap_putref(nodemap);
+ }
+#endif
+}
+
int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc)
{
struct mdt_device *mdt = info->mti_mdt;
PFID(mdt_object_fid(parent)), PNAME(&rr->rr_name),
PFID(child_fid));
- if (result != 0 && result != -ENOENT)
+ if (result != 0 && result != -ENOENT) {
+ /* in case of 'permission denied',
+ * hint the client with supp groups and ACLs
+ */
+ if (result == -EACCES)
+ mdt_pack_attr_acl(info, parent);
GOTO(out_parent_unlock, result);
+ }
CFS_RACE(OBD_FAIL_MDS_REINT_OPEN2);
if (result == 0)
result = mdt_attr_get_complex(info, child, ma);
- if (result != 0)
+ if (result != 0) {
+ /* in case of failure to create,
+ * hint the client with supp groups and ACLs
+ */
+ mdt_pack_attr_acl(info, parent);
GOTO(out_child, result);
+ }
}
created = 1;
mdt_counter_incr(req, LPROC_MDT_MKNOD,
chmod 640 $DIR/$tdir/fileA
chgrp grptest64g3 $DIR/$tdir/fileA
setfacl -m g:grptest64g2:r $DIR/$tdir/fileA
+ setfacl -m g:grptest64g2:rwx $DIR/$tdir
ls -lR $DIR/$tdir
setup_64
error "setting rbac file_perms failed"
wait_nm_sync c0 rbac
+ $RUNAS touch $DIR/$tdir/fileB &&
+ error "touch $DIR/$tdir/fileB should fail"
+ do_nodes $(comma_list $(all_mdts_nodes)) \
+ $LCTL set_param mdt.*.identity_int_flush=$RUNAS_ID
+ $RUNAS -G 5001 touch $DIR/$tdir/fileB ||
+ error "touch $DIR/$tdir/fileB failed"
+ do_nodes $(comma_list $(all_mdts_nodes)) \
+ $LCTL set_param mdt.*.identity_int_flush=$RUNAS_ID
+ $RUNAS -G 5000,5001 touch $DIR/$tdir/fileC ||
+ error "touch $DIR/$tdir/fileC failed"
+ do_nodes $(comma_list $(all_mdts_nodes)) \
+ $LCTL set_param mdt.*.identity_int_flush=$RUNAS_ID
$RUNAS cat $DIR/$tdir/fileA && error "cat $DIR/$tdir/fileA should fail"
+ do_nodes $(comma_list $(all_mdts_nodes)) \
+ $LCTL set_param mdt.*.identity_int_flush=$RUNAS_ID
$RUNAS -G 5000,5001 cat $DIR/$tdir/fileA ||
error "cat $DIR/$tdir/fileA failed"
}