patch-2.4.23 linux-2.4.23/fs/buffer.c
Next file: linux-2.4.23/fs/dquot.c
Previous file: linux-2.4.23/fs/binfmt_elf.c
Back to the patch index
Back to the overall index
- Lines: 166
- Date:
2003-11-28 10:26:21.000000000 -0800
- Orig file:
linux-2.4.22/fs/buffer.c
- Orig date:
2003-08-25 04:44:43.000000000 -0700
diff -urN linux-2.4.22/fs/buffer.c linux-2.4.23/fs/buffer.c
@@ -88,6 +88,13 @@
static int osync_buffers_list(struct list_head *);
static void __refile_buffer(struct buffer_head *);
+/*
+ * A global sysctl-controlled flag which puts the machine into "laptop mode"
+ */
+int laptop_mode;
+
+static DECLARE_WAIT_QUEUE_HEAD(kupdate_wait);
+
/* This is used by some architectures to estimate available memory. */
atomic_t buffermem_pages = ATOMIC_INIT(0);
@@ -612,7 +619,7 @@
if (buffer_attached(bh))
list_del(&bh->b_inode_buffers);
set_buffer_attached(bh);
- list_add(&bh->b_inode_buffers, list);
+ list_add_tail(&bh->b_inode_buffers, list);
spin_unlock(&lru_list_lock);
}
@@ -1016,7 +1023,7 @@
dirty *= 100;
dirty_limit = tot * bdf_prm.b_un.nfract_stop_bdflush;
- if (dirty > dirty_limit)
+ if (!laptop_mode && dirty > dirty_limit)
return 0;
return 1;
}
@@ -1066,6 +1073,8 @@
void mark_buffer_dirty(struct buffer_head *bh)
{
if (!atomic_set_buffer_dirty(bh)) {
+ if (block_dump)
+ printk("%s: dirtied buffer\n", current->comm);
__mark_dirty(bh);
balance_dirty();
}
@@ -1077,6 +1086,12 @@
}
EXPORT_SYMBOL(set_buffer_flushtime);
+inline int get_buffer_flushtime(void)
+{
+ return bdf_prm.b_un.interval;
+}
+EXPORT_SYMBOL(get_buffer_flushtime);
+
/*
* A buffer may need to be moved from one buffer list to another
* (e.g. in case it is not shared any more). Handle this.
@@ -1749,7 +1764,7 @@
if (!buffer_mapped(bh)) {
if (iblock < lblock) {
if (get_block(inode, iblock, bh, 0))
- continue;
+ SetPageError(page);
}
if (!buffer_mapped(bh)) {
memset(kmap(page) + i*blocksize, 0, blocksize);
@@ -1769,10 +1784,11 @@
if (!nr) {
/*
- * all buffers are uptodate - we can set the page
- * uptodate as well.
+ * All buffers are uptodate - we can set the page uptodate
+ * as well. But not if get_block() returned an error.
*/
- SetPageUptodate(page);
+ if (!PageError(page))
+ SetPageUptodate(page);
UnlockPage(page);
return 0;
}
@@ -2751,10 +2767,10 @@
#endif
printk("Buffer memory: %6dkB\n",
- atomic_read(&buffermem_pages) << (PAGE_SHIFT-10));
+ atomic_read(&buffermem_pages) << (PAGE_SHIFT-10));
- printk("Cache memory: %6dkB\n",
- (atomic_read(&page_cache_size)- atomic_read(&buffermem_pages)) << (PAGE_SHIFT-10));
+ printk("Cache memory: %6ldkB\n",
+ (page_cache_size - atomic_read(&buffermem_pages)) << (PAGE_SHIFT-10));
#ifdef CONFIG_SMP /* trylock does nothing on UP and so we could deadlock */
if (!spin_trylock(&lru_list_lock))
@@ -2859,6 +2875,12 @@
wake_up_interruptible(&bdflush_wait);
}
+void wakeup_kupdate(void)
+{
+ if (waitqueue_active(&kupdate_wait))
+ wake_up(&kupdate_wait);
+}
+
/*
* Here we attempt to write back old buffers. We also try to flush inodes
* and supers as well, since this function is essentially "update", and
@@ -2879,7 +2901,9 @@
spin_lock(&lru_list_lock);
bh = lru_list[BUF_DIRTY];
- if (!bh || time_before(jiffies, bh->b_flushtime))
+ if (!bh)
+ break;
+ if (time_before(jiffies, bh->b_flushtime) && !laptop_mode)
break;
if (write_some_buffers(NODEV))
continue;
@@ -3027,33 +3051,41 @@
complete((struct completion *)startup);
for (;;) {
+ DECLARE_WAITQUEUE(wait, tsk);
+
+ add_wait_queue(&kupdate_wait, &wait);
+
/* update interval */
interval = bdf_prm.b_un.interval;
if (interval) {
tsk->state = TASK_INTERRUPTIBLE;
schedule_timeout(interval);
} else {
- stop_kupdate:
tsk->state = TASK_STOPPED;
schedule(); /* wait for SIGCONT */
}
+ remove_wait_queue(&kupdate_wait, &wait);
/* check for sigstop */
if (signal_pending(tsk)) {
- int stopped = 0;
+ int sig, stopped = 0;
+ struct siginfo info;
+
spin_lock_irq(&tsk->sigmask_lock);
- if (sigismember(&tsk->pending.signal, SIGSTOP)) {
- sigdelset(&tsk->pending.signal, SIGSTOP);
+ sig = dequeue_signal(¤t->blocked, &info);
+ if (sig == SIGSTOP)
stopped = 1;
- }
- recalc_sigpending(tsk);
spin_unlock_irq(&tsk->sigmask_lock);
- if (stopped)
- goto stop_kupdate;
+ if (stopped) {
+ tsk->state = TASK_STOPPED;
+ schedule(); /* wait for SIGCONT */
+ }
}
#ifdef DEBUG
printk(KERN_DEBUG "kupdate() activated...\n");
#endif
sync_old_buffers();
+ if (laptop_mode)
+ fsync_dev(NODEV);
run_task_queue(&tq_disk);
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)