static uint64_t zpios_dmu_object_create(run_args_t *run_args, objset_t *os) { struct dmu_tx *tx; uint64_t obj = 0ULL; int rc; tx = dmu_tx_create(os); dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, OBJ_SIZE); rc = dmu_tx_assign(tx, TXG_WAIT); if (rc) { zpios_print(run_args->file, "dmu_tx_assign() failed: %d\n", rc); dmu_tx_abort(tx); return obj; } obj = dmu_object_alloc(os, DMU_OT_UINT64_OTHER, 0, DMU_OT_NONE, 0, tx); rc = dmu_object_set_blocksize(os, obj, 128ULL << 10, 0, tx); if (rc) { zpios_print(run_args->file, "dmu_object_set_blocksize() failed: %d\n", rc); dmu_tx_abort(tx); return obj; } dmu_tx_commit(tx); return obj; }
/* * Grow the block size for a file. * * IN: zp - znode of file to free data in. * size - requested block size * tx - open transaction. * * NOTE: this function assumes that the znode is write locked. */ void zfs_grow_blocksize(znode_t *zp, uint64_t size, dmu_tx_t *tx) { int error; u_longlong_t dummy; if (size <= zp->z_blksz) return; /* * If the file size is already greater than the current blocksize, * we will not grow. If there is more than one block in a file, * the blocksize cannot change. */ if (zp->z_blksz && zp->z_size > zp->z_blksz) return; error = dmu_object_set_blocksize(ZTOZSB(zp)->z_os, zp->z_id, size, 0, tx); if (error == ENOTSUP) return; ASSERT0(error); /* What blocksize did we actually get? */ dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &zp->z_blksz, &dummy); }
static dmu_buf_t* osd_mkreg(const struct lu_env *env, struct osd_device *osd, struct lu_attr *la, struct osd_thandle *oh) { dmu_buf_t *db; int rc; LASSERT(S_ISREG(la->la_mode)); rc = __osd_object_create(env, &osd->od_objset, &db, oh->ot_tx, la, osd_obj_tag); if (rc) return ERR_PTR(rc); /* * XXX: a hack, OST to use bigger blocksize. we need * a method in OSD API to control this from OFD/MDD */ if (!lu_device_is_md(osd2lu_dev(osd))) { rc = -dmu_object_set_blocksize(osd->od_objset.os, db->db_object, 128 << 10, 0, oh->ot_tx); if (unlikely(rc)) { CERROR("%s: can't change blocksize: %d\n", osd->od_svname, rc); return ERR_PTR(rc); } } return db; }
static dmu_buf_t *osd_mkreg(const struct lu_env *env, struct osd_object *obj, struct lu_attr *la, struct osd_thandle *oh) { const struct lu_fid *fid = lu_object_fid(&obj->oo_dt.do_lu); dmu_buf_t *db; int rc; struct osd_device *osd = osd_obj2dev(obj); LASSERT(S_ISREG(la->la_mode)); rc = __osd_object_create(env, obj, &db, oh->ot_tx, la); if (rc) return ERR_PTR(rc); if ((fid_is_idif(fid) || fid_is_norm(fid) || fid_is_echo(fid)) && osd->od_is_ost) { /* The minimum block size must be at least page size otherwise * it will break the assumption in tgt_thread_big_cache where * the array size is PTLRPC_MAX_BRW_PAGES. It will also affect * RDMA due to subpage transfer size */ rc = -dmu_object_set_blocksize(osd->od_os, db->db_object, PAGE_SIZE, 0, oh->ot_tx); if (unlikely(rc)) { CERROR("%s: can't change blocksize: %d\n", osd->od_svname, rc); return ERR_PTR(rc); } } return db; }
static dmu_buf_t *osd_mkreg(const struct lu_env *env, struct osd_object *obj, struct lu_attr *la, uint64_t parent, struct osd_thandle *oh) { dmu_buf_t *db; int rc; struct osd_device *osd = osd_obj2dev(obj); LASSERT(S_ISREG(la->la_mode)); rc = __osd_object_create(env, obj, &db, oh->ot_tx, la, parent); if (rc) return ERR_PTR(rc); /* * XXX: This heuristic is non-optimal. It would be better to * increase the blocksize up to osd->od_max_blksz during the write. * This is exactly how the ZPL behaves and it ensures that the right * blocksize is selected based on the file size rather than the * making broad assumptions based on the osd type. */ if (!lu_device_is_md(osd2lu_dev(osd))) { rc = -dmu_object_set_blocksize(osd->od_os, db->db_object, osd->od_max_blksz, 0, oh->ot_tx); if (unlikely(rc)) { CERROR("%s: can't change blocksize: %d\n", osd->od_svname, rc); return ERR_PTR(rc); } } return db; }
static dmu_buf_t *osd_mkreg(const struct lu_env *env, struct osd_object *obj, struct lu_attr *la, uint64_t parent, struct osd_thandle *oh) { dmu_buf_t *db; int rc; struct osd_device *osd = osd_obj2dev(obj); LASSERT(S_ISREG(la->la_mode)); rc = __osd_object_create(env, obj, &db, oh->ot_tx, la, parent); if (rc) return ERR_PTR(rc); if (!lu_device_is_md(osd2lu_dev(osd))) { /* uses 4K as default block size because clients write data * with page size that is 4K at minimum */ rc = -dmu_object_set_blocksize(osd->od_os, db->db_object, 4096, 0, oh->ot_tx); if (unlikely(rc)) { CERROR("%s: can't change blocksize: %d\n", osd->od_svname, rc); return ERR_PTR(rc); } } return db; }
static uint64_t zpios_dmu_object_create(run_args_t *run_args, objset_t *os) { struct dmu_tx *tx; uint64_t obj = 0ULL; uint64_t blksize = run_args->block_size; int rc; if (blksize < SPA_MINBLOCKSIZE || blksize > spa_maxblocksize(dmu_objset_spa(os)) || !ISP2(blksize)) { zpios_print(run_args->file, "invalid block size for pool: %d\n", (int)blksize); return (obj); } tx = dmu_tx_create(os); dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, OBJ_SIZE); rc = dmu_tx_assign(tx, TXG_WAIT); if (rc) { zpios_print(run_args->file, "dmu_tx_assign() failed: %d\n", rc); dmu_tx_abort(tx); return (obj); } obj = dmu_object_alloc(os, DMU_OT_UINT64_OTHER, 0, DMU_OT_NONE, 0, tx); rc = dmu_object_set_blocksize(os, obj, blksize, 0, tx); if (rc) { zpios_print(run_args->file, "dmu_object_set_blocksize to %d failed: %d\n", (int)blksize, rc); dmu_tx_abort(tx); return (obj); } dmu_tx_commit(tx); return (obj); }
/* * Set ZFS_PROP_VOLBLOCKSIZE set entry point. */ int zvol_set_volblocksize(const char *name, uint64_t volblocksize) { zvol_state_t *zv; dmu_tx_t *tx; int error; mutex_enter(&zvol_state_lock); zv = zvol_find_by_name(name); if (zv == NULL) { error = SET_ERROR(ENXIO); goto out; } if (zv->zv_flags & ZVOL_RDONLY) { error = SET_ERROR(EROFS); goto out; } tx = dmu_tx_create(zv->zv_objset); dmu_tx_hold_bonus(tx, ZVOL_OBJ); error = dmu_tx_assign(tx, TXG_WAIT); if (error) { dmu_tx_abort(tx); } else { error = dmu_object_set_blocksize(zv->zv_objset, ZVOL_OBJ, volblocksize, 0, tx); if (error == ENOTSUP) error = SET_ERROR(EBUSY); dmu_tx_commit(tx); if (error == 0) zv->zv_volblocksize = volblocksize; } out: mutex_exit(&zvol_state_lock); return (SET_ERROR(error)); }
int zvol_set_volblocksize(zfs_cmd_t *zc) { zvol_state_t *zv; dmu_tx_t *tx; int error; mutex_enter(&zvol_state_lock); if ((zv = zvol_minor_lookup(zc->zc_name)) == NULL) { mutex_exit(&zvol_state_lock); return (ENXIO); } 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_bonus(tx, ZVOL_OBJ); error = dmu_tx_assign(tx, TXG_WAIT); if (error) { dmu_tx_abort(tx); } else { error = dmu_object_set_blocksize(zv->zv_objset, ZVOL_OBJ, zc->zc_volblocksize, 0, tx); if (error == ENOTSUP) error = EBUSY; dmu_tx_commit(tx); } mutex_exit(&zvol_state_lock); return (error); }
int zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx, krw_t lti, int fatreader, zap_t **zapp) { zap_t *zap; dmu_buf_t *db; krw_t lt; int err; *zapp = NULL; err = dmu_buf_hold(os, obj, 0, NULL, &db); if (err) return (err); #ifdef ZFS_DEBUG { dmu_object_info_t doi; dmu_object_info_from_db(db, &doi); ASSERT(dmu_ot[doi.doi_type].ot_byteswap == zap_byteswap); } #endif zap = dmu_buf_get_user(db); if (zap == NULL) zap = mzap_open(os, obj, db); /* * We're checking zap_ismicro without the lock held, in order to * tell what type of lock we want. Once we have some sort of * lock, see if it really is the right type. In practice this * can only be different if it was upgraded from micro to fat, * and micro wanted WRITER but fat only needs READER. */ lt = (!zap->zap_ismicro && fatreader) ? RW_READER : lti; rw_enter(&zap->zap_rwlock, lt); if (lt != ((!zap->zap_ismicro && fatreader) ? RW_READER : lti)) { /* it was upgraded, now we only need reader */ ASSERT(lt == RW_WRITER); ASSERT(RW_READER == (!zap->zap_ismicro && fatreader) ? RW_READER : lti); rw_downgrade(&zap->zap_rwlock); lt = RW_READER; } zap->zap_objset = os; if (lt == RW_WRITER) dmu_buf_will_dirty(db, tx); ASSERT3P(zap->zap_dbuf, ==, db); ASSERT(!zap->zap_ismicro || zap->zap_m.zap_num_entries <= zap->zap_m.zap_num_chunks); if (zap->zap_ismicro && tx && zap->zap_m.zap_num_entries == zap->zap_m.zap_num_chunks) { uint64_t newsz = db->db_size + SPA_MINBLOCKSIZE; if (newsz > MZAP_MAX_BLKSZ) { dprintf("upgrading obj %llu: num_entries=%u\n", obj, zap->zap_m.zap_num_entries); mzap_upgrade(zap, tx); *zapp = zap; return (0); } err = dmu_object_set_blocksize(os, obj, newsz, 0, tx); ASSERT3U(err, ==, 0); zap->zap_m.zap_num_chunks = db->db_size / MZAP_ENT_LEN - 1; }