Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 361551
b: refs/heads/master
c: 172a271
h: refs/heads/master
i:
  361549: 8a18344
  361547: 5c9a13b
  361543: 99d82ef
  361535: 79934ac
v: v3
  • Loading branch information
Linus Torvalds committed Mar 21, 2013
1 parent 1d0a2ad commit 16303c1
Show file tree
Hide file tree
Showing 19 changed files with 299 additions and 147 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b56fb70870ad76f8295a4e826dab9a9fbb0033f6
refs/heads/master: 172a271b5e090da7468c66b9ccbcdb3d929eed75
4 changes: 2 additions & 2 deletions trunk/arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,8 @@ struct kvm_vcpu_arch {
gpa_t time;
struct pvclock_vcpu_time_info hv_clock;
unsigned int hw_tsc_khz;
unsigned int time_offset;
struct page *time_page;
struct gfn_to_hva_cache pv_time;
bool pv_time_enabled;
/* set guest stopped flag in pvclock flags field */
bool pvclock_set_guest_stopped_request;

Expand Down
64 changes: 31 additions & 33 deletions trunk/arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -1406,25 +1406,15 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
unsigned long flags, this_tsc_khz;
struct kvm_vcpu_arch *vcpu = &v->arch;
struct kvm_arch *ka = &v->kvm->arch;
void *shared_kaddr;
s64 kernel_ns, max_kernel_ns;
u64 tsc_timestamp, host_tsc;
struct pvclock_vcpu_time_info *guest_hv_clock;
struct pvclock_vcpu_time_info guest_hv_clock;
u8 pvclock_flags;
bool use_master_clock;

kernel_ns = 0;
host_tsc = 0;

/* Keep irq disabled to prevent changes to the clock */
local_irq_save(flags);
this_tsc_khz = __get_cpu_var(cpu_tsc_khz);
if (unlikely(this_tsc_khz == 0)) {
local_irq_restore(flags);
kvm_make_request(KVM_REQ_CLOCK_UPDATE, v);
return 1;
}

/*
* If the host uses TSC clock, then passthrough TSC as stable
* to the guest.
Expand All @@ -1436,6 +1426,15 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
kernel_ns = ka->master_kernel_ns;
}
spin_unlock(&ka->pvclock_gtod_sync_lock);

/* Keep irq disabled to prevent changes to the clock */
local_irq_save(flags);
this_tsc_khz = __get_cpu_var(cpu_tsc_khz);
if (unlikely(this_tsc_khz == 0)) {
local_irq_restore(flags);
kvm_make_request(KVM_REQ_CLOCK_UPDATE, v);
return 1;
}
if (!use_master_clock) {
host_tsc = native_read_tsc();
kernel_ns = get_kernel_ns();
Expand Down Expand Up @@ -1463,7 +1462,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)

local_irq_restore(flags);

if (!vcpu->time_page)
if (!vcpu->pv_time_enabled)
return 0;

/*
Expand Down Expand Up @@ -1525,12 +1524,12 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
*/
vcpu->hv_clock.version += 2;

shared_kaddr = kmap_atomic(vcpu->time_page);

guest_hv_clock = shared_kaddr + vcpu->time_offset;
if (unlikely(kvm_read_guest_cached(v->kvm, &vcpu->pv_time,
&guest_hv_clock, sizeof(guest_hv_clock))))
return 0;

/* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
pvclock_flags = (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED);
pvclock_flags = (guest_hv_clock.flags & PVCLOCK_GUEST_STOPPED);

if (vcpu->pvclock_set_guest_stopped_request) {
pvclock_flags |= PVCLOCK_GUEST_STOPPED;
Expand All @@ -1543,12 +1542,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)

vcpu->hv_clock.flags = pvclock_flags;

memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock,
sizeof(vcpu->hv_clock));

kunmap_atomic(shared_kaddr);

mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT);
kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
&vcpu->hv_clock,
sizeof(vcpu->hv_clock));
return 0;
}

Expand Down Expand Up @@ -1837,10 +1833,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)

static void kvmclock_reset(struct kvm_vcpu *vcpu)
{
if (vcpu->arch.time_page) {
kvm_release_page_dirty(vcpu->arch.time_page);
vcpu->arch.time_page = NULL;
}
vcpu->arch.pv_time_enabled = false;
}

static void accumulate_steal_time(struct kvm_vcpu *vcpu)
Expand Down Expand Up @@ -1947,6 +1940,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break;
case MSR_KVM_SYSTEM_TIME_NEW:
case MSR_KVM_SYSTEM_TIME: {
u64 gpa_offset;
kvmclock_reset(vcpu);

vcpu->arch.time = data;
Expand All @@ -1956,14 +1950,17 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (!(data & 1))
break;

/* ...but clean it before doing the actual write */
vcpu->arch.time_offset = data & ~(PAGE_MASK | 1);
gpa_offset = data & ~(PAGE_MASK | 1);

vcpu->arch.time_page =
gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT);
/* Check that the address is 32-byte aligned. */
if (gpa_offset & (sizeof(struct pvclock_vcpu_time_info) - 1))
break;

