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) ||
85 (sbi->ll_flags & LL_SBI_RMT_CLIENT)))
88 if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
90 if (xattr_type == XATTR_TRUSTED_T && !capable(CAP_SYS_ADMIN))
92 if (xattr_type == XATTR_OTHER_T)
99 int ll_setxattr_common(struct inode *inode, const char *name,
100 const void *value, size_t size,
101 int flags, __u64 valid)
103 struct ll_sb_info *sbi = ll_i2sbi(inode);
104 struct ptlrpc_request *req;
109 xattr_type = get_xattr_type(name);
110 rc = xattr_type_filter(sbi, xattr_type);
114 /* b10667: ignore lustre special xattr for now */
115 if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) ||
116 (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
119 oc = ll_mdscapa_get(inode);
120 rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name,
121 value, size, 0, flags, &req);
124 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
125 LCONSOLE_INFO("Disabling user_xattr feature because "
126 "it is not supported on the server\n");
127 sbi->ll_flags &= ~LL_SBI_USER_XATTR;
132 ptlrpc_req_finished(req);
136 int ll_setxattr(struct dentry *dentry, const char *name,
137 const void *value, size_t size, int flags)
139 struct inode *inode = dentry->d_inode;
144 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
145 inode->i_ino, inode->i_generation, inode, name);
147 ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1);
149 if ((strncmp(name, XATTR_TRUSTED_PREFIX,
150 sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
151 strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
152 (strncmp(name, XATTR_LUSTRE_PREFIX,
153 sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
154 strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
155 struct lov_user_md *lump = (struct lov_user_md *)value;
158 if (S_ISREG(inode->i_mode)) {
160 int flags = FMODE_WRITE;
163 rc = ll_lov_setstripe_ea_info(inode, &f, flags,
164 lump, sizeof(*lump));
165 /* b10667: rc always be 0 here for now */
167 } else if (S_ISDIR(inode->i_mode)) {
168 rc = ll_dir_setstripe(inode, lump, 0);
174 return ll_setxattr_common(inode, name, value, size, flags,
178 int ll_removexattr(struct dentry *dentry, const char *name)
180 struct inode *inode = dentry->d_inode;
185 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
186 inode->i_ino, inode->i_generation, inode, name);
188 ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1);
189 return ll_setxattr_common(inode, name, NULL, 0, 0,
194 int ll_getxattr_common(struct inode *inode, const char *name,
195 void *buffer, size_t size, __u64 valid)
197 struct ll_sb_info *sbi = ll_i2sbi(inode);
198 struct ptlrpc_request *req = NULL;
199 struct mdt_body *body;
205 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
206 inode->i_ino, inode->i_generation, inode);
208 /* listxattr have slightly different behavior from of ext3:
209 * without 'user_xattr' ext3 will list all xattr names but
210 * filtered out "^user..*"; we list them all for simplicity.
213 xattr_type = XATTR_OTHER_T;
217 xattr_type = get_xattr_type(name);
218 rc = xattr_type_filter(sbi, xattr_type);
222 /* posix acl is under protection of LOOKUP lock. when calling to this,
223 * we just have path resolution to the target inode, so we have great
224 * chance that cached ACL is uptodate.
226 #ifdef CONFIG_FS_POSIX_ACL
227 if (xattr_type == XATTR_ACL_ACCESS_T) {
228 struct ll_inode_info *lli = ll_i2info(inode);
229 struct posix_acl *acl;
231 spin_lock(&lli->lli_lock);
232 acl = posix_acl_dup(lli->lli_posix_acl);
233 spin_unlock(&lli->lli_lock);
238 rc = posix_acl_to_xattr(acl, buffer, size);
239 posix_acl_release(acl);
245 oc = ll_mdscapa_get(inode);
246 rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc, valid, name,
247 NULL, 0, size, 0, &req);
250 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
251 LCONSOLE_INFO("Disabling user_xattr feature because "
252 "it is not supported on the server\n");
253 sbi->ll_flags &= ~LL_SBI_USER_XATTR;
258 body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
260 LASSERT(lustre_rep_swabbed(req, REPLY_REC_OFF));
262 /* only detect the xattr size */
264 GOTO(out, rc = body->eadatasize);
266 if (size < body->eadatasize) {
267 CERROR("server bug: replied size %u > %u\n",
268 body->eadatasize, (int)size);
269 GOTO(out, rc = -ERANGE);
272 if (lustre_msg_bufcount(req->rq_repmsg) < 3) {
273 CERROR("reply bufcount %u\n",
274 lustre_msg_bufcount(req->rq_repmsg));
275 GOTO(out, rc = -EFAULT);
278 /* do not need swab xattr data */
279 lustre_set_rep_swabbed(req, REPLY_REC_OFF + 1);
280 xdata = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1,
283 CERROR("can't extract: %u : %u\n", body->eadatasize,
284 lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF + 1));
285 GOTO(out, rc = -EFAULT);
289 memcpy(buffer, xdata, body->eadatasize);
290 rc = body->eadatasize;
292 ptlrpc_req_finished(req);
296 ssize_t ll_getxattr(struct dentry *dentry, const char *name,
297 void *buffer, size_t size)
299 struct inode *inode = dentry->d_inode;
304 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
305 inode->i_ino, inode->i_generation, inode, name);
307 ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1);
309 if ((strncmp(name, XATTR_TRUSTED_PREFIX,
310 sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
311 strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
312 (strncmp(name, XATTR_LUSTRE_PREFIX,
313 sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
314 strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
315 struct lov_user_md *lump;
316 struct lov_mds_md *lmm = NULL;
317 struct ptlrpc_request *request = NULL;
320 if (S_ISREG(inode->i_mode)) {
321 rc = ll_lov_getstripe_ea_info(dentry->d_parent->d_inode,
322 dentry->d_name.name, &lmm,
324 } else if (S_ISDIR(inode->i_mode)) {
325 rc = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
331 GOTO(out, rc = lmmsize);
333 if (size < lmmsize) {
334 CERROR("server bug: replied size %u > %u\n",
336 GOTO(out, rc = -ERANGE);
339 lump = (struct lov_user_md *)buffer;
340 memcpy(lump, lmm, lmmsize);
344 ptlrpc_req_finished(request);
348 return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR);
351 ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
353 struct inode *inode = dentry->d_inode;
355 struct lov_mds_md *lmm = NULL;
356 struct ptlrpc_request *request = NULL;
361 CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
362 inode->i_ino, inode->i_generation, inode);
364 ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1);
366 rc = ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS);
368 if (S_ISREG(inode->i_mode)) {
369 struct ll_inode_info *lli = ll_i2info(inode);
370 struct lov_stripe_md *lsm = NULL;
374 } else if (S_ISDIR(inode->i_mode)) {
375 rc2 = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
381 const int prefix_len = sizeof(XATTR_LUSTRE_PREFIX) - 1;
382 const size_t name_len = sizeof("lov") - 1;
383 const size_t total_len = prefix_len + name_len + 1;
385 if (buffer && (rc + total_len) <= size) {
387 memcpy(buffer,XATTR_LUSTRE_PREFIX, prefix_len);
388 memcpy(buffer+prefix_len, "lov", name_len);
389 buffer[prefix_len + name_len] = '\0';
394 ptlrpc_req_finished(request);