AC_DEFINE(HAVE_DMU_USEROBJ_ACCOUNTING, 1,
[Have native dnode accounting in ZFS])
])
+ dnl # ZFS 0.7.x adds new method zap_lookup_by_dnode
+ dnl #
+ LB_CHECK_COMPILE([if ZFS has 'zap_lookup_by_dnode'],
+ zap_lookup_by_dnode, [
+ #include <sys/zap.h>
+ #include <sys/dnode.h>
+ ],[
+ dnode_t *dn = NULL;
+ zap_lookup_by_dnode(dn, NULL, 1, 1, NULL);
+ ],[
+ AC_DEFINE(HAVE_ZAP_LOOKUP_BY_DNODE, 1,
+ [Have zap_lookup_by_dnode() in ZFS])
+ ])
+ dnl #
+ dnl # ZFS 0.7.x adds new method zap_add_by_dnode
+ dnl #
+ LB_CHECK_COMPILE([if ZFS has 'zap_add_by_dnode'],
+ zap_add_by_dnode, [
+ #include <sys/zap.h>
+ #include <sys/dnode.h>
+ ],[
+ dnode_t *dn = NULL;
+ zap_add_by_dnode(dn, NULL, 1, 1, NULL, NULL);
+ ],[
+ AC_DEFINE(HAVE_ZAP_ADD_BY_DNODE, 1,
+ [Have zap_add_by_dnode() in ZFS])
+ ])
+ dnl #
+ dnl # ZFS 0.7.x adds new method zap_remove_by_dnode
+ dnl #
+ LB_CHECK_COMPILE([if ZFS has 'zap_remove_by_dnode'],
+ zap_remove_by_dnode, [
+ #include <sys/zap.h>
+ #include <sys/dnode.h>
+ ],[
+ dnode_t *dn = NULL;
+ zap_remove_by_dnode(dn, NULL, NULL);
+ ],[
+ AC_DEFINE(HAVE_ZAP_REMOVE_ADD_BY_DNODE, 1,
+ [Have zap_remove_by_dnode() in ZFS])
+ ])
+ dnl #
+ dnl # ZFS 0.7.x adds new method dmu_tx_hold_zap_by_dnode
+ dnl #
+ LB_CHECK_COMPILE([if ZFS has 'dmu_tx_hold_zap_by_dnode'],
+ dmu_tx_hold_zap_by_dnode, [
+ #include <sys/zap.h>
+ #include <sys/dnode.h>
+ ],[
+ dnode_t *dn = NULL;
+ dmu_tx_hold_zap_by_dnode(NULL, dn, TRUE, NULL);
+ ],[
+ AC_DEFINE(HAVE_DMU_TX_HOLD_ZAP_BY_DNODE, 1,
+ [Have dmu_tx_hold_zap_by_dnode() in ZFS])
+ ])
+ dnl #
+ dnl # ZFS 0.7.x adds new method dmu_tx_hold_write_by_dnode
+ dnl #
+ LB_CHECK_COMPILE([if ZFS has 'dmu_tx_hold_write_by_dnode'],
+ dmu_tx_hold_write_by_dnode, [
+ #include <sys/zap.h>
+ #include <sys/dnode.h>
+ ],[
+ dnode_t *dn = NULL;
+ dmu_tx_hold_write_by_dnode(NULL, dn, 0, 0);
+ ],[
+ AC_DEFINE(HAVE_DMU_TX_HOLD_WRITE_BY_DNODE, 1,
+ [Have dmu_tx_hold_write_by_dnode() in ZFS])
+ ])
+ dnl #
+ dnl # ZFS 0.7.x adds new method dmu_write_by_dnode
+ dnl #
+ LB_CHECK_COMPILE([if ZFS has 'dmu_write_by_dnode'],
+ dmu_write_by_dnode, [
+ #include <sys/zap.h>
+ #include <sys/dnode.h>
+ ],[
+ dnode_t *dn = NULL;
+ dmu_write_by_dnode(dn, 0, 0, NULL, NULL);
+ ],[
+ AC_DEFINE(HAVE_DMU_WRITE_BY_DNODE, 1,
+ [Have dmu_write_by_dnode() in ZFS])
+ ])
+ dnl #
+ dnl # ZFS 0.7.x adds new method dmu_read_by_dnode
+ dnl #
+ LB_CHECK_COMPILE([if ZFS has 'dmu_read_by_dnode'],
+ dmu_read_by_dnode, [
+ #include <sys/zap.h>
+ #include <sys/dnode.h>
+ ],[
+ dnode_t *dn = NULL;
+ dmu_read_by_dnode(dn, 0, 0, NULL, 0);
+ ],[
+ AC_DEFINE(HAVE_DMU_READ_BY_DNODE, 1,
+ [Have dmu_read_by_dnode() in ZFS])
+ ])
])
AM_CONDITIONAL(ZFS_ENABLED, [test "x$enable_zfs" = xyes])
RETURN(rc);
}
-static int osd_unlinked_object_free(struct osd_device *osd, uint64_t oid);
-
-static void osd_unlinked_list_emptify(struct osd_device *osd,
+static void osd_unlinked_list_emptify(const struct lu_env *env,
+ struct osd_device *osd,
struct list_head *list, bool free)
{
struct osd_object *obj;
list_del_init(&obj->oo_unlinked_linkage);
if (free)
- (void)osd_unlinked_object_free(osd, oid);
+ (void)osd_unlinked_object_free(env, osd, oid);
}
}
LASSERT(oh->ot_tx);
dmu_tx_abort(oh->ot_tx);
osd_object_sa_dirty_rele(oh);
- osd_unlinked_list_emptify(osd, &unlinked, false);
+ osd_unlinked_list_emptify(env, osd, &unlinked, false);
/* there won't be any commit, release reserved quota space now,
* if any */
qsd_op_end(env, osd->od_quota_slave, &oh->ot_quota_trans);
* by osd_trans_commit_cb already. */
dmu_tx_commit(oh->ot_tx);
- osd_unlinked_list_emptify(osd, &unlinked, true);
+ osd_unlinked_list_emptify(env, osd, &unlinked, true);
if (sync)
txg_wait_synced(dmu_objset_pool(osd->od_os), txg);
static int osd_objset_open(struct osd_device *o)
{
uint64_t version = ZPL_VERSION;
- uint64_t sa_obj;
+ uint64_t sa_obj, unlink_obj;
int rc;
ENTRY;
}
rc = -zap_lookup(o->od_os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET,
- 8, 1, &o->od_unlinkedid);
+ 8, 1, &unlink_obj);
if (rc) {
CERROR("%s: lookup for %s failed: rc = %d\n",
o->od_svname, ZFS_UNLINKED_SET, rc);
GOTO(out, rc = -ENOTSUPP);
}
+ rc = __osd_obj2dnode(o->od_os, unlink_obj, &o->od_unlinked);
+ if (rc) {
+ CERROR("%s: can't get dnode for unlinked: rc = %d\n",
+ o->od_svname, rc);
+ GOTO(out, rc);
+ }
+
out:
if (rc != 0 && o->od_os != NULL) {
dmu_objset_disown(o->od_os, o);
RETURN(rc);
}
-static int
-osd_unlinked_object_free(struct osd_device *osd, uint64_t oid)
+int osd_unlinked_object_free(const struct lu_env *env, struct osd_device *osd,
+ uint64_t oid)
{
+ char *key = osd_oti_get(env)->oti_str;
int rc;
dmu_tx_t *tx;
tx = dmu_tx_create(osd->od_os);
dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END);
- dmu_tx_hold_zap(tx, osd->od_unlinkedid, FALSE, NULL);
+ osd_tx_hold_zap(tx, osd->od_unlinked->dn_object, osd->od_unlinked,
+ FALSE, NULL);
rc = -dmu_tx_assign(tx, TXG_WAIT);
if (rc != 0) {
CWARN("%s: Cannot assign tx for %llu: rc = %d\n",
goto failed;
}
- rc = -zap_remove_int(osd->od_os, osd->od_unlinkedid, oid, tx);
+ snprintf(key, sizeof(osd_oti_get(env)->oti_str), "%llx", oid);
+ rc = osd_zap_remove(osd, osd->od_unlinked->dn_object,
+ osd->od_unlinked, key, tx);
if (rc != 0) {
CWARN("%s: Cannot remove %llu from unlinked set: rc = %d\n",
osd->od_svname, oid, rc);
zap_cursor_t zc;
zap_attribute_t *za = &osd_oti_get(env)->oti_za;
- zap_cursor_init(&zc, osd->od_os, osd->od_unlinkedid);
+ zap_cursor_init(&zc, osd->od_os, osd->od_unlinked->dn_object);
while (zap_cursor_retrieve(&zc, za) == 0) {
/* If cannot free the object, leave it in the unlinked set,
* until the OSD is mounted again when obd_unlinked_drain()
* will be called. */
- if (osd_unlinked_object_free(osd, za->za_first_integer) != 0)
+ if (osd_unlinked_object_free(env, osd, za->za_first_integer))
break;
zap_cursor_advance(&zc);
}
if (rc)
GOTO(err, rc);
- rc = __osd_obj2dnode(env, o->od_os, o->od_rootid, &rootdn);
+ rc = __osd_obj2dnode(o->od_os, o->od_rootid, &rootdn);
if (rc)
GOTO(err, rc);
-
o->od_root = rootdn->dn_object;
osd_dnode_rele(rootdn);
+ rc = __osd_obj2dnode(o->od_os, DMU_USERUSED_OBJECT,
+ &o->od_userused_dn);
+ if (rc)
+ GOTO(err, rc);
+
+ rc = __osd_obj2dnode(o->od_os, DMU_GROUPUSED_OBJECT,
+ &o->od_groupused_dn);
+ if (rc)
+ GOTO(err, rc);
+
/* 1. initialize oi before any file create or file open */
rc = osd_oi_init(env, o);
if (rc)
CERROR("%s: lost %d pinned dbuf(s)\n", o->od_svname,
atomic_read(&o->od_zerocopy_pin));
+ if (o->od_unlinked) {
+ osd_dnode_rele(o->od_unlinked);
+ o->od_unlinked = NULL;
+ }
+ if (o->od_userused_dn) {
+ osd_dnode_rele(o->od_userused_dn);
+ o->od_userused_dn = NULL;
+ }
+ if (o->od_groupused_dn) {
+ osd_dnode_rele(o->od_groupused_dn);
+ o->od_groupused_dn = NULL;
+ }
+
if (o->od_os != NULL) {
if (!o->od_dt_dev.dd_rdonly)
/* force a txg sync to get all commit callbacks */
}
memset(&oti->oti_zde.lzd_fid, 0, sizeof(struct lu_fid));
- rc = -zap_lookup(osd->od_os, obj->oo_dn->dn_object,
- (char *)key, 8, sizeof(oti->oti_zde) / 8,
- (void *)&oti->oti_zde);
+ rc = osd_zap_lookup(osd, obj->oo_dn->dn_object, obj->oo_dn,
+ (char *)key, 8, sizeof(oti->oti_zde) / 8,
+ (void *)&oti->oti_zde);
if (rc != 0)
RETURN(rc);
/* do not specify the key as then DMU is trying to look it up
* which is very expensive. usually the layers above lookup
* before insertion */
- dmu_tx_hold_zap(oh->ot_tx, object, TRUE, NULL);
+ osd_tx_hold_zap(oh->ot_tx, object, obj->oo_dn, TRUE, NULL);
osd_idc_find_or_init(env, osd, fid);
oti->oti_zde.lzd_fid = *fid;
/* Insert (key,oid) into ZAP */
- rc = -zap_add(osd->od_os, parent->oo_dn->dn_object,
- (char *)key, 8, sizeof(oti->oti_zde) / 8,
- (void *)&oti->oti_zde, oh->ot_tx);
+ rc = osd_zap_add(osd, parent->oo_dn->dn_object, parent->oo_dn,
+ (char *)key, 8, sizeof(oti->oti_zde) / 8,
+ (void *)&oti->oti_zde, oh->ot_tx);
if (unlikely(rc == -EEXIST &&
name[0] == '.' && name[1] == '.' && name[2] == 0))
/* Update (key,oid) in ZAP */
/* do not specify the key as then DMU is trying to look it up
* which is very expensive. usually the layers above lookup
* before deletion */
- dmu_tx_hold_zap(oh->ot_tx, dnode, FALSE, NULL);
+ osd_tx_hold_zap(oh->ot_tx, dnode, obj->oo_dn, FALSE, NULL);
RETURN(0);
}
}
/* Remove key from the ZAP */
- rc = -zap_remove(osd->od_os, zap_dn->dn_object,
- (char *) key, oh->ot_tx);
+ rc = osd_zap_remove(osd, zap_dn->dn_object, zap_dn,
+ (char *)key, oh->ot_tx);
if (unlikely(rc && rc != -ENOENT))
CERROR("%s: zap_remove failed: rc = %d\n", osd->od_svname, rc);
GOTO(out, rc = -EIO);
}
- rc = -zap_lookup(it->ozi_zc->zc_objset, it->ozi_zc->zc_zapobj,
- za->za_name, za->za_integer_length, 3, zde);
+ rc = osd_zap_lookup(osd_obj2dev(it->ozi_obj), it->ozi_zc->zc_zapobj,
+ it->ozi_obj->oo_dn, za->za_name,
+ za->za_integer_length, 3, zde);
if (rc)
GOTO(out, rc);
LASSERT(obj->oo_dn);
- dmu_tx_hold_bonus(oh->ot_tx, obj->oo_dn->dn_object);
-
/* do not specify the key as then DMU is trying to look it up
* which is very expensive. usually the layers above lookup
* before insertion */
- dmu_tx_hold_zap(oh->ot_tx, obj->oo_dn->dn_object, TRUE, NULL);
+ osd_tx_hold_zap(oh->ot_tx, obj->oo_dn->dn_object, obj->oo_dn,
+ TRUE, NULL);
RETURN(0);
}
/* do not specify the key as then DMU is trying to look it up
* which is very expensive. usually the layers above lookup
* before deletion */
- dmu_tx_hold_zap(oh->ot_tx, obj->oo_dn->dn_object, FALSE, NULL);
+ osd_tx_hold_zap(oh->ot_tx, obj->oo_dn->dn_object, obj->oo_dn,
+ FALSE, NULL);
RETURN(0);
}
/* information about underlying file system */
struct objset *od_os;
uint64_t od_rootid; /* id of root znode */
- uint64_t od_unlinkedid; /* id of unlinked zapobj */
+ dnode_t *od_unlinked; /* dnode of unlinked zapobj */
/* SA attr mapping->id,
* name is the same as in ZFS to use defines SA_ZPL_...*/
sa_attr_type_t *z_attr_table;
struct lu_site od_site;
/* object IDs of the inode accounting indexes */
- uint64_t od_iusr_oid;
- uint64_t od_igrp_oid;
+ uint64_t od_iusr_oid;
+ uint64_t od_igrp_oid;
+ dnode_t *od_groupused_dn;
+ dnode_t *od_userused_dn;
/* quota slave instance */
struct qsd_instance *od_quota_slave;
int osd_statfs(const struct lu_env *, struct dt_device *, struct obd_statfs *);
extern const struct dt_index_operations osd_acct_index_ops;
-int osd_quota_fid2dmu(const struct lu_fid *fid, uint64_t *oid);
+dnode_t *osd_quota_fid2dmu(const struct osd_device *, const struct lu_fid *fid);
extern struct lu_device_operations osd_lu_ops;
extern struct dt_index_operations osd_dir_ops;
int osd_declare_quota(const struct lu_env *env, struct osd_device *osd,
bool force);
uint64_t osd_objs_count_estimate(uint64_t refdbytes, uint64_t usedobjs,
uint64_t nrblocks, uint64_t est_maxblockshift);
+int osd_unlinked_object_free(const struct lu_env *env, struct osd_device *osd,
+ uint64_t oid);
/*
* Helpers.
/* osd_object.c */
extern char *osd_obj_tag;
void osd_object_sa_dirty_rele(struct osd_thandle *oh);
-int __osd_obj2dnode(const struct lu_env *env, objset_t *os,
- uint64_t oid, dnode_t **dnp);
+int __osd_obj2dnode(objset_t *os, uint64_t oid, dnode_t **dnp);
struct lu_object *osd_object_alloc(const struct lu_env *env,
const struct lu_object_header *hdr,
struct lu_device *d);
int osd_fid_lookup(const struct lu_env *env,
struct osd_device *, const struct lu_fid *, uint64_t *);
uint64_t osd_get_name_n_idx(const struct lu_env *env, struct osd_device *osd,
- const struct lu_fid *fid, char *buf, int bufsize);
+ const struct lu_fid *fid, char *buf, int bufsize,
+ dnode_t **zdn);
int osd_options_init(void);
int osd_ost_seq_exists(const struct lu_env *env, struct osd_device *osd,
__u64 seq);
}
#endif /* #ifdef HAVE_DMU_USEROBJ_ACCOUNTING */
+static inline int osd_zap_add(struct osd_device *osd, uint64_t zap,
+ dnode_t *dn, const char *key,
+ int int_size, int int_num,
+ const void *val, dmu_tx_t *tx)
+{
+ LASSERT(zap != 0);
+
+#ifdef HAVE_ZAP_ADD_BY_DNODE
+ if (dn)
+ return -zap_add_by_dnode(dn, key, int_size, int_num, val, tx);
+#endif
+ return -zap_add(osd->od_os, zap, key, int_size, int_num, val, tx);
+}
+
+static inline int osd_zap_remove(struct osd_device *osd, uint64_t zap,
+ dnode_t *dn, const char *key,
+ dmu_tx_t *tx)
+{
+ LASSERT(zap != 0);
+
+#ifdef HAVE_ZAP_ADD_BY_DNODE
+ if (dn)
+ return -zap_remove_by_dnode(dn, key, tx);
+#endif
+ return -zap_remove(osd->od_os, zap, key, tx);
+}
+
+
+static inline int osd_zap_lookup(struct osd_device *osd, uint64_t zap,
+ dnode_t *dn, const char *key,
+ int int_size, int int_num, void *v)
+{
+ LASSERT(zap != 0);
+
+#ifdef HAVE_ZAP_ADD_BY_DNODE
+ if (dn)
+ return -zap_lookup_by_dnode(dn, key, int_size, int_num, v);
+#endif
+ return -zap_lookup(osd->od_os, zap, key, int_size, int_num, v);
+}
+
+static inline void osd_tx_hold_zap(dmu_tx_t *tx, uint64_t zap,
+ dnode_t *dn, int add, const char *name)
+{
+#ifdef HAVE_DMU_TX_HOLD_ZAP_BY_DNODE
+ if (dn) {
+ dmu_tx_hold_zap_by_dnode(tx, dn, add, name);
+ return;
+ }
+#endif
+ dmu_tx_hold_zap(tx, zap, add, name);
+}
+
+static inline void osd_tx_hold_write(dmu_tx_t *tx, uint64_t oid,
+ dnode_t *dn, uint64_t off, int len)
+{
+#ifdef HAVE_DMU_TX_HOLD_ZAP_BY_DNODE
+ if (dn) {
+ dmu_tx_hold_write_by_dnode(tx, dn, off, len);
+ return;
+ }
+#endif
+ dmu_tx_hold_write(tx, oid, off, len);
+}
+
+static inline void osd_dmu_write(struct osd_device *osd, dnode_t *dn,
+ uint64_t offset, uint64_t size,
+ const char *buf, dmu_tx_t *tx)
+{
+ LASSERT(dn);
+#ifdef HAVE_DMU_WRITE_BY_DNODE
+ dmu_write_by_dnode(dn, offset, size, buf, tx);
+#else
+ dmu_write(osd->od_os, dn->dn_object, offset, size, buf, tx);
+#endif
+}
+
+static inline int osd_dmu_read(struct osd_device *osd, dnode_t *dn,
+ uint64_t offset, uint64_t size,
+ char *buf, int flags)
+{
+ LASSERT(dn);
+#ifdef HAVE_DMU_READ_BY_DNODE
+ return -dmu_read_by_dnode(dn, offset, size, buf, flags);
+#else
+ return -dmu_read(osd->od_os, dn->dn_object, offset, size, buf, flags);
+#endif
+}
+
#endif /* _OSD_INTERNAL_H */
record_start_io(osd, READ, 0);
- rc = -dmu_read(osd->od_os, obj->oo_dn->dn_object, *pos, size,
- buf->lb_buf, DMU_READ_PREFETCH);
+ rc = osd_dmu_read(osd, obj->oo_dn, *pos, size, buf->lb_buf,
+ DMU_READ_PREFETCH);
record_end_io(osd, READ, cfs_time_current() - start, size,
size >> PAGE_SHIFT);
if (pos == -1)
pos = max_t(loff_t, 256 * 8 * LLOG_MIN_CHUNK_SIZE,
obj->oo_attr.la_size + (2 << 20));
- dmu_tx_hold_write(oh->ot_tx, oid, pos, buf->lb_len);
+ osd_tx_hold_write(oh->ot_tx, oid, obj->oo_dn, pos, buf->lb_len);
/* dt_declare_write() is usually called for system objects, such
* as llog or last_rcvd files. We needn't enforce quota on those
LASSERT(th != NULL);
oh = container_of0(th, struct osd_thandle, ot_super);
- dmu_write(osd->od_os, obj->oo_dn->dn_object, offset,
- (uint64_t)buf->lb_len, buf->lb_buf, oh->ot_tx);
+ osd_dmu_write(osd, obj->oo_dn, 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;
continue;
}
- dmu_tx_hold_write(oh->ot_tx, obj->oo_dn->dn_object,
- offset, size);
+ osd_tx_hold_write(oh->ot_tx, obj->oo_dn->dn_object,
+ obj->oo_dn, offset, size);
/* Estimating space to be consumed by a write is rather
* complicated with ZFS. As a consequence, we don't account for
* indirect blocks and just use as a rough estimate the worse
}
if (size) {
- dmu_tx_hold_write(oh->ot_tx, obj->oo_dn->dn_object,
+ osd_tx_hold_write(oh->ot_tx, obj->oo_dn->dn_object, obj->oo_dn,
offset, size);
space += osd_roundup2blocksz(size, offset, blksz);
}
- dmu_tx_hold_sa(oh->ot_tx, obj->oo_sa_hdl, 0);
-
oh->ot_write_commit = 1; /* used in osd_trans_start() for fail_loc */
/* backend zfs filesystem might be configured to store multiple data
}
if (lnb[i].lnb_page->mapping == (void *)obj) {
- dmu_write(osd->od_os, obj->oo_dn->dn_object,
- lnb[i].lnb_file_offset, lnb[i].lnb_len,
- kmap(lnb[i].lnb_page), oh->ot_tx);
+ osd_dmu_write(osd, obj->oo_dn, lnb[i].lnb_file_offset,
+ lnb[i].lnb_len, kmap(lnb[i].lnb_page),
+ oh->ot_tx);
kunmap(lnb[i].lnb_page);
} else if (lnb[i].lnb_data) {
LASSERT(((unsigned long)lnb[i].lnb_data & 1) == 0);
read_unlock(&obj->oo_attr_lock);
}
- /* ... and we'll modify size attribute */
- dmu_tx_hold_sa(oh->ot_tx, obj->oo_sa_hdl, 0);
-
RETURN(osd_declare_quota(env, osd, obj->oo_attr.la_uid,
obj->oo_attr.la_gid, 0, oh, true, NULL,
false));
RETURN(rc);
}
-int __osd_obj2dnode(const struct lu_env *env, objset_t *os,
- uint64_t oid, dnode_t **dnp)
+int __osd_obj2dnode(objset_t *os, uint64_t oid, dnode_t **dnp)
{
- dmu_object_info_t *doi = &osd_oti_get(env)->oti_doi;
dmu_buf_t *db;
dmu_buf_impl_t *dbi;
int rc;
dbi = (dmu_buf_impl_t *)db;
DB_DNODE_ENTER(dbi);
*dnp = DB_DNODE(dbi);
-
LASSERT(*dnp != NULL);
- dmu_object_info_from_dnode(*dnp, doi);
- if (unlikely (oid != DMU_USERUSED_OBJECT &&
- oid != DMU_GROUPUSED_OBJECT && doi->doi_bonus_type != DMU_OT_SA)) {
- osd_dnode_rele(*dnp);
- *dnp = NULL;
- return -EINVAL;
- }
return 0;
}
rc = osd_fid_lookup(env, osd, lu_object_fid(l), &oid);
if (rc == 0) {
LASSERT(obj->oo_dn == NULL);
- rc = __osd_obj2dnode(env, osd->od_os, oid, &obj->oo_dn);
+ rc = __osd_obj2dnode(osd->od_os, oid, &obj->oo_dn);
/* EEXIST will be returned if object is being deleted in ZFS */
if (rc == -EEXIST) {
rc = 0;
struct osd_object *obj = osd_dt_obj(dt);
struct osd_device *osd = osd_obj2dev(obj);
struct osd_thandle *oh;
+ dnode_t *dn;
int rc;
uint64_t zapid;
ENTRY;
LASSERT(oh->ot_tx != NULL);
/* declare that we'll remove object from fid-dnode mapping */
- zapid = osd_get_name_n_idx(env, osd, fid, NULL, 0);
- dmu_tx_hold_zap(oh->ot_tx, zapid, FALSE, NULL);
+ zapid = osd_get_name_n_idx(env, osd, fid, NULL, 0, &dn);
+ osd_tx_hold_zap(oh->ot_tx, zapid, dn, FALSE, NULL);
osd_declare_xattrs_destroy(env, obj, oh);
dmu_tx_hold_free(oh->ot_tx, obj->oo_dn->dn_object,
0, DMU_OBJECT_END);
else
- dmu_tx_hold_zap(oh->ot_tx, osd->od_unlinkedid, TRUE, NULL);
+ osd_tx_hold_zap(oh->ot_tx, osd->od_unlinked->dn_object,
+ osd->od_unlinked, TRUE, NULL);
/* will help to find FID->ino when this object is being
* added to PENDING/ */
struct osd_thandle *oh;
int rc;
uint64_t oid, zapid;
+ dnode_t *zdn;
ENTRY;
down_write(&obj->oo_guard);
LASSERT(oh->ot_tx != NULL);
/* remove obj ref from index dir (it depends) */
- zapid = osd_get_name_n_idx(env, osd, fid, buf, sizeof(info->oti_str));
- rc = -zap_remove(osd->od_os, zapid, buf, oh->ot_tx);
+ zapid = osd_get_name_n_idx(env, osd, fid, buf,
+ sizeof(info->oti_str), &zdn);
+ rc = osd_zap_remove(osd, zapid, zdn, buf, oh->ot_tx);
if (rc) {
CERROR("%s: zap_remove(%s) failed: rc = %d\n",
osd->od_svname, buf, rc);
CERROR("%s: failed to free %s %llu: rc = %d\n",
osd->od_svname, buf, oid, rc);
} else { /* asynchronous destroy */
+ char *key = info->oti_key;
+
rc = osd_object_unlinked_add(obj, oh);
if (rc)
GOTO(out, rc);
- rc = -zap_add_int(osd->od_os, osd->od_unlinkedid,
- oid, oh->ot_tx);
+ snprintf(key, sizeof(info->oti_key), "%llx", oid);
+ rc = osd_zap_add(osd, osd->od_unlinked->dn_object,
+ osd->od_unlinked, key, 8, 1, &oid, oh->ot_tx);
if (rc)
CERROR("%s: zap_add_int() failed %s %llu: rc = %d\n",
osd->od_svname, buf, oid, rc);
struct osd_device *osd = osd_obj2dev(obj);
struct osd_thandle *oh;
uint64_t zapid;
+ dnode_t *dn;
int rc, dnode_size;
ENTRY;
}
/* and we'll add it to some mapping */
- zapid = osd_get_name_n_idx(env, osd, fid, NULL, 0);
- dmu_tx_hold_zap(oh->ot_tx, zapid, TRUE, NULL);
+ zapid = osd_get_name_n_idx(env, osd, fid, NULL, 0, &dn);
+ osd_tx_hold_zap(oh->ot_tx, zapid, dn, TRUE, NULL);
/* will help to find FID->ino mapping at dt_insert() */
osd_idc_find_and_init(env, osd, obj);
}
if (unlikely(*dnp == NULL))
- rc = __osd_obj2dnode(env, tx->tx_objset, oid, dnp);
+ rc = __osd_obj2dnode(tx->tx_objset, oid, dnp);
return rc;
}
struct osd_device *osd = osd_obj2dev(obj);
char *buf = info->oti_str;
struct osd_thandle *oh;
- dnode_t *dn = NULL;
+ dnode_t *dn = NULL, *zdn = NULL;
uint64_t zapid, parent = 0;
int rc;
zde->zde_dnode = dn->dn_object;
zde->zde_type = IFTODT(attr->la_mode & S_IFMT);
- zapid = osd_get_name_n_idx(env, osd, fid, buf, sizeof(info->oti_str));
-
- rc = -zap_add(osd->od_os, zapid, buf, 8, 1, zde, oh->ot_tx);
+ zapid = osd_get_name_n_idx(env, osd, fid, buf,
+ sizeof(info->oti_str), &zdn);
+ rc = osd_zap_add(osd, zapid, zdn, buf, 8, 1, zde, oh->ot_tx);
if (rc)
GOTO(out, rc);
obj->oo_dn = dn;
*/
static uint64_t
osd_get_idx_for_fid(struct osd_device *osd, const struct lu_fid *fid,
- char *buf)
+ char *buf, dnode_t **zdn)
{
struct osd_oi *oi;
oi = osd->od_oi_table[fid_seq(fid) & (osd->od_oi_count - 1)];
if (buf)
osd_fid2str(buf, fid);
+ if (zdn)
+ *zdn = oi->oi_dn;
return oi->oi_zapid;
}
uint64_t osd_get_name_n_idx(const struct lu_env *env, struct osd_device *osd,
- const struct lu_fid *fid, char *buf, int bufsize)
+ const struct lu_fid *fid, char *buf, int bufsize,
+ dnode_t **zdn)
{
uint64_t zapid;
LASSERT(fid);
+ if (zdn != NULL)
+ *zdn = NULL;
if (fid_is_on_ost(env, osd, fid) == 1 || fid_seq(fid) == FID_SEQ_ECHO) {
zapid = osd_get_idx_for_ost_obj(env, osd, fid, buf, bufsize);
if (fid_is_acct(fid))
zapid = MASTER_NODE_OBJ;
} else {
- zapid = osd_get_idx_for_fid(osd, fid, buf);
+ zapid = osd_get_idx_for_fid(osd, fid, buf, NULL);
}
} else {
- zapid = osd_get_idx_for_fid(osd, fid, buf);
+ zapid = osd_get_idx_for_fid(osd, fid, buf, zdn);
}
return zapid;
{
struct osd_thread_info *info = osd_oti_get(env);
char *buf = info->oti_buf;
- uint64_t zapid;
+ dnode_t *zdn;
+ uint64_t zapid;
int rc = 0;
ENTRY;
*oid = dev->od_root;
} else {
zapid = osd_get_name_n_idx(env, dev, fid, buf,
- sizeof(info->oti_buf));
- rc = -zap_lookup(dev->od_os, zapid, buf,
- 8, 1, &info->oti_zde);
+ sizeof(info->oti_buf), &zdn);
+ rc = osd_zap_lookup(dev, zapid, zdn, buf,
+ 8, 1, &info->oti_zde);
if (rc)
RETURN(rc);
*oid = info->oti_zde.lzd_reg.zde_dnode;
}
o->od_oi_table[key] = oi;
- __osd_obj2dnode(env, o->od_os, oi->oi_zapid, &oi->oi_dn);
+ __osd_obj2dnode(o->od_os, oi->oi_zapid, &oi->oi_dn);
return 0;
}
/**
* Helper function to retrieve DMU object id from fid for accounting object
*/
-inline int osd_quota_fid2dmu(const struct lu_fid *fid, uint64_t *oid)
+dnode_t *osd_quota_fid2dmu(const struct osd_device *osd,
+ const struct lu_fid *fid)
{
- int rc = 0;
-
LASSERT(fid_is_acct(fid));
- switch (fid_oid(fid)) {
- case ACCT_GROUP_OID:
- *oid = DMU_GROUPUSED_OBJECT;
- break;
- case ACCT_USER_OID:
- *oid = DMU_USERUSED_OBJECT;
- break;
- default:
- rc = -EINVAL;
- break;
- }
- return rc;
+ if (fid_oid(fid) == ACCT_GROUP_OID)
+ return osd->od_groupused_dn;
+ return osd->od_userused_dn;
}
/**
struct osd_object *obj = osd_dt_obj(dtobj);
struct osd_device *osd = osd_obj2dev(obj);
int rc;
- uint64_t oid = 0;
+ dnode_t *dn;
ENTRY;
rec->bspace = rec->ispace = 0;
/* convert the 64-bit uid/gid into a string */
snprintf(buf, buflen, "%llx", *((__u64 *)dtkey));
- /* fetch DMU object ID (DMU_USERUSED_OBJECT/DMU_GROUPUSED_OBJECT) to be
+ /* fetch DMU object (DMU_USERUSED_OBJECT/DMU_GROUPUSED_OBJECT) to be
* used */
- rc = osd_quota_fid2dmu(lu_object_fid(&dtobj->do_lu), &oid);
- if (rc)
- RETURN(rc);
+ dn = osd_quota_fid2dmu(osd, lu_object_fid(&dtobj->do_lu));
/* disk usage (in bytes) is maintained by DMU.
* DMU_USERUSED_OBJECT/DMU_GROUPUSED_OBJECT are special objects which
* not associated with any dmu_but_t (see dnode_special_open()). */
- rc = zap_lookup(osd->od_os, oid, buf, sizeof(uint64_t), 1,
- &rec->bspace);
+ rc = osd_zap_lookup(osd, dn->dn_object, dn, buf, sizeof(uint64_t), 1,
+ &rec->bspace);
if (rc == -ENOENT) {
/* user/group has not created anything yet */
CDEBUG(D_QUOTA, "%s: id %s not found in DMU accounting ZAP\n",
} else {
snprintf(buf, buflen, OSD_DMU_USEROBJ_PREFIX "%llx",
*((__u64 *)dtkey));
- rc = zap_lookup(osd->od_os, oid, buf, sizeof(uint64_t), 1,
- &rec->ispace);
+ rc = osd_zap_lookup(osd, dn->dn_object, dn, buf,
+ sizeof(uint64_t), 1, &rec->ispace);
if (rc == -ENOENT) {
CDEBUG(D_QUOTA,
"%s: id %s not found dnode accounting\n",
struct osd_it_quota *it;
struct lu_object *lo = &dt->do_lu;
struct osd_device *osd = osd_dev(lo->lo_dev);
- int rc;
+ dnode_t *dn;
+ int rc;
ENTRY;
LASSERT(lu_object_exists(lo));
RETURN(ERR_PTR(-ENOMEM));
memset(it, 0, sizeof(*it));
- rc = osd_quota_fid2dmu(lu_object_fid(lo), &it->oiq_oid);
- if (rc)
- RETURN(ERR_PTR(rc));
+ dn = osd_quota_fid2dmu(osd, lu_object_fid(lo));
+ it->oiq_oid = dn->dn_object;
/* initialize zap cursor */
rc = osd_zap_cursor_init(&it->oiq_zc, osd->od_os, it->oiq_oid, 0);
* to read bytes we need to call zap_lookup explicitly.
*/
static int osd_zap_cursor_retrieve_value(const struct lu_env *env,
- zap_cursor_t *zc, char *buf,
- int buf_size, int *bytes_read)
+ struct osd_it_quota *it,
+ char *buf, int buf_size,
+ int *bytes_read)
{
+ const struct lu_fid *fid = lu_object_fid(&it->oiq_obj->oo_dt.do_lu);
zap_attribute_t *za = &osd_oti_get(env)->oti_za;
+ zap_cursor_t *zc = it->oiq_zc;
+ struct osd_device *osd = osd_obj2dev(it->oiq_obj);
int rc, actual_size;
rc = -zap_cursor_retrieve(zc, za);
if (unlikely(rc != 0))
- return -rc;
+ return rc;
if (unlikely(za->za_integer_length <= 0))
return -ERANGE;
buf_size = za->za_num_integers;
}
- rc = -zap_lookup(zc->zc_objset, zc->zc_zapobj,
- za->za_name, za->za_integer_length,
- buf_size, buf);
-
+ /* use correct special ID to request bytes used */
+ rc = osd_zap_lookup(osd, fid_oid(fid) == ACCT_GROUP_OID ?
+ DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT, NULL,
+ za->za_name, za->za_integer_length, buf_size, buf);
if (likely(rc == 0))
*bytes_read = actual_size;
rec->ispace = rec->bspace = 0;
/* retrieve block usage from the DMU accounting object */
- rc = osd_zap_cursor_retrieve_value(env, it->oiq_zc,
- (char *)&rec->bspace,
+ rc = osd_zap_cursor_retrieve_value(env, it, (char *)&rec->bspace,
sizeof(uint64_t), &bytes_read);
if (rc)
RETURN(rc);
/* inode accounting is not maintained by DMU, so we use our own ZAP to
* track inode usage */
- rc = -zap_lookup(osd->od_os, it->oiq_obj->oo_dn->dn_object,
- za->za_name, sizeof(uint64_t), 1, &rec->ispace);
+ rc = osd_zap_lookup(osd, it->oiq_obj->oo_dn->dn_object,
+ it->oiq_obj->oo_dn, za->za_name, sizeof(uint64_t),
+ 1, &rec->ispace);
if (rc == -ENOENT)
/* user/group has not created any file yet */
CDEBUG(D_QUOTA, "%s: id %s not found in accounting ZAP\n",
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;
* 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;