if (is_error_page(vcpu->arch.time_page))
vcpu->arch.time_page = NULL;
if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
&vcpu->arch.pv_time, data & ~1ULL))
vcpu->arch.pv_time_enabled = false;
else
vcpu->arch.pv_time_enabled = true;

break;
}
Expand Down Expand Up @@ -2967,7 +2964,7 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu,
*/
static int kvm_set_guest_paused(struct kvm_vcpu *vcpu)
{
if (!vcpu->arch.time_page)
if (!vcpu->arch.pv_time_enabled)
return -EINVAL;
vcpu->arch.pvclock_set_guest_stopped_request = true;
kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
Expand Down Expand Up @@ -6718,6 +6715,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
goto fail_free_wbinvd_dirty_mask;

vcpu->arch.ia32_tsc_adjust_msr = 0x0;
vcpu->arch.pv_time_enabled = false;
kvm_async_pf_hash_reset(vcpu);
kvm_pmu_init(vcpu);

Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/md/dm-bufio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,8 @@ void dm_bufio_prefetch(struct dm_bufio_client *c,
{
struct blk_plug plug;

BUG_ON(dm_bufio_in_request());

blk_start_plug(&plug);
dm_bufio_lock(c);

Expand Down
64 changes: 51 additions & 13 deletions trunk/drivers/md/dm-cache-metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ struct cache_disk_superblock {
__le32 read_misses;
__le32 write_hits;
__le32 write_misses;

__le32 policy_version[CACHE_POLICY_VERSION_SIZE];
} __packed;

struct dm_cache_metadata {
Expand All @@ -109,6 +111,7 @@ struct dm_cache_metadata {
bool clean_when_opened:1;

char policy_name[CACHE_POLICY_NAME_SIZE];
unsigned policy_version[CACHE_POLICY_VERSION_SIZE];
size_t policy_hint_size;
struct dm_cache_statistics stats;
};
Expand Down Expand Up @@ -268,7 +271,8 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd)
memset(disk_super->uuid, 0, sizeof(disk_super->uuid));
disk_super->magic = cpu_to_le64(CACHE_SUPERBLOCK_MAGIC);
disk_super->version = cpu_to_le32(CACHE_VERSION);
memset(disk_super->policy_name, 0, CACHE_POLICY_NAME_SIZE);
memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name));
memset(disk_super->policy_version, 0, sizeof(disk_super->policy_version));
disk_super->policy_hint_size = 0;

r = dm_sm_copy_root(cmd->metadata_sm, &disk_super->metadata_space_map_root,
Expand All @@ -284,7 +288,6 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd)
disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
disk_super->data_block_size = cpu_to_le32(cmd->data_block_size);
disk_super->cache_blocks = cpu_to_le32(0);
memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name));

disk_super->read_hits = cpu_to_le32(0);
disk_super->read_misses = cpu_to_le32(0);
Expand Down Expand Up @@ -478,6 +481,9 @@ static void read_superblock_fields(struct dm_cache_metadata *cmd,
cmd->data_block_size = le32_to_cpu(disk_super->data_block_size);
cmd->cache_blocks = to_cblock(le32_to_cpu(disk_super->cache_blocks));
strncpy(cmd->policy_name, disk_super->policy_name, sizeof(cmd->policy_name));
cmd->policy_version[0] = le32_to_cpu(disk_super->policy_version[0]);
cmd->policy_version[1] = le32_to_cpu(disk_super->policy_version[1]);
cmd->policy_version[2] = le32_to_cpu(disk_super->policy_version[2]);
cmd->policy_hint_size = le32_to_cpu(disk_super->policy_hint_size);

cmd->stats.read_hits = le32_to_cpu(disk_super->read_hits);
Expand Down Expand Up @@ -572,6 +578,9 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
disk_super->discard_nr_blocks = cpu_to_le64(from_dblock(cmd->discard_nr_blocks));
disk_super->cache_blocks = cpu_to_le32(from_cblock(cmd->cache_blocks));
strncpy(disk_super->policy_name, cmd->policy_name, sizeof(disk_super->policy_name));
disk_super->policy_version[0] = cpu_to_le32(cmd->policy_version[0]);
disk_super->policy_version[1] = cpu_to_le32(cmd->policy_version[1]);
disk_super->policy_version[2] = cpu_to_le32(cmd->policy_version[2]);

disk_super->read_hits = cpu_to_le32(cmd->stats.read_hits);
disk_super->read_misses = cpu_to_le32(cmd->stats.read_misses);
Expand Down Expand Up @@ -854,18 +863,43 @@ struct thunk {
bool hints_valid;
};

static bool policy_unchanged(struct dm_cache_metadata *cmd,
struct dm_cache_policy *policy)
{
const char *policy_name = dm_cache_policy_get_name(policy);
const unsigned *policy_version = dm_cache_policy_get_version(policy);
size_t policy_hint_size = dm_cache_policy_get_hint_size(policy);

/*
* Ensure policy names match.
*/
if (strncmp(cmd->policy_name, policy_name, sizeof(cmd->policy_name)))
return false;

/*
* Ensure policy major versions match.
*/
if (cmd->policy_version[0] != policy_version[0])
return false;

/*
* Ensure policy hint sizes match.
*/
if (cmd->policy_hint_size != policy_hint_size)
return false;

return true;
}

static bool hints_array_initialized(struct dm_cache_metadata *cmd)
{
return cmd->hint_root && cmd->policy_hint_size;
}

static bool hints_array_available(struct dm_cache_metadata *cmd,
const char *policy_name)
struct dm_cache_policy *policy)
{
bool policy_names_match = !strncmp(cmd->policy_name, policy_name,
sizeof(cmd->policy_name));

return cmd->clean_when_opened && policy_names_match &&
return cmd->clean_when_opened && policy_unchanged(cmd, policy) &&
hints_array_initialized(cmd);
}

