Whamcloud - gitweb
LU-7991 quota: project quota against ZFS backend
[fs/lustre-release.git] / lustre / osd-zfs / osd_xattr.c
index 9c2bac9..aaa94ab 100644 (file)
@@ -38,7 +38,6 @@
 
 #define DEBUG_SUBSYSTEM S_OSD
 
-#include <lustre_ver.h>
 #include <libcfs/libcfs.h>
 #include <obd_support.h>
 #include <lustre_net.h>
 #include <linux/posix_acl_xattr.h>
 
 
-int __osd_xattr_load(struct osd_device *osd, uint64_t dnode, nvlist_t **sa)
+int __osd_xattr_load(struct osd_device *osd, sa_handle_t *hdl, nvlist_t **sa)
 {
-       sa_handle_t *sa_hdl;
        char        *buf;
        int          rc, size;
 
-       if (unlikely(dnode == ZFS_NO_OBJECT))
-               return -ENOENT;
-
-       rc = -sa_handle_get(osd->od_os, dnode, NULL, SA_HDL_PRIVATE, &sa_hdl);
-       if (rc)
-               return rc;
-
-       rc = -sa_size(sa_hdl, SA_ZPL_DXATTR(osd), &size);
+       rc = -sa_size(hdl, SA_ZPL_DXATTR(osd), &size);
        if (rc) {
                if (rc == -ENOENT)
                        rc = -nvlist_alloc(sa, NV_UNIQUE_NAME, KM_SLEEP);
@@ -90,24 +81,22 @@ int __osd_xattr_load(struct osd_device *osd, uint64_t dnode, nvlist_t **sa)
                rc = -ENOMEM;
                goto out_sa;
        }
-       rc = -sa_lookup(sa_hdl, SA_ZPL_DXATTR(osd), buf, size);
+       rc = -sa_lookup(hdl, SA_ZPL_DXATTR(osd), buf, size);
        if (rc == 0)
                rc = -nvlist_unpack(buf, size, sa, KM_SLEEP);
        osd_zio_buf_free(buf, size);
 out_sa:
-       sa_handle_destroy(sa_hdl);
 
        return rc;
 }
 
-static inline int __osd_xattr_cache(const struct lu_env *env,
-                                   struct osd_object *obj)
+static inline int __osd_xattr_cache(struct osd_object *obj)
 {
-       LASSERT(obj->oo_sa_xattr == NULL);
-       LASSERT(obj->oo_dn != NULL);
-
-       return __osd_xattr_load(osd_obj2dev(obj), obj->oo_dn->dn_object,
-                               &obj->oo_sa_xattr);
+       LASSERT(obj->oo_sa_hdl);
+       if (obj->oo_sa_xattr != NULL)
+               return 0;
+       return __osd_xattr_load(osd_obj2dev(obj),
+                               obj->oo_sa_hdl, &obj->oo_sa_xattr);
 }
 
 static int
@@ -115,19 +104,15 @@ __osd_sa_xattr_get(const struct lu_env *env, struct osd_object *obj,
                   const struct lu_buf *buf, const char *name, int *sizep)
 {
        uchar_t *nv_value;
-       int      rc;
-
-       LASSERT(obj->oo_sa_hdl);
+       int      rc = 0;
 
-       if (obj->oo_sa_xattr == NULL) {
-               rc = __osd_xattr_cache(env, obj);
-               if (rc)
-                       return rc;
-       }
+       rc = __osd_xattr_cache(obj);
+       if (rc)
+               return rc;
 
        LASSERT(obj->oo_sa_xattr);
-       rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
-                       sizep);
+       rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name,
+                                      &nv_value, sizep);
        if (rc)
                return rc;
 
@@ -162,7 +147,7 @@ int __osd_xattr_get_large(const struct lu_env *env, struct osd_device *osd,
        if (rc)
                return rc;
 
-       rc = __osd_obj2dnode(env, osd->od_os, xa_data_obj, &xa_data_dn);
+       rc = __osd_obj2dnode(osd->od_os, xa_data_obj, &xa_data_dn);
        if (rc)
                return rc;
 
@@ -361,6 +346,127 @@ int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt,
        RETURN(0);
 }
 
