1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2004 - 2005 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <linux/sched.h>
25 #include <linux/smp_lock.h>
27 #define DEBUG_SUBSYSTEM S_LLITE
29 #include <obd_support.h>
30 #include <lustre_lite.h>
31 #include <lustre_dlm.h>
32 #include <lustre_ver.h>
33 //#include <lustre_mdc.h>
34 #include <linux/lustre_acl.h>
36 #include "llite_internal.h"
38 #define XATTR_USER_PREFIX "user."
39 #define XATTR_TRUSTED_PREFIX "trusted."
40 #define XATTR_SECURITY_PREFIX "security."
41 #define XATTR_LUSTRE_PREFIX "lustre."
43 #define XATTR_USER_T (1)
44 #define XATTR_TRUSTED_T (2)
45 #define XATTR_SECURITY_T (3)
46 #define XATTR_ACL_ACCESS_T (4)
47 #define XATTR_ACL_DEFAULT_T (5)
48 #define XATTR_LUSTRE_T (6)
49 #define XATTR_OTHER_T (7)
52 int get_xattr_type(const char *name)
54 if (!strcmp(name, POSIX_ACL_XATTR_ACCESS))
55 return XATTR_ACL_ACCESS_T;
57 if (!strcmp(name, POSIX_ACL_XATTR_DEFAULT))
58 return XATTR_ACL_DEFAULT_T;
60 if (!strncmp(name, XATTR_USER_PREFIX,
61 sizeof(XATTR_USER_PREFIX) - 1))
64 if (!strncmp(name, XATTR_TRUSTED_PREFIX,
65 sizeof(XATTR_TRUSTED_PREFIX) - 1))
66 return XATTR_TRUSTED_T;
68 if (!strncmp(name, XATTR_SECURITY_PREFIX,
69 sizeof(XATTR_SECURITY_PREFIX) - 1))
70 return XATTR_SECURITY_T;
72 if (!strncmp(name, XATTR_LUSTRE_PREFIX,
73 sizeof(XATTR_LUSTRE_PREFIX) - 1))
74 return XATTR_LUSTRE_T;
80 int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type)
82 if ((xattr_type == XATTR_ACL_ACCESS_T ||
83 xattr_type == XATTR_ACL_DEFAULT_T) &&
84 !(sbi->ll_flags & LL_SBI_ACL))
87 if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
89 if (xattr_type == XATTR_TRUSTED_T && !capable(CAP_SYS_ADMIN))
91 if (xattr_type == XATTR_OTHER_T)
98 int ll_setxattr_common(struct inode *inode, const char *name,
99 const void *value, size_t size,
100 int flags, __u64 valid)
102 struct ll_sb_info *sbi = ll_i2sbi(inode);
103 struct ptlrpc_request *req;
106 posix_acl_xattr_header *new_value = NULL;
107 struct rmtacl_ctl_entry *rce = NULL;
108 ext_acl_xattr_header *acl = NULL;
109 const char *pv = value;
112 xattr_type = get_xattr_type(name);
113 rc = xattr_type_filter(sbi, xattr_type);
117 /* b10667: ignore lustre special xattr for now */
118 if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) ||
119 (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
122 #ifdef CONFIG_FS_POSIX_ACL
123 if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
124 (xattr_type == XATTR_ACL_ACCESS_T ||
125 xattr_type == XATTR_ACL_DEFAULT_T)) {
126 rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
128 (rce->rce_ops != RMT_LSETFACL &&
129 rce->rce_ops != RMT_RSETFACL))
132 if (rce->rce_ops == RMT_LSETFACL) {
133 struct eacl_entry *ee;
135 ee = et_search_del(&sbi->ll_et, cfs_curproc_pid(),
136 ll_inode2fid(inode), xattr_type);
138 if (valid & OBD_MD_FLXATTR) {
139 acl = lustre_acl_xattr_merge2ext(
140 (posix_acl_xattr_header *)value,
144 RETURN(PTR_ERR(acl));
146 size = CFS_ACL_XATTR_SIZE(\
147 le32_to_cpu(acl->a_count), \
149 pv = (const char *)acl;
152 } else if (rce->rce_ops == RMT_RSETFACL) {
153 size = lustre_posix_acl_xattr_filter(
154 (posix_acl_xattr_header *)value,
156 if (unlikely(size < 0))
159 pv = (const char *)new_value;
163 valid |= rce_ops2valid(rce->rce_ops);
166 oc = ll_mdscapa_get(inode);
167 rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
168 valid, name, pv, size, 0, flags, ll_i2suppgid(inode),
171 #ifdef CONFIG_FS_POSIX_ACL
172 if (new_value != NULL)
173 lustre_posix_acl_xattr_free(new_value, size);
175 lustre_ext_acl_xattr_free(acl);
178 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
179 LCONSOLE_INFO("Disabling user_xattr feature because "
180 "it is not supported on the server\n");
181 sbi->ll_flags &= ~LL_SBI_USER_XATTR;
186 ptlrpc_req_finished(req);
190 int ll_setxattr(struct dentry *dentry, const char *name,
191 const void *value, size_t size, int flags)
193 struct inode *inode = dentry->d_inode;
198 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
199 inode->i_ino, inode->i_generation, inode, name);
201 ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1);
203 if ((strncmp(name, XATTR_TRUSTED_PREFIX,
204 sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
205 strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
206 (strncmp(name, XATTR_LUSTRE_PREFIX,
207 sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
208 strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
209 struct lov_user_md *lump = (struct lov_user_md *)value;
212 if (S_ISREG(inode->i_mode)) {
214 int flags = FMODE_WRITE;
217 rc = ll_lov_setstripe_ea_info(inode, &f, flags,
218 lump, sizeof(*lump));
219 /* b10667: rc always be 0 here for now */
221 } else if (S_ISDIR(inode->i_mode)) {
222 rc = ll_dir_setstripe(inode, lump, 0);
228 return ll_setxattr_common(inode, name, value, size, flags,
232 int ll_removexattr(struct dentry *dentry, const char *name)
234 struct inode *inode = dentry->d_inode;
239 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
240 inode->i_ino, inode->i_generation, inode, name);
242 ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1);
243 return ll_setxattr_common(inode, name, NULL, 0, 0,
248 int ll_getxattr_common(struct inode *inode, const char *name,
249 void *buffer, size_t size, __u64 valid)
251 struct ll_sb_info *sbi = ll_i2sbi(inode);
252 struct ptlrpc_request *req = NULL;
253 struct mdt_body *body;
257 struct rmtacl_ctl_entry *rce = NULL;
260 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
261 inode->i_ino, inode->i_generation, inode);
263 /* listxattr have slightly different behavior from of ext3:
264 * without 'user_xattr' ext3 will list all xattr names but
265 * filtered out "^user..*"; we list them all for simplicity.
268 xattr_type = XATTR_OTHER_T;
272 xattr_type = get_xattr_type(name);
273 rc = xattr_type_filter(sbi, xattr_type);
277 #ifdef CONFIG_FS_POSIX_ACL
278 if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
279 (xattr_type == XATTR_ACL_ACCESS_T ||
280 xattr_type == XATTR_ACL_DEFAULT_T)) {
281 rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
283 (rce->rce_ops != RMT_LSETFACL &&
284 rce->rce_ops != RMT_LGETFACL &&
285 rce->rce_ops != RMT_RSETFACL &&
286 rce->rce_ops != RMT_RGETFACL))
291 /* posix acl is under protection of LOOKUP lock. when calling to this,
292 * we just have path resolution to the target inode, so we have great
293 * chance that cached ACL is uptodate.
295 #ifdef CONFIG_FS_POSIX_ACL
296 if (xattr_type == XATTR_ACL_ACCESS_T &&
297 !(sbi->ll_flags & LL_SBI_RMT_CLIENT)) {
298 struct ll_inode_info *lli = ll_i2info(inode);
299 struct posix_acl *acl;
301 spin_lock(&lli->lli_lock);
302 acl = posix_acl_dup(lli->lli_posix_acl);
303 spin_unlock(&lli->lli_lock);
308 rc = posix_acl_to_xattr(acl, buffer, size);
309 posix_acl_release(acl);
312 if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode))
317 oc = ll_mdscapa_get(inode);
318 rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
319 valid | (rce ? rce_ops2valid(rce->rce_ops) : 0),
320 name, NULL, 0, size, 0, &req);
323 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
324 LCONSOLE_INFO("Disabling user_xattr feature because "
325 "it is not supported on the server\n");
326 sbi->ll_flags &= ~LL_SBI_USER_XATTR;
331 body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
334 /* only detect the xattr size */
336 GOTO(out, rc = body->eadatasize);
338 if (size < body->eadatasize) {
339 CERROR("server bug: replied size %u > %u\n",
340 body->eadatasize, (int)size);
341 GOTO(out, rc = -ERANGE);
344 /* do not need swab xattr data */
345 xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA,
348 GOTO(out, rc = -EFAULT);
350 #ifdef CONFIG_FS_POSIX_ACL
351 if (body->eadatasize >= 0 && rce && rce->rce_ops == RMT_LSETFACL) {
352 ext_acl_xattr_header *acl;
354 acl = lustre_posix_acl_xattr_2ext((posix_acl_xattr_header *)xdata,
357 GOTO(out, rc = PTR_ERR(acl));
359 rc = ee_add(&sbi->ll_et, cfs_curproc_pid(), ll_inode2fid(inode),
361 if (unlikely(rc < 0)) {
362 lustre_ext_acl_xattr_free(acl);
367 if (xattr_type == XATTR_ACL_ACCESS_T && !body->eadatasize)
368 GOTO(out, rc = -ENODATA);
371 memcpy(buffer, xdata, body->eadatasize);
372 rc = body->eadatasize;
375 ptlrpc_req_finished(req);
379 ssize_t ll_getxattr(struct dentry *dentry, const char *name,
380 void *buffer, size_t size)
382 struct inode *inode = dentry->d_inode;
387 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
388 inode->i_ino, inode->i_generation, inode, name);
390 ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1);
392 if ((strncmp(name, XATTR_TRUSTED_PREFIX,
393 sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
394 strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
395 (strncmp(name, XATTR_LUSTRE_PREFIX,
396 sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
397 strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
398 struct lov_user_md *lump;
399 struct lov_mds_md *lmm = NULL;
400 struct ptlrpc_request *request = NULL;
403 if (S_ISREG(inode->i_mode)) {
404 rc = ll_lov_getstripe_ea_info(dentry->d_parent->d_inode,
405 dentry->d_name.name, &lmm,
407 } else if (S_ISDIR(inode->i_mode)) {
408 rc = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
414 GOTO(out, rc = lmmsize);
416 if (size < lmmsize) {
417 CERROR("server bug: replied size %u > %u\n",
419 GOTO(out, rc = -ERANGE);
422 lump = (struct lov_user_md *)buffer;
423 memcpy(lump, lmm, lmmsize);
427 ptlrpc_req_finished(request);
431 return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR);
434 ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
436 struct inode *inode = dentry->d_inode;
438 struct lov_mds_md *lmm = NULL;
439 struct ptlrpc_request *request = NULL;
444 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
445 inode->i_ino, inode->i_generation, inode);
447 ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1);
449 rc = ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS);
451 if (S_ISREG(inode->i_mode)) {
452 struct ll_inode_info *lli = ll_i2info(inode);
453 struct lov_stripe_md *lsm = NULL;
457 } else if (S_ISDIR(inode->i_mode)) {
458 rc2 = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
464 const int prefix_len = sizeof(XATTR_LUSTRE_PREFIX) - 1;
465 const size_t name_len = sizeof("lov") - 1;
466 const size_t total_len = prefix_len + name_len + 1;
468 if (buffer && (rc + total_len) <= size) {
470 memcpy(buffer,XATTR_LUSTRE_PREFIX, prefix_len);
471 memcpy(buffer+prefix_len, "lov", name_len);
472 buffer[prefix_len + name_len] = '\0';
477 ptlrpc_req_finished(request);