Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 209997
b: refs/heads/master
c: 5a55905
h: refs/heads/master
i:
  209995: 0b30d2a
v: v3
  • Loading branch information
Linus Torvalds committed Aug 25, 2010
1 parent 16d8de6 commit a04d999
Show file tree
Hide file tree
Showing 19 changed files with 322 additions and 224 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: 968591298514167d05b0379377757ddefc76f022
refs/heads/master: 5a559057b4fa0f60b2772fb590bf13e90af7a57d
2 changes: 2 additions & 0 deletions trunk/arch/x86/include/asm/tsc.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,7 @@ extern void check_tsc_sync_source(int cpu);
extern void check_tsc_sync_target(void);

extern int notsc_setup(char *);
extern void save_sched_clock_state(void);
extern void restore_sched_clock_state(void);

#endif /* _ASM_X86_TSC_H */
38 changes: 38 additions & 0 deletions trunk/arch/x86/kernel/tsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,44 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
local_irq_restore(flags);
}

static unsigned long long cyc2ns_suspend;

void save_sched_clock_state(void)
{
if (!sched_clock_stable)
return;

cyc2ns_suspend = sched_clock();
}

/*
* Even on processors with invariant TSC, TSC gets reset in some the
* ACPI system sleep states. And in some systems BIOS seem to reinit TSC to
* arbitrary value (still sync'd across cpu's) during resume from such sleep
* states. To cope up with this, recompute the cyc2ns_offset for each cpu so
* that sched_clock() continues from the point where it was left off during
* suspend.
*/
void restore_sched_clock_state(void)
{
unsigned long long offset;
unsigned long flags;
int cpu;

if (!sched_clock_stable)
return;

local_irq_save(flags);

get_cpu_var(cyc2ns_offset) = 0;
offset = cyc2ns_suspend - sched_clock();

for_each_possible_cpu(cpu)
per_cpu(cyc2ns_offset, cpu) = offset;

local_irq_restore(flags);
}

#ifdef CONFIG_CPU_FREQ

/* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/x86/power/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ static void __save_processor_state(struct saved_context *ctxt)
void save_processor_state(void)
{
__save_processor_state(&saved_context);
save_sched_clock_state();
}
#ifdef CONFIG_X86_32
EXPORT_SYMBOL(save_processor_state);
Expand Down Expand Up @@ -229,6 +230,7 @@ static void __restore_processor_state(struct saved_context *ctxt)
void restore_processor_state(void)
{
__restore_processor_state(&saved_context);
restore_sched_clock_state();
}
#ifdef CONFIG_X86_32
EXPORT_SYMBOL(restore_processor_state);
Expand Down
21 changes: 16 additions & 5 deletions trunk/drivers/xen/events.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ static inline unsigned long *cpu_evtchn_mask(int cpu)
#define VALID_EVTCHN(chn) ((chn) != 0)

static struct irq_chip xen_dynamic_chip;
static struct irq_chip xen_percpu_chip;

/* Constructor for packed IRQ information. */
static struct irq_info mk_unbound_info(void)
Expand Down Expand Up @@ -377,7 +378,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)
irq = find_unbound_irq();

set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
handle_level_irq, "event");
handle_edge_irq, "event");

evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_evtchn_info(evtchn);
Expand All @@ -403,8 +404,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
if (irq < 0)
goto out;

set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
handle_level_irq, "ipi");
set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
handle_percpu_irq, "ipi");

bind_ipi.vcpu = cpu;
if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
Expand Down Expand Up @@ -444,8 +445,8 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)

irq = find_unbound_irq();

set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
handle_level_irq, "virq");
set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
handle_percpu_irq, "virq");

evtchn_to_irq[evtchn] = irq;
irq_info[irq] = mk_virq_info(evtchn, virq);
Expand Down Expand Up @@ -964,6 +965,16 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
.retrigger = retrigger_dynirq,
};

static struct irq_chip xen_percpu_chip __read_mostly = {
.name = "xen-percpu",

.disable = disable_dynirq,
.mask = disable_dynirq,
.unmask = enable_dynirq,

.ack = ack_dynirq,
};

