Commit 5f248c9c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (96 commits)
  no need for list_for_each_entry_safe()/resetting with superblock list
  Fix sget() race with failing mount
  vfs: don't hold s_umount over close_bdev_exclusive() call
  sysv: do not mark superblock dirty on remount
  sysv: do not mark superblock dirty on mount
  btrfs: remove junk sb_dirt change
  BFS: clean up the superblock usage
  AFFS: wait for sb synchronization when needed
  AFFS: clean up dirty flag usage
  cifs: truncate fallout
  mbcache: fix shrinker function return value
  mbcache: Remove unused features
  add f_flags to struct statfs(64)
  pass a struct path to vfs_statfs
  update VFS documentation for method changes.
  All filesystems that need invalidate_inode_buffers() are doing that explicitly
  convert remaining ->clear_inode() to ->evict_inode()
  Make ->drop_inode() just return whether inode needs to be dropped
  fs/inode.c:clear_inode() is gone
  fs/inode.c:evict() doesn't care about delete vs. non-delete paths now
  ...

Fix up trivial conflicts in fs/nilfs2/super.c
parents f6cec0ae dca33252
......@@ -92,8 +92,8 @@ prototypes:
void (*destroy_inode)(struct inode *);
void (*dirty_inode) (struct inode *);
int (*write_inode) (struct inode *, int);
void (*drop_inode) (struct inode *);
void (*delete_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 *);
int (*sync_fs)(struct super_block *sb, int wait);
......@@ -101,14 +101,13 @@ prototypes:
int (*unfreeze_fs) (struct super_block *);
int (*statfs) (struct dentry *, struct kstatfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
void (*umount_begin) (struct super_block *);
int (*show_options)(struct seq_file *, struct vfsmount *);
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
locking rules:
All may block.
All may block [not true, see below]
None have BKL
s_umount
alloc_inode:
......@@ -116,22 +115,25 @@ destroy_inode:
dirty_inode: (must not sleep)
write_inode:
drop_inode: !!!inode_lock!!!
delete_inode:
evict_inode:
put_super: write
write_super: read
sync_fs: read
freeze_fs: read
unfreeze_fs: read
statfs: no
remount_fs: maybe (see below)
clear_inode:
statfs: maybe(read) (see below)
remount_fs: write
umount_begin: no
show_options: no (namespace_sem)
quota_read: no (see below)
quota_write: no (see below)
->remount_fs() will have the s_umount exclusive lock if it's already mounted.
When called from get_sb_single, it does NOT have the s_umount lock.
->statfs() has s_umount (shared) when called by ustat(2) (native or
compat), but that's an accident of bad API; s_umount is used to pin
the superblock down when we only have dev_t given us by userland to
identify the superblock. Everything else (statfs(), fstatfs(), etc.)
doesn't hold it when calling ->statfs() - superblock is pinned down
by resolving the pathname passed to syscall.
->quota_read() and ->quota_write() functions are both guaranteed to
be the only ones operating on the quota file by the quota code (via
dqio_sem) (unless an admin really wants to screw up something and
......
......@@ -273,3 +273,48 @@ it's safe to remove it. If you don't need it, remove it.
deliberate; as soon as struct block_device * is propagated in a reasonable
way by that code fixing will become trivial; until then nothing can be
done.
[mandatory]
block truncatation on error exit from ->write_begin, and ->direct_IO
moved from generic methods (block_write_begin, cont_write_begin,
nobh_write_begin, blockdev_direct_IO*) to callers. Take a look at
ext2_write_failed and callers for an example.
[mandatory]
->truncate is going away. The whole truncate sequence needs to be
implemented in ->setattr, which is now mandatory for filesystems
implementing on-disk size changes. Start with a copy of the old inode_setattr
and vmtruncate, and the reorder the vmtruncate + foofs_vmtruncate sequence to
be in order of zeroing blocks using block_truncate_page or similar helpers,
size update and on finally on-disk truncation which should not fail.
inode_change_ok now includes the size checks for ATTR_SIZE and must be called
in the beginning of ->setattr unconditionally.
[mandatory]
->clear_inode() and ->delete_inode() are gone; ->evict_inode() should
be used instead. It gets called whenever the inode is evicted, whether it has
remaining links or not. Caller does *not* evict the pagecache or inode-associated
metadata buffers; getting rid of those is responsibility of method, as it had
been for ->delete_inode().
->drop_inode() returns int now; it's called on final iput() with inode_lock
held and it returns true if filesystems wants the inode to be dropped. As before,
generic_drop_inode() is still the default and it's been updated appropriately.
generic_delete_inode() is also alive and it consists simply of return 1. Note that
all actual eviction work is done by caller after ->drop_inode() returns.
clear_inode() is gone; use end_writeback() instead. As before, it must
be called exactly once on each call of ->evict_inode() (as it used to be for
each call of ->delete_inode()). Unlike before, if you are using inode-associated
metadata buffers (i.e. mark_buffer_dirty_inode()), it's your responsibility to
call invalidate_inode_buffers() before end_writeback().
No async writeback (and thus no calls of ->write_inode()) will happen
after end_writeback() returns, so actions that should not overlap with ->write_inode()
(e.g. freeing on-disk inode if i_nlink is 0) ought to be done after that call.
NOTE: checking i_nlink in the beginning of ->write_inode() and bailing out
if it's zero is not *and* *never* *had* *been* enough. Final unlink() and iput()
may happen while the inode is in the middle of ->write_inode(); e.g. if you blindly
free the on-disk inode, you may end up doing that while ->write_inode() is writing
to it.
......@@ -234,11 +234,11 @@ linux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_st
}
static int
do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,
do_osf_statfs(struct path *path, struct osf_statfs __user *buffer,
unsigned long bufsiz)
{
struct kstatfs linux_stat;
int error = vfs_statfs(dentry, &linux_stat);
int error = vfs_statfs(path, &linux_stat);
if (!error)
error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
return error;
......@@ -252,7 +252,7 @@ SYSCALL_DEFINE3(osf_statfs, char __user *, pathname,
retval = user_path(pathname, &path);
if (!retval) {
retval = do_osf_statfs(path.dentry, buffer, bufsiz);
retval = do_osf_statfs(&path buffer, bufsiz);
path_put(&path);
}
return retval;
......@@ -267,7 +267,7 @@ SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd,
retval = -EBADF;
file = fget(fd);
if (file) {
retval = do_osf_statfs(file->f_path.dentry, buffer, bufsiz);
retval = do_osf_statfs(&file->f_path, buffer, bufsiz);
fput(file);
}
return retval;
......
......@@ -33,7 +33,8 @@ struct statfs {
/* Linux specials */
__kernel_fsid_t f_fsid;
long f_namelen;
long f_spare[6];
long f_flags;
long f_spare[5];
};
#if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32)
......@@ -53,7 +54,8 @@ struct statfs64 {
__u64 f_bavail;
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_spare[6];
__u32 f_flags;
__u32 f_spare[5];
};
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
......@@ -73,7 +75,8 @@ struct statfs64 { /* Same as struct statfs */
/* Linux specials */
__kernel_fsid_t f_fsid;
long f_namelen;
long f_spare[6];
long f_flags;
long f_spare[5];
};
struct compat_statfs64 {
......@@ -88,7 +91,8 @@ struct compat_statfs64 {
__u64 f_bavail;
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_spare[6];
__u32 f_flags;
__u32 f_spare[5];
};
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
......
......@@ -145,7 +145,7 @@ static int hpux_ustat(dev_t dev, struct hpux_ustat __user *ubuf)
s = user_get_super(dev);
if (s == NULL)
goto out;
err = vfs_statfs(s->s_root, &sbuf);
err = statfs_by_dentry(s->s_root, &sbuf);
drop_super(s);
if (err)
goto out;
......@@ -186,12 +186,12 @@ struct hpux_statfs {
int16_t f_pad;
};
static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf)
static int do_statfs_hpux(struct path *path, struct hpux_statfs *buf)
{
struct kstatfs st;
int retval;
retval = vfs_statfs(dentry, &st);
retval = vfs_statfs(path, &st);
if (retval)
return retval;
......@@ -219,7 +219,7 @@ asmlinkage long hpux_statfs(const char __user *pathname,
error = user_path(pathname, &path);
if (!error) {
struct hpux_statfs tmp;
error = vfs_statfs_hpux(path.dentry, &tmp);
error = do_statfs_hpux(&path, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
path_put(&path);
......@@ -237,7 +237,7 @@ asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
file = fget(fd);
if (!file)
goto out;
error = vfs_statfs_hpux(file->f_path.dentry, &tmp);
error = do_statfs_hpux(&file->f_path, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
fput(file);
......
......@@ -110,7 +110,9 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr)
if ((attr->ia_valid & ATTR_SIZE) &&
(attr->ia_size != inode->i_size))
return -EINVAL;
return inode_setattr(inode, attr);
setattr_copy(inode, attr);
mark_inode_dirty(inode);
return 0;
}
......@@ -141,15 +143,14 @@ out:
}
static void
spufs_delete_inode(struct inode *inode)
spufs_evict_inode(struct inode *inode)
{
struct spufs_inode_info *ei = SPUFS_I(inode);
end_writeback(inode);
if (ei->i_ctx)
put_spu_context(ei->i_ctx);
if (ei->i_gang)
put_spu_gang(ei->i_gang);
clear_inode(inode);
}
static void spufs_prune_dir(struct dentry *dir)
......@@ -777,8 +778,7 @@ spufs_fill_super(struct super_block *sb, void *data, int silent)
.alloc_inode = spufs_alloc_inode,
.destroy_inode = spufs_destroy_inode,
.statfs = simple_statfs,
.delete_inode = spufs_delete_inode,
.drop_inode = generic_delete_inode,
.evict_inode = spufs_evict_inode,
.show_options = generic_show_options,
};
......
......@@ -117,10 +117,10 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
return ret;
}
static void hypfs_drop_inode(struct inode *inode)
static void hypfs_evict_inode(struct inode *inode)
{
end_writeback(inode);
kfree(inode->i_private);
generic_delete_inode(inode);
}
static int hypfs_open(struct inode *inode, struct file *filp)
......@@ -460,7 +460,7 @@ static struct file_system_type hypfs_type = {
static const struct super_operations hypfs_s_ops = {
.statfs = simple_statfs,
.drop_inode = hypfs_drop_inode,
.evict_inode = hypfs_evict_inode,
.show_options = hypfs_show_options,
};
......
......@@ -33,7 +33,8 @@ struct statfs {
__kernel_fsid_t f_fsid;
int f_namelen;
int f_frsize;
int f_spare[5];
int f_flags;
int f_spare[4];
};
struct statfs64 {
......@@ -47,7 +48,8 @@ struct statfs64 {
__kernel_fsid_t f_fsid;
int f_namelen;
int f_frsize;
int f_spare[5];
int f_flags;
int f_spare[4];
};
struct compat_statfs64 {
......@@ -61,7 +63,8 @@ struct compat_statfs64 {
__kernel_fsid_t f_fsid;
__u32 f_namelen;
__u32 f_frsize;
__u32 f_spare[5];
__u32 f_flags;
__u32 f_spare[4];
};
#endif /* __s390x__ */
......
......@@ -161,6 +161,9 @@ extern int os_stat_filesystem(char *path, long *bsize_out,
long *spare_out);
extern int os_change_dir(char *dir);
extern int os_fchange_dir(int fd);
extern unsigned os_major(unsigned long long dev);
extern unsigned os_minor(unsigned long long dev);
extern unsigned long long os_makedev(unsigned major, unsigned minor);
/* start_up.c */
extern void os_early_checks(void);
......
......@@ -58,6 +58,9 @@ EXPORT_SYMBOL(os_accept_connection);
EXPORT_SYMBOL(os_rcv_fd);
EXPORT_SYMBOL(run_helper);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(os_major);
EXPORT_SYMBOL(os_minor);
EXPORT_SYMBOL(os_makedev);
EXPORT_SYMBOL(add_sigio_fd);
EXPORT_SYMBOL(ignore_sigio_fd);
......
......@@ -561,3 +561,18 @@ int os_lock_file(int fd, int excl)
out:
return err;
}
unsigned os_major(unsigned long long dev)
{
return major(dev);
}
unsigned os_minor(unsigned long long dev)
{
return minor(dev);
}
unsigned long long os_makedev(unsigned major, unsigned minor)
{
return makedev(major, minor);
}
......@@ -103,6 +103,10 @@ EXPORT_SYMBOL_PROTO(getuid);
EXPORT_SYMBOL_PROTO(fsync);
EXPORT_SYMBOL_PROTO(fdatasync);
EXPORT_SYMBOL_PROTO(lstat64);
EXPORT_SYMBOL_PROTO(fstat64);
EXPORT_SYMBOL_PROTO(mknod);
/* Export symbols used by GCC for the stack protector. */
extern void __stack_smash_handler(void *) __attribute__((weak));
EXPORT_SYMBOL(__stack_smash_handler);
......
......@@ -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);
......@@ -1217,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);
......@@ -1226,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,
......
......@@ -52,7 +52,7 @@ void v9fs_destroy_inode(struct inode *inode);
#endif
struct inode *v9fs_get_inode(struct super_block *sb, int mode);
void v9fs_clear_inode(struct inode *inode);
void v9fs_evict_inode(struct inode *inode);
ino_t v9fs_qid2ino(struct p9_qid *qid);
void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *);
void v9fs_stat2inode_dotl(struct p9_stat_dotl *, struct inode *);
......
......@@ -430,8 +430,10 @@ error:
* @inode: inode to release
*
*/
void v9fs_clear_inode(struct inode *inode)
void v9fs_evict_inode(struct inode *inode)
{
truncate_inode_pages(inode->i_mapping, 0);
end_writeback(inode);
filemap_fdatawrite(inode->i_mapping);
#ifdef CONFIG_9P_FSCACHE
......@@ -1209,10 +1211,19 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
}
retval = p9_client_wstat(fid, &wstat);
if (retval >= 0)
retval = inode_setattr(dentry->d_inode, iattr);
if (retval < 0)
return retval;
return retval;
if ((iattr->ia_valid & ATTR_SIZE) &&
iattr->ia_size != i_size_read(dentry->d_inode)) {
retval = vmtruncate(dentry->d_inode, iattr->ia_size);
if (retval)
return retval;
}
setattr_copy(dentry->d_inode, iattr);
mark_inode_dirty(dentry->d_inode);
return 0;
}
/**
......
......@@ -266,7 +266,7 @@ static const struct super_operations v9fs_super_ops = {
.destroy_inode = v9fs_destroy_inode,
#endif
.statfs = simple_statfs,
.clear_inode = v9fs_clear_inode,
.evict_inode = v9fs_evict_inode,
.show_options = generic_show_options,
.umount_begin = v9fs_umount_begin,
};
......@@ -277,7 +277,7 @@ static const struct super_operations v9fs_super_ops_dotl = {
.destroy_inode = v9fs_destroy_inode,
#endif
.statfs = v9fs_statfs,
.clear_inode = v9fs_clear_inode,
.evict_inode = v9fs_evict_inode,
.show_options = generic_show_options,
.umount_begin = v9fs_umount_begin,
};
......
......@@ -50,10 +50,19 @@ static int adfs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
{
int ret;
*pagep = NULL;
return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
adfs_get_block,
&ADFS_I(mapping->host)->mmu_private);
if (unlikely(ret)) {
loff_t isize = mapping->host->i_size;
if (pos + len > isize)
vmtruncate(mapping->host, isize);
}
return ret;
}
static sector_t _adfs_bmap(struct address_space *mapping, sector_t block)
......@@ -324,10 +333,7 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
/* XXX: this is missing some actual on-disk truncation.. */
if (ia_valid & ATTR_SIZE)
error = simple_setsize(inode, attr->ia_size);
if (error)
goto out;
truncate_setsize(inode, attr->ia_size);
if (ia_valid & ATTR_MTIME) {
inode->i_mtime = attr->ia_mtime;
......
......@@ -171,8 +171,7 @@ extern int affs_rename(struct inode *old_dir, struct dentry *old_dentry,
extern unsigned long affs_parent_ino(struct inode *dir);
extern struct inode *affs_new_inode(struct inode *dir);
extern int affs_notify_change(struct dentry *dentry, struct iattr *attr);
extern void affs_delete_inode(struct inode *inode);
extern void affs_clear_inode(struct inode *inode);
extern void affs_evict_inode(struct inode *inode);
extern struct inode *affs_iget(struct super_block *sb,
unsigned long ino);
extern int affs_write_inode(struct inode *inode,
......
......@@ -406,10 +406,19 @@ static int affs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
{
int ret;
*pagep = NULL;
return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
affs_get_block,
&AFFS_I(mapping->host)->mmu_private);
if (unlikely(ret)) {
loff_t isize = mapping->host->i_size;
if (pos + len > isize)
vmtruncate(mapping->host, isize);
}
return ret;
}
static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
......
......@@ -235,31 +235,36 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
goto out;
}
error = inode_setattr(inode, attr);
if (!error && (attr->ia_valid & ATTR_MODE))
if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) {
error = vmtruncate(inode, attr->ia_size);
if (error)
return error;
}
setattr_copy(inode, attr);
mark_inode_dirty(inode);
if (attr->ia_valid & ATTR_MODE)
mode_to_prot(inode);
out:
return error;
}
void
affs_delete_inode(struct inode *inode)
{
pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
truncate_inode_pages(&inode->i_data, 0);
inode->i_size = 0;
affs_truncate(inode);
clear_inode(inode);
affs_free_block(inode->i_sb, inode->i_ino);
}
void
affs_clear_inode(struct inode *inode)
affs_evict_inode(struct inode *inode)
{
unsigned long cache_page;
pr_debug("AFFS: evict_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
truncate_inode_pages(&inode->i_data, 0);
pr_debug("AFFS: clear_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
if (!inode->i_nlink) {
inode->i_size = 0;
affs_truncate(inode);
}
invalidate_inode_buffers(inode);
end_writeback(inode);
affs_free_prealloc(inode);
cache_page = (unsigned long)AFFS_I(inode)->i_lc;
if (cache_page) {
......@@ -271,6 +276,9 @@ affs_clear_inode(struct inode *inode)
affs_brelse(AFFS_I(inode)->i_ext_bh);
AFFS_I(inode)->i_ext_last = ~1;
AFFS_I(inode)->i_ext_bh = NULL;
if (!inode->i_nlink)
affs_free_block(inode->i_sb, inode->i_ino);
}
struct inode *
......
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