1 /* -*- MODE: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Lustre Metadata Server (mdd) routines
7 * Copyright (C) 2006 Cluster File Systems, Inc.
8 * Author: fangyong@clusterfs.com
10 * This file is part of the Lustre file system, http://www.lustre.org
11 * Lustre is a trademark of Cluster File Systems, Inc.
13 * You may have signed or agreed to another license before downloading
14 * this software. If so, you are bound by the terms and conditions
15 * of that agreement, and the following does not apply to you. See the
16 * LICENSE file included with this distribution for more information.
18 * If you did not agree to a different license, then this copy of Lustre
19 * is open source software; you can redistribute it and/or modify it
20 * under the terms of version 2 of the GNU General Public License as
21 * published by the Free Software Foundation.
23 * In either case, Lustre is distributed in the hope that it will be
24 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * license text for more details.
29 # define EXPORT_SYMTAB
31 #define DEBUG_SUBSYSTEM S_MDS
33 #include <linux/module.h>
34 #include <linux/jbd.h>
36 #include <obd_class.h>
37 #include <lustre_ver.h>
38 #include <obd_support.h>
39 #include <lprocfs_status.h>
41 #include <linux/ldiskfs_fs.h>
42 #include <lustre_mds.h>
43 #include <lustre/lustre_idl.h>
45 #ifdef CONFIG_FS_POSIX_ACL
46 # include <linux/posix_acl_xattr.h>
47 # include <linux/posix_acl.h>
50 #include "mdd_internal.h"
52 #define mdd_get_group_info(group_info) do { \
53 atomic_inc(&(group_info)->usage); \
56 #define mdd_put_group_info(group_info) do { \
57 if (atomic_dec_and_test(&(group_info)->usage)) \
58 groups_free(group_info); \
61 #define MDD_NGROUPS_PER_BLOCK ((int)(CFS_PAGE_SIZE / sizeof(gid_t)))
63 #define MDD_GROUP_AT(gi, i) \
64 ((gi)->blocks[(i) / MDD_NGROUPS_PER_BLOCK][(i) % MDD_NGROUPS_PER_BLOCK])
67 * groups_search() is copied from linux kernel!
70 static int mdd_groups_search(struct group_info *group_info, gid_t grp)
78 right = group_info->ngroups;
79 while (left < right) {
80 int mid = (left + right) / 2;
81 int cmp = grp - MDD_GROUP_AT(group_info, mid);
93 int mdd_in_group_p(struct md_ucred *uc, gid_t grp)
97 if (grp != uc->mu_fsgid) {
98 struct group_info *group_info = NULL;
100 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD) ||
101 (!uc->mu_ginfo && !uc->mu_identity))
102 if ((grp == uc->mu_suppgids[0]) ||
103 (grp == uc->mu_suppgids[1]))
107 group_info = uc->mu_ginfo;
108 else if (uc->mu_identity)
109 group_info = uc->mu_identity->mi_ginfo;
114 mdd_get_group_info(group_info);
115 rc = mdd_groups_search(group_info, grp);
116 mdd_put_group_info(group_info);
121 #ifdef CONFIG_FS_POSIX_ACL
122 static inline void mdd_acl_le_to_cpu(posix_acl_xattr_entry *p)
124 p->e_tag = le16_to_cpu(p->e_tag);
125 p->e_perm = le16_to_cpu(p->e_perm);
126 p->e_id = le32_to_cpu(p->e_id);
129 static inline void mdd_acl_cpu_to_le(posix_acl_xattr_entry *p)
131 p->e_tag = cpu_to_le16(p->e_tag);
132 p->e_perm = cpu_to_le16(p->e_perm);
133 p->e_id = cpu_to_le32(p->e_id);
137 * Check permission based on POSIX ACL.
139 static int mdd_posix_acl_permission(struct md_ucred *uc, struct lu_attr *la,
140 int want, posix_acl_xattr_entry *entry,
143 posix_acl_xattr_entry *pa, *pe, *mask_obj;
150 for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
151 mdd_acl_le_to_cpu(pa);
154 /* (May have been checked already) */
155 if (la->la_uid == uc->mu_fsuid)
159 if (pa->e_id == uc->mu_fsuid)
163 if (mdd_in_group_p(uc, la->la_gid)) {
165 if ((pa->e_perm & want) == want)
170 if (mdd_in_group_p(uc, pa->e_id)) {
172 if ((pa->e_perm & want) == want)
190 for (mask_obj = pa + 1; mask_obj <= pe; mask_obj++) {
191 mdd_acl_le_to_cpu(mask_obj);
192 if (mask_obj->e_tag == ACL_MASK) {
193 if ((pa->e_perm & mask_obj->e_perm & want) == want)
201 if ((pa->e_perm & want) == want)
208 * Get default acl EA only.
209 * Hold read_lock for mdd_obj.
211 int mdd_acl_def_get(const struct lu_env *env, struct mdd_object *mdd_obj,
214 struct dt_object *next = mdd_object_child(mdd_obj);
218 if (ma->ma_valid & MA_ACL_DEF)
221 rc = next->do_ops->do_xattr_get(env, next,
222 mdd_buf_get(env, ma->ma_acl,
224 XATTR_NAME_ACL_DEFAULT, BYPASS_CAPA);
226 ma->ma_acl_size = rc;
227 ma->ma_valid |= MA_ACL_DEF;
229 } else if ((rc == -EOPNOTSUPP) || (rc == -ENODATA)) {
236 * Modify the ACL for the chmod.
238 static int mdd_posix_acl_chmod_masq(posix_acl_xattr_entry *entry,
239 __u32 mode, int count)
241 posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
243 for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
244 mdd_acl_le_to_cpu(pa);
247 pa->e_perm = (mode & S_IRWXU) >> 6;
263 pa->e_perm = (mode & S_IRWXO);
269 mdd_acl_cpu_to_le(pa);
273 mask_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
277 group_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
284 * Hold write_lock for o.
286 int mdd_acl_chmod(const struct lu_env *env, struct mdd_object *o, __u32 mode,
287 struct thandle *handle)
289 struct dt_object *next;
291 posix_acl_xattr_header *head;
292 posix_acl_xattr_entry *entry;
298 next = mdd_object_child(o);
299 buf = &mdd_env_info(env)->mti_buf;
300 buf->lb_buf = mdd_env_info(env)->mti_xattr_buf;
301 buf->lb_len = sizeof(mdd_env_info(env)->mti_xattr_buf);
302 rc = next->do_ops->do_xattr_get(env, next, buf,
303 XATTR_NAME_ACL_ACCESS, BYPASS_CAPA);
304 if ((rc == -EOPNOTSUPP) || (rc == -ENODATA))
310 head = (posix_acl_xattr_header *)(buf->lb_buf);
311 entry = head->a_entries;
312 entry_count = (buf->lb_len - sizeof(head->a_version)) /
313 sizeof(posix_acl_xattr_entry);
314 if (entry_count <= 0)
317 rc = mdd_posix_acl_chmod_masq(entry, mode, entry_count);
321 rc = next->do_ops->do_xattr_set(env, next, buf, XATTR_NAME_ACL_ACCESS,
322 0, handle, BYPASS_CAPA);
327 * Modify acl when creating a new obj.
329 static int mdd_posix_acl_create_masq(posix_acl_xattr_entry *entry,
330 __u32 *mode_p, int count)
332 posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
333 __u32 mode = *mode_p;
336 for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
337 mdd_acl_le_to_cpu(pa);
340 pa->e_perm &= (mode >> 6) | ~S_IRWXO;
341 mode &= (pa->e_perm << 6) | ~S_IRWXU;
354 pa->e_perm &= mode | ~S_IRWXO;
355 mode &= pa->e_perm | ~S_IRWXO;
366 mdd_acl_cpu_to_le(pa);
370 mask_obj->e_perm = le16_to_cpu(mask_obj->e_perm) &
371 ((mode >> 3) | ~S_IRWXO);
372 mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
373 mask_obj->e_perm = cpu_to_le16(mask_obj->e_perm);
377 group_obj->e_perm = le16_to_cpu(group_obj->e_perm) &
378 ((mode >> 3) | ~S_IRWXO);
379 mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
380 group_obj->e_perm = cpu_to_le16(group_obj->e_perm);
383 *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
388 * Hold write_lock for obj.
390 int __mdd_acl_init(const struct lu_env *env, struct mdd_object *obj,
391 struct lu_buf *buf, __u32 *mode, struct thandle *handle)
393 struct dt_object *next;
394 posix_acl_xattr_header *head;
395 posix_acl_xattr_entry *entry;
401 head = (posix_acl_xattr_header *)(buf->lb_buf);
402 entry = head->a_entries;
403 entry_count = (buf->lb_len - sizeof(head->a_version)) /
404 sizeof(posix_acl_xattr_entry);
405 if (entry_count <= 0)
408 next = mdd_object_child(obj);
409 if (S_ISDIR(*mode)) {
410 rc = next->do_ops->do_xattr_set(env, next, buf,
411 XATTR_NAME_ACL_DEFAULT,
412 0, handle, BYPASS_CAPA);
417 rc = mdd_posix_acl_create_masq(entry, mode, entry_count);
421 rc = next->do_ops->do_xattr_set(env, next, buf,
422 XATTR_NAME_ACL_ACCESS,
423 0, handle, BYPASS_CAPA);
428 * Hold read_lock for pobj.
429 * Hold write_lock for cobj.
431 int mdd_acl_init(const struct lu_env *env, struct mdd_object *pobj,
432 struct mdd_object *cobj, __u32 *mode, struct thandle *handle)
434 struct dt_object *next = mdd_object_child(pobj);
435 struct lu_buf *buf = &mdd_env_info(env)->mti_buf;
443 buf->lb_buf = mdd_env_info(env)->mti_xattr_buf;
444 buf->lb_len = sizeof(mdd_env_info(env)->mti_xattr_buf);
445 rc = next->do_ops->do_xattr_get(env, next, buf,
446 XATTR_NAME_ACL_DEFAULT, BYPASS_CAPA);
447 if ((rc == -EOPNOTSUPP) || (rc == -ENODATA))
453 rc = __mdd_acl_init(env, cobj, buf, mode, handle);
459 * Hold read_lock for obj.
461 static int mdd_check_acl(const struct lu_env *env, struct mdd_object *obj,
462 struct lu_attr *la, int mask)
464 #ifdef CONFIG_FS_POSIX_ACL
465 struct dt_object *next;
466 struct lu_buf *buf = &mdd_env_info(env)->mti_buf;
467 struct md_ucred *uc = md_ucred(env);
468 posix_acl_xattr_header *head;
469 posix_acl_xattr_entry *entry;
474 next = mdd_object_child(obj);
476 buf->lb_buf = mdd_env_info(env)->mti_xattr_buf;
477 buf->lb_len = sizeof(mdd_env_info(env)->mti_xattr_buf);
478 rc = next->do_ops->do_xattr_get(env, next, buf,
479 XATTR_NAME_ACL_ACCESS,
480 mdd_object_capa(env, obj));
482 RETURN(rc ? : -EACCES);
485 head = (posix_acl_xattr_header *)(buf->lb_buf);
486 entry = head->a_entries;
487 entry_count = (buf->lb_len - sizeof(head->a_version)) /
488 sizeof(posix_acl_xattr_entry);
490 rc = mdd_posix_acl_permission(uc, la, mask, entry, entry_count);
498 int __mdd_permission_internal(const struct lu_env *env, struct mdd_object *obj,
499 struct lu_attr *la, int mask, int needlock)
501 struct md_ucred *uc = md_ucred(env);
509 /* These means unnecessary for permission check */
510 if ((uc == NULL) || (uc->mu_valid == UCRED_INIT))
513 /* Invalid user credit */
514 if (uc->mu_valid == UCRED_INVALID)
518 * Nobody gets write access to an immutable file.
520 if ((mask & MAY_WRITE) && mdd_is_immutable(obj))
524 la = &mdd_env_info(env)->mti_la;
525 rc = mdd_la_get(env, obj, la, BYPASS_CAPA);
531 if (uc->mu_fsuid == la->la_uid) {
534 if (mode & S_IRWXG) {
536 mdd_read_lock(env, obj);
537 rc = mdd_check_acl(env, obj, la, mask);
539 mdd_read_unlock(env, obj);
541 goto check_capabilities;
542 else if ((rc != -EAGAIN) && (rc != -EOPNOTSUPP) &&
546 if (mdd_in_group_p(uc, la->la_gid))
550 if (((mode & mask & S_IRWXO) == mask))
554 if (!(mask & MAY_EXEC) ||
555 (la->la_mode & S_IXUGO) || S_ISDIR(la->la_mode))
556 if (mdd_capable(uc, CAP_DAC_OVERRIDE))
559 if ((mask == MAY_READ) ||
560 (S_ISDIR(la->la_mode) && !(mask & MAY_WRITE)))
561 if (mdd_capable(uc, CAP_DAC_READ_SEARCH))
567 int mdd_permission(const struct lu_env *env, struct md_object *obj, int mask)
569 struct mdd_object *mdd_obj = md2mdd_obj(obj);
573 rc = mdd_permission_internal_locked(env, mdd_obj, NULL, mask);
578 int mdd_capa_get(const struct lu_env *env, struct md_object *obj,
579 struct lustre_capa *capa, int renewal)
581 struct dt_object *next;
582 struct mdd_object *mdd_obj = md2mdd_obj(obj);
587 LASSERT(lu_object_exists(mdd2lu_obj(mdd_obj)));
588 next = mdd_object_child(mdd_obj);
590 oc = next->do_ops->do_capa_get(env, next, renewal ? capa : NULL,