[pbs-devel] [PATCH proxmox-backup 06/11] api2/tape/drive: use run_drive_blocking_task where possible

Dominik Csapak d.csapak at proxmox.com
Thu Feb 18 15:40:25 CET 2021


Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
best viewed with '-w'
 src/api2/tape/drive.rs | 245 ++++++++++++++++++++---------------------
 1 file changed, 119 insertions(+), 126 deletions(-)

diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs
index b4cd4aa6..5ee56441 100644
--- a/src/api2/tape/drive.rs
+++ b/src/api2/tape/drive.rs
@@ -180,16 +180,15 @@ pub fn load_media(
 ///
 /// Issue a media load request to the associated changer device.
 pub async fn load_slot(drive: String, source_slot: u64) -> Result<(), Error> {
-
-    let (config, _digest) = config::drive::config()?;
-    let lock_guard = lock_tape_device(&config, &drive)?;
-
-    tokio::task::spawn_blocking(move || {
-        let _lock_guard = lock_guard; // keep lock guard
-
-        let (mut changer, _) = required_media_changer(&config, &drive)?;
-        changer.load_media_from_slot(source_slot)
-    }).await?
+    run_drive_blocking_task(
+        drive.clone(),
+        format!("load from slot {}", source_slot),
+        move |config| {
+            let (mut changer, _) = required_media_changer(&config, &drive)?;
+            changer.load_media_from_slot(source_slot)
+        },
+    )
+    .await
 }
 
 #[api(
@@ -211,19 +210,22 @@ pub async fn load_slot(drive: String, source_slot: u64) -> Result<(), Error> {
 )]
 /// Export media with specified label
 pub async fn export_media(drive: String, label_text: String) -> Result<u64, Error> {
-
-    let (config, _digest) = config::drive::config()?;
-    let lock_guard = lock_tape_device(&config, &drive)?;
-
-    tokio::task::spawn_blocking(move || {
-        let _lock_guard = lock_guard; // keep lock guard
-
-        let (mut changer, changer_name) = required_media_changer(&config, &drive)?;
-        match changer.export_media(&label_text)? {
-            Some(slot) => Ok(slot),
-            None => bail!("media '{}' is not online (via changer '{}')", label_text, changer_name),
+    run_drive_blocking_task(
+        drive.clone(),
+        format!("export media {}", label_text),
+        move |config| {
+            let (mut changer, changer_name) = required_media_changer(&config, &drive)?;
+            match changer.export_media(&label_text)? {
+                Some(slot) => Ok(slot),
+                None => bail!(
+                    "media '{}' is not online (via changer '{}')",
+                    label_text,
+                    changer_name
+                ),
+            }
         }
-    }).await?
+    )
+    .await
 }
 
 #[api(
@@ -584,29 +586,26 @@ pub async fn restore_key(
     drive: String,
     password: String,
 ) -> Result<(), Error> {
+    run_drive_blocking_task(
+        drive.clone(),
+        "restore key".to_string(),
+        move |config| {
+            let mut drive = open_drive(&config, &drive)?;
 
-    let (config, _digest) = config::drive::config()?;
-
-    // early check/lock before starting worker
-    let lock_guard = lock_tape_device(&config, &drive)?;
-
-    tokio::task::spawn_blocking(move || {
-        let _lock_guard = lock_guard; // keep lock guard
-
-        let mut drive = open_drive(&config, &drive)?;
+            let (_media_id, key_config) = drive.read_label()?;
 
-        let (_media_id, key_config) = drive.read_label()?;
+            if let Some(key_config) = key_config {
+                let password_fn = || { Ok(password.as_bytes().to_vec()) };
+                let (key, ..) = key_config.decrypt(&password_fn)?;
+                config::tape_encryption_keys::insert_key(key, key_config, true)?;
+            } else {
+                bail!("media does not contain any encryption key configuration");
+            }
 
-        if let Some(key_config) = key_config {
-            let password_fn = || { Ok(password.as_bytes().to_vec()) };
-            let (key, ..) = key_config.decrypt(&password_fn)?;
-            config::tape_encryption_keys::insert_key(key, key_config, true)?;
-        } else {
-            bail!("media does not contain any encryption key configuration");
+            Ok(())
         }
-
-        Ok(())
-    }).await?
+    )
+    .await
 }
 
  #[api(
@@ -630,65 +629,62 @@ pub async fn read_label(
     drive: String,
     inventorize: Option<bool>,
 ) -> Result<MediaIdFlat, Error> {
+    run_drive_blocking_task(
+        drive.clone(),
+        "reading label".to_string(),
+        move |config| {
+            let mut drive = open_drive(&config, &drive)?;
 
-    let (config, _digest) = config::drive::config()?;
-
-    // early check/lock before starting worker
-    let lock_guard = lock_tape_device(&config, &drive)?;
-
-    tokio::task::spawn_blocking(move || {
-        let _lock_guard = lock_guard; // keep lock guard
-
-        let mut drive = open_drive(&config, &drive)?;
-
-        let (media_id, _key_config) = drive.read_label()?;
-
-        let media_id = match media_id {
-            Some(media_id) => {
-                let mut flat = MediaIdFlat {
-                    uuid: media_id.label.uuid.clone(),
-                    label_text: media_id.label.label_text.clone(),
-                    ctime: media_id.label.ctime,
-                    media_set_ctime: None,
-                    media_set_uuid: None,
-                    encryption_key_fingerprint: None,
-                    pool: None,
-                    seq_nr: None,
-                };
-                if let Some(ref set) = media_id.media_set_label {
-                    flat.pool = Some(set.pool.clone());
-                    flat.seq_nr = Some(set.seq_nr);
-                    flat.media_set_uuid = Some(set.uuid.clone());
-                    flat.media_set_ctime = Some(set.ctime);
-                    flat.encryption_key_fingerprint = set
-                        .encryption_key_fingerprint
-                        .as_ref()
-                        .map(|fp| crate::tools::format::as_fingerprint(fp.bytes()));
-
-                    let encrypt_fingerprint = set.encryption_key_fingerprint.clone()
-                        .map(|fp| (fp, set.uuid.clone()));
+            let (media_id, _key_config) = drive.read_label()?;
+
+            let media_id = match media_id {
+                Some(media_id) => {
+                    let mut flat = MediaIdFlat {
+                        uuid: media_id.label.uuid.clone(),
+                        label_text: media_id.label.label_text.clone(),
+                        ctime: media_id.label.ctime,
+                        media_set_ctime: None,
+                        media_set_uuid: None,
+                        encryption_key_fingerprint: None,
+                        pool: None,
+                        seq_nr: None,
+                    };
+                    if let Some(ref set) = media_id.media_set_label {
+                        flat.pool = Some(set.pool.clone());
+                        flat.seq_nr = Some(set.seq_nr);
+                        flat.media_set_uuid = Some(set.uuid.clone());
+                        flat.media_set_ctime = Some(set.ctime);
+                        flat.encryption_key_fingerprint = set
+                            .encryption_key_fingerprint
+                            .as_ref()
+                            .map(|fp| crate::tools::format::as_fingerprint(fp.bytes()));
+
+                        let encrypt_fingerprint = set.encryption_key_fingerprint.clone()
+                            .map(|fp| (fp, set.uuid.clone()));
+
+                        if let Err(err) = drive.set_encryption(encrypt_fingerprint) {
+                            // try, but ignore errors. just log to stderr
+                            eprintln!("uable to load encryption key: {}", err);
+                        }
+                    }
 
-                    if let Err(err) = drive.set_encryption(encrypt_fingerprint) {
-                        // try, but ignore errors. just log to stderr
-                        eprintln!("uable to load encryption key: {}", err);
+                    if let Some(true) = inventorize {
+                        let state_path = Path::new(TAPE_STATUS_DIR);
+                        let mut inventory = Inventory::load(state_path)?;
+                        inventory.store(media_id, false)?;
                     }
-                }
 
-                if let Some(true) = inventorize {
-                    let state_path = Path::new(TAPE_STATUS_DIR);
-                    let mut inventory = Inventory::load(state_path)?;
-                    inventory.store(media_id, false)?;
+                    flat
                 }
+                None => {
+                    bail!("Media is empty (no label).");
+                }
+            };
 
-                flat
-            }
-            None => {
-                bail!("Media is empty (no label).");
-            }
-        };
-
-        Ok(media_id)
-    }).await?
+            Ok(media_id)
+        }
+    )
+    .await
 }
 
 #[api(
@@ -755,49 +751,46 @@ pub fn clean_drive(
 pub async fn inventory(
     drive: String,
 ) -> Result<Vec<LabelUuidMap>, Error> {
+    run_drive_blocking_task(
+        drive.clone(),
+        "inventorize".to_string(),
+        move |config| {
+            let (mut changer, changer_name) = required_media_changer(&config, &drive)?;
 
-    let (config, _digest) = config::drive::config()?;
-
-    // early check/lock before starting worker
-    let lock_guard = lock_tape_device(&config, &drive)?;
-
-    tokio::task::spawn_blocking(move || {
-        let _lock_guard = lock_guard; // keep lock guard
+            let label_text_list = changer.online_media_label_texts()?;
 
-        let (mut changer, changer_name) = required_media_changer(&config, &drive)?;
+            let state_path = Path::new(TAPE_STATUS_DIR);
 
-        let label_text_list = changer.online_media_label_texts()?;
+            let mut inventory = Inventory::load(state_path)?;
 
-        let state_path = Path::new(TAPE_STATUS_DIR);
+            update_changer_online_status(
+                &config,
+                &mut inventory,
+                &changer_name,
+                &label_text_list,
+            )?;
 
-        let mut inventory = Inventory::load(state_path)?;
+            let mut list = Vec::new();
 
-        update_changer_online_status(
-            &config,
-            &mut inventory,
-            &changer_name,
-            &label_text_list,
-        )?;
+            for label_text in label_text_list.iter() {
+                if label_text.starts_with("CLN") {
+                    // skip cleaning unit
+                    continue;
+                }
 
-        let mut list = Vec::new();
+                let label_text = label_text.to_string();
 
-        for label_text in label_text_list.iter() {
-            if label_text.starts_with("CLN") {
-                // skip cleaning unit
-                continue;
+                if let Some(media_id) = inventory.find_media_by_label_text(&label_text) {
+                    list.push(LabelUuidMap { label_text, uuid: Some(media_id.label.uuid.clone()) });
+                } else {
+                    list.push(LabelUuidMap { label_text, uuid: None });
+                }
             }
 
-            let label_text = label_text.to_string();
-
-            if let Some(media_id) = inventory.find_media_by_label_text(&label_text) {
-                list.push(LabelUuidMap { label_text, uuid: Some(media_id.label.uuid.clone()) });
-            } else {
-                list.push(LabelUuidMap { label_text, uuid: None });
-            }
+            Ok(list)
         }
-
-        Ok(list)
-    }).await?
+    )
+    .await
 }
 
 #[api(
-- 
2.20.1






More information about the pbs-devel mailing list