coda breakage
[safe/jmp/linux-2.6] / fs / dquot.c
index 1405755..7e27315 100644 (file)
@@ -69,7 +69,6 @@
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
@@ -79,6 +78,7 @@
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <linux/writeback.h> /* for inode_lock, oddly enough.. */
 
 #include <asm/uaccess.h>
 
@@ -131,7 +131,7 @@ static struct quota_format_type *quota_formats;     /* List of registered formats */
 static struct quota_module_name module_names[] = INIT_QUOTA_MODULE_NAMES;
 
 /* SLAB cache for dquot structures */
-static kmem_cache_t *dquot_cachep;
+static struct kmem_cache *dquot_cachep;
 
 int register_quota_format(struct quota_format_type *fmt)
 {
@@ -250,7 +250,7 @@ static inline struct dquot *find_dquot(unsigned int hashent, struct super_block
 /* Add a dquot to the tail of the free list */
 static inline void put_dquot_last(struct dquot *dquot)
 {
-       list_add(&dquot->dq_free, free_dquots.prev);
+       list_add_tail(&dquot->dq_free, &free_dquots);
        dqstats.free_dquots++;
 }
 
@@ -266,7 +266,7 @@ static inline void put_inuse(struct dquot *dquot)
 {
        /* We add to the back of inuse list so we don't have to restart
         * when traversing this list and we block */
-       list_add(&dquot->dq_inuse, inuse_list.prev);
+       list_add_tail(&dquot->dq_inuse, &inuse_list);
        dqstats.allocated_dquots++;
 }
 
@@ -474,7 +474,7 @@ int vfs_quota_sync(struct super_block *sb, int type)
                spin_lock(&dq_list_lock);
                dirty = &dqopt->info[cnt].dqi_dirty_list;
                while (!list_empty(dirty)) {
-                       dquot = list_entry(dirty->next, struct dquot, dq_dirty);
+                       dquot = list_first_entry(dirty, struct dquot, dq_dirty);
                        /* Dirty and inactive can be only bad dquot... */
                        if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
                                clear_dquot_dirty(dquot);
@@ -538,6 +538,11 @@ static int shrink_dqcache_memory(int nr, gfp_t gfp_mask)
        return (dqstats.free_dquots / 100) * sysctl_vfs_cache_pressure;
 }
 
+static struct shrinker dqcache_shrinker = {
+       .shrink = shrink_dqcache_memory,
+       .seeks = DEFAULT_SEEKS,
+};
+
 /*
  * Put reference to dquot
  * NOTE: If you change this function please check whether dqput_blocks() works right...
@@ -590,8 +595,7 @@ we_slept:
        atomic_dec(&dquot->dq_count);
 #ifdef __DQUOT_PARANOIA
        /* sanity check */
-       if (!list_empty(&dquot->dq_free))
-               BUG();
+       BUG_ON(!list_empty(&dquot->dq_free));
 #endif
        put_dquot_last(dquot);
        spin_unlock(&dq_list_lock);
@@ -601,11 +605,10 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
 {
        struct dquot *dquot;
 
-       dquot = kmem_cache_alloc(dquot_cachep, SLAB_NOFS);
+       dquot = kmem_cache_zalloc(dquot_cachep, GFP_NOFS);
        if(!dquot)
                return NODQUOT;
 
-       memset((caddr_t)dquot, 0, sizeof(struct dquot));
        mutex_init(&dquot->dq_lock);
        INIT_LIST_HEAD(&dquot->dq_free);
        INIT_LIST_HEAD(&dquot->dq_inuse);
@@ -666,8 +669,7 @@ we_slept:
                return NODQUOT;
        }
 #ifdef __DQUOT_PARANOIA
-       if (!dquot->dq_sb)      /* Has somebody invalidated entry under us? */
-               BUG();
+       BUG_ON(!dquot->dq_sb);  /* Has somebody invalidated entry under us? */
 #endif
 
        return dquot;
@@ -690,23 +692,27 @@ static int dqinit_needed(struct inode *inode, int type)
 /* This routine is guarded by dqonoff_mutex mutex */
 static void add_dquot_ref(struct super_block *sb, int type)
 {
-       struct list_head *p;
+       struct inode *inode;
 
 restart:
-       file_list_lock();
-       list_for_each(p, &sb->s_files) {
-               struct file *filp = list_entry(p, struct file, f_u.fu_list);
-               struct inode *inode = filp->f_dentry->d_inode;
-               if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
-                       struct dentry *dentry = dget(filp->f_dentry);
-                       file_list_unlock();
-                       sb->dq_op->initialize(inode, type);
-                       dput(dentry);
-                       /* As we may have blocked we had better restart... */
-                       goto restart;
-               }
+       spin_lock(&inode_lock);
+       list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+               if (!atomic_read(&inode->i_writecount))
+                       continue;
+               if (!dqinit_needed(inode, type))
+                       continue;
+               if (inode->i_state & (I_FREEING|I_WILL_FREE))
+                       continue;
+
+               __iget(inode);
+               spin_unlock(&inode_lock);
+
+               sb->dq_op->initialize(inode, type);
+               iput(inode);
+               /* As we may have blocked we had better restart... */
+               goto restart;
        }
-       file_list_unlock();
+       spin_unlock(&inode_lock);
 }
 
 /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
@@ -719,7 +725,8 @@ static inline int dqput_blocks(struct dquot *dquot)
 
 /* Remove references to dquots from inode - add dquot to list for freeing if needed */
 /* We can't race with anybody because we hold dqptr_sem for writing... */
-int remove_inode_dquot_ref(struct inode *inode, int type, struct list_head *tofree_head)
+static int remove_inode_dquot_ref(struct inode *inode, int type,
+                                 struct list_head *tofree_head)
 {
        struct dquot *dquot = inode->i_dquot[type];
 
@@ -758,15 +765,30 @@ static void put_dquot_list(struct list_head *tofree_head)
        }
 }
 
