int zvol_set_volsize(zfs_cmd_t *zc) { zvol_state_t *zv; dev_t dev = zc->zc_dev; dmu_tx_t *tx; int error; dmu_object_info_t doi; mutex_enter(&zvol_state_lock); if ((zv = zvol_minor_lookup(zc->zc_name)) == NULL) { mutex_exit(&zvol_state_lock); return (ENXIO); } if ((error = dmu_object_info(zv->zv_objset, ZVOL_OBJ, &doi)) != 0 || (error = zvol_check_volsize(zc, doi.doi_data_block_size)) != 0) { mutex_exit(&zvol_state_lock); return (error); } if (zv->zv_readonly || (zv->zv_mode & DS_MODE_READONLY)) { mutex_exit(&zvol_state_lock); return (EROFS); } tx = dmu_tx_create(zv->zv_objset); dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL); dmu_tx_hold_free(tx, ZVOL_OBJ, zc->zc_volsize, DMU_OBJECT_END); error = dmu_tx_assign(tx, TXG_WAIT); if (error) { dmu_tx_abort(tx); mutex_exit(&zvol_state_lock); return (error); } error = zap_update(zv->zv_objset, ZVOL_ZAP_OBJ, "size", 8, 1, &zc->zc_volsize, tx); if (error == 0) { error = dmu_free_range(zv->zv_objset, ZVOL_OBJ, zc->zc_volsize, DMU_OBJECT_END, tx); } dmu_tx_commit(tx); if (error == 0) { zv->zv_volsize = zc->zc_volsize; zvol_size_changed(zv, dev); } mutex_exit(&zvol_state_lock); return (error); }
void bplist_vacate(bplist_t *bpl, dmu_tx_t *tx) { mutex_enter(&bpl->bpl_lock); ASSERT3P(bpl->bpl_queue, ==, NULL); VERIFY(0 == bplist_hold(bpl)); dmu_buf_will_dirty(bpl->bpl_dbuf, tx); VERIFY(0 == dmu_free_range(bpl->bpl_mos, bpl->bpl_object, 0, -1ULL, tx)); bpl->bpl_phys->bpl_entries = 0; bpl->bpl_phys->bpl_bytes = 0; if (bpl->bpl_havecomp) { bpl->bpl_phys->bpl_comp = 0; bpl->bpl_phys->bpl_uncomp = 0; } mutex_exit(&bpl->bpl_lock); }
static int zap_table_grow(zap_t *zap, zap_table_phys_t *tbl, void (*transfer_func)(const uint64_t *src, uint64_t *dst, int n), dmu_tx_t *tx) { uint64_t b, newblk; dmu_buf_t *db_old, *db_new; int err; int bs = FZAP_BLOCK_SHIFT(zap); int hepb = 1<<(bs-4); /* hepb = half the number of entries in a block */ ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); ASSERT(tbl->zt_blk != 0); ASSERT(tbl->zt_numblks > 0); if (tbl->zt_nextblk != 0) { newblk = tbl->zt_nextblk; } else { newblk = zap_allocate_blocks(zap, tbl->zt_numblks * 2); tbl->zt_nextblk = newblk; ASSERT0(tbl->zt_blks_copied); dmu_prefetch(zap->zap_objset, zap->zap_object, tbl->zt_blk << bs, tbl->zt_numblks << bs); } /* * Copy the ptrtbl from the old to new location. */ b = tbl->zt_blks_copied; err = dmu_buf_hold(zap->zap_objset, zap->zap_object, (tbl->zt_blk + b) << bs, FTAG, &db_old, DMU_READ_NO_PREFETCH); if (err) return (err); /* first half of entries in old[b] go to new[2*b+0] */ VERIFY(0 == dmu_buf_hold(zap->zap_objset, zap->zap_object, (newblk + 2*b+0) << bs, FTAG, &db_new, DMU_READ_NO_PREFETCH)); dmu_buf_will_dirty(db_new, tx); transfer_func(db_old->db_data, db_new->db_data, hepb); dmu_buf_rele(db_new, FTAG); /* second half of entries in old[b] go to new[2*b+1] */ VERIFY(0 == dmu_buf_hold(zap->zap_objset, zap->zap_object, (newblk + 2*b+1) << bs, FTAG, &db_new, DMU_READ_NO_PREFETCH)); dmu_buf_will_dirty(db_new, tx); transfer_func((uint64_t *)db_old->db_data + hepb, db_new->db_data, hepb); dmu_buf_rele(db_new, FTAG); dmu_buf_rele(db_old, FTAG); tbl->zt_blks_copied++; dprintf("copied block %llu of %llu\n", tbl->zt_blks_copied, tbl->zt_numblks); if (tbl->zt_blks_copied == tbl->zt_numblks) { (void) dmu_free_range(zap->zap_objset, zap->zap_object, tbl->zt_blk << bs, tbl->zt_numblks << bs, tx); tbl->zt_blk = newblk; tbl->zt_numblks *= 2; tbl->zt_shift++; tbl->zt_nextblk = 0; tbl->zt_blks_copied = 0; dprintf("finished; numblocks now %llu (%lluk entries)\n", tbl->zt_numblks, 1<<(tbl->zt_shift-10)); } return (0); }
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; }