From 1025774ce411f2bd4b059ad7b53f0003569b74fa Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Jun 2010 11:30:02 +0200 Subject: remove inode_setattr Replace inode_setattr with opencoded variants of it in all callers. This moves the remaining call to vmtruncate into the filesystem methods where it can be replaced with the proper truncate sequence. In a few cases it was obvious that we would never end up calling vmtruncate so it was left out in the opencoded variant: spufs: explicitly checks for ATTR_SIZE earlier btrfs,hugetlbfs,logfs,dlmfs: explicitly clears ATTR_SIZE earlier ufs: contains an opencoded simple_seattr + truncate that sets the filesize just above In addition to that ncpfs called inode_setattr with handcrafted iattrs, which allowed to trim down the opencoded variant. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- drivers/staging/pohmelfs/inode.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index 643b413d9f0f..e818f53ccfd7 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c @@ -968,12 +968,18 @@ int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr) goto err_out_exit; } - err = inode_setattr(inode, attr); - if (err) { - dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); - goto err_out_exit; + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + err = vmtruncate(inode, attr->ia_size); + if (err) { + dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); + goto err_out_exit; + } } + setattr_copy(inode, attr); + mark_inode_dirty(inode); + dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n", __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode, inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size); -- cgit v1.2.3-70-g09d2 From 45321ac54316eaeeebde0b5f728a1791e500974c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Jun 2010 13:43:19 -0400 Subject: Make ->drop_inode() just return whether inode needs to be dropped ... and let iput_final() do the actual eviction or retention Signed-off-by: Al Viro --- drivers/staging/pohmelfs/inode.c | 4 +- fs/btrfs/ctree.h | 2 +- fs/btrfs/inode.c | 11 ++-- fs/cifs/cifsfs.c | 9 ++-- fs/gfs2/super.c | 4 +- fs/inode.c | 113 ++++++++++++--------------------------- fs/logfs/inode.c | 4 +- fs/ocfs2/inode.c | 8 +-- fs/ocfs2/inode.h | 2 +- include/linux/fs.h | 6 +-- 10 files changed, 60 insertions(+), 103 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index e818f53ccfd7..100e3a3c1b10 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c @@ -1223,7 +1223,7 @@ void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info) } } -static void pohmelfs_drop_inode(struct inode *inode) +static int pohmelfs_drop_inode(struct inode *inode) { struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); struct pohmelfs_inode *pi = POHMELFS_I(inode); @@ -1232,7 +1232,7 @@ static void pohmelfs_drop_inode(struct inode *inode) list_del_init(&pi->inode_entry); spin_unlock(&psb->ino_lock); - generic_drop_inode(inode); + return generic_drop_inode(inode); } static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb, diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 394d5422ab6a..eaf286abad17 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2395,7 +2395,7 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); void btrfs_dirty_inode(struct inode *inode); struct inode *btrfs_alloc_inode(struct super_block *sb); void btrfs_destroy_inode(struct inode *inode); -void btrfs_drop_inode(struct inode *inode); +int btrfs_drop_inode(struct inode *inode); int btrfs_init_cachep(void); void btrfs_destroy_cachep(void); long btrfs_ioctl_trans_end(struct file *file); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index ce02199ec4e5..2c54f04a0bf5 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3943,7 +3943,7 @@ again: if (atomic_read(&inode->i_count) > 1) d_prune_aliases(inode); /* - * btrfs_drop_inode will remove it from + * btrfs_drop_inode will have it removed from * the inode cache when its usage count * hits zero. */ @@ -6337,13 +6337,14 @@ free: kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); } -void btrfs_drop_inode(struct inode *inode) +int btrfs_drop_inode(struct inode *inode) { struct btrfs_root *root = BTRFS_I(inode)->root; - if (inode->i_nlink > 0 && btrfs_root_refs(&root->root_item) == 0) - generic_delete_inode(inode); + + if (btrfs_root_refs(&root->root_item) == 0) + return 1; else - generic_drop_inode(inode); + return generic_drop_inode(inode); } static void init_once(void *foo) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8a2cf129e535..20914f5627dd 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -480,14 +480,13 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data) return 0; } -void cifs_drop_inode(struct inode *inode) +static int cifs_drop_inode(struct inode *inode) { struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) - return generic_drop_inode(inode); - - return generic_delete_inode(inode); + /* no serverino => unconditional eviction */ + return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) || + generic_drop_inode(inode); } static const struct super_operations cifs_super_ops = { diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 555f5a417c67..fa865ab37f12 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1191,7 +1191,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) * node for later deallocation. */ -static void gfs2_drop_inode(struct inode *inode) +static int gfs2_drop_inode(struct inode *inode) { struct gfs2_inode *ip = GFS2_I(inode); @@ -1200,7 +1200,7 @@ static void gfs2_drop_inode(struct inode *inode) if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) clear_nlink(inode); } - generic_drop_inode(inode); + return generic_drop_inode(inode); } static int is_ancestor(const struct dentry *d1, const struct dentry *d2) diff --git a/fs/inode.c b/fs/inode.c index 82ca3562a688..0e077619cbf6 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1183,58 +1183,51 @@ void remove_inode_hash(struct inode *inode) } EXPORT_SYMBOL(remove_inode_hash); +int generic_delete_inode(struct inode *inode) +{ + return 1; +} +EXPORT_SYMBOL(generic_delete_inode); + /* - * Tell the filesystem that this inode is no longer of any interest and should - * be completely destroyed. - * - * We leave the inode in the inode hash table until *after* the filesystem's - * ->delete_inode completes. This ensures that an iget (such as nfsd might - * instigate) will always find up-to-date information either in the hash or on - * disk. - * - * I_FREEING is set so that no-one will take a new reference to the inode while - * it is being deleted. + * Normal UNIX filesystem behaviour: delete the + * inode when the usage count drops to zero, and + * i_nlink is zero. */ -void generic_delete_inode(struct inode *inode) +int generic_drop_inode(struct inode *inode) { - list_del_init(&inode->i_list); - list_del_init(&inode->i_sb_list); - WARN_ON(inode->i_state & I_NEW); - inode->i_state |= I_FREEING; - inodes_stat.nr_inodes--; - spin_unlock(&inode_lock); - - evict(inode); - - spin_lock(&inode_lock); - hlist_del_init(&inode->i_hash); - spin_unlock(&inode_lock); - wake_up_inode(inode); - BUG_ON(inode->i_state != (I_FREEING | I_CLEAR)); - destroy_inode(inode); + return !inode->i_nlink || hlist_unhashed(&inode->i_hash); } -EXPORT_SYMBOL(generic_delete_inode); +EXPORT_SYMBOL_GPL(generic_drop_inode); -/** - * generic_detach_inode - remove inode from inode lists - * @inode: inode to remove - * - * Remove inode from inode lists, write it if it's dirty. This is just an - * internal VFS helper exported for hugetlbfs. Do not use! +/* + * Called when we're dropping the last reference + * to an inode. * - * Returns 1 if inode should be completely destroyed. + * Call the FS "drop_inode()" function, defaulting to + * the legacy UNIX filesystem behaviour. If it tells + * us to evict inode, do so. Otherwise, retain inode + * in cache if fs is alive, sync and evict if fs is + * shutting down. */ -static int generic_detach_inode(struct inode *inode) +static void iput_final(struct inode *inode) { struct super_block *sb = inode->i_sb; + const struct super_operations *op = inode->i_sb->s_op; + int drop; + + if (op && op->drop_inode) + drop = op->drop_inode(inode); + else + drop = generic_drop_inode(inode); - if (!hlist_unhashed(&inode->i_hash)) { + if (!drop) { if (!(inode->i_state & (I_DIRTY|I_SYNC))) list_move(&inode->i_list, &inode_unused); inodes_stat.nr_unused++; if (sb->s_flags & MS_ACTIVE) { spin_unlock(&inode_lock); - return 0; + return; } WARN_ON(inode->i_state & I_NEW); inode->i_state |= I_WILL_FREE; @@ -1252,53 +1245,15 @@ static int generic_detach_inode(struct inode *inode) inode->i_state |= I_FREEING; inodes_stat.nr_inodes--; spin_unlock(&inode_lock); - return 1; -} - -static void generic_forget_inode(struct inode *inode) -{ - if (!generic_detach_inode(inode)) - return; evict(inode); + spin_lock(&inode_lock); + hlist_del_init(&inode->i_hash); + spin_unlock(&inode_lock); wake_up_inode(inode); + BUG_ON(inode->i_state != (I_FREEING | I_CLEAR)); destroy_inode(inode); } -/* - * Normal UNIX filesystem behaviour: delete the - * inode when the usage count drops to zero, and - * i_nlink is zero. - */ -void generic_drop_inode(struct inode *inode) -{ - if (!inode->i_nlink) - generic_delete_inode(inode); - else - generic_forget_inode(inode); -} -EXPORT_SYMBOL_GPL(generic_drop_inode); - -/* - * Called when we're dropping the last reference - * to an inode. - * - * Call the FS "drop()" function, defaulting to - * the legacy UNIX filesystem behaviour.. - * - * NOTE! NOTE! NOTE! We're called with the inode lock - * held, and the drop function is supposed to release - * the lock! - */ -static inline void iput_final(struct inode *inode) -{ - const struct super_operations *op = inode->i_sb->s_op; - void (*drop)(struct inode *) = generic_drop_inode; - - if (op && op->drop_inode) - drop = op->drop_inode; - drop(inode); -} - /** * iput - put an inode * @inode: inode to put diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 78be674d95c8..d8c71ece098f 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c @@ -287,7 +287,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc) } /* called with inode_lock held */ -static void logfs_drop_inode(struct inode *inode) +static int logfs_drop_inode(struct inode *inode) { struct logfs_super *super = logfs_super(inode->i_sb); struct logfs_inode *li = logfs_inode(inode); @@ -295,7 +295,7 @@ static void logfs_drop_inode(struct inode *inode) spin_lock(&logfs_inode_lock); list_move(&li->li_freeing_list, &super->s_freeing_list); spin_unlock(&logfs_inode_lock); - generic_drop_inode(inode); + return generic_drop_inode(inode); } static void logfs_set_ino_generation(struct super_block *sb, diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index eb7fd07c90f2..0492464916b1 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -1194,9 +1194,10 @@ void ocfs2_evict_inode(struct inode *inode) /* Called under inode_lock, with no more references on the * struct inode, so it's safe here to check the flags field * and to manipulate i_nlink without any other locks. */ -void ocfs2_drop_inode(struct inode *inode) +int ocfs2_drop_inode(struct inode *inode) { struct ocfs2_inode_info *oi = OCFS2_I(inode); + int res; mlog_entry_void(); @@ -1204,11 +1205,12 @@ void ocfs2_drop_inode(struct inode *inode) (unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags); if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED) - generic_delete_inode(inode); + res = 1; else - generic_drop_inode(inode); + res = generic_drop_inode(inode); mlog_exit_void(); + return res; } /* diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 975eedd7b243..6de5a869db30 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h @@ -124,7 +124,7 @@ static inline struct ocfs2_caching_info *INODE_CACHE(struct inode *inode) } void ocfs2_evict_inode(struct inode *inode); -void ocfs2_drop_inode(struct inode *inode); +int ocfs2_drop_inode(struct inode *inode); /* Flags for ocfs2_iget() */ #define OCFS2_FI_FLAG_SYSFILE 0x1 diff --git a/include/linux/fs.h b/include/linux/fs.h index 4eaa6b2e35db..8553adbda57b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1562,7 +1562,7 @@ struct super_operations { void (*dirty_inode) (struct inode *); int (*write_inode) (struct inode *, struct writeback_control *wbc); - void (*drop_inode) (struct inode *); + int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); void (*put_super) (struct super_block *); void (*write_super) (struct super_block *); @@ -2164,8 +2164,8 @@ extern void iput(struct inode *); extern struct inode * igrab(struct inode *); extern ino_t iunique(struct super_block *, ino_t); extern int inode_needs_sync(struct inode *inode); -extern void generic_delete_inode(struct inode *inode); -extern void generic_drop_inode(struct inode *inode); +extern int generic_delete_inode(struct inode *inode); +extern int generic_drop_inode(struct inode *inode); extern struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), -- cgit v1.2.3-70-g09d2