/*
- * Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved.
+ * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
static gboolean vfs_device_set_max_volume_usage_fn(Device *p_self,
DevicePropertyBase *base, GValue *val,
PropertySurety surety, PropertySource source);
+static gboolean vfs_device_set_enforce_max_volume_usage_fn(Device *p_self,
+ DevicePropertyBase *base, GValue *val,
+ PropertySurety surety, PropertySource source);
static gboolean property_get_monitor_free_space_fn(Device *p_self,
DevicePropertyBase *base, GValue *val,
PropertySurety *surety, PropertySource *source);
self->volume_bytes = 0;
self->volume_limit = 0;
self->leom = TRUE;
+ self->enforce_volume_limit = TRUE;
self->monitor_free_space = TRUE;
self->checked_fs_free_bytes = G_MAXUINT64;
g_value_unset(&response);
g_value_init(&response, G_TYPE_BOOLEAN);
- g_value_set_boolean(&response, FALSE);
+ g_value_set_boolean(&response, TRUE);
device_set_simple_property(dself, PROPERTY_LEOM,
&response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
g_value_unset(&response);
+ g_value_init(&response, G_TYPE_BOOLEAN);
+ g_value_set_boolean(&response, TRUE);
+ device_set_simple_property(dself, PROPERTY_ENFORCE_MAX_VOLUME_USAGE,
+ &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED);
+ g_value_unset(&response);
+
g_value_init(&response, G_TYPE_BOOLEAN);
g_value_set_boolean(&response, FALSE);
device_set_simple_property(dself, PROPERTY_COMPRESSION,
device_simple_property_get_fn,
vfs_device_set_max_volume_usage_fn);
+ device_class_register_property(device_class, PROPERTY_ENFORCE_MAX_VOLUME_USAGE,
+ (PROPERTY_ACCESS_GET_MASK | PROPERTY_ACCESS_SET_MASK) &
+ (~ PROPERTY_ACCESS_SET_INSIDE_FILE_WRITE),
+ device_simple_property_get_fn,
+ vfs_device_set_enforce_max_volume_usage_fn);
+
device_class_register_property(device_class, PROPERTY_COMPRESSION,
PROPERTY_ACCESS_GET_MASK,
device_simple_property_get_fn,
return device_simple_property_set_fn(p_self, base, val, surety, source);
}
+static gboolean
+vfs_device_set_enforce_max_volume_usage_fn(Device *p_self,
+ DevicePropertyBase *base, GValue *val,
+ PropertySurety surety, PropertySource source)
+{
+ VfsDevice *self = VFS_DEVICE(p_self);
+
+ self->enforce_volume_limit = g_value_get_boolean(val);
+
+ return device_simple_property_set_fn(p_self, base, val, surety, source);
+}
+
static gboolean
property_get_monitor_free_space_fn(Device *p_self, DevicePropertyBase *base G_GNUC_UNUSED,
GValue *val, PropertySurety *surety, PropertySource *source)
static gboolean delete_vfs_files_functor(const char * filename,
gpointer user_data) {
VfsDevice * self;
- Device * d_self;
char * path_name;
self = VFS_DEVICE(user_data);
- d_self = DEVICE(self);
/* Skip the volume lock. */
if (strcmp(filename, VOLUME_LOCKFILE_NAME) == 0)
return FALSE;
}
dumpfile_free(d_self->volume_header);
+ d_self->header_block_size = VFS_DEVICE_LABEL_SIZE;
d_self->volume_header = label_header;
self->volume_bytes = VFS_DEVICE_LABEL_SIZE;
return TRUE;
pself->is_eom = TRUE;
if (check_at_peom(self, size)) {
+ /* check_at_peom() only checks against MAX_VOLUME_USAGE limit */
pself->is_eom = TRUE;
device_set_error(pself,
- stralloc(_("No space left on device")),
+ stralloc(_("No space left on device: more than MAX_VOLUME_USAGE bytes written")),
DEVICE_STATUS_VOLUME_ERROR);
return FALSE;
}
self->volume_bytes += size;
self->checked_bytes_used += size;
pself->block ++;
+ g_mutex_lock(pself->device_mutex);
+ pself->bytes_written += size;
+ g_mutex_unlock(pself->device_mutex);
return TRUE;
}
switch (result) {
case RESULT_SUCCESS:
*size_req = size;
+ g_mutex_lock(pself->device_mutex);
+ pself->bytes_read += size;
+ g_mutex_unlock(pself->device_mutex);
pself->block++;
return size;
case RESULT_NO_DATA:
pself->is_eof = TRUE;
+ g_mutex_lock(pself->device_mutex);
pself->in_file = FALSE;
+ g_mutex_unlock(pself->device_mutex);
device_set_error(pself,
stralloc(_("EOF")),
DEVICE_STATUS_SUCCESS);
return FALSE;
}
+ g_mutex_lock(dself->device_mutex);
dself->in_file = FALSE;
+ g_mutex_unlock(dself->device_mutex);
if (mode == ACCESS_WRITE) {
promote_volume_lock(self);
release_file(self);
pself->access_mode = ACCESS_NULL;
+ g_mutex_lock(pself->device_mutex);
pself->in_file = FALSE;
+ g_mutex_unlock(pself->device_mutex);
if (device_in_error(self)) return FALSE;
dself->is_eom = TRUE;
if (check_at_peom(self, VFS_DEVICE_LABEL_SIZE)) {
+ /* check_at_peom() only checks against MAX_VOLUME_USAGE limit */
dself->is_eom = TRUE;
device_set_error(dself,
- stralloc(_("No space left on device")),
+ stralloc(_("No space left on device: more than MAX_VOLUME_USAGE bytes written")),
DEVICE_STATUS_DEVICE_ERROR);
return FALSE;
}
/* handle some accounting business */
self->volume_bytes += VFS_DEVICE_LABEL_SIZE;
self->checked_bytes_used += VFS_DEVICE_LABEL_SIZE;
- dself->in_file = TRUE;
dself->block = 0;
+ g_mutex_lock(dself->device_mutex);
+ dself->in_file = TRUE;
+ dself->bytes_written = 0;
+ g_mutex_unlock(dself->device_mutex);
/* make_new_file_name set pself->file for us */
return TRUE;
release_file(self);
+ g_mutex_lock(dself->device_mutex);
dself->in_file = FALSE;
+ g_mutex_unlock(dself->device_mutex);
return TRUE;
}
if (device_in_error(self)) return NULL;
- dself->in_file = FALSE;
dself->is_eof = FALSE;
dself->block = 0;
+ g_mutex_lock(dself->device_mutex);
+ dself->in_file = FALSE;
+ dself->bytes_read = 0;
+ g_mutex_unlock(dself->device_mutex);
release_file(self);
}
/* update our state */
+ if (requested_file == 0) {
+ dself->header_block_size = header_buffer_size;
+ }
+ g_mutex_lock(dself->device_mutex);
dself->in_file = TRUE;
+ g_mutex_unlock(dself->device_mutex);
dself->file = file;
return rval;
return FALSE;
/* handle VOLUME_LIMIT */
- if (self->volume_limit &&
+ if (self->enforce_volume_limit && self->volume_limit &&
self->volume_bytes + size + eom_warning_buffer > self->volume_limit) {
return TRUE;
}
static gboolean
check_at_peom(VfsDevice *self, guint64 size)
{
- if (self->volume_limit > 0) {
+ if (self->enforce_volume_limit && (self->volume_limit > 0)) {
guint64 newtotal = self->volume_bytes + size;
if (newtotal > self->volume_limit) {
return TRUE;
vfs_device_erase (Device * dself) {
VfsDevice *self = VFS_DEVICE(dself);
- if (!open_lock(self, 0, true))
- return false;
+ if (!open_lock(self, 0, TRUE))
+ return FALSE;
delete_vfs_files(self);
release_file(self);
+ dumpfile_free(dself->volume_header);
+ dself->volume_header = NULL;
+ device_set_error(dself, g_strdup("Unlabeled volume"),
+ DEVICE_STATUS_VOLUME_UNLABELED);
+
return TRUE;
}