+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;
+}
+