From 51529fb57f85210e292a15c882cf25a4689ea77d Mon Sep 17 00:00:00 2001 From: Alex Zhuravlev Date: Mon, 4 Sep 2023 15:34:44 +0300 Subject: [PATCH] LU-16966 osd: take trunc_lock for fallocate as fallocate may need few transactions (or transaction restarted) we have to avoid any concurrent writes/truncates on this object until fallocate supports 'restart-from-beginning' - first stop the transaction, then release the lock, then repeat again (like the write path does). Signed-off-by: Alex Zhuravlev Change-Id: I0bf38b1886fbf24656b45fe0f87fcbad2227672a Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/52264 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Arshad Hussain Reviewed-by: Oleg Drokin --- lustre/osd-ldiskfs/osd_io.c | 50 +++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/lustre/osd-ldiskfs/osd_io.c b/lustre/osd-ldiskfs/osd_io.c index bcfd1fe..e8a3e0b 100644 --- a/lustre/osd-ldiskfs/osd_io.c +++ b/lustre/osd-ldiskfs/osd_io.c @@ -2110,33 +2110,39 @@ static int osd_declare_fallocate(const struct lu_env *env, LASSERT(th); LASSERT(inode); - if (mode & FALLOC_FL_PUNCH_HOLE) { - rc = osd_declare_inode_qid(env, i_uid_read(inode), - i_gid_read(inode), - i_projid_read(inode), 0, oh, - osd_dt_obj(dt), NULL, OSD_QID_BLK); - if (rc == 0) - rc = osd_trunc_lock(osd_dt_obj(dt), oh, false); - RETURN(rc); - } - - /* quota space for metadata blocks - * approximate metadata estimate should be good enough. - */ - quota_space += PAGE_SIZE; - quota_space += depth * LDISKFS_BLOCK_SIZE(osd_sb(osd)); + if ((mode & FALLOC_FL_PUNCH_HOLE) == 0) { + /* quota space for metadata blocks + * approximate metadata estimate should be good enough. + */ + quota_space += PAGE_SIZE; + quota_space += depth * LDISKFS_BLOCK_SIZE(osd_sb(osd)); - /* quota space should be reported in 1K blocks */ - quota_space = toqb(quota_space) + toqb(end - start) + - LDISKFS_META_TRANS_BLOCKS(inode->i_sb); + /* quota space should be reported in 1K blocks */ + quota_space = toqb(quota_space) + toqb(end - start) + + LDISKFS_META_TRANS_BLOCKS(inode->i_sb); - /* We don't need to reserve credits for whole fallocate here. - * We reserve space only for metadata. Fallocate credits are - * extended as required - */ + /* + * We don't need to reserve credits for whole fallocate here. + * We reserve space only for metadata. Fallocate credits are + * extended as required + */ + } rc = osd_declare_inode_qid(env, i_uid_read(inode), i_gid_read(inode), i_projid_read(inode), quota_space, oh, osd_dt_obj(dt), NULL, OSD_QID_BLK); + if (rc) + RETURN(rc); + + /* + * The both hole punch and allocation may need few transactions + * to complete, so we have to avoid concurrent writes/truncates + * as we can't release object lock from within ldiskfs. + * Notice locking order: transaction start, then lock object + * (don't confuse object lock dt_{read|write}_lock() with the + * trunc lock. + */ + rc = osd_trunc_lock(osd_dt_obj(dt), oh, false); + RETURN(rc); } -- 1.8.3.1