X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fosd-zfs%2Fosd_object.c;h=34dfae4eba45ca16102945c970d51946eeb79aec;hp=9817cc5452555dd3ec48fb5cb5c6e9a0fbff3903;hb=d2e8208e22f21bb7354a9207f381217c222d3df3;hpb=77f5bb4dace53e0040dea4ce5c72156e901e6819 diff --git a/lustre/osd-zfs/osd_object.c b/lustre/osd-zfs/osd_object.c index 9817cc5..34dfae4 100644 --- a/lustre/osd-zfs/osd_object.c +++ b/lustre/osd-zfs/osd_object.c @@ -27,7 +27,6 @@ */ /* * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. * * lustre/osd-zfs/osd_object.c * @@ -128,17 +127,19 @@ void osd_object_sa_dirty_rele(const struct lu_env *env, struct osd_thandle *oh) write_lock(&obj->oo_attr_lock); list_del_init(&obj->oo_sa_linkage); write_unlock(&obj->oo_attr_lock); - if (obj->oo_late_xattr) { + if (obj->oo_late_xattr && obj->oo_destroyed == 0) { /* * take oo_guard to protect oo_sa_xattr buffer * from concurrent update by osd_xattr_set() */ LASSERT(oh->ot_assigned != 0); down_write(&obj->oo_guard); - if (obj->oo_late_attr_set) - __osd_sa_attr_init(env, obj, oh); - else if (obj->oo_late_xattr) - __osd_sa_xattr_update(env, obj, oh); + if (obj->oo_destroyed == 0) { + if (obj->oo_late_attr_set) + __osd_sa_attr_init(env, obj, oh); + else if (obj->oo_late_xattr) + __osd_sa_xattr_update(env, obj, oh); + } up_write(&obj->oo_guard); } sa_spill_rele(obj->oo_sa_hdl); @@ -616,9 +617,12 @@ zget: GOTO(out, rc = 0); rc = osd_check_lma(env, obj); - if ((!rc && !remote) || (rc != -EREMCHG)) + if (rc != -EREMCHG) GOTO(out, rc); + osd_scrub_refresh_mapping(env, osd, fid, oid, DTO_INDEX_DELETE, true, + NULL); + trigger: /* We still have chance to get the valid dnode: for the object that is * referenced by remote name entry, the object on the local MDT will be @@ -655,14 +659,15 @@ trigger: } /* The case NOT allow to trigger OI scrub automatically. */ - if (osd->od_auto_scrub_interval == AS_NEVER) + if (osd->od_scrub.os_auto_scrub_interval == AS_NEVER) GOTO(out, rc); /* It is me to trigger the OI scrub. */ rc1 = osd_scrub_start(env, osd, SS_CLEAR_DRYRUN | SS_CLEAR_FAILOUT | SS_AUTO_FULL); - LCONSOLE_WARN("%s: trigger OI scrub by RPC for the "DFID": rc = %d\n", - osd_name(osd), PFID(fid), rc1); + CDEBUG_LIMIT(D_LFSCK | D_CONSOLE | D_WARNING, + "%s: trigger OI scrub by RPC for "DFID"/%#llx: rc = %d\n", + osd_name(osd), PFID(fid), oid, rc1); if (!rc) { LASSERT(remote); @@ -851,12 +856,12 @@ static int osd_destroy(const struct lu_env *env, struct dt_object *dt, LASSERT(obj->oo_attr.la_size <= osd_sync_destroy_max_size); rc = -dmu_object_free(osd->od_os, oid, oh->ot_tx); if (rc) - CERROR("%s: failed to free %s %llu: rc = %d\n", + CERROR("%s: failed to free %s/%#llx: rc = %d\n", osd->od_svname, buf, oid, rc); } else if (obj->oo_destroy == OSD_DESTROY_SYNC) { rc = -dmu_object_free(osd->od_os, oid, oh->ot_tx); if (rc) - CERROR("%s: failed to free %s %llu: rc = %d\n", + CERROR("%s: failed to free %s/%#llx: rc = %d\n", osd->od_svname, buf, oid, rc); } else { /* asynchronous destroy */ char *key = info->oti_key; @@ -869,7 +874,7 @@ static int osd_destroy(const struct lu_env *env, struct dt_object *dt, 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", + CERROR("%s: zap_add_int() failed %s/%#llx: rc = %d\n", osd->od_svname, buf, oid, rc); } @@ -1013,7 +1018,7 @@ static int osd_attr_get(const struct lu_env *env, struct dt_object *dt, } read_unlock(&obj->oo_attr_lock); if (attr->la_valid & LA_FLAGS && attr->la_flags & LUSTRE_ORPHAN_FL) - CDEBUG(D_INFO, "%s: set orphan flag on "DFID" (%llx/%x)\n", + CDEBUG(D_INFO, "%s: set orphan flag on "DFID" (%#llx/%#x)\n", osd_obj2dev(obj)->od_svname, PFID(lu_object_fid(&dt->do_lu)), attr->la_valid, obj->oo_lma_flags); @@ -1043,67 +1048,6 @@ out: return rc; } -/* Simple wrapper on top of qsd API which implement quota transfer for osd - * setattr needs. As a reminder, only the root user can change ownership of - * a file, that's why EDQUOT & EINPROGRESS errors are discarded */ -static inline int qsd_transfer(const struct lu_env *env, - struct qsd_instance *qsd, - struct lquota_trans *trans, int qtype, - __u64 orig_id, __u64 new_id, __u64 bspace, - struct lquota_id_info *qi, bool ignore_edquot) -{ - int rc; - - if (unlikely(qsd == NULL)) - return 0; - - LASSERT(qtype >= 0 && qtype < LL_MAXQUOTAS); - qi->lqi_type = qtype; - - /* inode accounting */ - qi->lqi_is_blk = false; - - /* one more inode for the new owner ... */ - qi->lqi_id.qid_uid = new_id; - qi->lqi_space = 1; - rc = qsd_op_begin(env, qsd, trans, qi, NULL); - if (ignore_edquot && (rc == -EDQUOT || rc == -EINPROGRESS)) - rc = 0; - if (rc) - return rc; - - /* and one less inode for the current id */ - qi->lqi_id.qid_uid = orig_id;; - qi->lqi_space = -1; - /* can't get EDQUOT when reducing usage */ - rc = qsd_op_begin(env, qsd, trans, qi, NULL); - if (rc == -EINPROGRESS) - rc = 0; - if (rc) - return rc; - - /* block accounting */ - qi->lqi_is_blk = true; - - /* more blocks for the new owner ... */ - qi->lqi_id.qid_uid = new_id; - qi->lqi_space = bspace; - rc = qsd_op_begin(env, qsd, trans, qi, NULL); - if (ignore_edquot && (rc == -EDQUOT || rc == -EINPROGRESS)) - rc = 0; - if (rc) - return rc; - - /* and finally less blocks for the current owner */ - qi->lqi_id.qid_uid = orig_id; - qi->lqi_space = -bspace; - rc = qsd_op_begin(env, qsd, trans, qi, NULL); - /* can't get EDQUOT when reducing usage */ - if (rc == -EINPROGRESS) - rc = 0; - return rc; -} - static int osd_declare_attr_set(const struct lu_env *env, struct dt_object *dt, const struct lu_attr *attr, @@ -1128,7 +1072,7 @@ static int osd_declare_attr_set(const struct lu_env *env, down_read(&obj->oo_guard); if (unlikely(!dt_object_exists(dt) || obj->oo_destroyed)) - GOTO(out, rc = 0); + GOTO(out_sem, rc = 0); LASSERT(obj->oo_sa_hdl != NULL); LASSERT(oh->ot_tx != NULL); @@ -1150,7 +1094,7 @@ static int osd_declare_attr_set(const struct lu_env *env, if (!found) dmu_tx_hold_bonus(oh->ot_tx, obj->oo_dn->dn_object); if (oh->ot_tx->tx_err != 0) - GOTO(out, rc = -oh->ot_tx->tx_err); + GOTO(out_sem, rc = -oh->ot_tx->tx_err); if (attr && attr->la_valid & LA_FLAGS) { /* LMA is usually a part of bonus, no need to declare @@ -1166,66 +1110,69 @@ static int osd_declare_attr_set(const struct lu_env *env, osd->od_svname, attr->la_uid, attr->la_gid, bspace, blksize); } + /* to preserve locking order - qsd_transfer() may need to flush + * currently running transaction when we're out of quota. + */ + up_read(&obj->oo_guard); - if (attr && attr->la_valid & LA_UID) { - /* quota enforcement for user */ - if (attr->la_uid != obj->oo_attr.la_uid) { - rc = qsd_transfer(env, osd_def_qsd(osd), - &oh->ot_quota_trans, USRQUOTA, - obj->oo_attr.la_uid, attr->la_uid, - bspace, &info->oti_qi, true); - if (rc) - GOTO(out, rc); - } + /* quota enforcement for user */ + if (attr && attr->la_valid & LA_UID && + attr->la_uid != obj->oo_attr.la_uid) { + rc = qsd_transfer(env, osd_def_qsd(osd), + &oh->ot_quota_trans, USRQUOTA, + obj->oo_attr.la_uid, attr->la_uid, + bspace, &info->oti_qi); + if (rc) + GOTO(out, rc); } - if (attr && attr->la_valid & LA_GID) { - /* quota enforcement for group */ - if (attr->la_gid != obj->oo_attr.la_gid) { - rc = qsd_transfer(env, osd_def_qsd(osd), - &oh->ot_quota_trans, GRPQUOTA, - obj->oo_attr.la_gid, attr->la_gid, - bspace, &info->oti_qi, - !(attr->la_flags & - LUSTRE_SET_SYNC_FL)); - if (rc) - GOTO(out, rc); - } + + /* quota enforcement for group */ + if (attr && attr->la_valid & LA_GID && + attr->la_gid != obj->oo_attr.la_gid) { + rc = qsd_transfer(env, osd_def_qsd(osd), + &oh->ot_quota_trans, GRPQUOTA, + obj->oo_attr.la_gid, attr->la_gid, + bspace, &info->oti_qi); + if (rc) + GOTO(out, rc); } #ifdef ZFS_PROJINHERIT - if (attr && attr->la_valid & LA_PROJID) { - /* quota enforcement for project */ - if (attr->la_projid != obj->oo_attr.la_projid) { - if (!osd->od_projectused_dn) - GOTO(out, rc = -EOPNOTSUPP); - - /* Usually, if project quota is upgradable for the - * device, then the upgrade will be done before or when - * mount the device. So when we come here, this project - * should have project ID attribute already (that is - * zero by default). Otherwise, there was something - * wrong during the former upgrade, let's return failure - * to report that. - * - * Please note that, different from other attributes, - * you can NOT simply set the project ID attribute under - * such case, because adding (NOT change) project ID - * attribute needs to change the object's attribute - * layout to match zfs backend quota accounting - * requirement. */ - if (unlikely(!obj->oo_with_projid)) - GOTO(out, rc = -ENXIO); - - rc = qsd_transfer(env, osd_def_qsd(osd), - &oh->ot_quota_trans, PRJQUOTA, - obj->oo_attr.la_projid, - attr->la_projid, bspace, - &info->oti_qi, true); - if (rc) - GOTO(out, rc); - } + /* quota enforcement for project */ + if (attr && attr->la_valid & LA_PROJID && + attr->la_projid != obj->oo_attr.la_projid) { + if (!osd->od_projectused_dn) + GOTO(out, rc = -EOPNOTSUPP); + + /* Usually, if project quota is upgradable for the + * device, then the upgrade will be done before or when + * mount the device. So when we come here, this project + * should have project ID attribute already (that is + * zero by default). Otherwise, there was something + * wrong during the former upgrade, let's return failure + * to report that. + * + * Please note that, different from other attributes, + * you can NOT simply set the project ID attribute under + * such case, because adding (NOT change) project ID + * attribute needs to change the object's attribute + * layout to match zfs backend quota accounting + * requirement. + */ + if (unlikely(!obj->oo_with_projid)) + GOTO(out, rc = -ENXIO); + + rc = qsd_transfer(env, osd_def_qsd(osd), + &oh->ot_quota_trans, PRJQUOTA, + obj->oo_attr.la_projid, + attr->la_projid, bspace, + &info->oti_qi); + if (rc) + GOTO(out, rc); } #endif out: + RETURN(rc); +out_sem: up_read(&obj->oo_guard); RETURN(rc); }