From 03a4431dac1c59fa2b98501fc7dfb8451a0a2af8 Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Fri, 20 Mar 2020 17:59:32 +0800 Subject: [PATCH] LU-11025 osd: osd_attr_get() returns dirent count For osd-ldiskfs, to get dirent count it needs to iterate directory entries and sum it up, while for osd-zfs, zap_count() can get it from ZAP directly. Add a new field 'la_dirent_count' in struct lu_attr, and set it to directory entry count in osd_attr_get() if object is directory, and this value will be cached in osd_object for osd-ldiskfs, if directory is newly created, it will be set to '0', and later index_insert/delete will update its value, so the following osd_attr_get() can use the cached value. Signed-off-by: Lai Siyao Change-Id: If4225aecdba1c428d64d97c35b6c982c4932a265 Reviewed-on: https://review.whamcloud.com/38097 Tested-by: jenkins Reviewed-by: Andreas Dilger Reviewed-by: Hongchao Zhang Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/include/lu_object.h | 4 ++ lustre/osd-ldiskfs/osd_handler.c | 87 ++++++++++++++++++++++++++++++++++++++- lustre/osd-ldiskfs/osd_internal.h | 1 + lustre/osd-zfs/osd_object.c | 14 ++++--- 4 files changed, 99 insertions(+), 7 deletions(-) diff --git a/lustre/include/lu_object.h b/lustre/include/lu_object.h index 4bb797f..585b1ca 100644 --- a/lustre/include/lu_object.h +++ b/lustre/include/lu_object.h @@ -452,8 +452,12 @@ struct lu_attr { __u32 la_projid; /** set layout version to OST objects. */ __u32 la_layout_version; + /** dirent count */ + __u64 la_dirent_count; }; +#define LU_DIRENT_COUNT_UNSET ~0ULL + /** * Layer in the layered object. */ diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 109e985..e606f7d 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -1436,6 +1436,7 @@ static int osd_object_init(const struct lu_env *env, struct lu_object *l, result = 0; } } + obj->oo_dirent_count = LU_DIRENT_COUNT_UNSET; LINVRNT(osd_invariant(obj)); return result; @@ -2623,10 +2624,71 @@ static void osd_inode_getattr(const struct lu_env *env, attr->la_flags |= LUSTRE_PROJINHERIT_FL; } +static int osd_dirent_count(const struct lu_env *env, struct dt_object *dt, + u64 *count) +{ + struct osd_object *obj = osd_dt_obj(dt); + const struct dt_it_ops *iops; + struct dt_it *it; + int rc; + + ENTRY; + + LASSERT(S_ISDIR(obj->oo_inode->i_mode)); + LASSERT(fid_is_namespace_visible(lu_object_fid(&obj->oo_dt.do_lu))); + + if (obj->oo_dirent_count != LU_DIRENT_COUNT_UNSET) { + *count = obj->oo_dirent_count; + RETURN(0); + } + + /* directory not initialized yet */ + if (!dt->do_index_ops) { + *count = 0; + RETURN(0); + } + + iops = &dt->do_index_ops->dio_it; + it = iops->init(env, dt, LUDA_64BITHASH); + if (IS_ERR(it)) + RETURN(PTR_ERR(it)); + + rc = iops->load(env, it, 0); + if (rc < 0) { + if (rc == -ENODATA) { + rc = 0; + *count = 0; + } + GOTO(out, rc); + } + if (rc > 0) + rc = iops->next(env, it); + + for (*count = 0; rc == 0 || rc == -ESTALE; rc = iops->next(env, it)) { + if (rc == -ESTALE) + continue; + + if (iops->key_size(env, it) == 0) + continue; + + (*count)++; + } + if (rc == 1) { + obj->oo_dirent_count = *count; + rc = 0; + } +out: + iops->put(env, it); + iops->fini(env, it); + + RETURN(rc); +} + static int osd_attr_get(const struct lu_env *env, struct dt_object *dt, struct lu_attr *attr) { struct osd_object *obj = osd_dt_obj(dt); + int rc = 0; if (unlikely(!dt_object_exists(dt))) return -ENOENT; @@ -2644,7 +2706,11 @@ static int osd_attr_get(const struct lu_env *env, struct dt_object *dt, } spin_unlock(&obj->oo_guard); - return 0; + if (S_ISDIR(obj->oo_inode->i_mode) && + fid_is_namespace_visible(lu_object_fid(&dt->do_lu))) + rc = osd_dirent_count(env, dt, &attr->la_dirent_count); + + return rc; } static int osd_declare_attr_qid(const struct lu_env *env, @@ -3143,6 +3209,8 @@ static int osd_mkdir(struct osd_thread_info *info, struct osd_object *obj, oth = container_of(th, struct osd_thandle, ot_super); LASSERT(oth->ot_handle->h_transaction != NULL); + if (fid_is_namespace_visible(lu_object_fid(&obj->oo_dt.do_lu))) + obj->oo_dirent_count = 0; result = osd_mkfile(info, obj, mode, hint, th, attr); return result; @@ -5206,11 +5274,21 @@ static int osd_index_ea_delete(const struct lu_env *env, struct dt_object *dt, } else { rc = PTR_ERR(bh); } + + if (!rc && fid_is_namespace_visible(lu_object_fid(&dt->do_lu)) && + obj->oo_dirent_count != LU_DIRENT_COUNT_UNSET) { + /* NB, dirent count may not be accurate, because it's counted + * without lock. + */ + if (obj->oo_dirent_count) + obj->oo_dirent_count--; + else + obj->oo_dirent_count = LU_DIRENT_COUNT_UNSET; + } if (hlock != NULL) ldiskfs_htree_unlock(hlock); else up_write(&obj->oo_ext_idx_sem); - GOTO(out, rc); out: LASSERT(osd_invariant(obj)); @@ -5545,6 +5623,10 @@ static int osd_ea_add_rec(const struct lu_env *env, struct osd_object *pobj, hlock, th); } } + if (!rc && fid_is_namespace_visible(lu_object_fid(&pobj->oo_dt.do_lu)) + && pobj->oo_dirent_count != LU_DIRENT_COUNT_UNSET) + pobj->oo_dirent_count++; + if (hlock != NULL) ldiskfs_htree_unlock(hlock); else @@ -6098,6 +6180,7 @@ static int osd_index_ea_insert(const struct lu_env *env, struct dt_object *dt, iput(child_inode); LASSERT(osd_invariant(obj)); osd_trans_exec_check(env, th, OSD_OT_INSERT); + RETURN(rc); } diff --git a/lustre/osd-ldiskfs/osd_internal.h b/lustre/osd-ldiskfs/osd_internal.h index 1817ffa..81afee0 100644 --- a/lustre/osd-ldiskfs/osd_internal.h +++ b/lustre/osd-ldiskfs/osd_internal.h @@ -153,6 +153,7 @@ struct osd_object { struct list_head oo_xattr_list; struct lu_object_header *oo_header; + __u64 oo_dirent_count; }; struct osd_obj_seq { diff --git a/lustre/osd-zfs/osd_object.c b/lustre/osd-zfs/osd_object.c index f28bcb7..cce661c 100644 --- a/lustre/osd-zfs/osd_object.c +++ b/lustre/osd-zfs/osd_object.c @@ -990,10 +990,11 @@ static int osd_write_locked(const struct lu_env *env, struct dt_object *dt) static int osd_attr_get(const struct lu_env *env, struct dt_object *dt, struct lu_attr *attr) { - struct osd_object *obj = osd_dt_obj(dt); - uint64_t blocks; - uint32_t blksize; - int rc = 0; + struct osd_object *obj = osd_dt_obj(dt); + struct osd_device *osd = osd_obj2dev(obj); + uint64_t blocks; + uint32_t blksize; + int rc = 0; down_read(&obj->oo_guard); @@ -1025,8 +1026,11 @@ static int osd_attr_get(const struct lu_env *env, struct dt_object *dt, sa_object_size(obj->oo_sa_hdl, &blksize, &blocks); /* we do not control size of indices, so always calculate * it from number of blocks reported by DMU */ - if (S_ISDIR(attr->la_mode)) + if (S_ISDIR(attr->la_mode)) { attr->la_size = 512 * blocks; + rc = -zap_count(osd->od_os, obj->oo_dn->dn_object, + &attr->la_dirent_count); + } /* Block size may be not set; suggest maximal I/O transfers. */ if (blksize == 0) blksize = osd_spa_maxblocksize( -- 1.8.3.1