+int __osd_sa_attr_init(const struct lu_env *env, struct osd_object *obj,
+                      struct osd_thandle *oh)
+{
+       sa_bulk_attr_t  *bulk = osd_oti_get(env)->oti_attr_bulk;
+       struct osa_attr *osa = &osd_oti_get(env)->oti_osa;
+       struct lu_buf *lb = &osd_oti_get(env)->oti_xattr_lbuf;
+       struct osd_device *osd = osd_obj2dev(obj);
+       uint64_t crtime[2], gen;
+       timestruc_t now;
+       size_t size;
+       int rc, cnt;
+
+       obj->oo_late_xattr = 0;
+       obj->oo_late_attr_set = 0;
+
+       gen = dmu_tx_get_txg(oh->ot_tx);
+       gethrestime(&now);
+       ZFS_TIME_ENCODE(&now, crtime);
+
+       osa->atime[0] = obj->oo_attr.la_atime;
+       osa->ctime[0] = obj->oo_attr.la_ctime;
+       osa->mtime[0] = obj->oo_attr.la_mtime;
+       osa->mode = obj->oo_attr.la_mode;
+       osa->uid = obj->oo_attr.la_uid;
+       osa->gid = obj->oo_attr.la_gid;
+       osa->rdev = obj->oo_attr.la_rdev;
+       osa->nlink = obj->oo_attr.la_nlink;
+       osa->flags = attrs_fs2zfs(obj->oo_attr.la_flags);
+       osa->size  = obj->oo_attr.la_size;
+#ifdef ZFS_PROJINHERIT
+       if (osd->od_projectused_dn) {
+               if (obj->oo_attr.la_valid & LA_PROJID)
+                       osa->projid = obj->oo_attr.la_projid;
+               else
+                       osa->projid = ZFS_DEFAULT_PROJID;
+               osa->flags |= ZFS_PROJID;
+               obj->oo_with_projid = 1;
+       }
+#endif
+
+       cnt = 0;
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MODE(osd), NULL, &osa->mode, 8);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_SIZE(osd), NULL, &osa->size, 8);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_GEN(osd), NULL, &gen, 8);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_UID(osd), NULL, &osa->uid, 8);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_GID(osd), NULL, &osa->gid, 8);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_PARENT(osd), NULL,
+                        &obj->oo_parent, 8);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_FLAGS(osd), NULL, &osa->flags, 8);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(osd), NULL, osa->atime, 16);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(osd), NULL, osa->mtime, 16);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(osd), NULL, osa->ctime, 16);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CRTIME(osd), NULL, crtime, 16);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_LINKS(osd), NULL, &osa->nlink, 8);
+#ifdef ZFS_PROJINHERIT
+       if (osd->od_projectused_dn)
+               SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_PROJID(osd), NULL,
+                                &osa->projid, 8);
+#endif
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_RDEV(osd), NULL, &osa->rdev, 8);
+       LASSERT(cnt <= ARRAY_SIZE(osd_oti_get(env)->oti_attr_bulk));
+
+       /* Update the SA for additions, modifications, and removals. */
+       rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR);
+       if (rc)
+               return rc;
+
+       lu_buf_check_and_alloc(lb, size);
+       if (lb->lb_buf == NULL) {
+               CERROR("%s: can't allocate buffer for xattr update\n",
+                               osd->od_svname);
+               return -ENOMEM;
+       }
+
+       rc = -nvlist_pack(obj->oo_sa_xattr, (char **)&lb->lb_buf, &size,
+                         NV_ENCODE_XDR, KM_SLEEP);
+       if (rc)
+               return rc;
+
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_DXATTR(osd), NULL, lb->lb_buf, size);
+
+       rc = -sa_replace_all_by_template(obj->oo_sa_hdl, bulk, cnt, oh->ot_tx);
+
+       return rc;
+}
+
+int __osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj,
+                          struct osd_thandle *oh)
+{
+       struct lu_buf     *lb = &osd_oti_get(env)->oti_xattr_lbuf;
+       struct osd_device *osd = osd_obj2dev(obj);
+       char              *dxattr;
+       size_t             size;
+       int                rc;
+
+       obj->oo_late_xattr = 0;
+
+       /* Update the SA for additions, modifications, and removals. */
+       rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR);
+       if (rc)
+               return rc;
+
+       lu_buf_check_and_alloc(lb, size);
+       if (lb->lb_buf == NULL) {
+               CERROR("%s: can't allocate buffer for xattr update\n",
+                               osd->od_svname);
+               return -ENOMEM;
+       }
+
+       dxattr = lb->lb_buf;
+       rc = -nvlist_pack(obj->oo_sa_xattr, &dxattr, &size,
+                       NV_ENCODE_XDR, KM_SLEEP);
+       if (rc)
+               return rc;
+       LASSERT(dxattr == lb->lb_buf);
+
+       sa_update(obj->oo_sa_hdl, SA_ZPL_DXATTR(osd), dxattr, size, oh->ot_tx);
+
+       return 0;
+}
+
 /*
  * Set an extended attribute.
  * This transaction must have called udmu_xattr_declare_set() first.
@@ -369,36 +475,20 @@ int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt,
  *
  * No locking is done here.
  */
