From eea87ac9fb47f8c7f6093e34c738f3e9c3b465ab Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:35:35 -0500 Subject: [PATCH] Import 2.4.0-test2pre6 --- drivers/isdn/avmb1/capifs.c | 6 ++--- fs/affs/inode.c | 2 +- fs/affs/namei.c | 2 +- fs/bfs/dir.c | 2 +- fs/bfs/inode.c | 2 -- fs/coda/cnode.c | 2 +- fs/coda/dir.c | 13 +++++----- fs/coda/inode.c | 8 +++---- fs/coda/pioctl.c | 2 +- fs/devpts/inode.c | 4 ++-- fs/devpts/root.c | 2 +- fs/ext2/ialloc.c | 18 -------------- fs/ext2/namei.c | 2 +- fs/hfs/inode.c | 2 +- fs/hpfs/inode.c | 2 +- fs/inode.c | 48 +++++++++++++++++++++++-------------- fs/minix/bitmap.c | 18 -------------- fs/minix/namei.c | 2 +- fs/ncpfs/inode.c | 9 +------ fs/nfs/flushd.c | 2 +- fs/nfs/inode.c | 26 ++++++-------------- fs/nfsd/nfsfh.c | 2 +- fs/nfsd/vfs.c | 8 +------ fs/ntfs/fs.c | 2 +- fs/proc/inode.c | 12 +--------- fs/qnx4/bitmap.c | 19 --------------- fs/ramfs/inode.c | 2 +- fs/smbfs/inode.c | 15 +----------- fs/sysv/ialloc.c | 22 +---------------- fs/sysv/inode.c | 3 ++- fs/sysv/namei.c | 2 +- fs/udf/ialloc.c | 21 ---------------- fs/udf/namei.c | 2 +- fs/ufs/ialloc.c | 11 --------- fs/ufs/namei.c | 2 +- fs/umsdos/dir.c | 2 +- fs/umsdos/inode.c | 4 ++-- fs/umsdos/namei.c | 8 +++---- include/linux/fs.h | 3 ++- include/linux/wrapper.h | 3 --- kernel/ksyms.c | 1 + mm/mmap.c | 2 ++ 42 files changed, 89 insertions(+), 231 deletions(-) diff --git a/drivers/isdn/avmb1/capifs.c b/drivers/isdn/avmb1/capifs.c index fcefa3d68502..ec4f9c559073 100644 --- a/drivers/isdn/avmb1/capifs.c +++ b/drivers/isdn/avmb1/capifs.c @@ -209,7 +209,7 @@ static struct dentry *capifs_root_lookup(struct inode * dir, struct dentry * den dentry->d_inode = np->inode; if ( dentry->d_inode ) - dentry->d_inode->i_count++; + atomic_inc(&dentry->d_inode->i_count); d_add(dentry, dentry->d_inode); @@ -228,9 +228,9 @@ static void capifs_put_super(struct super_block *sb) for ( i = 0 ; i < sbi->max_ncci ; i++ ) { if ( (inode = sbi->nccis[i].inode) ) { - if ( inode->i_count != 1 ) + if ( atomic_read(&inode->i_count) != 1 ) printk("capifs_put_super: badness: entry %d count %d\n", - i, inode->i_count); + i, atomic_read(&inode->i_count)); inode->i_nlink--; iput(inode); } diff --git a/fs/affs/inode.c b/fs/affs/inode.c index b768576031f8..1551e613c7da 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -270,7 +270,7 @@ affs_put_inode(struct inode *inode) inode->i_ino,inode->i_nlink); affs_free_prealloc(inode); - if (inode->i_count == 1) { + if (atomic_read(&inode->i_count) == 1) { unsigned long cache_page = (unsigned long) inode->u.affs_i.i_ec; if (cache_page) { pr_debug("AFFS: freeing ext cache\n"); diff --git a/fs/affs/namei.c b/fs/affs/namei.c index e81e321e3848..8ad7b07a2e7a 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -512,7 +512,7 @@ affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) dir->i_version = ++event; mark_inode_dirty(dir); mark_inode_dirty(oldinode); - oldinode->i_count++; + atomic_inc(&oldinode->i_count); d_instantiate(dentry,oldinode); } mark_inode_dirty(inode); diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index bd8be88c3f2a..76e55be5dea2 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -152,7 +152,7 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new inode->i_nlink++; inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(new, inode); return 0; } diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 6f3765399250..9551d701631d 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -139,8 +139,6 @@ static void bfs_delete_inode(struct inode * inode) dprintf("ino=%08lx\n", inode->i_ino); - if (!inode || !inode->i_dev || inode->i_count > 1 || inode->i_nlink || !s) - return; if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > inode->i_sb->su_lasti) { printf("invalid ino=%08lx\n", inode->i_ino); return; diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 47f853c14ef3..197855e1db25 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -139,7 +139,7 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) if ( coda_fideq(fid, &cnp->c_fid) ) { CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n", - (*inode)->i_ino, (*inode)->i_count, + (*inode)->i_ino, atomic_read(&(*inode)->i_count), coda_f2s(&cnp->c_fid)); EXIT; return 0; diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 83f7bbcc5e69..2031b4f6e039 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -117,7 +117,7 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry) error = coda_cnode_makectl(&res_inode, dir->i_sb); CDEBUG(D_SPECIAL, "Lookup on CTL object; dir ino %ld, count %d\n", - dir->i_ino, dir->i_count); + dir->i_ino, atomic_read(&dir->i_count)); goto exit; } @@ -358,7 +358,7 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode, if ( ! error ) { dir_cnp->c_flags |= C_VATTR; - ++inode->i_count; + atomic_inc(&inode->i_count); d_instantiate(de, inode); inode->i_nlink++; } else { @@ -597,9 +597,9 @@ int coda_open(struct inode *i, struct file *f) cnp->c_ocount++; CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n", - error, i->i_count, i->i_ino); + error, atomic_read(&i->i_count), i->i_ino); CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", - cnp->c_ovp->i_ino, cnp->c_ovp->i_count, + cnp->c_ovp->i_ino, atomic_read(&cnp->c_ovp->i_count), (cnp->c_ovp->i_op)); EXIT; return 0; @@ -622,8 +622,9 @@ int coda_release(struct inode *i, struct file *f) CHECK_CNODE(cnp); CDEBUG(D_FILE, "RELEASE coda (ino %ld, ct %d) cache (ino %ld, ct %d)\n", - i->i_ino, i->i_count, (cnp->c_ovp ? cnp->c_ovp->i_ino : 0), - (cnp->c_ovp ? cnp->c_ovp->i_count : -99)); + i->i_ino, atomic_read(&i->i_count), + (cnp->c_ovp ? cnp->c_ovp->i_ino : 0), + (cnp->c_ovp ? atomic_read(&cnp->c_ovp->i_count) : -99)); /* even when c_ocount=0 we cannot put c_ovp to diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 7f163acf95c1..09b3c2eadb28 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -148,9 +148,9 @@ static void coda_put_inode(struct inode *inode) { ENTRY; - CDEBUG(D_INODE,"ino: %ld, count %d\n", inode->i_ino, inode->i_count); + CDEBUG(D_INODE,"ino: %ld, count %d\n", inode->i_ino, atomic_read(&inode->i_count)); - if ( inode->i_count == 1 ) { + if ( atomic_read(&inode->i_count) == 1 ) { write_inode_now(inode); inode->i_nlink = 0; } @@ -163,7 +163,7 @@ static void coda_delete_inode(struct inode *inode) ENTRY; CDEBUG(D_SUPER, " inode->ino: %ld, count: %d\n", - inode->i_ino, inode->i_count); + inode->i_ino, atomic_read(&inode->i_count)); cii = ITOC(inode); if ( inode->i_ino == CTL_INO || cii->c_magic != CODA_CNODE_MAGIC ) { @@ -179,7 +179,7 @@ static void coda_delete_inode(struct inode *inode) open_inode = cii->c_ovp; if ( open_inode ) { CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n", - open_inode->i_ino, open_inode->i_count); + open_inode->i_ino, atomic_read(&open_inode->i_count)); cii->c_ovp = NULL; inode->i_mapping = &inode->i_data; iput(open_inode); diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index d29c18ccd882..d97204125698 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -120,7 +120,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp, CDEBUG(D_PIOCTL, "ioctl on inode %ld\n", target_inode->i_ino); CDEBUG(D_DOWNCALL, "dput on ino: %ld, icount %d, dcount %d\n", target_inode->i_ino, - target_inode->i_count, nd.dentry->d_count); + atomic_read(&target_inode->i_count), nd.dentry->d_count); path_release(&nd); return error; } diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 67cc1c7b1c13..6a26bf981cac 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -37,9 +37,9 @@ static void devpts_put_super(struct super_block *sb) for ( i = 0 ; i < sbi->max_ptys ; i++ ) { if ( (inode = sbi->inodes[i]) ) { - if ( inode->i_count != 1 ) + if ( atomic_read(&inode->i_count) != 1 ) printk("devpts_put_super: badness: entry %d count %d\n", - i, inode->i_count); + i, atomic_read(&inode->i_count)); inode->i_nlink--; iput(inode); } diff --git a/fs/devpts/root.c b/fs/devpts/root.c index 39ea6afe38f2..06f6b3baa2ee 100644 --- a/fs/devpts/root.c +++ b/fs/devpts/root.c @@ -129,7 +129,7 @@ static struct dentry *devpts_root_lookup(struct inode * dir, struct dentry * den dentry->d_inode = sbi->inodes[entry]; if ( dentry->d_inode ) - dentry->d_inode->i_count++; + atomic_inc(&dentry->d_inode->i_count); d_add(dentry, dentry->d_inode); diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 277562ec717f..3c95ccd70c4f 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -186,24 +186,6 @@ void ext2_free_inode (struct inode * inode) struct ext2_group_desc * gdp; struct ext2_super_block * es; - if (!inode->i_dev) { - printk ("ext2_free_inode: inode has no device\n"); - return; - } - if (inode->i_count > 1) { - printk ("ext2_free_inode: inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) { - printk ("ext2_free_inode: inode has nlink=%d\n", - inode->i_nlink); - return; - } - if (!sb) { - printk("ext2_free_inode: inode on nonexistent device\n"); - return; - } - ino = inode->i_ino; ext2_debug ("freeing inode %lu\n", ino); diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 3e471f42bfb7..46e2739353e9 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -685,7 +685,7 @@ static int ext2_link (struct dentry * old_dentry, inode->i_nlink++; inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); return 0; } diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 4d506b787a08..371538b9d26b 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -80,7 +80,7 @@ void hfs_put_inode(struct inode * inode) struct hfs_cat_entry *entry = HFS_I(inode)->entry; hfs_cat_put(entry); - if (inode->i_count == 1) { + if (atomic_read(&inode->i_count) == 1) { struct hfs_hdr_layout *tmp = HFS_I(inode)->layout; if (tmp) { diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 69303cb9e91a..7938970c84c7 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -233,7 +233,7 @@ void hpfs_write_inode(struct inode *i) struct inode *parent; if (!i->i_nlink) return; if (i->i_ino == i->i_sb->s_hpfs_root) return; - if (i->i_hpfs_rddir_off && !i->i_count) { + if (i->i_hpfs_rddir_off && !atomic_read(&i->i_count)) { if (*i->i_hpfs_rddir_off) printk("HPFS: write_inode: some position still there\n"); kfree(i->i_hpfs_rddir_off); i->i_hpfs_rddir_off = NULL; diff --git a/fs/inode.c b/fs/inode.c index 64373d6ad05d..e46359b032af 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -170,15 +170,16 @@ static inline void write_inode(struct inode *inode) static inline void __iget(struct inode * inode) { - if (!inode->i_count++) - { - if (!(inode->i_state & I_DIRTY)) - { - list_del(&inode->i_list); - list_add(&inode->i_list, &inode_in_use); - } - inodes_stat.nr_unused--; + if (atomic_read(&inode->i_count)) { + atomic_inc(&inode->i_count); + return; + } + atomic_inc(&inode->i_count); + if (!(inode->i_state & I_DIRTY)) { + list_del(&inode->i_list); + list_add(&inode->i_list, &inode_in_use); } + inodes_stat.nr_unused--; } static inline void sync_one(struct inode *inode) @@ -191,8 +192,9 @@ static inline void sync_one(struct inode *inode) spin_lock(&inode_lock); } else { list_del(&inode->i_list); - list_add(&inode->i_list, - inode->i_count ? &inode_in_use : &inode_unused); + list_add(&inode->i_list, atomic_read(&inode->i_count) + ? &inode_in_use + : &inode_unused); /* Set I_LOCK, reset I_DIRTY */ inode->i_state ^= I_DIRTY | I_LOCK; spin_unlock(&inode_lock); @@ -347,7 +349,7 @@ static int invalidate_list(struct list_head *head, struct super_block * sb, stru inode = list_entry(tmp, struct inode, i_list); if (inode->i_sb != sb) continue; - if (!inode->i_count) { + if (!atomic_read(&inode->i_count)) { list_del(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash); list_del(&inode->i_list); @@ -433,7 +435,7 @@ void prune_icache(int goal) BUG(); if (!CAN_UNUSE(inode)) continue; - if (inode->i_count) + if (atomic_read(&inode->i_count)) BUG(); list_del(tmp); list_del(&inode->i_hash); @@ -551,7 +553,7 @@ struct inode * get_empty_inode(void) inode->i_dev = 0; inode->i_ino = ++last_ino; inode->i_flags = 0; - inode->i_count = 1; + atomic_set(&inode->i_count, 1); inode->i_state = 0; spin_unlock(&inode_lock); clean_inode(inode); @@ -583,7 +585,7 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s inode->i_dev = sb->s_dev; inode->i_ino = ino; inode->i_flags = 0; - inode->i_count = 1; + atomic_set(&inode->i_count, 1); inode->i_state = I_LOCK; spin_unlock(&inode_lock); @@ -758,7 +760,7 @@ void iput(struct inode *inode) op->put_inode(inode); spin_lock(&inode_lock); - if (!--inode->i_count) { + if (atomic_dec_and_test(&inode->i_count)) { if (!inode->i_nlink) { list_del(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash); @@ -807,15 +809,15 @@ kdevname(inode->i_dev), inode->i_ino); if (!list_empty(&inode->i_dentry)) printk(KERN_ERR "iput: device %s inode %ld still has aliases!\n", kdevname(inode->i_dev), inode->i_ino); -if (inode->i_count) +if (atomic_read(&inode->i_count)) printk(KERN_ERR "iput: device %s inode %ld count changed, count=%d\n", -kdevname(inode->i_dev), inode->i_ino, inode->i_count); +kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_count)); if (atomic_read(&inode->i_sem.count) != 1) printk(KERN_ERR "iput: Aieee, semaphore in use inode %s/%ld, count=%d\n", kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count)); #endif } - if (inode->i_count > (1<<31)) { + if ((unsigned)atomic_read(&inode->i_count) > (1U<<31)) { printk(KERN_ERR "iput: inode %s/%ld count wrapped\n", kdevname(inode->i_dev), inode->i_ino); } @@ -825,6 +827,16 @@ kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count)); } } +void force_delete(struct inode *inode) +{ + /* + * Kill off unused inodes ... iput() will unhash and + * delete the inode if we set i_nlink to zero. + */ + if (atomic_read(&inode->i_count) == 1) + inode->i_nlink = 0; +} + /** * bmap - find a block number in a file * @inode: inode of file diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index 0a504e59db2f..075574876c2e 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -205,24 +205,6 @@ void minix_free_inode(struct inode * inode) struct buffer_head * bh; unsigned long ino; - if (!inode) - return; - if (!inode->i_dev) { - printk("free_inode: inode has no device\n"); - return; - } - if (inode->i_count > 1) { - printk("free_inode: inode has count=%d\n",inode->i_count); - return; - } - if (inode->i_nlink) { - printk("free_inode: inode has nlink=%d\n",inode->i_nlink); - return; - } - if (!inode->i_sb) { - printk("free_inode: inode on nonexistent device\n"); - return; - } if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.minix_sb.s_ninodes) { printk("free_inode: inode 0 or nonexistent inode\n"); return; diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 653c3415ad70..0de210186445 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -520,7 +520,7 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir, inode->i_nlink++; inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); return 0; } diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index f6ff5e420ea9..e885aed47bf3 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -31,14 +31,13 @@ #include "ncplib_kernel.h" -static void ncp_put_inode(struct inode *); static void ncp_delete_inode(struct inode *); static void ncp_put_super(struct super_block *); static int ncp_statfs(struct super_block *, struct statfs *); static struct super_operations ncp_sops = { - put_inode: ncp_put_inode, + put_inode: force_delete, delete_inode: ncp_delete_inode, put_super: ncp_put_super, statfs: ncp_statfs, @@ -239,12 +238,6 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info) return inode; } -static void ncp_put_inode(struct inode *inode) -{ - if (inode->i_count == 1) - inode->i_nlink = 0; -} - static void ncp_delete_inode(struct inode *inode) { diff --git a/fs/nfs/flushd.c b/fs/nfs/flushd.c index 02024c90e4a9..700504dedac6 100644 --- a/fs/nfs/flushd.c +++ b/fs/nfs/flushd.c @@ -175,7 +175,7 @@ static void inode_append_flushd(struct inode *inode) * it from disappearing when on the flush list */ NFS_FLAGS(inode) |= NFS_INO_FLUSH; - inode->i_count++; + atomic_inc(&inode->i_count); out: spin_unlock(&nfs_flushd_lock); } diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index cf0ea6ef34cb..31b9705d76a3 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -44,7 +44,6 @@ void nfs_zap_caches(struct inode *); static void nfs_invalidate_inode(struct inode *); static void nfs_read_inode(struct inode *); -static void nfs_put_inode(struct inode *); static void nfs_delete_inode(struct inode *); static void nfs_put_super(struct super_block *); static void nfs_umount_begin(struct super_block *); @@ -52,7 +51,7 @@ static int nfs_statfs(struct super_block *, struct statfs *); static struct super_operations nfs_sops = { read_inode: nfs_read_inode, - put_inode: nfs_put_inode, + put_inode: force_delete, delete_inode: nfs_delete_inode, put_super: nfs_put_super, statfs: nfs_statfs, @@ -114,17 +113,6 @@ nfs_read_inode(struct inode * inode) NFS_ATTRTIMEO_UPDATE(inode) = jiffies; } -static void -nfs_put_inode(struct inode * inode) -{ - dprintk("NFS: put_inode(%x/%ld)\n", inode->i_dev, inode->i_ino); - /* - * We want to get rid of unused inodes ... - */ - if (inode->i_count == 1) - inode->i_nlink = 0; -} - static void nfs_delete_inode(struct inode * inode) { @@ -690,7 +678,7 @@ nfs_inode_is_stale(struct inode *inode, struct nfs_fattr *fattr) * don't invalidate their inodes even if all dentries are * unhashed. */ - if (unhashed && inode->i_count == unhashed + 1 + if (unhashed && atomic_read(&inode->i_count) == unhashed + 1 && !S_ISSOCK(inode->i_mode) && !S_ISFIFO(inode->i_mode)) is_stale = 1; @@ -784,7 +772,7 @@ __nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr) break; dprintk("__nfs_fhget: inode %ld still busy, i_count=%d\n", - inode->i_ino, inode->i_count); + inode->i_ino, atomic_read(&inode->i_count)); nfs_zap_caches(inode); remove_inode_hash(inode); iput(inode); @@ -795,7 +783,7 @@ __nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr) nfs_fill_inode(inode, fattr); dprintk("NFS: __nfs_fhget(%x/%ld ct=%d)\n", - inode->i_dev, inode->i_ino, inode->i_count); + inode->i_dev, inode->i_ino, atomic_read(&inode->i_count)); out: return inode; @@ -870,7 +858,7 @@ nfs_wait_on_inode(struct inode *inode, int flag) int error; if (!(NFS_FLAGS(inode) & flag)) return 0; - inode->i_count++; + atomic_inc(&inode->i_count); error = nfs_wait_event(clnt, inode->i_wait, !(NFS_FLAGS(inode) & flag)); iput(inode); return error; @@ -1019,8 +1007,8 @@ nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) goto out; dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d info=0x%x)\n", - inode->i_dev, inode->i_ino, inode->i_count, - fattr->valid); + inode->i_dev, inode->i_ino, + atomic_read(&inode->i_count), fattr->valid); if (NFS_FSID(inode) != fattr->fsid || diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index f8816159375c..85a98c874070 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -142,7 +142,7 @@ static struct dentry *nfsd_iget(struct super_block *sb, unsigned long ino, __u32 /* we didn't find the right inode.. */ dprintk("fh_verify: Inode %lu, Bad count: %d %d or version %u %u\n", inode->i_ino, - inode->i_nlink, inode->i_count, + inode->i_nlink, atomic_read(&inode->i_count), inode->i_generation, generation); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1110e09382ce..3bdeb2c0705d 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -492,16 +492,10 @@ nfsd_close(struct file *filp) struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; - if (!inode->i_count) - printk(KERN_WARNING "nfsd: inode count == 0!\n"); - if (!dentry->d_count) - printk(KERN_WARNING "nfsd: wheee, %s/%s d_count == 0!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); if (filp->f_op && filp->f_op->release) filp->f_op->release(inode, filp); - if (filp->f_mode & FMODE_WRITE) { + if (filp->f_mode & FMODE_WRITE) put_write_access(inode); - } } /* diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c index 3d58541ad471..e0649ec7bded 100644 --- a/fs/ntfs/fs.c +++ b/fs/ntfs/fs.c @@ -218,7 +218,7 @@ static int ntfs_readdir(struct file* filp, void *dirent, filldir_t filldir) (unsigned)dir->i_ino,(unsigned int)dir->i_mode); ntfs_debug(DEBUG_OTHER, "readdir: Looking for file %x dircount %d\n", - (unsigned)filp->f_pos,dir->i_count); + (unsigned)filp->f_pos,atomic_read(&dir->i_count)); cb.pl=filp->f_pos & 0xFFFF; cb.ph=filp->f_pos >> 16; /* end of directory */ diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 67273b3ba528..7b571398af8c 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -52,16 +52,6 @@ void de_put(struct proc_dir_entry *de) } } -static void proc_put_inode(struct inode *inode) -{ - /* - * Kill off unused inodes ... VFS will unhash and - * delete the inode if we set i_nlink to zero. - */ - if (inode->i_count == 1) - inode->i_nlink = 0; -} - /* * Decrement the use count of the proc_dir_entry. */ @@ -102,7 +92,7 @@ static int proc_statfs(struct super_block *sb, struct statfs *buf) static struct super_operations proc_sops = { read_inode: proc_read_inode, - put_inode: proc_put_inode, + put_inode: force_delete, delete_inode: proc_delete_inode, statfs: proc_statfs, }; diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c index b185960dbe1c..03e89e64da67 100644 --- a/fs/qnx4/bitmap.c +++ b/fs/qnx4/bitmap.c @@ -153,25 +153,6 @@ static void qnx4_clear_inode(struct inode *inode) void qnx4_free_inode(struct inode *inode) { - if (!inode) { - return; - } - if (!inode->i_dev) { - printk("free_inode: inode has no device\n"); - return; - } - if (inode->i_count > 1) { - printk("free_inode: inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) { - printk("free_inode: inode has nlink=%d\n", inode->i_nlink); - return; - } - if (!inode->i_sb) { - printk("free_inode: inode on nonexistent device\n"); - return; - } if (inode->i_ino < 1) { printk("free_inode: inode 0 or nonexistent inode\n"); return; diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 4416e8be6885..f87d30e0bb16 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -181,7 +181,7 @@ static int ramfs_link(struct dentry *old_dentry, struct inode * dir, struct dent return -EPERM; inode->i_nlink++; - inode->i_count++; /* New dentry reference */ + atomic_inc(&inode->i_count); /* New dentry reference */ dget(dentry); /* Extra pinning count for the created dentry */ d_instantiate(dentry, inode); return 0; diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 9ed649a3bd97..769aa7e5695d 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -29,7 +29,6 @@ #define SMBFS_PARANOIA 1 /* #define SMBFS_DEBUG_VERBOSE 1 */ -static void smb_put_inode(struct inode *); static void smb_delete_inode(struct inode *); static void smb_put_super(struct super_block *); static int smb_statfs(struct super_block *, struct statfs *); @@ -37,7 +36,7 @@ static void smb_set_inode_attr(struct inode *, struct smb_fattr *); static struct super_operations smb_sops = { - put_inode: smb_put_inode, + put_inode: force_delete, delete_inode: smb_delete_inode, put_super: smb_put_super, statfs: smb_statfs, @@ -271,18 +270,6 @@ out: return error; } -/* - * This routine is called for every iput(). We clear i_nlink - * on the last use to force a call to delete_inode. - */ -static void -smb_put_inode(struct inode *ino) -{ - pr_debug("smb_put_inode: count = %d\n", ino->i_count); - if (ino->i_count == 1) - ino->i_nlink = 0; -} - /* * This routine is called when i_nlink == 0 and i_count goes to 0. * All blocking cleanup operations need to go here to avoid races. diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c index 0bdceb2f5634..d7cc12187f66 100644 --- a/fs/sysv/ialloc.c +++ b/fs/sysv/ialloc.c @@ -56,24 +56,7 @@ void sysv_free_inode(struct inode * inode) struct buffer_head * bh; struct sysv_inode * raw_inode; - if (!inode) - return; - if (!inode->i_dev) { - printk("sysv_free_inode: inode has no device\n"); - return; - } - if (inode->i_count != 1) { - printk("sysv_free_inode: inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) { - printk("sysv_free_inode: inode has nlink=%d\n", inode->i_nlink); - return; - } - if (!(sb = inode->i_sb)) { - printk("sysv_free_inode: inode on nonexistent device\n"); - return; - } + sb = inode->i_sb; ino = inode->i_ino; if (ino <= SYSV_ROOT_INO || ino > sb->sv_ninodes) { printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n"); @@ -112,7 +95,6 @@ struct inode * sysv_new_inode(const struct inode * dir) return NULL; sb = dir->i_sb; inode->i_sb = sb; - inode->i_flags = 0; lock_super(sb); /* protect against task switches */ if ((*sb->sv_sb_fic_count == 0) || (*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)-1) == 0) /* Applies only to SystemV2 FS */ @@ -149,8 +131,6 @@ struct inode * sysv_new_inode(const struct inode * dir) mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */ if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1); sb->s_dirt = 1; /* and needs time stamp */ - inode->i_count = 1; - inode->i_nlink = 1; inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index ad459a1c7549..45581895975f 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -43,7 +43,8 @@ void sysv_print_inode(struct inode * inode) printk("ino %lu mode 0%6.6o lk %d uid %d gid %d" " sz %lu blks %lu cnt %u\n", inode->i_ino, inode->i_mode, inode->i_nlink, inode->i_uid, - inode->i_gid, inode->i_size, inode->i_blocks, inode->i_count); + inode->i_gid, inode->i_size, inode->i_blocks, + atomic_read(&inode->i_count)); printk(" db <0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx" " 0x%lx 0x%lx>\n", inode->u.sysv_i.i_data[0], inode->u.sysv_i.i_data[1], diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index ef1e0438130e..517371319fc6 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -507,7 +507,7 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir, oldinode->i_nlink++; oldinode->i_ctime = CURRENT_TIME; mark_inode_dirty(oldinode); - oldinode->i_count++; + atomic_inc(&oldinode->i_count); d_instantiate(dentry, oldinode); return 0; } diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 914527765e72..11e5711f5e0b 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -38,27 +38,6 @@ void udf_free_inode(struct inode * inode) int is_directory; unsigned long ino; - if (!inode->i_dev) - { - udf_debug("inode has no device\n"); - return; - } - if (inode->i_count > 1) - { - udf_debug("inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) - { - udf_debug("inode has nlink=%d\n", inode->i_nlink); - return; - } - if (!sb) - { - udf_debug("inode on nonexistent device\n"); - return; - } - ino = inode->i_ino; /* diff --git a/fs/udf/namei.c b/fs/udf/namei.c index d56ff9a0ccf1..16821704e83a 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -1108,7 +1108,7 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir, inode->i_ctime = CURRENT_TIME; UDF_I_UCTIME(inode) = CURRENT_UTIME; mark_inode_dirty(inode); - inode->i_count ++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); return 0; } diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 93b520a0bba4..3b7bf8410f77 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -70,22 +70,11 @@ void ufs_free_inode (struct inode * inode) UFSD(("ENTER, ino %lu\n", inode->i_ino)) - if (!inode) - return; sb = inode->i_sb; swab = sb->u.ufs_sb.s_swab; uspi = sb->u.ufs_sb.s_uspi; usb1 = ubh_get_usb_first(USPI_UBH); - if (inode->i_count > 1) { - ufs_warning(sb, "ufs_free_inode", "inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) { - ufs_warning(sb, "ufs_free_inode", "inode has nlink=%d\n", inode->i_nlink); - return; - } - ino = inode->i_ino; lock_super (sb); diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 2bd998cf30d8..7966998d98a8 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -834,7 +834,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir, inode->i_nlink++; inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); return 0; } diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index 9d37f24bc4f4..2d8e60895ea8 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -537,7 +537,7 @@ printk("umsdos_lookup_x: skipping DOS/linux\n"); * We've found it OK. Now hash the dentry with the inode. */ out_add: - inode->i_count++; + atomic_inc(&inode->i_count); d_add (dentry, inode); dentry->d_op = &umsdos_dentry_operations; ret = 0; diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c index af69877d9c5f..14b23467d134 100644 --- a/fs/umsdos/inode.c +++ b/fs/umsdos/inode.c @@ -51,14 +51,14 @@ void UMSDOS_put_inode (struct inode *inode) "put inode %p (%lu) pos %lu count=%d\n" ,inode, inode->i_ino ,inode->u.umsdos_i.pos - ,inode->i_count)); + ,atomic_read(&inode->i_count))); if (inode == pseudo_root) { printk (KERN_ERR "Umsdos: Oops releasing pseudo_root." " Notify jacques@solucorp.qc.ca\n"); } - if (inode->i_count == 1) + if (atomic_read(&inode->i_count) == 1) inode->u.umsdos_i.i_patched = 0; } diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c index d3fe5eb6188d..c4cb0cb9f8ef 100644 --- a/fs/umsdos/namei.c +++ b/fs/umsdos/namei.c @@ -279,14 +279,14 @@ static int umsdos_create_any (struct inode *dir, struct dentry *dentry, goto out_remove_dput; inode = fake->d_inode; - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate (dentry, inode); dput(fake); - if (inode->i_count > 1) { + if (atomic_read(&inode->i_count) > 1) { printk(KERN_WARNING "umsdos_create_any: %s/%s, ino=%ld, icount=%d??\n", dentry->d_parent->d_name.name, dentry->d_name.name, - inode->i_ino, inode->i_count); + inode->i_ino, atomic_read(&inode->i_count)); } umsdos_lookup_patch_new(dentry, &info); @@ -809,7 +809,7 @@ dentry->d_parent->d_name.name, info.fake.fname); inode = temp->d_inode; down(&inode->i_sem); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); /* N.B. this should have an option to create the EMD ... */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 2cf4508c2715..285f21f16234 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -376,7 +376,7 @@ struct inode { struct list_head i_dentry; unsigned long i_ino; - unsigned int i_count; + atomic_t i_count; kdev_t i_dev; umode_t i_mode; nlink_t i_nlink; @@ -1071,6 +1071,7 @@ extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) extern void iput(struct inode *); +extern void force_delete(struct inode *); extern struct inode * igrab(struct inode *); extern ino_t iunique(struct super_block *, ino_t); diff --git a/include/linux/wrapper.h b/include/linux/wrapper.h index bcfaff073a67..36d80ef1eba4 100644 --- a/include/linux/wrapper.h +++ b/include/linux/wrapper.h @@ -19,9 +19,6 @@ #define module_unregister_blkdev unregister_blkdev #define inode_get_rdev(i) i->i_rdev -#define inode_get_count(i) i->i_count -#define inode_inc_count(i) i->i_count++ -#define inode_dec_count(i) i->i_count-- #define file_get_flags(f) f->f_flags diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 4a5f167635c9..0274d48fc9c6 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -136,6 +136,7 @@ EXPORT_SYMBOL(igrab); EXPORT_SYMBOL(iunique); EXPORT_SYMBOL(iget4); EXPORT_SYMBOL(iput); +EXPORT_SYMBOL(force_delete); EXPORT_SYMBOL(follow_up); EXPORT_SYMBOL(follow_down); EXPORT_SYMBOL(path_init); diff --git a/mm/mmap.c b/mm/mmap.c index 8a81bfb20ba7..f5bb2599c8d4 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -320,6 +320,8 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned lon goto unmap_and_free_vma; } else if (flags & MAP_SHARED) { error = map_zero_setup(vma); + if (error) + goto free_vma; } /* -- 2.39.5