int xen_set_callback_via(uint64_t via)
{
struct xen_hvm_param a;
Expand Down
13 changes: 8 additions & 5 deletions trunk/fs/xfs/linux-2.6/xfs_aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,8 +852,8 @@ xfs_convert_page(
SetPageUptodate(page);

if (count) {
wbc->nr_to_write--;
if (wbc->nr_to_write <= 0)
if (--wbc->nr_to_write <= 0 &&
wbc->sync_mode == WB_SYNC_NONE)
done = 1;
}
xfs_start_page_writeback(page, !page_dirty, count);
Expand Down Expand Up @@ -1068,7 +1068,7 @@ xfs_vm_writepage(
* by themselves.
*/
if ((current->flags & (PF_MEMALLOC|PF_KSWAPD)) == PF_MEMALLOC)
goto out_fail;
goto redirty;

/*
* We need a transaction if there are delalloc or unwritten buffers
Expand All @@ -1080,7 +1080,7 @@ xfs_vm_writepage(
*/
xfs_count_page_state(page, &delalloc, &unwritten);
if ((current->flags & PF_FSTRANS) && (delalloc || unwritten))
goto out_fail;
goto redirty;

/* Is this page beyond the end of the file? */
offset = i_size_read(inode);
Expand Down Expand Up @@ -1245,12 +1245,15 @@ xfs_vm_writepage(
if (iohead)
xfs_cancel_ioend(iohead);

if (err == -EAGAIN)
goto redirty;

xfs_aops_discard_page(page);
ClearPageUptodate(page);
unlock_page(page);
return err;

out_fail:
redirty:
redirty_page_for_writepage(wbc, page);
unlock_page(page);
return 0;
Expand Down
9 changes: 7 additions & 2 deletions trunk/fs/xfs/linux-2.6/xfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,7 @@ xfs_fs_statfs(
struct xfs_inode *ip = XFS_I(dentry->d_inode);
__uint64_t fakeinos, id;
xfs_extlen_t lsize;
__int64_t ffree;

statp->f_type = XFS_SB_MAGIC;
statp->f_namelen = MAXNAMELEN - 1;
Expand All @@ -1249,7 +1250,11 @@ xfs_fs_statfs(
statp->f_files = min_t(typeof(statp->f_files),
statp->f_files,
mp->m_maxicount);
statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);

/* make sure statp->f_ffree does not underflow */
ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
statp->f_ffree = max_t(__int64_t, ffree, 0);

spin_unlock(&mp->m_sb_lock);

if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) ||
Expand Down Expand Up @@ -1402,7 +1407,7 @@ xfs_fs_freeze(

xfs_save_resvblks(mp);
xfs_quiesce_attr(mp);
return -xfs_fs_log_dummy(mp);
return -xfs_fs_log_dummy(mp, SYNC_WAIT);
}

STATIC int
Expand Down
42 changes: 6 additions & 36 deletions trunk/fs/xfs/linux-2.6/xfs_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "xfs_inode_item.h"
#include "xfs_quota.h"
#include "xfs_trace.h"
#include "xfs_fsops.h"

#include <linux/kthread.h>
#include <linux/freezer.h>
Expand Down Expand Up @@ -340,38 +341,6 @@ xfs_sync_attr(
XFS_ICI_NO_TAG, 0, NULL);
}

STATIC int
xfs_commit_dummy_trans(
struct xfs_mount *mp,
uint flags)
{
struct xfs_inode *ip = mp->m_rootip;
struct xfs_trans *tp;
int error;

/*
* Put a dummy transaction in the log to tell recovery
* that all others are OK.
*/
tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
if (error) {
xfs_trans_cancel(tp, 0);
return error;
}

xfs_ilock(ip, XFS_ILOCK_EXCL);

xfs_trans_ijoin(tp, ip);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
error = xfs_trans_commit(tp, 0);
xfs_iunlock(ip, XFS_ILOCK_EXCL);

/* the log force ensures this transaction is pushed to disk */
xfs_log_force(mp, (flags & SYNC_WAIT) ? XFS_LOG_SYNC : 0);
return error;
}

STATIC int
xfs_sync_fsdata(
struct xfs_mount *mp)
Expand Down Expand Up @@ -432,7 +401,7 @@ xfs_quiesce_data(

/* mark the log as covered if needed */
if (xfs_log_need_covered(mp))
error2 = xfs_commit_dummy_trans(mp, SYNC_WAIT);
error2 = xfs_fs_log_dummy(mp, SYNC_WAIT);

/* flush data-only devices */
if (mp->m_rtdev_targp)
Expand Down Expand Up @@ -563,7 +532,7 @@ xfs_flush_inodes(
/*
* Every sync period we need to unpin all items, reclaim inodes and sync
* disk quotas. We might need to cover the log to indicate that the
* filesystem is idle.
* filesystem is idle and not frozen.
*/
STATIC void
xfs_sync_worker(
Expand All @@ -577,8 +546,9 @@ xfs_sync_worker(
xfs_reclaim_inodes(mp, 0);
/* dgc: errors ignored here */
error = xfs_qm_sync(mp, SYNC_TRYLOCK);
if (xfs_log_need_covered(mp))
error = xfs_commit_dummy_trans(mp, 0);
if (mp->m_super->s_frozen == SB_UNFROZEN &&
xfs_log_need_covered(mp))
error = xfs_fs_log_dummy(mp, 0);
}
mp->m_sync_seq++;
wake_up(&mp->m_wait_single_sync_task);
Expand Down
31 changes: 18 additions & 13 deletions trunk/fs/xfs/xfs_fsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,31 +604,36 @@ xfs_reserve_blocks(
return 0;
}

/*
* Dump a transaction into the log that contains no real change. This is needed
* to be able to make the log dirty or stamp the current tail LSN into the log
* during the covering operation.
*
* We cannot use an inode here for this - that will push dirty state back up
* into the VFS and then periodic inode flushing will prevent log covering from
* making progress. Hence we log a field in the superblock instead.
*/
int
xfs_fs_log_dummy(
xfs_mount_t *mp)
xfs_mount_t *mp,
int flags)
{
xfs_trans_t *tp;
xfs_inode_t *ip;
int error;

tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1, KM_SLEEP);
error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
XFS_DEFAULT_LOG_COUNT);
if (error) {
xfs_trans_cancel(tp, 0);
return error;
}

ip = mp->m_rootip;
xfs_ilock(ip, XFS_ILOCK_EXCL);

xfs_trans_ijoin(tp, ip);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp, 0);

xfs_iunlock(ip, XFS_ILOCK_EXCL);
return error;
/* log the UUID because it is an unchanging field */
xfs_mod_sb(tp, XFS_SB_UUID);
if (flags & SYNC_WAIT)
xfs_trans_set_sync(tp);
return xfs_trans_commit(tp, 0);
}

int
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/xfs/xfs_fsops.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ extern int xfs_fs_counts(xfs_mount_t *mp, xfs_fsop_counts_t *cnt);
extern int xfs_reserve_blocks(xfs_mount_t *mp, __uint64_t *inval,
xfs_fsop_resblks_t *outval);
extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags);
extern int xfs_fs_log_dummy(xfs_mount_t *mp);
extern int xfs_fs_log_dummy(xfs_mount_t *mp, int flags);

#endif /* __XFS_FSOPS_H__ */
16 changes: 10 additions & 6 deletions trunk/fs/xfs/xfs_ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,6 @@ xfs_imap_lookup(
struct xfs_inobt_rec_incore rec;
struct xfs_btree_cur *cur;
struct xfs_buf *agbp;
xfs_agino_t startino;
int error;
int i;

Expand All @@ -1227,13 +1226,13 @@ xfs_imap_lookup(
}

/*
* derive and lookup the exact inode record for the given agino. If the
* record cannot be found, then it's an invalid inode number and we
* should abort.
* Lookup the inode record for the given agino. If the record cannot be
* found, then it's an invalid inode number and we should abort. Once
* we have a record, we need to ensure it contains the inode number
* we are looking up.
*/
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
startino = agino & ~(XFS_IALLOC_INODES(mp) - 1);
error = xfs_inobt_lookup(cur, startino, XFS_LOOKUP_EQ, &i);
error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
if (!error) {
if (i)
error = xfs_inobt_get_rec(cur, &rec, &i);
Expand All @@ -1246,6 +1245,11 @@ xfs_imap_lookup(
if (error)
return error;

/* check that the returned record contains the required inode */
if (rec.ir_startino > agino ||
rec.ir_startino + XFS_IALLOC_INODES(mp) <= agino)
return EINVAL;

/* for untrusted inodes check it is allocated first */
if ((flags & XFS_IGET_UNTRUSTED) &&
(rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino)))
Expand Down
Loading

0 comments on commit a04d999

Please sign in to comment.