Expand Down Expand Up @@ -899,7 +933,8 @@ static int __load_mapping(void *context, uint64_t cblock, void *leaf)
return r;
}

static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_name,
static int __load_mappings(struct dm_cache_metadata *cmd,
struct dm_cache_policy *policy,
load_mapping_fn fn, void *context)
{
struct thunk thunk;
Expand All @@ -909,18 +944,19 @@ static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_nam

thunk.cmd = cmd;
thunk.respect_dirty_flags = cmd->clean_when_opened;
thunk.hints_valid = hints_array_available(cmd, policy_name);
thunk.hints_valid = hints_array_available(cmd, policy);

return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk);
}

int dm_cache_load_mappings(struct dm_cache_metadata *cmd, const char *policy_name,
int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
struct dm_cache_policy *policy,
load_mapping_fn fn, void *context)
{
int r;

down_read(&cmd->root_lock);
r = __load_mappings(cmd, policy_name, fn, context);
r = __load_mappings(cmd, policy, fn, context);
up_read(&cmd->root_lock);

return r;
Expand Down Expand Up @@ -979,7 +1015,7 @@ static int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty
/* nothing to be done */
return 0;

value = pack_value(oblock, flags | (dirty ? M_DIRTY : 0));
value = pack_value(oblock, (flags & ~M_DIRTY) | (dirty ? M_DIRTY : 0));
__dm_bless_for_disk(&value);

r = dm_array_set_value(&cmd->info, cmd->root, from_cblock(cblock),
Expand Down Expand Up @@ -1070,13 +1106,15 @@ static int begin_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *po
__le32 value;
size_t hint_size;
const char *policy_name = dm_cache_policy_get_name(policy);
const unsigned *policy_version = dm_cache_policy_get_version(policy);

if (!policy_name[0] ||
(strlen(policy_name) > sizeof(cmd->policy_name) - 1))
return -EINVAL;

if (strcmp(cmd->policy_name, policy_name)) {
if (!policy_unchanged(cmd, policy)) {
strncpy(cmd->policy_name, policy_name, sizeof(cmd->policy_name));
memcpy(cmd->policy_version, policy_version, sizeof(cmd->policy_version));

hint_size = dm_cache_policy_get_hint_size(policy);
if (!hint_size)
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/md/dm-cache-metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ typedef int (*load_mapping_fn)(void *context, dm_oblock_t oblock,
dm_cblock_t cblock, bool dirty,
uint32_t hint, bool hint_valid);
int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
const char *policy_name,
struct dm_cache_policy *policy,
load_mapping_fn fn,
void *context);

Expand Down
7 changes: 5 additions & 2 deletions trunk/drivers/md/dm-cache-policy-cleaner.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
/*----------------------------------------------------------------*/

#define DM_MSG_PREFIX "cache cleaner"
#define CLEANER_VERSION "1.0.0"

/* Cache entry struct. */
struct wb_cache_entry {
Expand Down Expand Up @@ -434,6 +433,7 @@ static struct dm_cache_policy *wb_create(dm_cblock_t cache_size,

static struct dm_cache_policy_type wb_policy_type = {
.name = "cleaner",
.version = {1, 0, 0},
.hint_size = 0,
.owner = THIS_MODULE,
.create = wb_create
Expand All @@ -446,7 +446,10 @@ static int __init wb_init(void)
if (r < 0)
DMERR("register failed %d", r);
else
DMINFO("version " CLEANER_VERSION " loaded");
DMINFO("version %u.%u.%u loaded",
wb_policy_type.version[0],
wb_policy_type.version[1],
wb_policy_type.version[2]);

return r;
}
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/md/dm-cache-policy-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ void dm_cache_policy_destroy(struct dm_cache_policy *p);
*/
const char *dm_cache_policy_get_name(struct dm_cache_policy *p);

const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p);

size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p);

/*----------------------------------------------------------------*/
Expand Down
Loading

0 comments on commit 16303c1

Please sign in to comment.