Whamcloud - gitweb
LU-16692 osp: osp_fid_diff vs rollover_new_seq race 87/54087/2
authorLi Dongyang <dongyangli@ddn.com>
Mon, 19 Feb 2024 02:27:22 +0000 (13:27 +1100)
committerOleg Drokin <green@whamcloud.com>
Mon, 4 Mar 2024 19:56:33 +0000 (19:56 +0000)
osp_fid_diff/osp_objs_precreated is accessing the
last_created_fid and pre_used_fid without opd_pre_lock,
and this could race with osp_precreate_rollover_new_seq()
when updating them to new fids.

Change-Id: I3a61c99570b5532776ddc43247c1513b8c89fb32
Signed-off-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54087
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Alexander Boyko <alexander.boyko@hpe.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/osp/osp_internal.h
lustre/osp/osp_precreate.c

index f98a7a4..1ba8c54 100644 (file)
@@ -613,12 +613,22 @@ static inline bool osp_precreate_end_seq(struct osp_device *osp)
        return rc;
 }
 
-static inline int osp_objs_precreated(struct osp_device *osp)
+static inline int osp_objs_precreated_nolock(struct osp_device *osp)
 {
        return osp_fid_diff(&osp->opd_pre_last_created_fid,
                            &osp->opd_pre_used_fid);
 }
 
+static inline int osp_objs_precreated(struct osp_device *osp)
+{
+       int diff;
+
+       spin_lock(&osp->opd_pre_lock);
+       diff = osp_objs_precreated_nolock(osp);
+       spin_unlock(&osp->opd_pre_lock);
+       return diff;
+}
+
 static inline int osp_is_fid_client(struct osp_device *osp)
 {
        struct obd_import *imp = osp->opd_obd->u.cli.cl_import;
index c5e2ca9..64d5a80 100644 (file)
@@ -317,7 +317,7 @@ void osp_statfs_need_now(struct osp_device *d)
  */
 static inline int osp_precreate_is_low_nolock(struct osp_device *d)
 {
-       int available = osp_objs_precreated(d) - d->opd_pre_reserved;
+       int available = osp_objs_precreated_nolock(d) - d->opd_pre_reserved;
        int precreate_needed = d->opd_pre_create_count > 1024 ?
                d->opd_pre_create_count / 4 : d->opd_pre_create_count / 2;
 
@@ -681,16 +681,18 @@ static int osp_precreate_send(const struct lu_env *env, struct osp_device *d)
        ostid_to_fid(fid, &body->oa.o_oi, d->opd_index);
 
 ready:
+       spin_lock(&d->opd_pre_lock);
+
        if (osp_fid_diff(fid, &d->opd_pre_used_fid) <= 0) {
                CERROR("%s: precreate fid "DFID" <= local used fid "DFID
                       ": rc = %d\n", d->opd_obd->obd_name,
                       PFID(fid), PFID(&d->opd_pre_used_fid), -ESTALE);
+               spin_unlock(&d->opd_pre_lock);
                GOTO(out_req, rc = -ESTALE);
        }
 
        diff = osp_fid_diff(fid, &d->opd_pre_last_created_fid);
 
-       spin_lock(&d->opd_pre_lock);
        if (diff < grow) {
                /* the OST has not managed to create all the
                 * objects we asked for */
@@ -1477,21 +1479,18 @@ int osp_precreate_reserve(const struct lu_env *env, struct osp_device *d,
        while ((rc = d->opd_pre_status) == 0 || rc == -ENOSPC ||
                rc == -ENODEV || rc == -EAGAIN || rc == -ENOTCONN) {
 
+               spin_lock(&d->opd_pre_lock);
+               precreated = osp_objs_precreated_nolock(d);
                /*
                 * increase number of precreations
                 */
-               precreated = osp_objs_precreated(d);
                if (d->opd_pre_create_count < d->opd_pre_max_create_count &&
                    d->opd_pre_create_slow == 0 &&
                    precreated <= (d->opd_pre_create_count / 4 + 1)) {
-                       spin_lock(&d->opd_pre_lock);
                        d->opd_pre_create_slow = 1;
                        d->opd_pre_create_count *= 2;
-                       spin_unlock(&d->opd_pre_lock);
                }
 
-               spin_lock(&d->opd_pre_lock);
-               precreated = osp_objs_precreated(d);
                if (!d->opd_pre_recovering && !d->opd_force_creation) {
                        if (precreated > d->opd_pre_reserved) {
                                d->opd_pre_reserved++;