Whamcloud - gitweb
bc4558277b594e67dcaa03eecb5a322176ed45d5
[fs/lustre-release.git] / lustre / osd-zfs / osd_xattr.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * Copyright (c) 2012, 2013, Intel Corporation.
32  * Use is subject to license terms.
33  */
34 /*
35  * This file is part of Lustre, http://www.lustre.org/
36  * Lustre is a trademark of Sun Microsystems, Inc.
37  *
38  * lustre/osd-zfs/osd_xattr.c
39  * functions to manipulate extended attributes and system attributes
40  *
41  * Author: Alex Zhuravlev <bzzz@whamcloud.com>
42  * Author: Mike Pershin <tappro@whamcloud.com>
43  */
44
45 #define DEBUG_SUBSYSTEM S_OSD
46
47 #include <lustre_ver.h>
48 #include <libcfs/libcfs.h>
49 #include <obd_support.h>
50 #include <lustre_net.h>
51 #include <obd.h>
52 #include <obd_class.h>
53 #include <lustre_disk.h>
54 #include <lustre_fid.h>
55
56 #include "osd_internal.h"
57
58 #include <sys/dnode.h>
59 #include <sys/dbuf.h>
60 #include <sys/spa.h>
61 #include <sys/stat.h>
62 #include <sys/zap.h>
63 #include <sys/spa_impl.h>
64 #include <sys/zfs_znode.h>
65 #include <sys/dmu_tx.h>
66 #include <sys/dmu_objset.h>
67 #include <sys/dsl_prop.h>
68 #include <sys/sa_impl.h>
69 #include <sys/txg.h>
70
71 #include <linux/posix_acl_xattr.h>
72
73 /*
74  * Copy an extended attribute into the buffer provided, or compute the
75  * required buffer size.
76  *
77  * If buf is NULL, it computes the required buffer size.
78  *
79  * Returns 0 on success or a negative error number on failure.
80  * On success, the number of bytes used / required is stored in 'size'.
81  *
82  * No locking is done here.
83  */
84 int __osd_xattr_load(udmu_objset_t *uos, uint64_t dnode, nvlist_t **sa_xattr)
85 {
86         sa_handle_t *sa_hdl;
87         char        *buf;
88         int          rc, size;
89
90         if (unlikely(dnode == ZFS_NO_OBJECT))
91                 return -ENOENT;
92
93         rc = -sa_handle_get(uos->os, dnode, NULL, SA_HDL_PRIVATE, &sa_hdl);
94         if (rc)
95                 return rc;
96
97         rc = -sa_size(sa_hdl, SA_ZPL_DXATTR(uos), &size);
98         if (rc) {
99                 if (rc == -ENOENT)
100                         rc = -nvlist_alloc(sa_xattr, NV_UNIQUE_NAME, KM_SLEEP);
101                 goto out_sa;
102         }
103
104         buf = sa_spill_alloc(KM_SLEEP);
105         if (buf == NULL) {
106                 rc = -ENOMEM;
107                 goto out_sa;
108         }
109         rc = -sa_lookup(sa_hdl, SA_ZPL_DXATTR(uos), buf, size);
110         if (rc == 0)
111                 rc = -nvlist_unpack(buf, size, sa_xattr, KM_SLEEP);
112         sa_spill_free(buf);
113 out_sa:
114         sa_handle_destroy(sa_hdl);
115
116         return rc;
117 }
118
119 static inline int __osd_xattr_cache(const struct lu_env *env,
120                                     struct osd_object *obj)
121 {
122         LASSERT(obj->oo_sa_xattr == NULL);
123         LASSERT(obj->oo_db != NULL);
124
125         return __osd_xattr_load(&osd_obj2dev(obj)->od_objset,
126                                 obj->oo_db->db_object, &obj->oo_sa_xattr);
127 }
128
129 int __osd_sa_xattr_get(const struct lu_env *env, struct osd_object *obj,
130                 const struct lu_buf *buf, const char *name, int *sizep)
131 {
132         uchar_t *nv_value;
133         int      rc;
134
135         LASSERT(obj->oo_sa_hdl);
136
137         if (obj->oo_sa_xattr == NULL) {
138                 rc = __osd_xattr_cache(env, obj);
139                 if (rc)
140                         return rc;
141         }
142
143         LASSERT(obj->oo_sa_xattr);
144         rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
145                         sizep);
146         if (rc)
147                 return rc;
148
149         if (buf == NULL || buf->lb_buf == NULL) {
150                 /* return the required size by *sizep */
151                 return 0;
152         }
153
154         if (*sizep > buf->lb_len)
155                 return -ERANGE; /* match ldiskfs error */
156
157         memcpy(buf->lb_buf, nv_value, *sizep);
158         return 0;
159 }
160
161 int __osd_xattr_get_large(const struct lu_env *env, udmu_objset_t *uos,
162                           uint64_t xattr, struct lu_buf *buf,
163                           const char *name, int *sizep)
164 {
165         dmu_buf_t       *xa_data_db;
166         sa_handle_t     *sa_hdl = NULL;
167         uint64_t         xa_data_obj, size;
168         int              rc;
169
170         /* are there any extended attributes? */
171         if (xattr == ZFS_NO_OBJECT)
172                 return -ENOENT;
173
174         /* Lookup the object number containing the xattr data */
175         rc = -zap_lookup(uos->os, xattr, name, sizeof(uint64_t), 1,
176                         &xa_data_obj);
177         if (rc)
178                 return rc;
179
180         rc = __osd_obj2dbuf(env, uos->os, xa_data_obj, &xa_data_db, FTAG);
181         if (rc)
182                 return rc;
183
184         rc = -sa_handle_get(uos->os, xa_data_obj, NULL, SA_HDL_PRIVATE,
185                         &sa_hdl);
186         if (rc)
187                 goto out_rele;
188
189         /* Get the xattr value length / object size */
190         rc = -sa_lookup(sa_hdl, SA_ZPL_SIZE(uos), &size, 8);
191         if (rc)
192                 goto out;
193
194         if (size > INT_MAX) {
195                 rc = -EOVERFLOW;
196                 goto out;
197         }
198
199         *sizep = (int)size;
200
201         if (buf == NULL || buf->lb_buf == NULL) {
202                 /* We only need to return the required size */
203                 goto out;
204         }
205         if (*sizep > buf->lb_len) {
206                 rc = -ERANGE; /* match ldiskfs error */
207                 goto out;
208         }
209
210         rc = -dmu_read(uos->os, xa_data_db->db_object, 0,
211                         size, buf->lb_buf, DMU_READ_PREFETCH);
212
213 out:
214         sa_handle_destroy(sa_hdl);
215 out_rele:
216         dmu_buf_rele(xa_data_db, FTAG);
217
218         return rc;
219 }
220
221 int __osd_xattr_get(const struct lu_env *env, struct osd_object *obj,
222                 struct lu_buf *buf, const char *name, int *sizep)
223 {
224         int rc;
225
226         /* check SA_ZPL_DXATTR first then fallback to directory xattr */
227         rc = __osd_sa_xattr_get(env, obj, buf, name, sizep);
228         if (rc != -ENOENT)
229                 return rc;
230
231         rc = __osd_xattr_get_large(env, &osd_obj2dev(obj)->od_objset,
232                                    obj->oo_xattr, buf, name, sizep);
233
234         return rc;
235 }
236
237 int osd_xattr_get(const struct lu_env *env, struct dt_object *dt,
238                 struct lu_buf *buf, const char *name,
239                 struct lustre_capa *capa)
240 {
241         struct osd_object  *obj  = osd_dt_obj(dt);
242         int                 rc, size = 0;
243         ENTRY;
244
245         LASSERT(obj->oo_db != NULL);
246         LASSERT(osd_invariant(obj));
247         LASSERT(dt_object_exists(dt));
248
249         if (!osd_obj2dev(obj)->od_posix_acl &&
250             (!strcmp(name, POSIX_ACL_XATTR_ACCESS) ||
251              !strcmp(name, POSIX_ACL_XATTR_DEFAULT)))
252                 RETURN(-EOPNOTSUPP);
253
254         down(&obj->oo_guard);
255         rc = __osd_xattr_get(env, obj, buf, name, &size);
256         up(&obj->oo_guard);
257
258         if (rc == -ENOENT)
259                 rc = -ENODATA;
260         else if (rc == 0)
261                 rc = size;
262         RETURN(rc);
263 }
264
265 void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj,
266                         int vallen, const char *name, struct osd_thandle *oh)
267 {
268         struct osd_device *osd = osd_obj2dev(obj);
269         udmu_objset_t     *uos = &osd->od_objset;
270         dmu_buf_t         *db = obj->oo_db;
271         dmu_tx_t          *tx = oh->ot_tx;
272         uint64_t           xa_data_obj;
273         int                rc = 0;
274         int                here;
275
276         here = dt_object_exists(&obj->oo_dt);
277
278         /* object may be not yet created */
279         if (here) {
280                 LASSERT(db);
281                 LASSERT(obj->oo_sa_hdl);
282                 /* we might just update SA_ZPL_DXATTR */
283                 dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1);
284
285                 if (obj->oo_xattr == ZFS_NO_OBJECT)
286                         rc = -ENOENT;
287         }
288
289         if (!here || rc == -ENOENT) {
290                 /* we'll be updating SA_ZPL_XATTR */
291                 if (here) {
292                         LASSERT(obj->oo_sa_hdl);
293                         dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1);
294                 }
295                 /* xattr zap + entry */
296                 dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, TRUE, (char *) name);
297                 /* xattr value obj */
298                 dmu_tx_hold_sa_create(tx, ZFS_SA_BASE_ATTR_SIZE);
299                 dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, vallen);
300                 return;
301         }
302
303         rc = -zap_lookup(uos->os, obj->oo_xattr, name, sizeof(uint64_t), 1,
304                         &xa_data_obj);
305         if (rc == 0) {
306                 /*
307                  * Entry already exists.
308                  * We'll truncate the existing object.
309                  */
310                 dmu_tx_hold_bonus(tx, xa_data_obj);
311                 dmu_tx_hold_free(tx, xa_data_obj, vallen, DMU_OBJECT_END);
312                 dmu_tx_hold_write(tx, xa_data_obj, 0, vallen);
313                 return;
314         } else if (rc == -ENOENT) {
315                 /*
316                  * Entry doesn't exist, we need to create a new one and a new
317                  * object to store the value.
318                  */
319                 dmu_tx_hold_bonus(tx, obj->oo_xattr);
320                 dmu_tx_hold_zap(tx, obj->oo_xattr, TRUE, (char *) name);
321                 dmu_tx_hold_sa_create(tx, ZFS_SA_BASE_ATTR_SIZE);
322                 dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, vallen);
323                 return;
324         }
325
326         /* An error happened */
327         tx->tx_err = -rc;
328 }
329
330 int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt,
331                 const struct lu_buf *buf, const char *name,
332                 int fl, struct thandle *handle)
333 {
334         struct osd_object  *obj = osd_dt_obj(dt);
335         struct osd_thandle *oh;
336         ENTRY;
337
338         LASSERT(handle != NULL);
339         oh = container_of0(handle, struct osd_thandle, ot_super);
340
341         down(&obj->oo_guard);
342         __osd_xattr_declare_set(env, obj, buf->lb_len, name, oh);
343         up(&obj->oo_guard);
344
345         RETURN(0);
346 }
347
348 /*
349  * Set an extended attribute.
350  * This transaction must have called udmu_xattr_declare_set() first.
351  *
352  * Returns 0 on success or a negative error number on failure.
353  *
354  * No locking is done here.
355  */
356 static int
357 __osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj,
358                         struct osd_thandle *oh)
359 {
360         struct osd_device *osd = osd_obj2dev(obj);
361         udmu_objset_t     *uos = &osd->od_objset;
362         char              *dxattr;
363         size_t             sa_size;
364         int                rc;
365
366         ENTRY;
367         LASSERT(obj->oo_sa_hdl);
368         LASSERT(obj->oo_sa_xattr);
369
370         /* Update the SA for additions, modifications, and removals. */
371         rc = -nvlist_size(obj->oo_sa_xattr, &sa_size, NV_ENCODE_XDR);
372         if (rc)
373                 return rc;
374
375         dxattr = sa_spill_alloc(KM_SLEEP);
376         if (dxattr == NULL)
377                 RETURN(-ENOMEM);
378
379         rc = -nvlist_pack(obj->oo_sa_xattr, &dxattr, &sa_size,
380                                 NV_ENCODE_XDR, KM_SLEEP);
381         if (rc)
382                 GOTO(out_free, rc);
383
384         rc = osd_object_sa_update(obj, SA_ZPL_DXATTR(uos), dxattr, sa_size, oh);
385 out_free:
386         sa_spill_free(dxattr);
387         RETURN(rc);
388 }
389
390 int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
391                         const struct lu_buf *buf, const char *name, int fl,
392                         struct osd_thandle *oh)
393 {
394         uchar_t *nv_value;
395         size_t  size;
396         int     nv_size;
397         int     rc;
398         int     too_big = 0;
399
400         LASSERT(obj->oo_sa_hdl);
401         if (obj->oo_sa_xattr == NULL) {
402                 rc = __osd_xattr_cache(env, obj);
403                 if (rc)
404                         return rc;
405         }
406
407         LASSERT(obj->oo_sa_xattr);
408         /* Limited to 32k to keep nvpair memory allocations small */
409         if (buf->lb_len > DXATTR_MAX_ENTRY_SIZE) {
410                 too_big = 1;
411         } else {
412                 /* Prevent the DXATTR SA from consuming the entire SA
413                  * region */
414                 rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR);
415                 if (rc)
416                         return rc;
417
418                 if (size + buf->lb_len > DXATTR_MAX_SA_SIZE)
419                         too_big = 1;
420         }
421
422         /* even in case of -EFBIG we must lookup xattr and check can we
423          * rewrite it then delete from SA */
424         rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
425                                         &nv_size);
426         if (rc == 0) {
427                 if (fl & LU_XATTR_CREATE) {
428                         return -EEXIST;
429                 } else if (too_big) {
430                         rc = -nvlist_remove(obj->oo_sa_xattr, name,
431                                                 DATA_TYPE_BYTE_ARRAY);
432                         if (rc < 0)
433                                 return rc;
434                         rc = __osd_sa_xattr_update(env, obj, oh);
435                         return rc == 0 ? -EFBIG : rc;
436                 }
437         } else if (rc == -ENOENT) {
438                 if (fl & LU_XATTR_REPLACE)
439                         return -ENODATA;
440                 else if (too_big)
441                         return -EFBIG;
442         } else {
443                 return rc;
444         }
445
446         /* Ensure xattr doesn't exist in ZAP */
447         if (obj->oo_xattr != ZFS_NO_OBJECT) {
448                 udmu_objset_t     *uos = &osd_obj2dev(obj)->od_objset;
449                 uint64_t           xa_data_obj;
450                 rc = -zap_lookup(uos->os, obj->oo_xattr,
451                                  name, 8, 1, &xa_data_obj);
452                 if (rc == 0) {
453                         rc = __osd_object_free(uos, xa_data_obj, oh->ot_tx);
454                         if (rc == 0)
455                                 zap_remove(uos->os, obj->oo_xattr,
456                                            name, oh->ot_tx);
457                 }
458         }
459
460         rc = -nvlist_add_byte_array(obj->oo_sa_xattr, name,
461                                     (uchar_t *)buf->lb_buf, buf->lb_len);
462         if (rc)
463                 return rc;
464
465         rc = __osd_sa_xattr_update(env, obj, oh);
466         return rc;
467 }
468
469 int
470 __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
471                 const struct lu_buf *buf, const char *name, int fl,
472                 struct osd_thandle *oh)
473 {
474         struct osd_device *osd = osd_obj2dev(obj);
475         udmu_objset_t     *uos = &osd->od_objset;
476         dmu_buf_t         *xa_zap_db = NULL;
477         dmu_buf_t         *xa_data_db = NULL;
478         uint64_t           xa_data_obj;
479         sa_handle_t       *sa_hdl = NULL;
480         dmu_tx_t          *tx = oh->ot_tx;
481         uint64_t           size;
482         int                rc;
483
484         LASSERT(obj->oo_sa_hdl);
485
486         if (obj->oo_xattr == ZFS_NO_OBJECT) {
487                 struct lu_attr *la = &osd_oti_get(env)->oti_la;
488
489                 la->la_valid = LA_MODE;
490                 la->la_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
491                 rc = __osd_zap_create(env, uos, &xa_zap_db, tx, la,
492                                       obj->oo_db->db_object, FTAG, 0);
493                 if (rc)
494                         return rc;
495
496                 obj->oo_xattr = xa_zap_db->db_object;
497                 rc = osd_object_sa_update(obj, SA_ZPL_XATTR(uos),
498                                 &obj->oo_xattr, 8, oh);
499                 if (rc)
500                         goto out;
501         }
502
503         rc = -zap_lookup(uos->os, obj->oo_xattr, name, sizeof(uint64_t), 1,
504                         &xa_data_obj);
505         if (rc == 0) {
506                 if (fl & LU_XATTR_CREATE) {
507                         rc = -EEXIST;
508                         goto out;
509                 }
510                 /*
511                  * Entry already exists.
512                  * We'll truncate the existing object.
513                  */
514                 rc = __osd_obj2dbuf(env, uos->os, xa_data_obj,
515                                         &xa_data_db, FTAG);
516                 if (rc)
517                         goto out;
518
519                 rc = -sa_handle_get(uos->os, xa_data_obj, NULL,
520                                         SA_HDL_PRIVATE, &sa_hdl);
521                 if (rc)
522                         goto out;
523
524                 rc = -sa_lookup(sa_hdl, SA_ZPL_SIZE(uos), &size, 8);
525                 if (rc)
526                         goto out_sa;
527
528                 rc = -dmu_free_range(uos->os, xa_data_db->db_object,
529                                         0, DMU_OBJECT_END, tx);
530                 if (rc)
531                         goto out_sa;
532         } else if (rc == -ENOENT) {
533                 struct lu_attr *la = &osd_oti_get(env)->oti_la;
534                 /*
535                  * Entry doesn't exist, we need to create a new one and a new
536                  * object to store the value.
537                  */
538                 if (fl & LU_XATTR_REPLACE) {
539                         /* should be ENOATTR according to the
540                          * man, but that is undefined here */
541                         rc = -ENODATA;
542                         goto out;
543                 }
544
545                 la->la_valid = LA_MODE;
546                 la->la_mode = S_IFREG | S_IRUGO | S_IWUSR;
547                 rc = __osd_object_create(env, uos, &xa_data_db, tx, la,
548                                          obj->oo_xattr, FTAG);
549                 if (rc)
550                         goto out;
551                 xa_data_obj = xa_data_db->db_object;
552
553                 rc = -sa_handle_get(uos->os, xa_data_obj, NULL,
554                                         SA_HDL_PRIVATE, &sa_hdl);
555                 if (rc)
556                         goto out;
557
558                 rc = -zap_add(uos->os, obj->oo_xattr, name, sizeof(uint64_t),
559                                 1, &xa_data_obj, tx);
560                 if (rc)
561                         goto out_sa;
562         } else {
563                 /* There was an error looking up the xattr name */
564                 goto out;
565         }
566
567         /* Finally write the xattr value */
568         dmu_write(uos->os, xa_data_obj, 0, buf->lb_len, buf->lb_buf, tx);
569
570         size = buf->lb_len;
571         rc = -sa_update(sa_hdl, SA_ZPL_SIZE(uos), &size, 8, tx);
572
573 out_sa:
574         sa_handle_destroy(sa_hdl);
575 out:
576         if (xa_data_db != NULL)
577                 dmu_buf_rele(xa_data_db, FTAG);
578         if (xa_zap_db != NULL)
579                 dmu_buf_rele(xa_zap_db, FTAG);
580
581         return rc;
582 }
583
584 int osd_xattr_set(const struct lu_env *env, struct dt_object *dt,
585                   const struct lu_buf *buf, const char *name, int fl,
586                   struct thandle *handle, struct lustre_capa *capa)
587 {
588         struct osd_object  *obj = osd_dt_obj(dt);
589         struct osd_thandle *oh;
590         int rc = 0;
591         ENTRY;
592
593         LASSERT(handle != NULL);
594         LASSERT(osd_invariant(obj));
595         LASSERT(dt_object_exists(dt));
596         LASSERT(obj->oo_db);
597
598         if (!osd_obj2dev(obj)->od_posix_acl &&
599             (!strcmp(name, POSIX_ACL_XATTR_ACCESS) ||
600              !strcmp(name, POSIX_ACL_XATTR_DEFAULT)))
601                 RETURN(-EOPNOTSUPP);
602
603         oh = container_of0(handle, struct osd_thandle, ot_super);
604
605         down(&obj->oo_guard);
606         CDEBUG(D_INODE, "Setting xattr %s with size %d\n",
607                 name, (int)buf->lb_len);
608         rc = osd_xattr_set_internal(env, obj, buf, name, fl, oh, capa);
609         up(&obj->oo_guard);
610
611         RETURN(rc);
612 }
613
614 static void
615 __osd_xattr_declare_del(const struct lu_env *env, struct osd_object *obj,
616                         const char *name, struct osd_thandle *oh)
617 {
618         struct osd_device *osd = osd_obj2dev(obj);
619         udmu_objset_t     *uos = &osd->od_objset;
620         dmu_tx_t          *tx = oh->ot_tx;
621         uint64_t           xa_data_obj;
622         int                rc;
623
624         /* update SA_ZPL_DXATTR if xattr was in SA */
625         dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 0);
626
627         if (obj->oo_xattr == ZFS_NO_OBJECT)
628                 return;
629
630         rc = -zap_lookup(uos->os, obj->oo_xattr, name, 8, 1, &xa_data_obj);
631         if (rc == 0) {
632                 /*
633                  * Entry exists.
634                  * We'll delete the existing object and ZAP entry.
635                  */
636                 dmu_tx_hold_bonus(tx, xa_data_obj);
637                 dmu_tx_hold_free(tx, xa_data_obj, 0, DMU_OBJECT_END);
638                 dmu_tx_hold_zap(tx, obj->oo_xattr, FALSE, (char *) name);
639                 return;
640         } else if (rc == -ENOENT) {
641                 /*
642                  * Entry doesn't exist, nothing to be changed.
643                  */
644                 return;
645         }
646
647         /* An error happened */
648         tx->tx_err = -rc;
649 }
650
651 int osd_declare_xattr_del(const struct lu_env *env, struct dt_object *dt,
652                         const char *name, struct thandle *handle)
653 {
654         struct osd_object  *obj = osd_dt_obj(dt);
655         struct osd_thandle *oh;
656         ENTRY;
657
658         LASSERT(handle != NULL);
659         LASSERT(dt_object_exists(dt));
660         LASSERT(osd_invariant(obj));
661
662         oh = container_of0(handle, struct osd_thandle, ot_super);
663         LASSERT(oh->ot_tx != NULL);
664         LASSERT(obj->oo_db != NULL);
665
666         down(&obj->oo_guard);
667         __osd_xattr_declare_del(env, obj, name, oh);
668         up(&obj->oo_guard);
669
670         RETURN(0);
671 }
672
673 int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj,
674                         const char *name, struct osd_thandle *oh)
675 {
676         int rc;
677
678         if (obj->oo_sa_xattr == NULL) {
679                 rc = __osd_xattr_cache(env, obj);
680                 if (rc)
681                         return rc;
682         }
683
684         rc = -nvlist_remove(obj->oo_sa_xattr, name, DATA_TYPE_BYTE_ARRAY);
685         if (rc == 0)
686                 rc = __osd_sa_xattr_update(env, obj, oh);
687         return rc;
688 }
689
690 int __osd_xattr_del(const struct lu_env *env, struct osd_object *obj,
691                         const char *name, struct osd_thandle *oh)
692 {
693         struct osd_device *osd = osd_obj2dev(obj);
694         udmu_objset_t     *uos = &osd->od_objset;
695         uint64_t           xa_data_obj;
696         int                rc;
697
698         /* try remove xattr from SA at first */
699         rc = __osd_sa_xattr_del(env, obj, name, oh);
700         if (rc != -ENOENT)
701                 return rc;
702
703         if (obj->oo_xattr == ZFS_NO_OBJECT)
704                 return 0;
705
706         rc = -zap_lookup(uos->os, obj->oo_xattr, name, sizeof(uint64_t), 1,
707                         &xa_data_obj);
708         if (rc == -ENOENT) {
709                 rc = 0;
710         } else if (rc == 0) {
711                 /*
712                  * Entry exists.
713                  * We'll delete the existing object and ZAP entry.
714                  */
715                 rc = __osd_object_free(uos, xa_data_obj, oh->ot_tx);
716                 if (rc)
717                         return rc;
718
719                 rc = -zap_remove(uos->os, obj->oo_xattr, name, oh->ot_tx);
720         }
721
722         return rc;
723 }
724
725 int osd_xattr_del(const struct lu_env *env, struct dt_object *dt,
726                 const char *name, struct thandle *handle,
727                 struct lustre_capa *capa)
728 {
729         struct osd_object  *obj = osd_dt_obj(dt);
730         struct osd_thandle *oh;
731         int                 rc;
732         ENTRY;
733
734         LASSERT(handle != NULL);
735         LASSERT(obj->oo_db != NULL);
736         LASSERT(osd_invariant(obj));
737         LASSERT(dt_object_exists(dt));
738         oh = container_of0(handle, struct osd_thandle, ot_super);
739         LASSERT(oh->ot_tx != NULL);
740
741         if (!osd_obj2dev(obj)->od_posix_acl &&
742             (!strcmp(name, POSIX_ACL_XATTR_ACCESS) ||
743              !strcmp(name, POSIX_ACL_XATTR_DEFAULT)))
744                 RETURN(-EOPNOTSUPP);
745
746         down(&obj->oo_guard);
747         rc = __osd_xattr_del(env, obj, name, oh);
748         up(&obj->oo_guard);
749
750         RETURN(rc);
751 }
752
753 static int
754 osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj,
755                 struct lu_buf *lb)
756 {
757         nvpair_t *nvp = NULL;
758         int       len, counted = 0, remain = lb->lb_len;
759         int       rc = 0;
760
761         if (obj->oo_sa_xattr == NULL) {
762                 rc = __osd_xattr_cache(env, obj);
763                 if (rc)
764                         return rc;
765         }
766
767         LASSERT(obj->oo_sa_xattr);
768
769         while ((nvp = nvlist_next_nvpair(obj->oo_sa_xattr, nvp)) != NULL) {
770                 const char *name = nvpair_name(nvp);
771
772                 if (!osd_obj2dev(obj)->od_posix_acl &&
773                     (!strcmp(name, POSIX_ACL_XATTR_ACCESS) ||
774                      !strcmp(name, POSIX_ACL_XATTR_DEFAULT)))
775                         continue;
776
777                 len = strlen(nvpair_name(nvp));
778                 if (lb->lb_buf != NULL) {
779                         if (len + 1 > remain)
780                                 return -ERANGE;
781
782                         memcpy(lb->lb_buf, name, len);
783                         lb->lb_buf += len;
784                         *((char *)lb->lb_buf) = '\0';
785                         lb->lb_buf++;
786                         remain -= len + 1;
787                 }
788                 counted += len + 1;
789         }
790         return counted;
791 }
792
793 int osd_xattr_list(const struct lu_env *env, struct dt_object *dt,
794                 struct lu_buf *lb, struct lustre_capa *capa)
795 {
796         struct osd_thread_info *oti = osd_oti_get(env);
797         struct osd_object      *obj = osd_dt_obj(dt);
798         struct osd_device      *osd = osd_obj2dev(obj);
799         udmu_objset_t          *uos = &osd->od_objset;
800         zap_cursor_t           *zc;
801         int                    rc, counted = 0, remain = lb->lb_len;
802         ENTRY;
803
804         LASSERT(obj->oo_db != NULL);
805         LASSERT(osd_invariant(obj));
806         LASSERT(dt_object_exists(dt));
807
808         down(&obj->oo_guard);
809
810         rc = osd_sa_xattr_list(env, obj, lb);
811         if (rc < 0)
812                 GOTO(out, rc);
813         counted = rc;
814         remain -= counted;
815
816         /* continue with dnode xattr if any */
817         if (obj->oo_xattr == ZFS_NO_OBJECT)
818                 GOTO(out, rc = counted);
819
820         rc = -udmu_zap_cursor_init(&zc, uos, obj->oo_xattr, 0);
821         if (rc)
822                 GOTO(out, rc);
823
824         while ((rc = -udmu_zap_cursor_retrieve_key(env, zc, oti->oti_key,
825                                                 MAXNAMELEN)) == 0) {
826                 if (!osd_obj2dev(obj)->od_posix_acl &&
827                     (!strcmp(oti->oti_key, POSIX_ACL_XATTR_ACCESS) ||
828                      !strcmp(oti->oti_key, POSIX_ACL_XATTR_DEFAULT))) {
829                         zap_cursor_advance(zc);
830                         continue;
831                 }
832
833                 rc = strlen(oti->oti_key);
834                 if (lb->lb_buf != NULL) {
835                         if (rc + 1 > remain)
836                                 RETURN(-ERANGE);
837
838                         memcpy(lb->lb_buf, oti->oti_key, rc);
839                         lb->lb_buf += rc;
840                         *((char *)lb->lb_buf) = '\0';
841                         lb->lb_buf++;
842                         remain -= rc + 1;
843                 }
844                 counted += rc + 1;
845
846                 zap_cursor_advance(zc);
847         }
848         if (rc == -ENOENT) /* no more kes in the index */
849                 rc = 0;
850         else if (unlikely(rc < 0))
851                 GOTO(out_fini, rc);
852         rc = counted;
853
854 out_fini:
855         udmu_zap_cursor_fini(zc);
856 out:
857         up(&obj->oo_guard);
858         RETURN(rc);
859
860 }
861
862