/* * Set an extended attribute. * This transaction must have called udmu_xattr_declare_set() first. * * Returns 0 on success or a negative error number on failure. * * No locking is done here. */ static 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); udmu_objset_t *uos = &osd->od_objset; 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 = sa_spill_alloc(KM_SLEEP); if (dxattr == NULL) RETURN(-ENOMEM); rc = -nvlist_pack(obj->oo_sa_xattr, &dxattr, &sa_size, NV_ENCODE_XDR, KM_SLEEP); if (rc) GOTO(out_free, rc); rc = osd_object_sa_update(obj, SA_ZPL_DXATTR(uos), dxattr, sa_size, oh); out_free: sa_spill_free(dxattr); RETURN(rc); }
/* * Concurrency: @dt is write locked. */ static int osd_object_ref_del(const struct lu_env *env, struct dt_object *dt, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; struct osd_device *osd = osd_obj2dev(obj); udmu_objset_t *uos = &osd->od_objset; uint64_t nlink; int rc; ENTRY; LASSERT(osd_invariant(obj)); LASSERT(dt_object_exists(dt)); LASSERT(obj->oo_sa_hdl != NULL); oh = container_of0(handle, struct osd_thandle, ot_super); LASSERT(!lu_object_is_dying(dt->do_lu.lo_header)); write_lock(&obj->oo_attr_lock); nlink = --obj->oo_attr.la_nlink; write_unlock(&obj->oo_attr_lock); rc = osd_object_sa_update(obj, SA_ZPL_LINKS(uos), &nlink, 8, oh); return rc; }
/* * Concurrency: @dt is write locked. */ static int osd_object_ref_del(const struct lu_env *env, struct dt_object *dt, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; struct osd_device *osd = osd_obj2dev(obj); uint64_t nlink; int rc; ENTRY; down_read(&obj->oo_guard); if (unlikely(!dt_object_exists(dt) || obj->oo_destroyed)) GOTO(out, rc = -ENOENT); LASSERT(osd_invariant(obj)); LASSERT(obj->oo_sa_hdl != NULL); oh = container_of0(handle, struct osd_thandle, ot_super); LASSERT(!lu_object_is_dying(dt->do_lu.lo_header)); write_lock(&obj->oo_attr_lock); nlink = --obj->oo_attr.la_nlink; write_unlock(&obj->oo_attr_lock); rc = osd_object_sa_update(obj, SA_ZPL_LINKS(osd), &nlink, 8, oh); out: up_read(&obj->oo_guard); RETURN(rc); }
/* * Concurrency: @dt is write locked. */ static int osd_object_ref_add(const struct lu_env *env, struct dt_object *dt, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; struct osd_device *osd = osd_obj2dev(obj); uint64_t nlink; int rc; ENTRY; LASSERT(osd_invariant(obj)); LASSERT(dt_object_exists(dt)); LASSERT(obj->oo_sa_hdl != NULL); oh = container_of0(handle, struct osd_thandle, ot_super); write_lock(&obj->oo_attr_lock); nlink = ++obj->oo_attr.la_nlink; write_unlock(&obj->oo_attr_lock); rc = osd_object_sa_update(obj, SA_ZPL_LINKS(osd), &nlink, 8, oh); return rc; }
static ssize_t osd_write(const struct lu_env *env, struct dt_object *dt, const struct lu_buf *buf, loff_t *pos, struct thandle *th, int ignore_quota) { struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); struct osd_thandle *oh; uint64_t offset = *pos; int rc; ENTRY; LASSERT(dt_object_exists(dt)); LASSERT(obj->oo_db); LASSERT(th != NULL); oh = container_of0(th, struct osd_thandle, ot_super); record_start_io(osd, WRITE, 0); dmu_write(osd->od_os, obj->oo_db->db_object, offset, (uint64_t)buf->lb_len, buf->lb_buf, oh->ot_tx); write_lock(&obj->oo_attr_lock); if (obj->oo_attr.la_size < offset + buf->lb_len) { obj->oo_attr.la_size = offset + buf->lb_len; write_unlock(&obj->oo_attr_lock); /* osd_object_sa_update() will be copying directly from oo_attr * into dbuf. any update within a single txg will copy the * most actual */ rc = osd_object_sa_update(obj, SA_ZPL_SIZE(osd), &obj->oo_attr.la_size, 8, oh); if (unlikely(rc)) GOTO(out, rc); } else { write_unlock(&obj->oo_attr_lock); } *pos += buf->lb_len; rc = buf->lb_len; out: record_end_io(osd, WRITE, 0, buf->lb_len, buf->lb_len >> PAGE_CACHE_SHIFT); RETURN(rc); }
int __osd_xattr_set(const struct lu_env *env, struct osd_object *obj, const struct lu_buf *buf, const char *name, int fl, struct osd_thandle *oh) { struct osd_device *osd = osd_obj2dev(obj); dmu_buf_t *xa_zap_db = NULL; dmu_buf_t *xa_data_db = NULL; uint64_t xa_data_obj; sa_handle_t *sa_hdl = NULL; dmu_tx_t *tx = oh->ot_tx; uint64_t size; int rc; LASSERT(obj->oo_sa_hdl); if (obj->oo_xattr == ZFS_NO_OBJECT) { struct lu_attr *la = &osd_oti_get(env)->oti_la; 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); if (rc) return rc; obj->oo_xattr = xa_zap_db->db_object; rc = osd_object_sa_update(obj, SA_ZPL_XATTR(osd), &obj->oo_xattr, 8, oh); if (rc) goto out; } rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t), 1, &xa_data_obj); if (rc == 0) { if (fl & LU_XATTR_CREATE) { rc = -EEXIST; goto out; } /* * Entry already exists. * We'll truncate the existing object. */ rc = __osd_obj2dbuf(env, osd->od_os, xa_data_obj, &xa_data_db); if (rc) goto out; rc = -sa_handle_get(osd->od_os, xa_data_obj, NULL, SA_HDL_PRIVATE, &sa_hdl); if (rc) goto out; rc = -sa_lookup(sa_hdl, SA_ZPL_SIZE(osd), &size, 8); if (rc) goto out_sa; rc = -dmu_free_range(osd->od_os, xa_data_db->db_object, 0, DMU_OBJECT_END, tx); if (rc) goto out_sa; } else if (rc == -ENOENT) { struct lu_attr *la = &osd_oti_get(env)->oti_la; /* * Entry doesn't exist, we need to create a new one and a new * object to store the value. */ if (fl & LU_XATTR_REPLACE) { /* should be ENOATTR according to the * man, but that is undefined here */ rc = -ENODATA; goto out; } 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); if (rc) goto out; xa_data_obj = xa_data_db->db_object; rc = -sa_handle_get(osd->od_os, xa_data_obj, NULL, SA_HDL_PRIVATE, &sa_hdl); if (rc) goto out; rc = -zap_add(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t), 1, &xa_data_obj, tx); if (rc) goto out_sa; } else { /* There was an error looking up the xattr name */ goto out; } /* Finally write the xattr value */ dmu_write(osd->od_os, xa_data_obj, 0, buf->lb_len, buf->lb_buf, tx); size = buf->lb_len; rc = -sa_update(sa_hdl, SA_ZPL_SIZE(osd), &size, 8, tx); out_sa: sa_handle_destroy(sa_hdl); out: if (xa_data_db != NULL) dmu_buf_rele(xa_data_db, FTAG); if (xa_zap_db != NULL) dmu_buf_rele(xa_zap_db, FTAG); return rc; }
/** * Inserts (key, value) pair in \a directory object. * * \param dt osd index object * \param key key for index * \param rec record reference * \param th transaction handler * \param capa capability descriptor * \param ignore_quota update should not affect quota * * \retval 0 success * \retval -ve failure */ static int osd_dir_insert(const struct lu_env *env, struct dt_object *dt, const struct dt_rec *rec, const struct dt_key *key, struct thandle *th, struct lustre_capa *capa, int ignore_quota) { struct osd_thread_info *oti = osd_oti_get(env); struct osd_object *parent = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(parent); struct lu_fid *fid = (struct lu_fid *)rec; struct osd_thandle *oh; struct osd_object *child = NULL; __u32 attr; char *name = (char *)key; int rc; ENTRY; LASSERT(parent->oo_db); LASSERT(udmu_object_is_zap(parent->oo_db)); LASSERT(dt_object_exists(dt)); LASSERT(osd_invariant(parent)); LASSERT(th != NULL); oh = container_of0(th, struct osd_thandle, ot_super); rc = osd_remote_fid(env, osd, fid); if (rc < 0) { CERROR("%s: Can not find object "DFID": rc = %d\n", osd->od_svname, PFID(fid), rc); RETURN(rc); } if (unlikely(rc == 1)) { /* Insert remote entry */ memset(&oti->oti_zde.lzd_reg, 0, sizeof(oti->oti_zde.lzd_reg)); oti->oti_zde.lzd_reg.zde_type = IFTODT(S_IFDIR & S_IFMT); } else { /* * To simulate old Orion setups with ./.. stored in the * directories */ /* Insert local entry */ child = osd_object_find(env, dt, fid); if (IS_ERR(child)) RETURN(PTR_ERR(child)); LASSERT(child->oo_db); if (name[0] == '.') { if (name[1] == 0) { /* do not store ".", instead generate it * during iteration */ GOTO(out, rc = 0); } else if (name[1] == '.' && name[2] == 0) { /* update parent dnode in the child. * later it will be used to generate ".." */ udmu_objset_t *uos = &osd->od_objset; rc = osd_object_sa_update(parent, SA_ZPL_PARENT(uos), &child->oo_db->db_object, 8, oh); GOTO(out, rc); } } CLASSERT(sizeof(oti->oti_zde.lzd_reg) == 8); CLASSERT(sizeof(oti->oti_zde) % 8 == 0); attr = child->oo_dt.do_lu.lo_header ->loh_attr; oti->oti_zde.lzd_reg.zde_type = IFTODT(attr & S_IFMT); oti->oti_zde.lzd_reg.zde_dnode = child->oo_db->db_object; } oti->oti_zde.lzd_fid = *fid; /* Insert (key,oid) into ZAP */ rc = -zap_add(osd->od_objset.os, parent->oo_db->db_object, (char *)key, 8, sizeof(oti->oti_zde) / 8, (void *)&oti->oti_zde, oh->ot_tx); out: if (child != NULL) osd_object_put(env, child); RETURN(rc); }