Whamcloud - gitweb
LU-15451 sec: retry ro mount if read-only flag set 90/47490/6
authorSebastien Buisson <sbuisson@ddn.com>
Wed, 25 May 2022 14:53:57 +0000 (16:53 +0200)
committerOleg Drokin <green@whamcloud.com>
Sat, 15 Oct 2022 05:56:04 +0000 (05:56 +0000)
In case client mount fails with -EROFS because the read-only nodemap
flag is set and ro mount option is not specified, just retry ro mount
internally. This is to avoid the need for users to manually retry the
mount with ro option.

Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I0dedd1394eeb6804f7fdde930275f6649b935bab
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/47490
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/doc/lctl-nodemap-modify.8
lustre/fld/fld_request.c
lustre/include/lu_object.h
lustre/ldlm/ldlm_lib.c
lustre/llite/llite_lib.c
lustre/lmv/lmv_obd.c
lustre/obdclass/lu_tgt_descs.c
lustre/tests/sanity-sec.sh

index c46f7f4..1bead96 100644 (file)
@@ -78,7 +78,7 @@ map UIDs, gid to map GIDs, both to map UIDs and GIDs, and projid to map PROJIDs.
 readonly_mount
 .RS 4
 Defaults to off, which lets clients mount in read-write mode. If set to 1,
-clients are only allowed to mount in read-only mount, and get -EROFS otherwise.
+clients are forced to a read-only mount if not specified explicitly.
 .RE
 
 .RE
index e381eb8..fecf82d 100644 (file)
@@ -222,6 +222,7 @@ int fld_client_del_target(struct lu_client_fld *fld, u64 idx)
        spin_unlock(&fld->lcf_lock);
        RETURN(-ENOENT);
 }
+EXPORT_SYMBOL(fld_client_del_target);
 
 struct dentry *fld_debugfs_dir;
 