+static void remove_dquot_ref(struct super_block *sb, int type,
+               struct list_head *tofree_head)
+{
+       struct inode *inode;
+
+       spin_lock(&inode_lock);
+       list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+               if (!IS_NOQUOTA(inode))
+                       remove_inode_dquot_ref(inode, type, tofree_head);
+       }
+       spin_unlock(&inode_lock);
+}
+
 /* Gather all references from inodes and drop them */
 static void drop_dquot_ref(struct super_block *sb, int type)
 {
        LIST_HEAD(tofree_head);
 
-       down_write(&sb_dqopt(sb)->dqptr_sem);
-       remove_dquot_ref(sb, type, &tofree_head);
-       up_write(&sb_dqopt(sb)->dqptr_sem);
-       put_dquot_list(&tofree_head);
+       if (sb->dq_op) {
+               down_write(&sb_dqopt(sb)->dqptr_sem);
+               remove_dquot_ref(sb, type, &tofree_head);
+               up_write(&sb_dqopt(sb)->dqptr_sem);
+               put_dquot_list(&tofree_head);
+       }
 }
 
 static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
@@ -830,18 +852,23 @@ static inline int need_print_warning(struct dquot *dquot)
 static void print_warning(struct dquot *dquot, const char warntype)
 {
        char *msg = NULL;
+       struct tty_struct *tty;
        int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS_B :
          ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES_B : 0);
 
        if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags)))
                return;
 
-       tty_write_message(current->signal->tty, dquot->dq_sb->s_id);
+       mutex_lock(&tty_mutex);
+       tty = get_current_tty();
+       if (!tty)
+               goto out_lock;
+       tty_write_message(tty, dquot->dq_sb->s_id);
        if (warntype == ISOFTWARN || warntype == BSOFTWARN)
-               tty_write_message(current->signal->tty, ": warning, ");
+               tty_write_message(tty, ": warning, ");
        else
-               tty_write_message(current->signal->tty, ": write failed, ");
-       tty_write_message(current->signal->tty, quotatypes[dquot->dq_type]);
+               tty_write_message(tty, ": write failed, ");
+       tty_write_message(tty, quotatypes[dquot->dq_type]);
        switch (warntype) {
                case IHARDWARN:
                        msg = " file limit reached.\r\n";
@@ -862,7 +889,9 @@ static void print_warning(struct dquot *dquot, const char warntype)
                        msg = " block quota exceeded.\r\n";
                        break;
        }
-       tty_write_message(current->signal->tty, msg);
+       tty_write_message(tty, msg);
+out_lock:
+       mutex_unlock(&tty_mutex);
 }
 
 static inline void flush_warnings(struct dquot **dquots, char *warntype)
@@ -1397,7 +1426,7 @@ int vfs_quota_off(struct super_block *sb, int type)
                        /* If quota was reenabled in the meantime, we have
                         * nothing to do */
                        if (!sb_has_quota_enabled(sb, cnt)) {
-                               mutex_lock(&toputinode[cnt]->i_mutex);
+                               mutex_lock_nested(&toputinode[cnt]->i_mutex, I_MUTEX_QUOTA);
                                toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
                                  S_NOATIME | S_NOQUOTA);
                                truncate_inode_pages(&toputinode[cnt]->i_data, 0);
@@ -1408,7 +1437,7 @@ int vfs_quota_off(struct super_block *sb, int type)
                        mutex_unlock(&dqopt->dqonoff_mutex);
                }
        if (sb->s_bdev)
-               invalidate_bdev(sb->s_bdev, 0);
+               invalidate_bdev(sb->s_bdev);
        return 0;
 }
 
@@ -1444,7 +1473,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
         * we see all the changes from userspace... */
        write_inode_now(inode, 1);
        /* And now flush the block cache so that kernel sees the changes */
-       invalidate_bdev(sb->s_bdev, 0);
+       invalidate_bdev(sb->s_bdev);
        mutex_lock(&inode->i_mutex);
        mutex_lock(&dqopt->dqonoff_mutex);
        if (sb_has_quota_enabled(sb, type)) {
@@ -1817,11 +1846,12 @@ static int __init dquot_init(void)
 
        printk(KERN_NOTICE "VFS: Disk quotas %s\n", __DQUOT_VERSION__);
 
-       register_sysctl_table(sys_table, 0);
+       register_sysctl_table(sys_table);
 
        dquot_cachep = kmem_cache_create("dquot", 
                        sizeof(struct dquot), sizeof(unsigned long) * 4,
-                       SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|SLAB_PANIC,
+                       (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
+                               SLAB_MEM_SPREAD|SLAB_PANIC),
                        NULL, NULL);
 
        order = 0;
@@ -1845,7 +1875,7 @@ static int __init dquot_init(void)
        printk("Dquot-cache hash table entries: %ld (order %ld, %ld bytes)\n",
                        nr_hash, order, (PAGE_SIZE << order));
 
-       set_shrinker(DEFAULT_SEEKS, shrink_dqcache_memory);
+       register_shrinker(&dqcache_shrinker);
 
        return 0;
 }