X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fosd-zfs%2Fosd_xattr.c;h=d3cdb9f3a18add57619c1bc961a0f0cb5c86b07e;hb=bfd4600f31691fdad676a8489f591bccc24f2100;hp=9a220a7c7cf26693dfb41cea6c23d1565e4afd1d;hpb=d9e86108724c06e3e6d25081caaf5803abf4416c;p=fs%2Flustre-release.git diff --git a/lustre/osd-zfs/osd_xattr.c b/lustre/osd-zfs/osd_xattr.c index 9a220a7..d3cdb9f 100644 --- a/lustre/osd-zfs/osd_xattr.c +++ b/lustre/osd-zfs/osd_xattr.c @@ -15,11 +15,7 @@ * * You should have received a copy of the GNU General Public License * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ @@ -27,7 +23,7 @@ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2012, 2014, Intel Corporation. + * Copyright (c) 2012, 2015, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -229,6 +225,9 @@ int __osd_xattr_get(const struct lu_env *env, struct osd_object *obj, { int rc; + if (unlikely(!dt_object_exists(&obj->oo_dt) || obj->oo_destroyed)) + return -ENOENT; + /* check SA_ZPL_DXATTR first then fallback to directory xattr */ rc = __osd_sa_xattr_get(env, obj, buf, name, sizep); if (rc != -ENOENT) @@ -239,8 +238,7 @@ int __osd_xattr_get(const struct lu_env *env, struct osd_object *obj, } int osd_xattr_get(const struct lu_env *env, struct dt_object *dt, - struct lu_buf *buf, const char *name, - struct lustre_capa *capa) + struct lu_buf *buf, const char *name) { struct osd_object *obj = osd_dt_obj(dt); int rc, size = 0; @@ -248,16 +246,15 @@ int osd_xattr_get(const struct lu_env *env, struct dt_object *dt, LASSERT(obj->oo_db != NULL); LASSERT(osd_invariant(obj)); - LASSERT(dt_object_exists(dt)); if (!osd_obj2dev(obj)->od_posix_acl && - (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 || - strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)) + (strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 || + strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) RETURN(-EOPNOTSUPP); - down(&obj->oo_guard); + down_read(&obj->oo_guard); rc = __osd_xattr_get(env, obj, buf, name, &size); - up(&obj->oo_guard); + up_read(&obj->oo_guard); if (rc == -ENOENT) rc = -ENODATA; @@ -266,36 +263,18 @@ int osd_xattr_get(const struct lu_env *env, struct dt_object *dt, RETURN(rc); } -void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj, - int vallen, const char *name, - struct osd_thandle *oh) +/* the function is used to declare EAs when SA is not supported */ +void __osd_xattr_declare_legacy(const struct lu_env *env, + struct osd_object *obj, + int vallen, const char *name, + struct osd_thandle *oh) { struct osd_device *osd = osd_obj2dev(obj); - dmu_buf_t *db = obj->oo_db; - dmu_tx_t *tx = oh->ot_tx; - uint64_t xa_data_obj; - int rc = 0; - int here; - - here = dt_object_exists(&obj->oo_dt); - - /* object may be not yet created */ - if (here) { - LASSERT(db); - LASSERT(obj->oo_sa_hdl); - /* we might just update SA_ZPL_DXATTR */ - dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1); - - if (obj->oo_xattr == ZFS_NO_OBJECT) - rc = -ENOENT; - } + dmu_tx_t *tx = oh->ot_tx; + uint64_t xa_data_obj; + int rc; - if (!here || rc == -ENOENT) { - /* we'll be updating SA_ZPL_XATTR */ - if (here) { - LASSERT(obj->oo_sa_hdl); - dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1); - } + if (obj->oo_xattr == ZFS_NO_OBJECT) { /* xattr zap + entry */ dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, TRUE, (char *) name); /* xattr value obj */ @@ -314,7 +293,6 @@ void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj, dmu_tx_hold_bonus(tx, xa_data_obj); dmu_tx_hold_free(tx, xa_data_obj, vallen, DMU_OBJECT_END); dmu_tx_hold_write(tx, xa_data_obj, 0, vallen); - return; } else if (rc == -ENOENT) { /* * Entry doesn't exist, we need to create a new one and a new @@ -324,11 +302,43 @@ void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj, dmu_tx_hold_zap(tx, obj->oo_xattr, TRUE, (char *) name); dmu_tx_hold_sa_create(tx, ZFS_SA_BASE_ATTR_SIZE); dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, vallen); + } +} + +void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj, + int vallen, const char *name, + struct osd_thandle *oh) +{ + dmu_buf_t *db = obj->oo_db; + dmu_tx_t *tx = oh->ot_tx; + + if (unlikely(obj->oo_destroyed)) + return; + + if (unlikely(!osd_obj2dev(obj)->od_xattr_in_sa)) { + __osd_xattr_declare_legacy(env, obj, vallen, name, oh); return; } - /* An error happened */ - tx->tx_err = -rc; + /* declare EA in SA */ + if (dt_object_exists(&obj->oo_dt)) { + LASSERT(obj->oo_sa_hdl); + /* XXX: it should be possible to skip spill + * declaration if specific EA is part of + * bonus and doesn't grow */ + dmu_tx_hold_spill(tx, db->db_object); + return; + } + + /* the object doesn't exist, but we've declared bonus + * in osd_declare_object_create() yet */ + if (obj->oo_ea_in_bonus > DN_MAX_BONUSLEN) { + /* spill has been declared already */ + } else if (obj->oo_ea_in_bonus + vallen > DN_MAX_BONUSLEN) { + /* we're about to exceed bonus, let's declare spill */ + dmu_tx_hold_spill(tx, DMU_NEW_OBJECT); + } + obj->oo_ea_in_bonus += vallen; } int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt, @@ -342,9 +352,9 @@ int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt, LASSERT(handle != NULL); oh = container_of0(handle, struct osd_thandle, ot_super); - down(&obj->oo_guard); + down_read(&obj->oo_guard); __osd_xattr_declare_set(env, obj, buf->lb_len, name, oh); - up(&obj->oo_guard); + up_read(&obj->oo_guard); RETURN(0); } @@ -357,8 +367,7 @@ int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt, * * No locking is done here. */ -static int -__osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj, +int __osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj, struct osd_thandle *oh) { struct osd_device *osd = osd_obj2dev(obj); @@ -490,8 +499,7 @@ __osd_xattr_set(const struct lu_env *env, struct osd_object *obj, la->la_valid = LA_MODE; la->la_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; - rc = __osd_zap_create(env, osd, &xa_zap_db, tx, la, - obj->oo_db->db_object, 0); + rc = __osd_zap_create(env, osd, &xa_zap_db, tx, la, 0); if (rc) return rc; @@ -546,8 +554,7 @@ __osd_xattr_set(const struct lu_env *env, struct osd_object *obj, la->la_valid = LA_MODE; la->la_mode = S_IFREG | S_IRUGO | S_IWUSR; - rc = __osd_object_create(env, obj, &xa_data_db, tx, la, - obj->oo_xattr); + rc = __osd_object_create(env, obj, &xa_data_db, tx, la); if (rc) goto out; xa_data_obj = xa_data_db->db_object; @@ -585,7 +592,7 @@ out: int osd_xattr_set(const struct lu_env *env, struct dt_object *dt, const struct lu_buf *buf, const char *name, int fl, - struct thandle *handle, struct lustre_capa *capa) + struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; @@ -594,12 +601,10 @@ int osd_xattr_set(const struct lu_env *env, struct dt_object *dt, LASSERT(handle != NULL); LASSERT(osd_invariant(obj)); - LASSERT(dt_object_exists(dt)); - LASSERT(obj->oo_db); if (!osd_obj2dev(obj)->od_posix_acl && - (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 || - strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)) + (strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 || + strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) RETURN(-EOPNOTSUPP); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_OVERFLOW) && @@ -608,11 +613,11 @@ int osd_xattr_set(const struct lu_env *env, struct dt_object *dt, oh = container_of0(handle, struct osd_thandle, ot_super); - down(&obj->oo_guard); + down_write(&obj->oo_guard); CDEBUG(D_INODE, "Setting xattr %s with size %d\n", name, (int)buf->lb_len); - rc = osd_xattr_set_internal(env, obj, buf, name, fl, oh, capa); - up(&obj->oo_guard); + rc = osd_xattr_set_internal(env, obj, buf, name, fl, oh); + up_write(&obj->oo_guard); RETURN(rc); } @@ -661,22 +666,22 @@ int osd_declare_xattr_del(const struct lu_env *env, struct dt_object *dt, ENTRY; LASSERT(handle != NULL); - LASSERT(dt_object_exists(dt)); LASSERT(osd_invariant(obj)); oh = container_of0(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_tx != NULL); LASSERT(obj->oo_db != NULL); - down(&obj->oo_guard); - __osd_xattr_declare_del(env, obj, name, oh); - up(&obj->oo_guard); + down_read(&obj->oo_guard); + if (likely(dt_object_exists(&obj->oo_dt) && !obj->oo_destroyed)) + __osd_xattr_declare_del(env, obj, name, oh); + up_read(&obj->oo_guard); RETURN(0); } -int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj, - const char *name, struct osd_thandle *oh) +static int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj, + const char *name, struct osd_thandle *oh) { int rc; @@ -692,13 +697,16 @@ int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj, return rc; } -int __osd_xattr_del(const struct lu_env *env, struct osd_object *obj, - const char *name, struct osd_thandle *oh) +static int __osd_xattr_del(const struct lu_env *env, struct osd_object *obj, + const char *name, struct osd_thandle *oh) { struct osd_device *osd = osd_obj2dev(obj); uint64_t xa_data_obj; int rc; + if (unlikely(!dt_object_exists(&obj->oo_dt) || obj->oo_destroyed)) + return -ENOENT; + /* try remove xattr from SA at first */ rc = __osd_sa_xattr_del(env, obj, name, oh); if (rc != -ENOENT) @@ -727,8 +735,7 @@ int __osd_xattr_del(const struct lu_env *env, struct osd_object *obj, } int osd_xattr_del(const struct lu_env *env, struct dt_object *dt, - const char *name, struct thandle *handle, - struct lustre_capa *capa) + const char *name, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; @@ -743,17 +750,107 @@ int osd_xattr_del(const struct lu_env *env, struct dt_object *dt, LASSERT(oh->ot_tx != NULL); if (!osd_obj2dev(obj)->od_posix_acl && - (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 || - strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)) + (strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 || + strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) RETURN(-EOPNOTSUPP); - down(&obj->oo_guard); + down_write(&obj->oo_guard); rc = __osd_xattr_del(env, obj, name, oh); - up(&obj->oo_guard); + up_write(&obj->oo_guard); RETURN(rc); } +void osd_declare_xattrs_destroy(const struct lu_env *env, + struct osd_object *obj, struct osd_thandle *oh) +{ + struct osd_device *osd = osd_obj2dev(obj); + zap_attribute_t *za = &osd_oti_get(env)->oti_za; + uint64_t oid = obj->oo_xattr, xid; + dmu_tx_t *tx = oh->ot_tx; + zap_cursor_t *zc; + int rc; + + if (oid == ZFS_NO_OBJECT) + return; /* Nothing to do for SA xattrs */ + + /* Declare to free the ZAP holding xattrs */ + dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END); + + rc = osd_zap_cursor_init(&zc, osd->od_os, oid, 0); + if (rc) + goto out; + + while (zap_cursor_retrieve(zc, za) == 0) { + LASSERT(za->za_num_integers == 1); + LASSERT(za->za_integer_length == sizeof(uint64_t)); + + rc = -zap_lookup(osd->od_os, oid, za->za_name, + sizeof(uint64_t), 1, &xid); + if (rc) { + CERROR("%s: xattr %s lookup failed: rc = %d\n", + osd->od_svname, za->za_name, rc); + break; + } + dmu_tx_hold_free(tx, xid, 0, DMU_OBJECT_END); + + zap_cursor_advance(zc); + } + + osd_zap_cursor_fini(zc); +out: + if (rc && tx->tx_err == 0) + tx->tx_err = -rc; +} + +int osd_xattrs_destroy(const struct lu_env *env, + struct osd_object *obj, struct osd_thandle *oh) +{ + struct osd_device *osd = osd_obj2dev(obj); + dmu_tx_t *tx = oh->ot_tx; + zap_attribute_t *za = &osd_oti_get(env)->oti_za; + zap_cursor_t *zc; + uint64_t xid; + int rc; + + /* The transaction must have been assigned to a transaction group. */ + LASSERT(tx->tx_txg != 0); + + if (obj->oo_xattr == ZFS_NO_OBJECT) + return 0; /* Nothing to do for SA xattrs */ + + /* Free the ZAP holding the xattrs */ + rc = osd_zap_cursor_init(&zc, osd->od_os, obj->oo_xattr, 0); + if (rc) + return rc; + + while (zap_cursor_retrieve(zc, za) == 0) { + LASSERT(za->za_num_integers == 1); + LASSERT(za->za_integer_length == sizeof(uint64_t)); + + rc = -zap_lookup(osd->od_os, obj->oo_xattr, za->za_name, + sizeof(uint64_t), 1, &xid); + if (rc) { + CERROR("%s: lookup xattr %s failed: rc = %d\n", + osd->od_svname, za->za_name, rc); + } else { + rc = -dmu_object_free(osd->od_os, xid, tx); + if (rc) + CERROR("%s: free xattr %s failed: rc = %d\n", + osd->od_svname, za->za_name, rc); + } + zap_cursor_advance(zc); + } + osd_zap_cursor_fini(zc); + + rc = -dmu_object_free(osd->od_os, obj->oo_xattr, tx); + if (rc) + CERROR("%s: free xattr %llu failed: rc = %d\n", + osd->od_svname, obj->oo_xattr, rc); + + return rc; +} + static int osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj, const struct lu_buf *lb) @@ -774,8 +871,8 @@ osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj, const char *name = nvpair_name(nvp); if (!osd_obj2dev(obj)->od_posix_acl && - (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 || - strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)) + (strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 || + strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) continue; len = strlen(name); @@ -791,7 +888,7 @@ osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj, } int osd_xattr_list(const struct lu_env *env, struct dt_object *dt, - const struct lu_buf *lb, struct lustre_capa *capa) + const struct lu_buf *lb) { struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); @@ -804,7 +901,7 @@ int osd_xattr_list(const struct lu_env *env, struct dt_object *dt, LASSERT(osd_invariant(obj)); LASSERT(dt_object_exists(dt)); - down(&obj->oo_guard); + down_read(&obj->oo_guard); rc = osd_sa_xattr_list(env, obj, lb); if (rc < 0) @@ -822,8 +919,8 @@ int osd_xattr_list(const struct lu_env *env, struct dt_object *dt, while ((rc = -zap_cursor_retrieve(zc, za)) == 0) { if (!osd_obj2dev(obj)->od_posix_acl && - (strcmp(za->za_name, POSIX_ACL_XATTR_ACCESS) == 0 || - strcmp(za->za_name, POSIX_ACL_XATTR_DEFAULT) == 0)) { + (strcmp(za->za_name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 || + strcmp(za->za_name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) { zap_cursor_advance(zc); continue; } @@ -831,7 +928,7 @@ int osd_xattr_list(const struct lu_env *env, struct dt_object *dt, rc = strlen(za->za_name); if (lb->lb_buf != NULL) { if (counted + rc + 1 > lb->lb_len) - RETURN(-ERANGE); + GOTO(out_fini, rc = -ERANGE); memcpy(lb->lb_buf + counted, za->za_name, rc + 1); } @@ -848,7 +945,7 @@ int osd_xattr_list(const struct lu_env *env, struct dt_object *dt, out_fini: osd_zap_cursor_fini(zc); out: - up(&obj->oo_guard); + up_read(&obj->oo_guard); RETURN(rc); }