index 97dc3de..03db2eb 100644 (file)
@@ -1738,6 +1738,7 @@ struct lu_tgt_descs {
 
 u64 lu_prandom_u64_max(u64 ep_ro);
 int lu_qos_add_tgt(struct lu_qos *qos, struct lu_tgt_desc *ltd);
+int lu_qos_del_tgt(struct lu_qos *qos, struct lu_tgt_desc *ltd);
 void lu_tgt_qos_weight_calc(struct lu_tgt_desc *tgt);
 
 int lu_tgt_descs_init(struct lu_tgt_descs *ltd, bool is_mdt);
index 6d16a63..1738310 100644 (file)
@@ -654,6 +654,16 @@ int client_connect_import(const struct lu_env *env,
 
        LASSERT(obd->obd_namespace);
 
+       spin_lock(&imp->imp_lock);
+       if (imp->imp_state == LUSTRE_IMP_CLOSED && imp->imp_deactive) {
+               /* need to reactivate import if trying to connect
+                * to a previously disconnected
+                */
+               imp->imp_deactive = 0;
+               imp->imp_invalid = 0;
+       }
+       spin_unlock(&imp->imp_lock);
+
        imp->imp_dlm_handle = conn;
        rc = ptlrpc_init_import(imp);
        if (rc != 0)
@@ -694,8 +704,7 @@ out_ldlm:
 out_sem:
        up_write(&cli->cl_sem);
 
-       if (!rc && localdata) {
-               LASSERT(cli->cl_cache == NULL); /* only once */
+       if (!rc && localdata && !cli->cl_cache) {
                cli->cl_cache = (struct cl_client_cache *)localdata;
                cl_cache_incref(cli->cl_cache);
                cli->cl_lru_left = &cli->cl_cache->ccc_lru_left;
index a0c8cca..d688d1b 100644 (file)
@@ -358,8 +358,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
        data->ocd_ibits_known = MDS_INODELOCK_FULL;
        data->ocd_version = LUSTRE_VERSION_CODE;
 
-       if (sb->s_flags & SB_RDONLY)
-               data->ocd_connect_flags |= OBD_CONNECT_RDONLY;
        if (test_bit(LL_SBI_USER_XATTR, sbi->ll_flags))
                data->ocd_connect_flags |= OBD_CONNECT_XATTR;
 
@@ -387,6 +385,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
 
        data->ocd_brw_size = MD_MAX_BRW_SIZE;
 
+retry_connect:
+       if (sb->s_flags & SB_RDONLY)
+               data->ocd_connect_flags |= OBD_CONNECT_RDONLY;
        err = obd_connect(NULL, &sbi->ll_md_exp, sbi->ll_md_obd,
                          &sbi->ll_sb_uuid, data, sbi->ll_cache);
        if (err == -EBUSY) {
@@ -416,8 +417,20 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
        err = obd_statfs(NULL, sbi->ll_md_exp, osfs,
                        ktime_get_seconds() - sbi->ll_statfs_max_age,
                        OBD_STATFS_FOR_MDT0);
-       if (err)
+       if (err == -EROFS && !(sb->s_flags & SB_RDONLY)) {
+               /* We got -EROFS from the server, maybe it is imposing
+                * read-only mount. So just retry like this.
+                */
+               cfs_tty_write_msg("Forcing read-only mount.\n\r");
+               CERROR("%s: mount failed with %d, forcing read-only mount.\n",
+                      sbi->ll_md_exp->exp_obd->obd_name, err);
+               sb->s_flags |= SB_RDONLY;
+               obd_fid_fini(sbi->ll_md_exp->exp_obd);
+               obd_disconnect(sbi->ll_md_exp);
+               GOTO(retry_connect, err);
+       } else if (err) {
                GOTO(out_md_fid, err);
+       }
 
        /* This needs to be after statfs to ensure connect has finished.
         * Note that "data" does NOT contain the valid connect reply.
@@ -1428,7 +1441,8 @@ out_free_cfg:
        if (err)
                ll_put_super(sb);
        else if (test_bit(LL_SBI_VERBOSE, sbi->ll_flags))
-               LCONSOLE_WARN("Mounted %s\n", profilenm);
+               LCONSOLE_WARN("Mounted %s%s\n", profilenm,
+                             sb->s_flags & SB_RDONLY ? " read-only" : "");
        RETURN(err);
 } /* ll_fill_super */
 
index a65802d..9290f08 100644 (file)
@@ -509,24 +509,33 @@ static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
                                          mdc_obd->obd_name);
        }
 
+       rc = lu_qos_del_tgt(&lmv->lmv_qos, tgt);
+       if (rc)
+               CERROR("%s: Can't del target from QoS table: rc = %d\n",
+                      tgt->ltd_exp->exp_obd->obd_name, rc);
+
+       rc = fld_client_del_target(&lmv->lmv_fld, tgt->ltd_index);
+       if (rc)
+               CERROR("%s: Can't del fld targets: rc = %d\n",
+                      tgt->ltd_exp->exp_obd->obd_name, rc);
+
        rc = obd_fid_fini(tgt->ltd_exp->exp_obd);
        if (rc)
-               CERROR("Can't finalize fids factory\n");
+               CERROR("%s: Can't finalize fids factory: rc = %d\n",
+                      tgt->ltd_exp->exp_obd->obd_name, rc);
 
        CDEBUG(D_INFO, "Disconnected from %s(%s) successfully\n",
               tgt->ltd_exp->exp_obd->obd_name,
               tgt->ltd_exp->exp_obd->obd_uuid.uuid);
 
+       lmv_activate_target(lmv, tgt, 0);
        obd_register_observer(tgt->ltd_exp->exp_obd, NULL);
        rc = obd_disconnect(tgt->ltd_exp);
        if (rc) {
-               if (tgt->ltd_active) {
-                       CERROR("Target %s disconnect error %d\n",
-                              tgt->ltd_uuid.uuid, rc);
-               }
+               CERROR("%s: Target %s disconnect error: rc = %d\n",
+                      tgt->ltd_exp->exp_obd->obd_name,
+                      tgt->ltd_uuid.uuid, rc);
        }
-
-       lmv_activate_target(lmv, tgt, 0);
        tgt->ltd_exp = NULL;
        RETURN(0);
 }
index 1effd99..bfb5816 100644 (file)
@@ -175,7 +175,7 @@ EXPORT_SYMBOL(lu_qos_add_tgt);
  * \retval 0                   on success
  * \retval -ENOENT             if no server was found
  */
-static int lu_qos_del_tgt(struct lu_qos *qos, struct lu_tgt_desc *ltd)
+int lu_qos_del_tgt(struct lu_qos *qos, struct lu_tgt_desc *ltd)
 {
        struct lu_svr_qos *svr;
        int rc = 0;
@@ -187,12 +187,12 @@ static int lu_qos_del_tgt(struct lu_qos *qos, struct lu_tgt_desc *ltd)
        if (!svr)
                GOTO(out, rc = -ENOENT);
 
+       ltd->ltd_qos.ltq_svr = NULL;
        svr->lsq_tgt_count--;
        if (svr->lsq_tgt_count == 0) {
                CDEBUG(D_OTHER, "removing server %s\n",
                       obd_uuid2str(&svr->lsq_uuid));
                list_del(&svr->lsq_svr_list);
-               ltd->ltd_qos.ltq_svr = NULL;
                OBD_FREE_PTR(svr);
        }
 
@@ -204,6 +204,7 @@ out:
        up_write(&qos->lq_rw_sem);
        RETURN(rc);
 }
+EXPORT_SYMBOL(lu_qos_del_tgt);
 
 static inline __u64 tgt_statfs_bavail(struct lu_tgt_desc *tgt)
 {
index d4d7c30..360e3ca 100755 (executable)
@@ -5092,14 +5092,26 @@ test_61() {
        do_facet mgs $LCTL nodemap_modify --name default \
                --property readonly_mount --value 1
        wait_nm_sync default readonly_mount
-       mount_client $MOUNT ${MOUNT_OPTS},rw &&
-               error "mount '-o rw' should have failed"
+       mount_client $MOUNT ${MOUNT_OPTS} ||
+               error "mount failed"
+       findmnt $MOUNT --output=options -n -f | grep -q "ro," ||
+               error "mount should have been turned into ro"
+       cat $testfile || error "read $testfile failed (1)"
+       echo b > $testfile && error "write $testfile should fail (1)"
+       umount_client $MOUNT || error "umount $MOUNT failed (3)"
+       mount_client $MOUNT ${MOUNT_OPTS},rw ||
+               error "mount '-o rw' failed"
+       findmnt $MOUNT --output=options -n -f | grep -q "ro," ||
+               error "mount rw should have been turned into ro"
+       cat $testfile || error "read $testfile failed (2)"
+       echo b > $testfile && error "write $testfile should fail (2)"
+       umount_client $MOUNT || error "umount $MOUNT failed (4)"
        mount_client $MOUNT ${MOUNT_OPTS},ro ||
                error "mount '-o ro' failed"
        wait_ssk
-       cat $testfile || error "read $testfile failed"
-       echo b > $testfile && error "write $testfile should fail"
-       umount_client $MOUNT || error "umount $MOUNT failed (3)"
+       cat $testfile || error "read $testfile failed (3)"
+       echo b > $testfile && error "write $testfile should fail (3)"
+       umount_client $MOUNT || error "umount $MOUNT failed (5)"
 }
 run_test 61 "Nodemap enforces read-only mount"