Fix #865, #839, #680: Do not create or remove Qgroups when snapshots are created or removed

This fixes multiple issues related to quota groups but also removes the ability to display columns for 'Size' and 'Unshared Size' for BTRFS snapshots.
This commit is contained in:
Tony George 2022-05-28 11:18:28 +05:30 committed by Clement Lefebvre
parent 428ebd30e3
commit 8d77b18fe7
4 changed files with 2 additions and 267 deletions

View File

@ -94,8 +94,6 @@ public class Main : GLib.Object{
public int count_hourly = 6;
public int count_boot = 5;
public bool btrfs_use_qgroup = true;
public string app_mode = "";
public bool dry_run = false;
@ -2889,8 +2887,6 @@ public class Main : GLib.Object{
log_msg(string.nfill(78, '-'));
query_subvolume_quotas();
thread_restore_running = false;
return thr_success;
}
@ -3062,7 +3058,6 @@ public class Main : GLib.Object{
config.set_string_member("include_btrfs_home_for_backup", include_btrfs_home_for_backup.to_string());
config.set_string_member("include_btrfs_home_for_restore", include_btrfs_home_for_restore.to_string());
config.set_string_member("stop_cron_emails", stop_cron_emails.to_string());
config.set_string_member("btrfs_use_qgroup", btrfs_use_qgroup.to_string());
config.set_string_member("schedule_monthly", schedule_monthly.to_string());
config.set_string_member("schedule_weekly", schedule_weekly.to_string());
@ -3159,8 +3154,7 @@ public class Main : GLib.Object{
include_btrfs_home_for_restore = json_get_bool(config, "include_btrfs_home_for_restore", include_btrfs_home_for_restore);
stop_cron_emails = json_get_bool(config, "stop_cron_emails", stop_cron_emails);
btrfs_use_qgroup = json_get_bool(config, "btrfs_use_qgroup", btrfs_use_qgroup);
if (cmd_btrfs_mode != null){
btrfs_mode = cmd_btrfs_mode; //override
}
@ -3851,31 +3845,6 @@ public class Main : GLib.Object{
return;
}
//query quota
ok = query_subvolume_quotas();
if (!ok){
if (btrfs_use_qgroup){
//try enabling quota
ok = enable_subvolume_quotas();
if (!ok){
thread_subvol_info_success = false;
thread_subvol_info_running = false;
return;
}
//query quota again
ok = query_subvolume_quotas();
if (!ok){
thread_subvol_info_success = false;
thread_subvol_info_running = false;
return;
}
}
}
thread_subvol_info_success = true;
thread_subvol_info_running = false;
return;
@ -3950,198 +3919,6 @@ public class Main : GLib.Object{
return true;
}
public bool query_subvolume_quotas(){
bool ok = query_subvolume_quota("@");
if (repo.device.uuid != repo.device_home.uuid){
ok = ok && query_subvolume_quota("@home");
}
return ok;
}
public bool query_subvolume_quota(string subvol_name){
log_debug("query_subvolume_quota():%s".printf(subvol_name));
string cmd = "";
string std_out;
string std_err;
int ret_val;
string options = use_option_raw ? "--raw" : "";
cmd = "btrfs qgroup show %s '%s'".printf(options, repo.mount_paths[subvol_name]);
log_debug(cmd);
ret_val = exec_sync(cmd, out std_out, out std_err);
if (ret_val != 0){
if (use_option_raw){
use_option_raw = false;
// try again without --raw option
cmd = "btrfs qgroup show '%s'".printf(repo.mount_paths[subvol_name]);
log_debug(cmd);
ret_val = exec_sync(cmd, out std_out, out std_err);
}
if (ret_val != 0){
log_error (std_err);
log_error(_("btrfs returned an error") + ": %d".printf(ret_val));
log_error(_("Failed to query subvolume quota"));
return false;
}
}
/* Sample Output:
*
qgroupid rfer excl
-------- ---- ----
0/5 106496 106496
0/257 3825262592 557056
0/258 12689408 49152
* */
foreach(string line in std_out.split("\n")){
if (line == null) { continue; }
string[] parts = line.split(" ");
if (parts.length < 3) { continue; }
if (parts[0].split("/").length < 2) { continue; }
int subvol_id = int.parse(parts[0].split("/")[1]);
Subvolume subvol = null;
if ((sys_subvolumes.size > 0) && (sys_subvolumes["@"].id == subvol_id)){
subvol = sys_subvolumes["@"];
}
else if ((sys_subvolumes.size > 0)
&& sys_subvolumes.has_key("@home")
&& (sys_subvolumes["@home"].id == subvol_id)){
subvol = sys_subvolumes["@home"];
}
else {
foreach(var bak in repo.snapshots){
foreach(var sub in bak.subvolumes.values){
if (sub.id == subvol_id){
subvol = sub;
}
}
}
}
if (subvol != null){
int part_num = -1;
foreach(string part in parts){
if (part.strip().length > 0){
part_num ++;
switch (part_num){
case 1:
subvol.total_bytes = int64.parse(part);
break;
case 2:
subvol.unshared_bytes = int64.parse(part);
break;
default:
//ignore
break;
}
}
}
}
}
foreach(var bak in repo.snapshots){
bak.update_control_file();
}
return true;
}
public bool enable_subvolume_quotas(){
if (!btrfs_use_qgroup){ return false; }
bool ok = enable_subvolume_quota("@");
if (repo.device.uuid != repo.device_home.uuid){
ok = ok && enable_subvolume_quota("@home");
}
if (ok){
log_msg(_("Enabled subvolume quota support"));
}
return ok;
}
public bool enable_subvolume_quota(string subvol_name){
if (!btrfs_use_qgroup){ return false; }
log_debug("enable_subvolume_quota():%s".printf(subvol_name));
string cmd = "";
string std_out;
string std_err;
int ret_val;
cmd = "btrfs quota enable '%s'".printf(repo.mount_paths[subvol_name]);
log_debug(cmd);
ret_val = exec_sync(cmd, out std_out, out std_err);
if (ret_val != 0){
log_error (std_err);
log_error(_("btrfs returned an error") + ": %d".printf(ret_val));
log_error(_("Failed to enable subvolume quota"));
return false;
}
return true;
}
public bool rescan_subvolume_quotas(){
bool ok = rescan_subvolume_quota("@");
if (repo.device.uuid != repo.device_home.uuid){
ok = ok && rescan_subvolume_quota("@home");
}
if (ok){
log_msg(_("Enabled subvolume quota support"));
}
return ok;
}
public bool rescan_subvolume_quota(string subvol_name){
log_debug("rescan_subvolume_quota():%s".printf(subvol_name));
string cmd = "";
string std_out;
string std_err;
int ret_val;
cmd = "btrfs quota rescan '%s'".printf(repo.mount_paths[subvol_name]);
log_debug(cmd);
ret_val = exec_sync(cmd, out std_out, out std_err);
if (ret_val != 0){
log_error (std_err);
log_error(_("btrfs returned an error") + ": %d".printf(ret_val));
log_error(_("Failed to rescan subvolume quota"));
return false;
}
return true;
}
// cron jobs
public void cron_job_update(){

View File

@ -165,21 +165,6 @@ public class Subvolume : GLib.Object{
}
log_msg("%s: %s (Id:%ld)\n".printf(_("Deleted subvolume"), name, id));
if ((id > 0) && (repo != null)){
log_msg("%s: 0/%ld".printf(_("Destroying qgroup"), id));
cmd = "btrfs qgroup destroy 0/%ld '%s'".printf(id, repo.mount_paths[name]);
log_debug(cmd);
ret_val = exec_sync(cmd, out std_out, out std_err);
if (ret_val != 0){
log_error(_("Failed to destroy qgroup") + ": '0/%ld'".printf(id));
return false;
}
log_msg("%s: 0/%ld\n".printf(_("Destroyed qgroup"), id));
}
return true;
}

View File

@ -36,11 +36,7 @@ class MiscBox : Gtk.Box{
private Gtk.Window parent_window;
private bool restore_mode = false;
//private Gtk.CheckButton chk_include_btrfs_home;
//private Gtk.CheckButton chk_enable_qgroups;
public MiscBox (Gtk.Window _parent_window, bool _restore_mode) {
log_debug("MiscBox: MiscBox()");

View File

@ -41,7 +41,6 @@ class UsersBox : Gtk.Box{
private Gtk.Box box_btrfs;
private Gtk.Label lbl_message;
private Gtk.CheckButton chk_include_btrfs_home;
private Gtk.CheckButton chk_enable_qgroups;
private bool restore_mode = false;
public UsersBox (Gtk.Window _parent_window, ExcludeBox _exclude_box, bool _restore_mode) {
@ -73,8 +72,6 @@ class UsersBox : Gtk.Box{
add(box_btrfs);
init_btrfs_home_option(box_btrfs);
init_btrfs_qgroup_option(box_btrfs);
refresh();
@ -347,26 +344,6 @@ class UsersBox : Gtk.Box{
}
}
private void init_btrfs_qgroup_option(Gtk.Box box){
if (!restore_mode){
var label = add_label_header(box, _("Miscellaneous"), true);
label.margin_top = 12;
chk_enable_qgroups = new Gtk.CheckButton.with_label(_("Enable BTRFS qgroups (recommended)"));
box.add(chk_enable_qgroups);
chk_enable_qgroups.set_tooltip_text(_("Required for displaying shared and unshared size for snapshots in the main window"));
chk_enable_qgroups.active = App.btrfs_use_qgroup;
chk_enable_qgroups.toggled.connect(()=>{
App.btrfs_use_qgroup = chk_enable_qgroups.active;
});
}
}
// helpers
public void refresh(){