-int __osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj,
-                     struct osd_thandle *oh)
+int __osd_sa_xattr_schedule_update(const struct lu_env *env,
+                                  struct osd_object *obj,
+                                  struct osd_thandle *oh)
 {
-       struct osd_device *osd = osd_obj2dev(obj);
-       char              *dxattr;
-       size_t             sa_size;
-       int                rc;
-
        ENTRY;
        LASSERT(obj->oo_sa_hdl);
        LASSERT(obj->oo_sa_xattr);
 
-       /* Update the SA for additions, modifications, and removals. */
-       rc = -nvlist_size(obj->oo_sa_xattr, &sa_size, NV_ENCODE_XDR);
-       if (rc)
-               return rc;
-
-       dxattr = osd_zio_buf_alloc(sa_size);
-       if (dxattr == NULL)
-               RETURN(-ENOMEM);
+       /* schedule batched SA update in osd_object_sa_dirty_rele() */
+       obj->oo_late_xattr = 1;
+       osd_object_sa_dirty_add(obj, oh);
 
-       rc = -nvlist_pack(obj->oo_sa_xattr, &dxattr, &sa_size,
-                               NV_ENCODE_XDR, KM_SLEEP);
-       if (rc)
-               GOTO(out_free, rc);
+       RETURN(0);
 
-       rc = osd_object_sa_update(obj, SA_ZPL_DXATTR(osd), dxattr, sa_size, oh);
-out_free:
-       osd_zio_buf_free(dxattr, sa_size);
-       RETURN(rc);
 }
 
 int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
@@ -411,12 +501,9 @@ int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
        int     rc;
        int     too_big = 0;
 
-       LASSERT(obj->oo_sa_hdl);
-       if (obj->oo_sa_xattr == NULL) {
-               rc = __osd_xattr_cache(env, obj);
-               if (rc)
-                       return rc;
-       }
+       rc = __osd_xattr_cache(obj);
+       if (rc)
+               return rc;
 
        LASSERT(obj->oo_sa_xattr);
        /* Limited to 32k to keep nvpair memory allocations small */
@@ -445,7 +532,7 @@ int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
                                                DATA_TYPE_BYTE_ARRAY);
                        if (rc < 0)
                                return rc;
-                       rc = __osd_sa_xattr_update(env, obj, oh);
+                       rc = __osd_sa_xattr_schedule_update(env, obj, oh);
                        return rc == 0 ? -EFBIG : rc;
                }
        } else if (rc == -ENOENT) {
@@ -476,7 +563,13 @@ int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
        if (rc)
                return rc;
 
-       rc = __osd_sa_xattr_update(env, obj, oh);
+       /* batch updates only for just created dnodes where we
+        * used to set number of EAs in a single transaction */
+       if (obj->oo_dn->dn_allocated_txg == oh->ot_tx->tx_txg)
+               rc = __osd_sa_xattr_schedule_update(env, obj, oh);
+       else
+               rc = __osd_sa_xattr_update(env, obj, oh);
+
        return rc;
 }
 
@@ -501,7 +594,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_dn, tx, la, 0);
+               rc = __osd_zap_create(env, osd, &xa_zap_dn, tx, la, 0, 0);
                if (rc)
                        return rc;
 
@@ -523,7 +616,7 @@ __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
                 * Entry already exists.
                 * We'll truncate the existing object.
                 */
-               rc = __osd_obj2dnode(env, osd->od_os, xa_data_obj, &xa_data_dn);
+               rc = __osd_obj2dnode(osd->od_os, xa_data_obj, &xa_data_dn);
                if (rc)
                        goto out;
 
@@ -682,15 +775,13 @@ static int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj,
 {
        int rc;
 
-       if (obj->oo_sa_xattr == NULL) {
-               rc = __osd_xattr_cache(env, obj);
-               if (rc)
-                       return rc;
-       }
+       rc = __osd_xattr_cache(obj);
+       if (rc)
+               return rc;
 
        rc = -nvlist_remove(obj->oo_sa_xattr, name, DATA_TYPE_BYTE_ARRAY);
        if (rc == 0)
-               rc = __osd_sa_xattr_update(env, obj, oh);
+               rc = __osd_sa_xattr_schedule_update(env, obj, oh);
        return rc;
 }
 
@@ -856,13 +947,9 @@ osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj,
        int       len, counted = 0;
        int       rc = 0;
 
-       if (obj->oo_sa_xattr == NULL) {
-               rc = __osd_xattr_cache(env, obj);
-               if (rc)
-                       return rc;
-       }
-
-       LASSERT(obj->oo_sa_xattr);
+       rc = __osd_xattr_cache(obj);
+       if (rc)
+               return rc;
 
        while ((nvp = nvlist_next_nvpair(obj->oo_sa_xattr, nvp)) != NULL) {
                const char *name = nvpair_name(nvp);