mirror of
https://github.com/linuxmint/timeshift.git
synced 2024-09-11 17:07:43 +03:00
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:
parent
428ebd30e3
commit
8d77b18fe7
@ -94,8 +94,6 @@ public class Main : GLib.Object{
|
|||||||
public int count_hourly = 6;
|
public int count_hourly = 6;
|
||||||
public int count_boot = 5;
|
public int count_boot = 5;
|
||||||
|
|
||||||
public bool btrfs_use_qgroup = true;
|
|
||||||
|
|
||||||
public string app_mode = "";
|
public string app_mode = "";
|
||||||
|
|
||||||
public bool dry_run = false;
|
public bool dry_run = false;
|
||||||
@ -2889,8 +2887,6 @@ public class Main : GLib.Object{
|
|||||||
|
|
||||||
log_msg(string.nfill(78, '-'));
|
log_msg(string.nfill(78, '-'));
|
||||||
|
|
||||||
query_subvolume_quotas();
|
|
||||||
|
|
||||||
thread_restore_running = false;
|
thread_restore_running = false;
|
||||||
return thr_success;
|
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_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("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("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_monthly", schedule_monthly.to_string());
|
||||||
config.set_string_member("schedule_weekly", schedule_weekly.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);
|
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);
|
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){
|
if (cmd_btrfs_mode != null){
|
||||||
btrfs_mode = cmd_btrfs_mode; //override
|
btrfs_mode = cmd_btrfs_mode; //override
|
||||||
}
|
}
|
||||||
@ -3851,31 +3845,6 @@ public class Main : GLib.Object{
|
|||||||
return;
|
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_success = true;
|
||||||
thread_subvol_info_running = false;
|
thread_subvol_info_running = false;
|
||||||
return;
|
return;
|
||||||
@ -3950,198 +3919,6 @@ public class Main : GLib.Object{
|
|||||||
return true;
|
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
|
// cron jobs
|
||||||
|
|
||||||
public void cron_job_update(){
|
public void cron_job_update(){
|
||||||
|
@ -165,21 +165,6 @@ public class Subvolume : GLib.Object{
|
|||||||
}
|
}
|
||||||
|
|
||||||
log_msg("%s: %s (Id:%ld)\n".printf(_("Deleted subvolume"), name, id));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,7 @@ class MiscBox : Gtk.Box{
|
|||||||
|
|
||||||
private Gtk.Window parent_window;
|
private Gtk.Window parent_window;
|
||||||
private bool restore_mode = false;
|
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) {
|
public MiscBox (Gtk.Window _parent_window, bool _restore_mode) {
|
||||||
|
|
||||||
log_debug("MiscBox: MiscBox()");
|
log_debug("MiscBox: MiscBox()");
|
||||||
|
@ -41,7 +41,6 @@ class UsersBox : Gtk.Box{
|
|||||||
private Gtk.Box box_btrfs;
|
private Gtk.Box box_btrfs;
|
||||||
private Gtk.Label lbl_message;
|
private Gtk.Label lbl_message;
|
||||||
private Gtk.CheckButton chk_include_btrfs_home;
|
private Gtk.CheckButton chk_include_btrfs_home;
|
||||||
private Gtk.CheckButton chk_enable_qgroups;
|
|
||||||
private bool restore_mode = false;
|
private bool restore_mode = false;
|
||||||
|
|
||||||
public UsersBox (Gtk.Window _parent_window, ExcludeBox _exclude_box, bool _restore_mode) {
|
public UsersBox (Gtk.Window _parent_window, ExcludeBox _exclude_box, bool _restore_mode) {
|
||||||
@ -73,8 +72,6 @@ class UsersBox : Gtk.Box{
|
|||||||
add(box_btrfs);
|
add(box_btrfs);
|
||||||
|
|
||||||
init_btrfs_home_option(box_btrfs);
|
init_btrfs_home_option(box_btrfs);
|
||||||
|
|
||||||
init_btrfs_qgroup_option(box_btrfs);
|
|
||||||
|
|
||||||
refresh();
|
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
|
// helpers
|
||||||
|
|
||||||
public void refresh(){
|
public void refresh(){
|
||||||
|
Loading…
Reference in New Issue
Block a user