From 501b0c82875df80f99c2235bd5a0519e032c42aa Mon Sep 17 00:00:00 2001 From: Alex Zhuravlev Date: Wed, 15 Apr 2020 17:54:07 +0300 Subject: [PATCH] LU-13453 osd-ldiskfs: do not leak inode if OI insertion fails osd_create() should destroy just created inode if OI insertion fails. also fixes lustre_index_restore() to drop nlink for object to be removed. the patch adds two tests: - ENOSPC on OI insertion - ENOSPC on .. insertion, i.e. directory block allocation Lustre-change: https://review.whamcloud.com/38235 Lustre-commit: e45e8a92a2ecab742b3680716a55aaa1d9827057 Test-Parameters: testlist=sanity-scrub mdscount=2 mdtcount=4 Test-Parameters: testlist=sanity-scrub mdscount=2 mdtcount=4 Signed-off-by: Alex Zhuravlev Change-Id: I2a5db657c7dab54b8dc2c50bc29365d5ee754a2e Reviewed-by: Andreas Dilger Reviewed-by: Mike Pershin Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/52846 Tested-by: jenkins Tested-by: Andreas Dilger --- lustre/include/obd_support.h | 2 ++ lustre/obdclass/scrub.c | 11 ++++++++++- lustre/osd-ldiskfs/osd_handler.c | 21 ++++++++++++++++++++- lustre/tests/sanity-scrub.sh | 30 ++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index cda5e5a..78d16f2 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -289,6 +289,8 @@ extern char obd_jobid_var[]; #define OBD_FAIL_OSD_TXN_START 0x19a #define OBD_FAIL_OSD_DUPLICATE_MAP 0x19b #define OBD_FAIL_OSD_REF_DEL 0x19c +#define OBD_FAIL_OSD_OI_ENOSPC 0x19d +#define OBD_FAIL_OSD_DOTDOT_ENOSPC 0x19e #define OBD_FAIL_OSD_SCRUB_STALE 0x19f #define OBD_FAIL_OSD_FID_REUSE 0x1a0 diff --git a/lustre/obdclass/scrub.c b/lustre/obdclass/scrub.c index dc0bcc7..a6b5d7e 100644 --- a/lustre/obdclass/scrub.c +++ b/lustre/obdclass/scrub.c @@ -1062,6 +1062,10 @@ int lustre_index_restore(const struct lu_env *env, struct dt_device *dev, if (rc) GOTO(stop, rc); + rc = dt_declare_ref_del(env, tgt_obj, th); + if (rc) + GOTO(stop, rc); + rc = dt_declare_destroy(env, tgt_obj, th); if (rc) GOTO(stop, rc); @@ -1075,7 +1079,12 @@ int lustre_index_restore(const struct lu_env *env, struct dt_device *dev, GOTO(stop, rc); dt_write_lock(env, tgt_obj, 0); - rc = dt_destroy(env, tgt_obj, th); + rc = dt_ref_del(env, tgt_obj, th); + if (rc == 0) { + if (S_ISDIR(tgt_obj->do_lu.lo_header->loh_attr)) + dt_ref_del(env, tgt_obj, th); + rc = dt_destroy(env, tgt_obj, th); + } dt_write_unlock(env, tgt_obj); dt_trans_stop(env, dev, th); if (rc) diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index dd3cc93..afa5af5 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -3689,6 +3689,9 @@ static int __osd_oi_insert(const struct lu_env *env, struct osd_object *obj, LASSERT(obj->oo_inode != NULL); + if (CFS_FAIL_CHECK(OBD_FAIL_OSD_OI_ENOSPC)) + return -ENOSPC; + oh = container_of(th, struct osd_thandle, ot_super); LASSERT(oh->ot_handle); osd_trans_exec_op(env, th, OSD_OT_INSERT); @@ -4075,6 +4078,9 @@ static int osd_add_dot_dotdot_internal(struct osd_thread_info *info, __u32 saved_nlink = dir->i_nlink; int rc; + if (OBD_FAIL_CHECK(OBD_FAIL_OSD_DOTDOT_ENOSPC)) + return -ENOSPC; + dot_dot_ldp = (struct ldiskfs_dentry_param *)info->oti_ldp2; osd_get_ldiskfs_dirent_param(dot_dot_ldp, dot_dot_fid); @@ -4333,8 +4339,21 @@ static int osd_create(const struct lu_env *env, struct dt_object *dt, obj->oo_dt.do_body_ops = &osd_body_ops; } - if (!result && !CFS_FAIL_CHECK(OBD_FAIL_OSD_NO_OI_ENTRY)) + if (!result && !CFS_FAIL_CHECK(OBD_FAIL_OSD_NO_OI_ENTRY)) { + struct inode *inode = obj->oo_inode; + result = __osd_oi_insert(env, obj, fid, th); + if (result && inode) { + spin_lock(&obj->oo_guard); + clear_nlink(inode); + spin_unlock(&obj->oo_guard); + osd_dirty_inode(inode, I_DIRTY_DATASYNC); + ldiskfs_set_inode_state(inode, + LDISKFS_STATE_LUSTRE_DESTROY); + iput(inode); + obj->oo_inode = NULL; + } + } /* * a small optimization - dt_insert() isn't usually applied diff --git a/lustre/tests/sanity-scrub.sh b/lustre/tests/sanity-scrub.sh index d1de679..19c5a4e 100755 --- a/lustre/tests/sanity-scrub.sh +++ b/lustre/tests/sanity-scrub.sh @@ -1301,6 +1301,36 @@ test_16() { } run_test 16 "Initial OI scrub can rebuild crashed index objects" +test_17a() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test" + +#define OBD_FAIL_OSD_OI_ENOSPC 0x19d + do_facet mds1 $LCTL set_param fail_loc=0x8000019d + mkdir_on_mdt0 $DIR/$tdir && error "mkdir should fail" + stop mds1 + local devname=$(mdsdevname 1) + + stack_trap "start mds1 $devname $MDS_MOUNT_OPTS" EXIT + FSCK_MAX_ERR=0 run_e2fsck $(facet_active_host mds1) $devname -n || + error "e2fsck returned $?" +} +run_test 17a "ENOSPC on OI insert shouldn't leak inodes" + +test_17b() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test" + +#define OBD_FAIL_OSD_DOTDOT_ENOSPC 0x19e + do_facet mds1 $LCTL set_param fail_loc=0x8000019e + mkdir_on_mdt0 $DIR/$tdir && error "mkdir should fail" + stop mds1 + local devname=$(mdsdevname 1) + + stack_trap "start mds1 $devname $MDS_MOUNT_OPTS" EXIT + FSCK_MAX_ERR=0 run_e2fsck $(facet_active_host mds1) $devname -n || + error "e2fsck returned $?" +} +run_test 17b "ENOSPC on .. insertion shouldn't leak inodes" + test_18() { local n local fids=() -- 1.8.3.1