Commit 0c20a351 authored by Linus Torvalds's avatar Linus Torvalds

v2.4.14.9 -> v2.4.15

  - Jan Kara: fix quota SMP races with BKL
parent 1040c54c
...@@ -887,9 +887,15 @@ CONFIG_IDEDMA_PCI_AUTO ...@@ -887,9 +887,15 @@ CONFIG_IDEDMA_PCI_AUTO
IGNORE word93 Validation BITS IGNORE word93 Validation BITS
CONFIG_IDEDMA_IVB CONFIG_IDEDMA_IVB
Since various rules were applied and created ... et al. as it There are unclear terms is ATA-4 and ATA-5 standards how certain
relates the detection of valid cable signals. This is a result of hardware (an 80c ribbon) should be detected. Different interpretations
unclear terms in ATA-4 and ATA-5 standards. of the standards have been released in hardware. This causes problems:
for example, a host with Ultra Mode 4 (or higher) will not run
in that mode with an 80c ribbon.
If you are experiencing compatibility or performance problems, you
MAY try to answering Y here. However, it does not necessarily solve
any of your problems, it could even cause more of them.
It is normally safe to answer Y; however, the default is N. It is normally safe to answer Y; however, the default is N.
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 4 PATCHLEVEL = 4
SUBLEVEL = 15 SUBLEVEL = 15
EXTRAVERSION =-pre9 EXTRAVERSION =-greased-turkey
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
......
...@@ -92,5 +92,5 @@ SECTIONS ...@@ -92,5 +92,5 @@ SECTIONS
.debug_typenames 0 : { *(.debug_typenames) } .debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) } .debug_varnames 0 : { *(.debug_varnames) }
/DISCARD/ : { *(.text.exit) *(.data.exit) } /DISCARD/ : { *(.text.exit) *(.data.exit) *(.exitcall.exit) }
} }
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/malloc.h> #include <linux/slab.h>
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/malloc.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/threads.h> #include <linux/threads.h>
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/malloc.h> #include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/time.h> #include <linux/time.h>
......
...@@ -189,11 +189,8 @@ static inline void move_dquot_head(struct dquot *dquot) ...@@ -189,11 +189,8 @@ static inline void move_dquot_head(struct dquot *dquot)
static inline void remove_free_dquot(struct dquot *dquot) static inline void remove_free_dquot(struct dquot *dquot)
{ {
/* sanity check */ if (list_empty(&dquot->dq_free))
if (list_empty(&dquot->dq_free)) { return;
printk("remove_free_dquot: dquot not on the free list??\n");
return; /* J.K. Just don't do anything */
}
list_del(&dquot->dq_free); list_del(&dquot->dq_free);
INIT_LIST_HEAD(&dquot->dq_free); INIT_LIST_HEAD(&dquot->dq_free);
nr_free_dquots--; nr_free_dquots--;
...@@ -330,24 +327,6 @@ static void read_dquot(struct dquot *dquot) ...@@ -330,24 +327,6 @@ static void read_dquot(struct dquot *dquot)
unlock_dquot(dquot); unlock_dquot(dquot);
} }
/*
* Unhash and selectively clear the dquot structure,
* but preserve the use count, list pointers, and
* wait queue.
*/
void clear_dquot(struct dquot *dquot)
{
/* unhash it first */
remove_dquot_hash(dquot);
dquot->dq_sb = NULL;
dquot->dq_id = 0;
dquot->dq_dev = NODEV;
dquot->dq_type = -1;
dquot->dq_flags = 0;
dquot->dq_referenced = 0;
memset(&dquot->dq_dqb, 0, sizeof(struct dqblk));
}
/* Invalidate all dquots on the list, wait for all users. Note that this function is called /* Invalidate all dquots on the list, wait for all users. Note that this function is called
* after quota is disabled so no new quota might be created. As we only insert to the end of * after quota is disabled so no new quota might be created. As we only insert to the end of
* inuse list, we don't have to restart searching... */ * inuse list, we don't have to restart searching... */
...@@ -363,6 +342,7 @@ static void invalidate_dquots(struct super_block *sb, short type) ...@@ -363,6 +342,7 @@ static void invalidate_dquots(struct super_block *sb, short type)
continue; continue;
if (dquot->dq_type != type) if (dquot->dq_type != type)
continue; continue;
dquot->dq_flags |= DQ_INVAL;
if (dquot->dq_count) if (dquot->dq_count)
/* /*
* Wait for any users of quota. As we have already cleared the flags in * Wait for any users of quota. As we have already cleared the flags in
...@@ -384,6 +364,7 @@ int sync_dquots(kdev_t dev, short type) ...@@ -384,6 +364,7 @@ int sync_dquots(kdev_t dev, short type)
struct list_head *head; struct list_head *head;
struct dquot *dquot; struct dquot *dquot;
lock_kernel();
restart: restart:
for (head = inuse_list.next; head != &inuse_list; head = head->next) { for (head = inuse_list.next; head != &inuse_list; head = head->next) {
dquot = list_entry(head, struct dquot, dq_inuse); dquot = list_entry(head, struct dquot, dq_inuse);
...@@ -405,6 +386,7 @@ int sync_dquots(kdev_t dev, short type) ...@@ -405,6 +386,7 @@ int sync_dquots(kdev_t dev, short type)
goto restart; goto restart;
} }
dqstats.syncs++; dqstats.syncs++;
unlock_kernel();
return 0; return 0;
} }
...@@ -428,7 +410,9 @@ static void prune_dqcache(int count) ...@@ -428,7 +410,9 @@ static void prune_dqcache(int count)
int shrink_dqcache_memory(int priority, unsigned int gfp_mask) int shrink_dqcache_memory(int priority, unsigned int gfp_mask)
{ {
lock_kernel();
prune_dqcache(nr_free_dquots / (priority + 1)); prune_dqcache(nr_free_dquots / (priority + 1));
unlock_kernel();
kmem_cache_shrink(dquot_cachep); kmem_cache_shrink(dquot_cachep);
return 0; return 0;
} }
...@@ -465,12 +449,13 @@ static void dqput(struct dquot *dquot) ...@@ -465,12 +449,13 @@ static void dqput(struct dquot *dquot)
return; return;
} }
dquot->dq_count--; dquot->dq_count--;
/* Place at end of LRU free queue */ /* If dquot is going to be invalidated invalidate_dquots() is going to free it so */
put_dquot_last(dquot); if (!(dquot->dq_flags & DQ_INVAL))
put_dquot_last(dquot); /* Place at end of LRU free queue */
wake_up(&dquot->dq_wait_free); wake_up(&dquot->dq_wait_free);
} }
struct dquot *get_empty_dquot(void) static struct dquot *get_empty_dquot(void)
{ {
struct dquot *dquot; struct dquot *dquot;
...@@ -633,9 +618,11 @@ int remove_inode_dquot_ref(struct inode *inode, short type, struct list_head *to ...@@ -633,9 +618,11 @@ int remove_inode_dquot_ref(struct inode *inode, short type, struct list_head *to
/* Free list of dquots - called from inode.c */ /* Free list of dquots - called from inode.c */
void put_dquot_list(struct list_head *tofree_head) void put_dquot_list(struct list_head *tofree_head)
{ {
struct list_head *act_head = tofree_head->next; struct list_head *act_head;
struct dquot *dquot; struct dquot *dquot;
lock_kernel();
act_head = tofree_head->next;
/* So now we have dquots on the list... Just free them */ /* So now we have dquots on the list... Just free them */
while (act_head != tofree_head) { while (act_head != tofree_head) {
dquot = list_entry(act_head, struct dquot, dq_free); dquot = list_entry(act_head, struct dquot, dq_free);
...@@ -644,6 +631,7 @@ void put_dquot_list(struct list_head *tofree_head) ...@@ -644,6 +631,7 @@ void put_dquot_list(struct list_head *tofree_head)
INIT_LIST_HEAD(&dquot->dq_free); INIT_LIST_HEAD(&dquot->dq_free);
dqput(dquot); dqput(dquot);
} }
unlock_kernel();
} }
static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number) static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
...@@ -1289,6 +1277,7 @@ int quota_off(struct super_block *sb, short type) ...@@ -1289,6 +1277,7 @@ int quota_off(struct super_block *sb, short type)
short cnt; short cnt;
struct quota_mount_options *dqopt = sb_dqopt(sb); struct quota_mount_options *dqopt = sb_dqopt(sb);
lock_kernel();
if (!sb) if (!sb)
goto out; goto out;
...@@ -1313,6 +1302,7 @@ int quota_off(struct super_block *sb, short type) ...@@ -1313,6 +1302,7 @@ int quota_off(struct super_block *sb, short type)
} }
up(&dqopt->dqoff_sem); up(&dqopt->dqoff_sem);
out: out:
unlock_kernel();
return 0; return 0;
} }
......
...@@ -1209,9 +1209,9 @@ void remove_dquot_ref(struct super_block *sb, short type) ...@@ -1209,9 +1209,9 @@ void remove_dquot_ref(struct super_block *sb, short type)
if (!sb->dq_op) if (!sb->dq_op)
return; /* nothing to do */ return; /* nothing to do */
/* We have to be protected against other CPUs */ /* We have to be protected against other CPUs */
spin_lock(&inode_lock); lock_kernel(); /* This lock is for quota code */
spin_lock(&inode_lock); /* This lock is for inodes code */
list_for_each(act_head, &inode_in_use) { list_for_each(act_head, &inode_in_use) {
inode = list_entry(act_head, struct inode, i_list); inode = list_entry(act_head, struct inode, i_list);
...@@ -1234,6 +1234,7 @@ void remove_dquot_ref(struct super_block *sb, short type) ...@@ -1234,6 +1234,7 @@ void remove_dquot_ref(struct super_block *sb, short type)
remove_inode_dquot_ref(inode, type, &tofree_head); remove_inode_dquot_ref(inode, type, &tofree_head);
} }
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
unlock_kernel();
put_dquot_list(&tofree_head); put_dquot_list(&tofree_head);
} }
......
...@@ -154,6 +154,7 @@ extern int dquot_root_squash; ...@@ -154,6 +154,7 @@ extern int dquot_root_squash;
#define DQ_BLKS 0x10 /* uid/gid has been warned about blk limit */ #define DQ_BLKS 0x10 /* uid/gid has been warned about blk limit */
#define DQ_INODES 0x20 /* uid/gid has been warned about inode limit */ #define DQ_INODES 0x20 /* uid/gid has been warned about inode limit */
#define DQ_FAKE 0x40 /* no limits only usage */ #define DQ_FAKE 0x40 /* no limits only usage */
#define DQ_INVAL 0x80 /* dquot is going to be invalidated */
struct dquot { struct dquot {
struct list_head dq_hash; /* Hash list in memory */ struct list_head dq_hash; /* Hash list in memory */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment