Whamcloud - gitweb
Changelog update
[fs/lustre-release.git] / lustre / mds / mds_xattr.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/mds/mds_xattr.c
37  *
38  * Lustre Metadata Server (mds) extended attributes handling
39  */
40
41 #ifndef EXPORT_SYMTAB
42 # define EXPORT_SYMTAB
43 #endif
44 #define DEBUG_SUBSYSTEM S_MDS
45
46 #include <linux/fs.h>
47 #include <obd_support.h>
48 #include <obd_class.h>
49 #include <obd.h>
50 #include <lustre_lib.h>
51 #include <lustre/lustre_idl.h>
52 #include <lustre_mds.h>
53 #include <lustre_dlm.h>
54 #include <lustre_fsfilt.h>
55 #include <lustre_ucache.h>
56
57 #include "mds_internal.h" 
58
59 #ifndef XATTR_NAME_ACL_ACCESS
60 #define XATTR_NAME_ACL_ACCESS   "system.posix_acl_access"
61 #endif
62
63 #ifndef XATTR_NAME_ACL_DEFAULT
64 #define XATTR_NAME_ACL_DEFAULT  "system.posix_acl_default"
65 #endif
66
67 static int mds_getxattr_pack_msg(struct ptlrpc_request *req,
68                                  struct dentry *de,
69                                  struct mds_body *body)
70 {
71         struct inode *inode = de->d_inode;
72         char *xattr_name;
73         int size[3] = { sizeof(struct ptlrpc_body), sizeof(*body) };
74         int bufcnt = 2, rc = -EOPNOTSUPP, rc2;
75
76         if (inode == NULL)
77                 return -ENOENT;
78
79         if (body->valid & OBD_MD_FLXATTR) {
80                 xattr_name = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF+1,0);
81                 if (!xattr_name) {
82                         CERROR("can't extract xattr name\n");
83                         return -EFAULT;
84                 }
85
86                 if (!(req->rq_export->exp_connect_flags & OBD_CONNECT_XATTR) &&
87                     (strncmp(xattr_name, "user.", 5) == 0))
88                         return -EOPNOTSUPP;
89
90                 if (inode->i_op && inode->i_op->getxattr)
91                         rc = inode->i_op->getxattr(de, xattr_name, NULL, 0);
92         } else if (body->valid & OBD_MD_FLXATTRLS) {
93                 if (inode->i_op && inode->i_op->listxattr)
94                         rc = inode->i_op->listxattr(de, NULL, 0);
95         } else {
96                 CERROR("valid bits: "LPX64"\n", body->valid);
97                 return -EINVAL;
98         }
99
100         if (rc < 0) {
101                 if (rc != -ENODATA && rc != -EOPNOTSUPP)
102                         CWARN("get inode %lu EA size error: %d\n",
103                               inode->i_ino, rc);
104                 bufcnt = 1;
105         } else {
106                 size[bufcnt++] = min_t(int, body->eadatasize, rc);
107         }
108
109         if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETXATTR_PACK)) {
110                 CERROR("failed MDS_GETXATTR_PACK test\n");
111                 req->rq_status = -ENOMEM;
112                 return -ENOMEM;
113         }
114
115         rc2 = lustre_pack_reply(req, bufcnt, size, NULL);
116         if (rc2)
117                 return rc2;
118
119         if (rc < 0)
120                 req->rq_status = rc;
121         return 0;
122 }
123
124 static int mds_getxattr_internal(struct obd_device *obd,
125                                  struct dentry *dentry,
126                                  struct ptlrpc_request *req,
127                                  struct mds_body *reqbody)
128 {
129         struct mds_body *repbody;
130         struct inode *inode = dentry->d_inode;
131         char *xattr_name;
132         void *buf = NULL;
133         int buflen, rc = -EOPNOTSUPP;
134         ENTRY;
135
136         if (inode == NULL)
137                 GOTO(out, rc = -ENOENT);
138
139         repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
140                                  sizeof(*repbody));
141         LASSERT(repbody != NULL);
142
143         buflen = lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF + 1);
144         if (buflen)
145                 buf = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1, buflen);
146
147         if (reqbody->valid & OBD_MD_FLXATTR) {
148                 xattr_name = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF+1,0);
149                 DEBUG_REQ(D_INODE, req, "getxattr %s", xattr_name);
150
151                 if (inode->i_op && inode->i_op->getxattr) {
152                         rc = inode->i_op->getxattr(dentry, xattr_name,
153                                                    buf, buflen);
154                 }
155
156                 if (rc < 0 && rc != -ENODATA && rc != -EOPNOTSUPP &&
157                     rc != -ERANGE)
158                         CDEBUG(D_OTHER, "getxattr failed: %d\n", rc);
159         } else if (reqbody->valid & OBD_MD_FLXATTRLS) {
160                 DEBUG_REQ(D_INODE, req, "listxattr");
161
162                 if (inode->i_op && inode->i_op->listxattr)
163                         rc = inode->i_op->listxattr(dentry, buf, buflen);
164                 if (rc < 0)
165                         CDEBUG(D_OTHER, "listxattr failed: %d\n", rc);
166         } else
167                 LBUG();
168
169         if (rc >= 0) {
170                 repbody->eadatasize = rc;
171                 rc = 0;
172         }
173 out:
174         req->rq_status = rc;
175         RETURN(0);
176 }
177
178 int mds_getxattr(struct ptlrpc_request *req)
179 {
180         struct mds_obd *mds = mds_req2mds(req);
181         struct obd_device *obd = req->rq_export->exp_obd;
182         struct lvfs_run_ctxt saved;
183         struct dentry *de;
184         struct mds_body *body;
185         struct lvfs_ucred uc = { NULL, };
186         int rc = 0;
187         ENTRY;
188
189         mds_counter_incr(req->rq_export, LPROC_MDS_GETXATTR);
190
191         body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
192                                   lustre_swab_mds_body);
193         if (body == NULL)
194                 RETURN(-EFAULT);
195
196         rc = mds_init_ucred(&uc, req, REQ_REC_OFF);
197         if (rc)
198                 GOTO(out_ucred, rc);
199
200         push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
201         de = mds_fid2dentry(mds, &body->fid1, NULL);
202         if (IS_ERR(de)) {
203                 rc = req->rq_status = PTR_ERR(de);
204                 GOTO(out_pop, rc);
205         }
206
207         rc = mds_getxattr_pack_msg(req, de, body);
208         if (rc != 0 || req->rq_status)
209                 GOTO(out_dput, rc);
210
211         rc = mds_getxattr_internal(obd, de, req, body);
212
213 out_dput:
214         l_dput(de);
215 out_pop:
216         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
217 out_ucred:
218         mds_exit_ucred(&uc, mds);
219         return rc;
220 }
221
222 /*
223  * alwasy return 0, and set req->rq_status as error number in case
224  * of failures.
225  */
226 static
227 int mds_setxattr_internal(struct ptlrpc_request *req, struct mds_body *body)
228 {
229         struct mds_obd *mds = mds_req2mds(req);
230         struct obd_device *obd = req->rq_export->exp_obd;
231         struct dentry *de;
232         struct inode *inode = NULL;
233         struct inode *inodes[PTLRPC_NUM_VERSIONS] = { NULL };
234         struct lustre_handle lockh;
235         void *handle = NULL;
236         char *xattr_name;
237         char *xattr = NULL;
238         int xattrlen;
239         int rc = -EOPNOTSUPP, err = 0, sync = 0;
240         __u64 lockpart;
241         ENTRY;
242
243         LASSERT(body);
244
245         DEBUG_REQ(D_INODE, req, "setxattr "LPU64"/%u",
246                   body->fid1.id, body->fid1.generation);
247
248         MDS_CHECK_RESENT(req, mds_reconstruct_generic(req));
249
250         lockpart = MDS_INODELOCK_UPDATE;
251
252         /* various sanity check for xattr name */
253         xattr_name = lustre_msg_string(req->rq_reqmsg, REQ_REC_OFF + 1, 0);
254         if (!xattr_name) {
255                 CERROR("can't extract xattr name\n");
256                 GOTO(out, rc = -EPROTO);
257         }
258
259         DEBUG_REQ(D_INODE, req, "%sxattr %s",
260                   body->valid & OBD_MD_FLXATTR ? "set" : "remove",
261                   xattr_name);
262
263         if (strncmp(xattr_name, "trusted.", 8) == 0) {
264                 if (strcmp(xattr_name + 8, XATTR_LUSTRE_MDS_LOV_EA) == 0)
265                         GOTO(out, rc = -EACCES);
266                 if (strcmp(xattr_name + 8, "lma") == 0 &&
267                     !OBD_FAIL_CHECK(OBD_FAIL_MDS_ALLOW_COMMON_EA_SETTING))
268                         GOTO(out, rc = 0);
269         }
270
271         if (!(req->rq_export->exp_connect_flags & OBD_CONNECT_XATTR) &&
272             (strncmp(xattr_name, "user.", 5) == 0)) {
273                 GOTO(out, rc = -EOPNOTSUPP);
274         }
275
276         /* currently lustre limit xattr size */
277         if (body->valid & OBD_MD_FLXATTR &&
278             (strcmp(xattr_name, XATTR_NAME_ACL_ACCESS) == 0 ||
279              strcmp(xattr_name, XATTR_NAME_ACL_DEFAULT) == 0 ))  {
280                 xattrlen = lustre_msg_buflen(req->rq_reqmsg,
281                                              REQ_REC_OFF + 2);
282
283                 if (xattrlen > LUSTRE_POSIX_ACL_MAX_SIZE)
284                         GOTO(out, -ERANGE);
285         }
286
287         /* Revoke all clients' lookup lock, since the access
288          * permissions for this inode is changed when ACL_ACCESS is
289          * set. This isn't needed for ACL_DEFAULT, since that does
290          * not change the access permissions of this inode, nor any
291          * other existing inodes. It is setting the ACLs inherited 
292          * by new directories/files at create time. */
293         if (!strcmp(xattr_name, XATTR_NAME_ACL_ACCESS))
294                 lockpart |= MDS_INODELOCK_LOOKUP;
295
296         de = mds_fid2locked_dentry(obd, &body->fid1, NULL, LCK_EX,
297                                    &lockh, NULL, 0, lockpart);
298         if (IS_ERR(de))
299                 GOTO(out, rc = PTR_ERR(de));
300
301         inode = de->d_inode;
302         LASSERT(inode);
303
304         OBD_FAIL_WRITE(obd, OBD_FAIL_MDS_SETXATTR_WRITE, inode->i_sb);
305
306         /* version recovery check */
307         rc = mds_version_get_check(req, inode, 0);
308         if (rc)
309                 GOTO(out_dput, rc);
310
311         /* filter_op simply use setattr one */
312         handle = fsfilt_start(obd, inode, FSFILT_OP_SETATTR, NULL);
313         if (IS_ERR(handle))
314                 GOTO(out_dput, rc = PTR_ERR(handle));
315
316         if (body->valid & OBD_MD_FLXATTR) {
317                 if (inode->i_op && inode->i_op->setxattr) {
318                         if (lustre_msg_bufcount(req->rq_reqmsg) < 4) {
319                                 CERROR("no xattr data supplied\n");
320                                 GOTO(out_trans, rc = -EFAULT);
321                         }
322
323                         xattrlen = lustre_msg_buflen(req->rq_reqmsg,
324                                                      REQ_REC_OFF + 2);
325
326                         xattr = lustre_msg_buf(req->rq_reqmsg,
327                                                REQ_REC_OFF+2, xattrlen);
328
329                         LOCK_INODE_MUTEX(inode);
330                         rc = inode->i_op->setxattr(de, xattr_name, xattr,
331                                                    xattrlen, body->flags);
332                         UNLOCK_INODE_MUTEX(inode);
333                 }
334         } else if (body->valid & OBD_MD_FLXATTRRM) {
335                 if (inode->i_op && inode->i_op->removexattr) {
336                         LOCK_INODE_MUTEX(inode);
337                         rc = inode->i_op->removexattr(de, xattr_name);
338                         UNLOCK_INODE_MUTEX(inode);
339                 }
340         } else {
341                 CERROR("valid bits: "LPX64"\n", body->valid);
342                 rc = -EINVAL;
343         }
344
345         LASSERT(rc <= 0);
346 out_trans:
347         /* security-replated changes may require sync */
348         if (!strcmp(xattr_name, XATTR_NAME_ACL_ACCESS))
349                 sync = mds->mds_sync_permission;
350         inodes[0] = inode;
351         err = mds_finish_transno(mds, inodes, handle, req, rc, 0, sync);
352 out_dput:
353         l_dput(de);
354         if (rc)
355                 ldlm_lock_decref(&lockh, LCK_EX);
356         else
357                 ptlrpc_save_lock (req, &lockh, LCK_EX);
358
359         if (err && !rc)
360                 rc = err;
361 out:
362         req->rq_status = rc;
363         return 0;
364 }
365
366 int mds_setxattr(struct ptlrpc_request *req)
367 {
368         struct mds_obd *mds = mds_req2mds(req);
369         struct obd_device *obd = req->rq_export->exp_obd;
370         struct lvfs_run_ctxt saved;
371         struct mds_body *body;
372         struct lvfs_ucred uc = { NULL, };
373         int rc;
374         ENTRY;
375
376         mds_counter_incr(req->rq_export, LPROC_MDS_SETXATTR);
377
378         body = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*body),
379                                   lustre_swab_mds_body);
380         if (body == NULL)
381                 RETURN(-EFAULT);
382
383         if (lustre_msg_bufcount(req->rq_reqmsg) < 3)
384                 RETURN(-EFAULT);
385
386         rc = mds_init_ucred(&uc, req, REQ_REC_OFF);
387         if (rc)
388                 GOTO(out_ucred, rc);
389
390         push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
391
392         rc = lustre_pack_reply(req, 1, NULL, NULL);
393         if (rc)
394                 GOTO(out_pop, rc);
395
396         rc = mds_setxattr_internal(req, body);
397
398 out_pop:
399         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
400 out_ucred:
401         mds_exit_ucred(&uc, mds);
402         return rc;
403 }