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