return -1;
}
+ if (!dvr_vfs_rec_start_check(cfg)) {
+ dvr_rec_fatal_error(de, "Not enough free disk space");
+ return SM_CODE_NO_SPACE;
+ }
+
if (!(muxer = prch->prch_muxer)) {
if (profile_chain_reopen(prch, &cfg->dvr_muxcnf, 0)) {
dvr_rec_fatal_error(de, "Unable to reopen muxer");
if (!dvr_thread_global_lock(de, run))
return 0;
dvr_rec_set_state(de, DVR_RS_WAIT_PROGRAM_START, 0);
- if(dvr_rec_start(de, ss) == 0) {
+ int code = dvr_rec_start(de, ss);
+ if(code == 0) {
ret = 1;
*started = 1;
} else
- dvr_stop_recording(de, SM_CODE_INVALID_TARGET, 1, 0);
+ dvr_stop_recording(de, code == SM_CODE_NO_SPACE ? SM_CODE_NO_SPACE : SM_CODE_INVALID_TARGET, 1, 0);
dvr_thread_global_unlock(de);
}
return ret;
* Only "Keep until space needed" recordings are deleted, starting with the oldest one
*/
static int64_t
-dvr_disk_space_cleanup(dvr_config_t *cfg)
+dvr_disk_space_cleanup(dvr_config_t *cfg, int include_active)
{
dvr_entry_t *de, *oldest;
time_t stoptime;
dvr_disk_space_config_lastdelete = mclk();
dvr_entry_cancel_remove(oldest, 0); /* Remove stored files and mark as "removed" */
} else {
- tvhwarn(LS_DVR, "%s \"until space needed\" recordings found for config \"%s\", you are running out of disk space very soon!",
- loops > 0 ? "Not enough" : "No", configName);
+ /* Stop active recordings if cleanup is not possible */
+ if (loops == 0 && include_active) {
+ tvhwarn(LS_DVR, "No \"until space needed\" recordings found for config \"%s\", aborting active recordings now!", configName);
+ LIST_FOREACH(de, &dvrentries, de_global_link) {
+ if (de->de_sched_state != DVR_RECORDING || !de->de_config || de->de_config != cfg)
+ continue;
+ dvr_stop_recording(de, SM_CODE_NO_SPACE, 1, 0);
+ }
+ }
goto finish;
}
}
/* only cleanup one directory at the time as the system needs time to delete the actual files */
- dvr_disk_space_cleanup(de->de_config);
+ dvr_disk_space_cleanup(de->de_config, 1);
cleanupDone = 1;
dvr_disk_space_config_idx = idx;
break;
mtimer_arm_rel(&dvr_disk_space_timer, dvr_get_disk_space_cb, NULL, sec2mono(15));
}
+/**
+ * Returns the available disk space for a new recording.
+ * If '0' (= below configured minimum), a new recording should not be started.
+ */
+int64_t
+dvr_vfs_rec_start_check(dvr_config_t *cfg)
+{
+ struct statvfs diskdata;
+ dvr_vfs_t *dvfs;
+ int64_t availBytes, requiredBytes, usedBytes, maximalBytes, cleanedBytes;
+
+ lock_assert(&global_lock);
+ if (!cfg || !cfg->dvr_enabled || statvfs(cfg->dvr_storage, &diskdata) == -1)
+ return 0;
+ availBytes = diskdata.f_bsize * (int64_t)diskdata.f_bavail;
+ requiredBytes = MIB(cfg->dvr_cleanup_threshold_free);
+ maximalBytes = MIB(cfg->dvr_cleanup_threshold_used);
+ dvfs = dvr_vfs_find(NULL, tvh_fsid(diskdata.f_fsid));
+ usedBytes = dvfs->used_size;
+
+ if (availBytes < requiredBytes || ((maximalBytes < usedBytes) && cfg->dvr_cleanup_threshold_used)) {
+ /* Not enough space to start recording, check if cleanup helps */
+ cleanedBytes = dvr_disk_space_cleanup(cfg, 0);
+ availBytes += cleanedBytes;
+ usedBytes -= cleanedBytes;
+ if (availBytes < requiredBytes || ((maximalBytes < usedBytes) && cfg->dvr_cleanup_threshold_used))
+ return 0;
+ }
+ return availBytes;
+}
+
/**
*
*/