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:
  remove detritus left by "mm: make read_cache_page synchronous"
  fix fs/sysv s_dirt handling
  fat: convert to use the new truncate convention.
  ext2: convert to use the new truncate convention.
  tmpfs: convert to use the new truncate convention
  fs: convert simple fs to new truncate
  kill spurious reference to vmtruncate
  fs: introduce new truncate sequence
  fs/super: fix kernel-doc warning
  fs/minix: bugfix, number of indirect block ptrs per block depends on block size
  rename the generic fsync implementations
  drop unused dentry argument to ->fsync
  fs: Add missing mutex_unlock
  Fix racy use of anon_inode_getfd() in perf_event.c
  get rid of the magic around f_count in aio
  VFS: fix recent breakage of FS_REVAL_DOT
  Revert "anon_inode: set S_IFREG on the anon_inode"
This commit is contained in:
Linus Torvalds 2010-05-28 10:07:48 -07:00
commit 89ad6a6173
112 changed files with 785 additions and 418 deletions

View File

@ -380,7 +380,7 @@ prototypes:
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
int (*fsync) (struct file *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);

View File

@ -401,11 +401,16 @@ otherwise noted.
started might not be in the page cache at the end of the
walk).
truncate: called by the VFS to change the size of a file. The
truncate: Deprecated. This will not be called if ->setsize is defined.
Called by the VFS to change the size of a file. The
i_size field of the inode is set to the desired size by the
VFS before this method is called. This method is called by
the truncate(2) system call and related functionality.
Note: ->truncate and vmtruncate are deprecated. Do not add new
instances/calls of these. Filesystems should be converted to do their
truncate sequence via ->setattr().
permission: called by the VFS to check for access rights on a POSIX-like
filesystem.
@ -729,7 +734,7 @@ struct file_operations {
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
int (*fsync) (struct file *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);

View File

@ -1849,8 +1849,7 @@ out:
return ret;
}
static int spufs_mfc_fsync(struct file *file, struct dentry *dentry,
int datasync)
static int spufs_mfc_fsync(struct file *file, int datasync)
{
return spufs_mfc_flush(file, NULL);
}

View File

@ -251,7 +251,7 @@ const struct file_operations spufs_context_fops = {
.llseek = dcache_dir_lseek,
.read = generic_read_dir,
.readdir = dcache_readdir,
.fsync = simple_sync_file,
.fsync = noop_fsync,
};
EXPORT_SYMBOL_GPL(spufs_context_fops);

View File

@ -305,8 +305,7 @@ static int ps3flash_flush(struct file *file, fl_owner_t id)
return ps3flash_writeback(ps3flash_dev);
}
static int ps3flash_fsync(struct file *file, struct dentry *dentry,
int datasync)
static int ps3flash_fsync(struct file *file, int datasync)
{
return ps3flash_writeback(ps3flash_dev);
}

View File

@ -189,8 +189,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
return new_offset;
}
static int vol_cdev_fsync(struct file *file, struct dentry *dentry,
int datasync)
static int vol_cdev_fsync(struct file *file, int datasync)
{
struct ubi_volume_desc *desc = file->private_data;
struct ubi_device *ubi = desc->vol->ubi;

View File

@ -880,7 +880,7 @@ static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
/*
* We want fsync() to work on POHMELFS.
*/
static int pohmelfs_fsync(struct file *file, struct dentry *dentry, int datasync)
static int pohmelfs_fsync(struct file *file, int datasync)
{
struct inode *inode = file->f_mapping->host;
struct writeback_control wbc = {

View File

@ -794,7 +794,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
}
static int
printer_fsync(struct file *fd, struct dentry *dentry, int datasync)
printer_fsync(struct file *fd, int datasync)
{
struct printer_dev *dev = fd->private_data;
unsigned long flags;

View File

@ -66,7 +66,7 @@ static int fb_deferred_io_fault(struct vm_area_struct *vma,
return 0;
}
int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync)
int fb_deferred_io_fsync(struct file *file, int datasync)
{
struct fb_info *info = file->private_data;

View File

@ -257,15 +257,13 @@ v9fs_file_write(struct file *filp, const char __user * data,
return total;
}
static int v9fs_file_fsync(struct file *filp, struct dentry *dentry,
int datasync)
static int v9fs_file_fsync(struct file *filp, int datasync)
{
struct p9_fid *fid;
struct p9_wstat wstat;
int retval;
P9_DPRINTK(P9_DEBUG_VFS, "filp %p dentry %p datasync %x\n", filp,
dentry, datasync);
P9_DPRINTK(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
fid = filp->private_data;
v9fs_blank_wstat(&wstat);

View File

@ -197,7 +197,7 @@ const struct file_operations adfs_dir_operations = {
.read = generic_read_dir,
.llseek = generic_file_llseek,
.readdir = adfs_readdir,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
};
static int

View File

@ -26,7 +26,7 @@ const struct file_operations adfs_file_operations = {
.read = do_sync_read,
.aio_read = generic_file_aio_read,
.mmap = generic_file_mmap,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.splice_read = generic_file_splice_read,

View File

@ -322,8 +322,9 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
if (error)
goto out;
/* XXX: this is missing some actual on-disk truncation.. */
if (ia_valid & ATTR_SIZE)
error = vmtruncate(inode, attr->ia_size);
error = simple_setsize(inode, attr->ia_size);
if (error)
goto out;

View File

@ -183,7 +183,7 @@ extern int affs_add_entry(struct inode *dir, struct inode *inode, struct dent
void affs_free_prealloc(struct inode *inode);
extern void affs_truncate(struct inode *);
int affs_file_fsync(struct file *, struct dentry *, int);
int affs_file_fsync(struct file *, int);
/* dir.c */

View File

@ -916,9 +916,9 @@ affs_truncate(struct inode *inode)
affs_free_prealloc(inode);
}
int affs_file_fsync(struct file *filp, struct dentry *dentry, int datasync)
int affs_file_fsync(struct file *filp, int datasync)
{
struct inode * inode = dentry->d_inode;
struct inode *inode = filp->f_mapping->host;
int ret, err;
ret = write_inode_now(inode, 0);

View File

@ -740,7 +740,7 @@ extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
unsigned long, loff_t);
extern int afs_writeback_all(struct afs_vnode *);
extern int afs_fsync(struct file *, struct dentry *, int);
extern int afs_fsync(struct file *, int);
/*****************************************************************************/

View File

@ -701,8 +701,9 @@ int afs_writeback_all(struct afs_vnode *vnode)
* - the return status from this call provides a reliable indication of
* whether any write errors occurred for this process.
*/
int afs_fsync(struct file *file, struct dentry *dentry, int datasync)
int afs_fsync(struct file *file, int datasync)
{
struct dentry *dentry = file->f_path.dentry;
struct afs_writeback *wb, *xwb;
struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
int ret;

View File

@ -527,7 +527,7 @@ static void aio_fput_routine(struct work_struct *data)
/* Complete the fput(s) */
if (req->ki_filp != NULL)
__fput(req->ki_filp);
fput(req->ki_filp);
/* Link the iocb into the context's free list */
spin_lock_irq(&ctx->ctx_lock);
@ -560,11 +560,11 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
/*
* Try to optimize the aio and eventfd file* puts, by avoiding to
* schedule work in case it is not __fput() time. In normal cases,
* schedule work in case it is not final fput() time. In normal cases,
* we would not be holding the last reference to the file*, so
* this function will be executed w/out any aio kthread wakeup.
*/
if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) {
if (unlikely(!fput_atomic(req->ki_filp))) {
get_ioctx(ctx);
spin_lock(&fput_lock);
list_add(&req->ki_list, &fput_head);

View File

@ -205,7 +205,7 @@ static struct inode *anon_inode_mkinode(void)
* that it already _is_ on the dirty list.
*/
inode->i_state = I_DIRTY;
inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
inode->i_mode = S_IRUSR | S_IWUSR;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
inode->i_flags |= S_PRIVATE;

View File

@ -67,14 +67,14 @@ EXPORT_SYMBOL(inode_change_ok);
* @offset: the new size to assign to the inode
* @Returns: 0 on success, -ve errno on failure
*
* inode_newsize_ok must be called with i_mutex held.
*
* inode_newsize_ok will check filesystem limits and ulimits to check that the
* new inode size is within limits. inode_newsize_ok will also send SIGXFSZ
* when necessary. Caller must not proceed with inode size change if failure is
* returned. @inode must be a file (not directory), with appropriate
* permissions to allow truncate (inode_newsize_ok does NOT check these
* conditions).
*
* inode_newsize_ok must be called with i_mutex held.
*/
int inode_newsize_ok(const struct inode *inode, loff_t offset)
{
@ -104,17 +104,25 @@ out_big:
}
EXPORT_SYMBOL(inode_newsize_ok);
int inode_setattr(struct inode * inode, struct iattr * attr)
/**
* generic_setattr - copy simple metadata updates into the generic inode
* @inode: the inode to be updated
* @attr: the new attributes
*
* generic_setattr must be called with i_mutex held.
*
* generic_setattr updates the inode's metadata with that specified
* in attr. Noticably missing is inode size update, which is more complex
* as it requires pagecache updates. See simple_setsize.
*
* The inode is not marked as dirty after this operation. The rationale is
* that for "simple" filesystems, the struct inode is the inode storage.
* The caller is free to mark the inode dirty afterwards if needed.
*/
void generic_setattr(struct inode *inode, const struct iattr *attr)
{
unsigned int ia_valid = attr->ia_valid;
if (ia_valid & ATTR_SIZE &&
attr->ia_size != i_size_read(inode)) {
int error = vmtruncate(inode, attr->ia_size);
if (error)
return error;
}
if (ia_valid & ATTR_UID)
inode->i_uid = attr->ia_uid;
if (ia_valid & ATTR_GID)
@ -135,6 +143,28 @@ int inode_setattr(struct inode * inode, struct iattr * attr)
mode &= ~S_ISGID;
inode->i_mode = mode;
}
}
EXPORT_SYMBOL(generic_setattr);
/*
* note this function is deprecated, the new truncate sequence should be
* used instead -- see eg. simple_setsize, generic_setattr.
*/
int inode_setattr(struct inode *inode, const struct iattr *attr)
{
unsigned int ia_valid = attr->ia_valid;
if (ia_valid & ATTR_SIZE &&
attr->ia_size != i_size_read(inode)) {
int error;
error = vmtruncate(inode, attr->ia_size);
if (error)
return error;
}
generic_setattr(inode, attr);
mark_inode_dirty(inode);
return 0;

View File

@ -93,8 +93,7 @@ static int bad_file_release(struct inode *inode, struct file *filp)
return -EIO;
}
static int bad_file_fsync(struct file *file, struct dentry *dentry,
int datasync)
static int bad_file_fsync(struct file *file, int datasync)
{
return -EIO;
}

View File

@ -78,7 +78,7 @@ static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
const struct file_operations bfs_dir_operations = {
.read = generic_read_dir,
.readdir = bfs_readdir,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
.llseek = generic_file_llseek,
};

View File

@ -172,8 +172,9 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode),
iov, offset, nr_segs, blkdev_get_blocks, NULL);
return blockdev_direct_IO_no_locking_newtrunc(rw, iocb, inode,
I_BDEV(inode), iov, offset, nr_segs,
blkdev_get_blocks, NULL);
}
int __sync_blockdev(struct block_device *bdev, int wait)
@ -309,8 +310,8 @@ static int blkdev_write_begin(struct file *file, struct address_space *mapping,
struct page **pagep, void **fsdata)
{
*pagep = NULL;
return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
blkdev_get_block);
return block_write_begin_newtrunc(file, mapping, pos, len, flags,
pagep, fsdata, blkdev_get_block);
}
static int blkdev_write_end(struct file *file, struct address_space *mapping,
@ -358,12 +359,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
return retval;
}
/*
* Filp is never NULL; the only case when ->fsync() is called with
* NULL first argument is nfsd_sync_dir() and that's not a directory.
*/
int blkdev_fsync(struct file *filp, struct dentry *dentry, int datasync)
int blkdev_fsync(struct file *filp, int datasync)
{
struct inode *bd_inode = filp->f_mapping->host;
struct block_device *bdev = I_BDEV(bd_inode);

View File

@ -2434,7 +2434,7 @@ void btrfs_update_iflags(struct inode *inode);
void btrfs_inherit_iflags(struct inode *inode, struct inode *dir);
/* file.c */
int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync);
int btrfs_sync_file(struct file *file, int datasync);
int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
int skip_pinned);
int btrfs_check_file(struct btrfs_root *root, struct inode *inode);

View File

@ -1101,8 +1101,9 @@ int btrfs_release_file(struct inode *inode, struct file *filp)
* important optimization for directories because holding the mutex prevents
* new operations on the dir while we write to disk.
*/
int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
int btrfs_sync_file(struct file *file, int datasync)
{
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root;
int ret = 0;

View File

@ -1949,14 +1949,11 @@ static int __block_commit_write(struct inode *inode, struct page *page,
}
/*
* block_write_begin takes care of the basic task of block allocation and
* bringing partial write blocks uptodate first.
*
* If *pagep is not NULL, then block_write_begin uses the locked page
* at *pagep rather than allocating its own. In this case, the page will
* not be unlocked or deallocated on failure.
* Filesystems implementing the new truncate sequence should use the
* _newtrunc postfix variant which won't incorrectly call vmtruncate.
* The filesystem needs to handle block truncation upon failure.
*/
int block_write_begin(struct file *file, struct address_space *mapping,
int block_write_begin_newtrunc(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata,
get_block_t *get_block)
@ -1992,20 +1989,50 @@ int block_write_begin(struct file *file, struct address_space *mapping,
unlock_page(page);
page_cache_release(page);
*pagep = NULL;
/*
* prepare_write() may have instantiated a few blocks
* outside i_size. Trim these off again. Don't need
* i_size_read because we hold i_mutex.
*/
if (pos + len > inode->i_size)
vmtruncate(inode, inode->i_size);
}
}
out:
return status;
}
EXPORT_SYMBOL(block_write_begin_newtrunc);
/*
* block_write_begin takes care of the basic task of block allocation and
* bringing partial write blocks uptodate first.
*
* If *pagep is not NULL, then block_write_begin uses the locked page
* at *pagep rather than allocating its own. In this case, the page will
* not be unlocked or deallocated on failure.
*/
int block_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata,
get_block_t *get_block)
{
int ret;
ret = block_write_begin_newtrunc(file, mapping, pos, len, flags,
pagep, fsdata, get_block);
/*
* prepare_write() may have instantiated a few blocks
* outside i_size. Trim these off again. Don't need
* i_size_read because we hold i_mutex.
*
* Filesystems which pass down their own page also cannot
* call into vmtruncate here because it would lead to lock
* inversion problems (*pagep is locked). This is a further
* example of where the old truncate sequence is inadequate.
*/
if (unlikely(ret) && *pagep == NULL) {
loff_t isize = mapping->host->i_size;
if (pos + len > isize)
vmtruncate(mapping->host, isize);
}
return ret;
}
EXPORT_SYMBOL(block_write_begin);
int block_write_end(struct file *file, struct address_space *mapping,
@ -2324,7 +2351,7 @@ out:
* For moronic filesystems that do not allow holes in file.
* We may have to extend the file.
*/
int cont_write_begin(struct file *file, struct address_space *mapping,
int cont_write_begin_newtrunc(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata,
get_block_t *get_block, loff_t *bytes)
@ -2345,11 +2372,30 @@ int cont_write_begin(struct file *file, struct address_space *mapping,
}
*pagep = NULL;
err = block_write_begin(file, mapping, pos, len,
err = block_write_begin_newtrunc(file, mapping, pos, len,
flags, pagep, fsdata, get_block);
out:
return err;
}
EXPORT_SYMBOL(cont_write_begin_newtrunc);
int cont_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata,
get_block_t *get_block, loff_t *bytes)
{
int ret;
ret = cont_write_begin_newtrunc(file, mapping, pos, len, flags,
pagep, fsdata, get_block, bytes);
if (unlikely(ret)) {
loff_t isize = mapping->host->i_size;
if (pos + len > isize)
vmtruncate(mapping->host, isize);
}
return ret;
}
EXPORT_SYMBOL(cont_write_begin);
int block_prepare_write(struct page *page, unsigned from, unsigned to,
@ -2381,7 +2427,7 @@ EXPORT_SYMBOL(block_commit_write);
*
* We are not allowed to take the i_mutex here so we have to play games to
* protect against truncate races as the page could now be beyond EOF. Because
* vmtruncate() writes the inode size before removing pages, once we have the
* truncate writes the inode size before removing pages, once we have the
* page lock we can determine safely if the page is beyond EOF. If it is not
* beyond EOF, then the page is guaranteed safe against truncation until we
* unlock the page.
@ -2464,10 +2510,11 @@ static void attach_nobh_buffers(struct page *page, struct buffer_head *head)
}
/*
* On entry, the page is fully not uptodate.
* On exit the page is fully uptodate in the areas outside (from,to)
* Filesystems implementing the new truncate sequence should use the
* _newtrunc postfix variant which won't incorrectly call vmtruncate.
* The filesystem needs to handle block truncation upon failure.
*/
int nobh_write_begin(struct file *file, struct address_space *mapping,
int nobh_write_begin_newtrunc(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata,
get_block_t *get_block)
@ -2500,8 +2547,8 @@ int nobh_write_begin(struct file *file, struct address_space *mapping,
unlock_page(page);
page_cache_release(page);
*pagep = NULL;
return block_write_begin(file, mapping, pos, len, flags, pagep,
fsdata, get_block);
return block_write_begin_newtrunc(file, mapping, pos, len,
flags, pagep, fsdata, get_block);
}
if (PageMappedToDisk(page))
@ -2605,8 +2652,34 @@ out_release:
page_cache_release(page);
*pagep = NULL;
if (pos + len > inode->i_size)
vmtruncate(inode, inode->i_size);
return ret;
}
EXPORT_SYMBOL(nobh_write_begin_newtrunc);
/*
* On entry, the page is fully not uptodate.
* On exit the page is fully uptodate in the areas outside (from,to)
*/
int nobh_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata,
get_block_t *get_block)
{
int ret;
ret = nobh_write_begin_newtrunc(file, mapping, pos, len, flags,
pagep, fsdata, get_block);
/*
* prepare_write() may have instantiated a few blocks
* outside i_size. Trim these off again. Don't need
* i_size_read because we hold i_mutex.
*/
if (unlikely(ret)) {
loff_t isize = mapping->host->i_size;
if (pos + len > isize)
vmtruncate(mapping->host, isize);
}
return ret;
}

View File

@ -1776,9 +1776,9 @@ out:
spin_unlock(&ci->i_unsafe_lock);
}
int ceph_fsync(struct file *file, struct dentry *dentry, int datasync)
int ceph_fsync(struct file *file, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = file->f_mapping->host;
struct ceph_inode_info *ci = ceph_inode(inode);
unsigned flush_tid;
int ret;

View File

@ -1107,10 +1107,9 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
* an fsync() on a dir will wait for any uncommitted directory
* operations to commit.
*/
static int ceph_dir_fsync(struct file *file, struct dentry *dentry,
int datasync)
static int ceph_dir_fsync(struct file *file, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = file->f_path.dentry->d_inode;
struct ceph_inode_info *ci = ceph_inode(inode);
struct list_head *head = &ci->i_unsafe_dirops;
struct ceph_mds_request *req;

View File

@ -811,7 +811,7 @@ extern void ceph_put_cap(struct ceph_cap *cap);
extern void ceph_queue_caps_release(struct inode *inode);
extern int ceph_write_inode(struct inode *inode, struct writeback_control *wbc);
extern int ceph_fsync(struct file *file, struct dentry *dentry, int datasync);
extern int ceph_fsync(struct file *file, int datasync);
extern void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session);
extern int ceph_get_cap_mds(struct inode *inode);

View File

@ -84,7 +84,7 @@ extern ssize_t cifs_user_read(struct file *file, char __user *read_data,
extern ssize_t cifs_user_write(struct file *file, const char __user *write_data,
size_t write_size, loff_t *poffset);
extern int cifs_lock(struct file *, int, struct file_lock *);
extern int cifs_fsync(struct file *, struct dentry *, int);
extern int cifs_fsync(struct file *, int);
extern int cifs_flush(struct file *, fl_owner_t id);
extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
extern const struct file_operations cifs_dir_ops;

View File

@ -1676,7 +1676,7 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
return rc;
}
int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
int cifs_fsync(struct file *file, int datasync)
{
int xid;
int rc = 0;
@ -1688,7 +1688,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
xid = GetXid();
cFYI(1, "Sync file - name: %s datasync: 0x%x",
dentry->d_name.name, datasync);
file->f_path.dentry->d_name.name, datasync);
rc = filemap_write_and_wait(inode->i_mapping);
if (rc == 0) {

View File

@ -11,8 +11,7 @@ extern int coda_fake_statfs;
void coda_destroy_inodecache(void);
int coda_init_inodecache(void);
int coda_fsync(struct file *coda_file, struct dentry *coda_dentry,
int datasync);
int coda_fsync(struct file *coda_file, int datasync);
void coda_sysctl_init(void);
void coda_sysctl_clean(void);

View File

@ -202,10 +202,10 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
return 0;
}
int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
int coda_fsync(struct file *coda_file, int datasync)
{
struct file *host_file;
struct inode *coda_inode = coda_dentry->d_inode;
struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
struct coda_file_info *cfi;
int err = 0;

View File

@ -72,16 +72,11 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
if (!sd)
return -EINVAL;
error = simple_setattr(dentry, iattr);
if (error)
return error;
sd_iattr = sd->s_iattr;
error = inode_change_ok(inode, iattr);
if (error)
return error;
error = inode_setattr(inode, iattr);
if (error)
return error;
if (!sd_iattr) {
/* setting attributes for the first time, allocate now */
sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);

View File

@ -1134,27 +1134,8 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
return ret;
}
/*
* This is a library function for use by filesystem drivers.
*
* The locking rules are governed by the flags parameter:
* - if the flags value contains DIO_LOCKING we use a fancy locking
* scheme for dumb filesystems.
* For writes this function is called under i_mutex and returns with
* i_mutex held, for reads, i_mutex is not held on entry, but it is
* taken and dropped again before returning.
* For reads and writes i_alloc_sem is taken in shared mode and released
* on I/O completion (which may happen asynchronously after returning to
* the caller).
*
* - if the flags value does NOT contain DIO_LOCKING we don't use any
* internal locking but rather rely on the filesystem to synchronize
* direct I/O reads/writes versus each other and truncate.
* For reads and writes both i_mutex and i_alloc_sem are not held on
* entry and are never taken.
*/
ssize_t
__blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
__blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode,
struct block_device *bdev, const struct iovec *iov, loff_t offset,
unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
dio_submit_t submit_io, int flags)
@ -1247,9 +1228,46 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
nr_segs, blkbits, get_block, end_io,
submit_io, dio);
out:
return retval;
}
EXPORT_SYMBOL(__blockdev_direct_IO_newtrunc);
/*
* This is a library function for use by filesystem drivers.
*
* The locking rules are governed by the flags parameter:
* - if the flags value contains DIO_LOCKING we use a fancy locking
* scheme for dumb filesystems.
* For writes this function is called under i_mutex and returns with
* i_mutex held, for reads, i_mutex is not held on entry, but it is
* taken and dropped again before returning.
* For reads and writes i_alloc_sem is taken in shared mode and released
* on I/O completion (which may happen asynchronously after returning to
* the caller).
*
* - if the flags value does NOT contain DIO_LOCKING we don't use any
* internal locking but rather rely on the filesystem to synchronize
* direct I/O reads/writes versus each other and truncate.
* For reads and writes both i_mutex and i_alloc_sem are not held on
* entry and are never taken.
*/
ssize_t
__blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
struct block_device *bdev, const struct iovec *iov, loff_t offset,
unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
dio_submit_t submit_io, int flags)
{
ssize_t retval;
retval = __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov,
offset, nr_segs, get_block, end_io, submit_io, flags);
/*
* In case of error extending write may have instantiated a few
* blocks outside i_size. Trim these off again for DIO_LOCKING.
* NOTE: DIO_NO_LOCK/DIO_OWN_LOCK callers have to handle this in
* their own manner. This is a further example of where the old
* truncate sequence is inadequate.
*
* NOTE: filesystems with their own locking have to handle this
* on their own.
@ -1257,12 +1275,13 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
if (flags & DIO_LOCKING) {
if (unlikely((rw & WRITE) && retval < 0)) {
loff_t isize = i_size_read(inode);
loff_t end = offset + iov_length(iov, nr_segs);
if (end > isize)
vmtruncate(inode, isize);
}
}
out:
return retval;
}
EXPORT_SYMBOL(__blockdev_direct_IO);

View File

@ -274,7 +274,7 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
}
static int
ecryptfs_fsync(struct file *file, struct dentry *dentry, int datasync)
ecryptfs_fsync(struct file *file, int datasync)
{
return vfs_fsync(ecryptfs_file_to_lower(file), datasync);
}

View File

@ -805,7 +805,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
- (ia->ia_size & ~PAGE_CACHE_MASK));
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
rc = vmtruncate(inode, ia->ia_size);
rc = simple_setsize(inode, ia->ia_size);
if (rc)
goto out;
lower_ia->ia_size = ia->ia_size;
@ -830,7 +830,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
goto out;
}
}
vmtruncate(inode, ia->ia_size);
simple_setsize(inode, ia->ia_size);
rc = ecryptfs_write_inode_size_to_metadata(inode);
if (rc) {
printk(KERN_ERR "Problem with "

View File

@ -40,12 +40,11 @@ static int exofs_release_file(struct inode *inode, struct file *filp)
return 0;
}
static int exofs_file_fsync(struct file *filp, struct dentry *dentry,
int datasync)
static int exofs_file_fsync(struct file *filp, int datasync)
{
int ret;
struct address_space *mapping = filp->f_mapping;
struct inode *inode = dentry->d_inode;
struct inode *inode = mapping->host;
struct super_block *sb;
ret = filemap_write_and_wait(mapping);
@ -66,7 +65,7 @@ static int exofs_file_fsync(struct file *filp, struct dentry *dentry,
static int exofs_flush(struct file *file, fl_owner_t id)
{
exofs_file_fsync(file, file->f_path.dentry, 1);
exofs_file_fsync(file, 1);
/* TODO: Flush the OSD target */
return 0;
}

View File

@ -122,7 +122,6 @@ extern int ext2_write_inode (struct inode *, struct writeback_control *);
extern void ext2_delete_inode (struct inode *);
extern int ext2_sync_inode (struct inode *);
extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern void ext2_truncate (struct inode *);
extern int ext2_setattr (struct dentry *, struct iattr *);
extern void ext2_set_inode_flags(struct inode *inode);
extern void ext2_get_inode_flags(struct ext2_inode_info *);
@ -155,7 +154,7 @@ extern void ext2_write_super (struct super_block *);
extern const struct file_operations ext2_dir_operations;
/* file.c */
extern int ext2_fsync(struct file *file, struct dentry *dentry, int datasync);
extern int ext2_fsync(struct file *file, int datasync);
extern const struct inode_operations ext2_file_inode_operations;
extern const struct file_operations ext2_file_operations;
extern const struct file_operations ext2_xip_file_operations;

View File

@ -40,13 +40,13 @@ static int ext2_release_file (struct inode * inode, struct file * filp)
return 0;
}
int ext2_fsync(struct file *file, struct dentry *dentry, int datasync)
int ext2_fsync(struct file *file, int datasync)
{
int ret;
struct super_block *sb = dentry->d_inode->i_sb;
struct super_block *sb = file->f_mapping->host->i_sb;
struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
ret = simple_fsync(file, dentry, datasync);
ret = generic_file_fsync(file, datasync);
if (ret == -EIO || test_and_clear_bit(AS_EIO, &mapping->flags)) {
/* We don't really know where the IO error happened... */
ext2_error(sb, __func__,
@ -95,7 +95,6 @@ const struct file_operations ext2_xip_file_operations = {
#endif
const struct inode_operations ext2_file_inode_operations = {
.truncate = ext2_truncate,
#ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,

View File

@ -54,6 +54,18 @@ static inline int ext2_inode_is_fast_symlink(struct inode *inode)
inode->i_blocks - ea_blocks == 0);
}
static void ext2_truncate_blocks(struct inode *inode, loff_t offset);
static void ext2_write_failed(struct address_space *mapping, loff_t to)
{
struct inode *inode = mapping->host;
if (to > inode->i_size) {
truncate_pagecache(inode, to, inode->i_size);
ext2_truncate_blocks(inode, inode->i_size);
}
}
/*
* Called at the last iput() if i_nlink is zero.
*/
@ -71,7 +83,7 @@ void ext2_delete_inode (struct inode * inode)
inode->i_size = 0;
if (inode->i_blocks)
ext2_truncate (inode);
ext2_truncate_blocks(inode, 0);
ext2_free_inode (inode);
return;
@ -757,8 +769,8 @@ int __ext2_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
{
return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
ext2_get_block);
return block_write_begin_newtrunc(file, mapping, pos, len, flags,
pagep, fsdata, ext2_get_block);
}
static int
@ -766,8 +778,25 @@ ext2_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 __ext2_write_begin(file, mapping, pos, len, flags, pagep,fsdata);
ret = __ext2_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
if (ret < 0)
ext2_write_failed(mapping, pos + len);
return ret;
}
static int ext2_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata)
{
int ret;
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
if (ret < len)
ext2_write_failed(mapping, pos + len);
return ret;
}
static int
@ -775,13 +804,18 @@ ext2_nobh_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
{
int ret;
/*
* Dir-in-pagecache still uses ext2_write_begin. Would have to rework
* directory handling code to pass around offsets rather than struct
* pages in order to make this work easily.
*/
return nobh_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
ext2_get_block);
ret = nobh_write_begin_newtrunc(file, mapping, pos, len, flags, pagep,
fsdata, ext2_get_block);
if (ret < 0)
ext2_write_failed(mapping, pos + len);
return ret;
}
static int ext2_nobh_writepage(struct page *page,
@ -800,10 +834,15 @@ ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
loff_t offset, unsigned long nr_segs)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
ssize_t ret;
return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
offset, nr_segs, ext2_get_block, NULL);
ret = blockdev_direct_IO_newtrunc(rw, iocb, inode, inode->i_sb->s_bdev,
iov, offset, nr_segs, ext2_get_block, NULL);
if (ret < 0 && (rw & WRITE))
ext2_write_failed(mapping, offset + iov_length(iov, nr_segs));
return ret;
}
static int
@ -818,7 +857,7 @@ const struct address_space_operations ext2_aops = {
.writepage = ext2_writepage,
.sync_page = block_sync_page,
.write_begin = ext2_write_begin,
.write_end = generic_write_end,
.write_end = ext2_write_end,
.bmap = ext2_bmap,
.direct_IO = ext2_direct_IO,
.writepages = ext2_writepages,
@ -1027,7 +1066,7 @@ static void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int de
ext2_free_data(inode, p, q);
}
void ext2_truncate(struct inode *inode)
static void __ext2_truncate_blocks(struct inode *inode, loff_t offset)
{
__le32 *i_data = EXT2_I(inode)->i_data;
struct ext2_inode_info *ei = EXT2_I(inode);
@ -1039,27 +1078,8 @@ void ext2_truncate(struct inode *inode)
int n;
long iblock;
unsigned blocksize;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
if (ext2_inode_is_fast_symlink(inode))
return;
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
return;
blocksize = inode->i_sb->s_blocksize;
iblock = (inode->i_size + blocksize-1)
>> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
if (mapping_is_xip(inode->i_mapping))
xip_truncate_page(inode->i_mapping, inode->i_size);
else if (test_opt(inode->i_sb, NOBH))
nobh_truncate_page(inode->i_mapping,
inode->i_size, ext2_get_block);
else
block_truncate_page(inode->i_mapping,
inode->i_size, ext2_get_block);
iblock = (offset + blocksize-1) >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
n = ext2_block_to_path(inode, iblock, offsets, NULL);
if (n == 0)
@ -1127,6 +1147,62 @@ do_indirects:
ext2_discard_reservation(inode);
mutex_unlock(&ei->truncate_mutex);
}
static void ext2_truncate_blocks(struct inode *inode, loff_t offset)
{
/*
* XXX: it seems like a bug here that we don't allow
* IS_APPEND inode to have blocks-past-i_size trimmed off.
* review and fix this.
*
* Also would be nice to be able to handle IO errors and such,
* but that's probably too much to ask.
*/
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
if (ext2_inode_is_fast_symlink(inode))
return;
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
return;
__ext2_truncate_blocks(inode, offset);
}
int ext2_setsize(struct inode *inode, loff_t newsize)
{
loff_t oldsize;
int error;
error = inode_newsize_ok(inode, newsize);
if (error)
return error;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return -EINVAL;
if (ext2_inode_is_fast_symlink(inode))
return -EINVAL;
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
return -EPERM;
if (mapping_is_xip(inode->i_mapping))
error = xip_truncate_page(inode->i_mapping, newsize);
else if (test_opt(inode->i_sb, NOBH))
error = nobh_truncate_page(inode->i_mapping,
newsize, ext2_get_block);
else
error = block_truncate_page(inode->i_mapping,
newsize, ext2_get_block);
if (error)
return error;
oldsize = inode->i_size;
i_size_write(inode, newsize);
truncate_pagecache(inode, oldsize, newsize);
__ext2_truncate_blocks(inode, newsize);
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
if (inode_needs_sync(inode)) {
sync_mapping_buffers(inode->i_mapping);
@ -1134,6 +1210,8 @@ do_indirects:
} else {
mark_inode_dirty(inode);
}
return 0;
}
static struct ext2_inode *ext2_get_inode(struct super_block *sb, ino_t ino,
@ -1474,8 +1552,15 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
if (error)
return error;
}
error = inode_setattr(inode, iattr);
if (!error && (iattr->ia_valid & ATTR_MODE))
if (iattr->ia_valid & ATTR_SIZE) {
error = ext2_setsize(inode, iattr->ia_size);
if (error)
return error;
}
generic_setattr(inode, iattr);
if (iattr->ia_valid & ATTR_MODE)
error = ext2_acl_chmod(inode);
mark_inode_dirty(inode);
return error;
}

View File

@ -43,9 +43,9 @@
* inode to disk.
*/
int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
int ext3_sync_file(struct file *file, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = file->f_mapping->host;
struct ext3_inode_info *ei = EXT3_I(inode);
journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
int ret, needs_barrier = 0;

View File

@ -1519,7 +1519,7 @@ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
extern void ext4_htree_free_dir_info(struct dir_private_info *p);
/* fsync.c */
extern int ext4_sync_file(struct file *, struct dentry *, int);
extern int ext4_sync_file(struct file *, int);
/* hash.c */
extern int ext4fs_dirhash(const char *name, int len, struct

View File

@ -71,9 +71,9 @@ static void ext4_sync_parent(struct inode *inode)
* i_mutex lock is held when entering and exiting this function
*/
int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
int ext4_sync_file(struct file *file, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = file->f_mapping->host;
struct ext4_inode_info *ei = EXT4_I(inode);
journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
int ret;
@ -81,7 +81,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
J_ASSERT(ext4_journal_current_handle() == NULL);
trace_ext4_sync_file(file, dentry, datasync);
trace_ext4_sync_file(file, datasync);
if (inode->i_sb->s_flags & MS_RDONLY)
return 0;
@ -91,7 +91,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
return ret;
if (!journal) {
ret = simple_fsync(file, dentry, datasync);
ret = generic_file_fsync(file, datasync);
if (!ret && !list_empty(&inode->i_dentry))
ext4_sync_parent(inode);
return ret;

View File

@ -306,11 +306,11 @@ extern long fat_generic_ioctl(struct file *filp, unsigned int cmd,
extern const struct file_operations fat_file_operations;
extern const struct inode_operations fat_file_inode_operations;
extern int fat_setattr(struct dentry * dentry, struct iattr * attr);
extern void fat_truncate(struct inode *inode);
extern int fat_setsize(struct inode *inode, loff_t offset);
extern void fat_truncate_blocks(struct inode *inode, loff_t offset);
extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat);
extern int fat_file_fsync(struct file *file, struct dentry *dentry,
int datasync);
extern int fat_file_fsync(struct file *file, int datasync);
/* fat/inode.c */
extern void fat_attach(struct inode *inode, loff_t i_pos);

View File

@ -149,12 +149,12 @@ static int fat_file_release(struct inode *inode, struct file *filp)
return 0;
}
int fat_file_fsync(struct file *filp, struct dentry *dentry, int datasync)
int fat_file_fsync(struct file *filp, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = filp->f_mapping->host;
int res, err;
res = simple_fsync(filp, dentry, datasync);
res = generic_file_fsync(filp, datasync);
err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);
return res ? res : err;
@ -283,7 +283,7 @@ static int fat_free(struct inode *inode, int skip)
return fat_free_clusters(inode, free_start);
}
void fat_truncate(struct inode *inode)
void fat_truncate_blocks(struct inode *inode, loff_t offset)
{
struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
const unsigned int cluster_size = sbi->cluster_size;
@ -293,10 +293,10 @@ void fat_truncate(struct inode *inode)
* This protects against truncating a file bigger than it was then
* trying to write into the hole.
*/
if (MSDOS_I(inode)->mmu_private > inode->i_size)
MSDOS_I(inode)->mmu_private = inode->i_size;
if (MSDOS_I(inode)->mmu_private > offset)
MSDOS_I(inode)->mmu_private = offset;
nr_clusters = (inode->i_size + (cluster_size - 1)) >> sbi->cluster_bits;
nr_clusters = (offset + (cluster_size - 1)) >> sbi->cluster_bits;
fat_free(inode, nr_clusters);
fat_flush_inodes(inode->i_sb, inode, NULL);
@ -364,6 +364,18 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
return 0;
}
int fat_setsize(struct inode *inode, loff_t offset)
{
int error;
error = simple_setsize(inode, offset);
if (error)
return error;
fat_truncate_blocks(inode, offset);
return error;
}
#define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
/* valid file mode bits */
#define FAT_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXUGO)
@ -378,7 +390,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
/*
* Expand the file. Since inode_setattr() updates ->i_size
* before calling the ->truncate(), but FAT needs to fill the
* hole before it.
* hole before it. XXX: this is no longer true with new truncate
* sequence.
*/
if (attr->ia_valid & ATTR_SIZE) {
if (attr->ia_size > inode->i_size) {
@ -427,15 +440,20 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
attr->ia_valid &= ~ATTR_MODE;
}
if (attr->ia_valid)
error = inode_setattr(inode, attr);
if (attr->ia_valid & ATTR_SIZE) {
error = fat_setsize(inode, attr->ia_size);
if (error)
goto out;
}
generic_setattr(inode, attr);
mark_inode_dirty(inode);
out:
return error;
}
EXPORT_SYMBOL_GPL(fat_setattr);
const struct inode_operations fat_file_inode_operations = {
.truncate = fat_truncate,
.setattr = fat_setattr,
.getattr = fat_getattr,
};

View File

@ -142,14 +142,29 @@ static int fat_readpages(struct file *file, struct address_space *mapping,
return mpage_readpages(mapping, pages, nr_pages, fat_get_block);
}
static void fat_write_failed(struct address_space *mapping, loff_t to)
{
struct inode *inode = mapping->host;
if (to > inode->i_size) {
truncate_pagecache(inode, to, inode->i_size);
fat_truncate_blocks(inode, inode->i_size);
}
}
static int fat_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
{
int err;
*pagep = NULL;
return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
fat_get_block,
err = cont_write_begin_newtrunc(file, mapping, pos, len, flags,
pagep, fsdata, fat_get_block,
&MSDOS_I(mapping->host)->mmu_private);
if (err < 0)
fat_write_failed(mapping, pos + len);
return err;
}
static int fat_write_end(struct file *file, struct address_space *mapping,
@ -159,6 +174,8 @@ static int fat_write_end(struct file *file, struct address_space *mapping,
struct inode *inode = mapping->host;
int err;
err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
if (err < len)
fat_write_failed(mapping, pos + len);
if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
@ -172,7 +189,9 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
loff_t offset, unsigned long nr_segs)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
ssize_t ret;
if (rw == WRITE) {
/*
@ -193,8 +212,12 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
* FAT need to use the DIO_LOCKING for avoiding the race
* condition of fat_get_block() and ->truncate().
*/
return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
offset, nr_segs, fat_get_block, NULL);
ret = blockdev_direct_IO_newtrunc(rw, iocb, inode, inode->i_sb->s_bdev,
iov, offset, nr_segs, fat_get_block, NULL);
if (ret < 0 && (rw & WRITE))
fat_write_failed(mapping, offset + iov_length(iov, nr_segs));
return ret;
}
static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
@ -429,7 +452,7 @@ static void fat_delete_inode(struct inode *inode)
{
truncate_inode_pages(&inode->i_data, 0);
inode->i_size = 0;
fat_truncate(inode);
fat_truncate_blocks(inode, 0);
clear_inode(inode);
}

View File

@ -194,14 +194,6 @@ struct file *alloc_file(struct path *path, fmode_t mode,
}
EXPORT_SYMBOL(alloc_file);
void fput(struct file *file)
{
if (atomic_long_dec_and_test(&file->f_count))
__fput(file);
}
EXPORT_SYMBOL(fput);
/**
* drop_file_write_access - give up ability to write to a file
* @file: the file to which we will stop writing
@ -227,10 +219,9 @@ void drop_file_write_access(struct file *file)
}
EXPORT_SYMBOL_GPL(drop_file_write_access);
/* __fput is called from task context when aio completion releases the last
* last use of a struct file *. Do not use otherwise.
/* the real guts of fput() - releasing the last reference to file
*/
void __fput(struct file *file)
static void __fput(struct file *file)
{
struct dentry *dentry = file->f_path.dentry;
struct vfsmount *mnt = file->f_path.mnt;
@ -268,6 +259,14 @@ void __fput(struct file *file)
mntput(mnt);
}
void fput(struct file *file)
{
if (atomic_long_dec_and_test(&file->f_count))
__fput(file);
}
EXPORT_SYMBOL(fput);
struct file *fget(unsigned int fd)
{
struct file *file;

View File

@ -1156,10 +1156,9 @@ static int fuse_dir_release(struct inode *inode, struct file *file)
return 0;
}
static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
static int fuse_dir_fsync(struct file *file, int datasync)
{
/* nfsd can call this with no file */
return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
return fuse_fsync_common(file, datasync, 1);
}
static bool update_mtime(unsigned ivalid)

View File

@ -351,10 +351,9 @@ static void fuse_sync_writes(struct inode *inode)
fuse_release_nowrite(inode);
}
int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
int isdir)
int fuse_fsync_common(struct file *file, int datasync, int isdir)
{
struct inode *inode = de->d_inode;
struct inode *inode = file->f_mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
struct fuse_req *req;
@ -403,9 +402,9 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
return err;
}
static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
static int fuse_fsync(struct file *file, int datasync)
{
return fuse_fsync_common(file, de, datasync, 0);
return fuse_fsync_common(file, datasync, 0);
}
void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,

View File

@ -568,8 +568,7 @@ void fuse_release_common(struct file *file, int opcode);
/**
* Send FSYNC or FSYNCDIR request
*/
int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
int isdir);
int fuse_fsync_common(struct file *file, int datasync, int isdir);
/**
* Notify poll wakeup

View File

@ -700,8 +700,14 @@ out:
return 0;
page_cache_release(page);
/*
* XXX(hch): the call below should probably be replaced with
* a call to the gfs2-specific truncate blocks helper to actually
* release disk blocks..
*/
if (pos + len > ip->i_inode.i_size)
vmtruncate(&ip->i_inode, ip->i_inode.i_size);
simple_setsize(&ip->i_inode, ip->i_inode.i_size);
out_endtrans:
gfs2_trans_end(sdp);
out_trans_fail:

View File

@ -554,9 +554,9 @@ static int gfs2_close(struct inode *inode, struct file *file)
* Returns: errno
*/
static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync)
static int gfs2_fsync(struct file *file, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = file->f_mapping->host;
int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC);
int ret = 0;

View File

@ -1071,6 +1071,9 @@ int gfs2_permission(struct inode *inode, int mask)
return error;
}
/*
* XXX: should be changed to have proper ordering by opencoding simple_setsize
*/
static int setattr_size(struct inode *inode, struct iattr *attr)
{
struct gfs2_inode *ip = GFS2_I(inode);
@ -1081,7 +1084,7 @@ static int setattr_size(struct inode *inode, struct iattr *attr)
error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
if (error)
return error;
error = vmtruncate(inode, attr->ia_size);
error = simple_setsize(inode, attr->ia_size);
gfs2_trans_end(sdp);
if (error)
return error;

View File

@ -411,9 +411,9 @@ int hostfs_file_open(struct inode *ino, struct file *file)
return 0;
}
int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
int hostfs_fsync(struct file *file, int datasync)
{
return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync);
return fsync_file(HOSTFS_I(file->f_mapping->host)->fd, datasync);
}
static const struct file_operations hostfs_file_fops = {

View File

@ -19,9 +19,9 @@ static int hpfs_file_release(struct inode *inode, struct file *file)
return 0;
}
int hpfs_file_fsync(struct file *file, struct dentry *dentry, int datasync)
int hpfs_file_fsync(struct file *file, int datasync)
{
/*return file_fsync(file, dentry);*/
/*return file_fsync(file, datasync);*/
return 0; /* Don't fsync :-) */
}

View File

@ -268,7 +268,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, const char *,
/* file.c */
int hpfs_file_fsync(struct file *, struct dentry *, int);
int hpfs_file_fsync(struct file *, int);
extern const struct file_operations hpfs_file_ops;
extern const struct inode_operations hpfs_file_iops;
extern const struct address_space_operations hpfs_aops;

View File

@ -587,7 +587,7 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
return err;
}
static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync)
static int hppfs_fsync(struct file *file, int datasync)
{
return 0;
}

View File

@ -688,7 +688,7 @@ static void init_once(void *foo)
const struct file_operations hugetlbfs_file_operations = {
.read = hugetlbfs_read,
.mmap = hugetlbfs_file_mmap,
.fsync = simple_sync_file,
.fsync = noop_fsync,
.get_unmapped_area = hugetlb_get_unmapped_area,
};

View File

@ -26,9 +26,9 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
struct page **pagep, void **fsdata);
static int jffs2_readpage (struct file *filp, struct page *pg);
int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync)
int jffs2_fsync(struct file *filp, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = filp->f_mapping->host;
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
/* Trigger GC to flush any pending writes for this inode */

View File

@ -169,13 +169,13 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);
/* We have to do the vmtruncate() without f->sem held, since
/* We have to do the simple_setsize() without f->sem held, since
some pages may be locked and waiting for it in readpage().
We are protected from a simultaneous write() extending i_size
back past iattr->ia_size, because do_truncate() holds the
generic inode semaphore. */
if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
vmtruncate(inode, iattr->ia_size);
simple_setsize(inode, iattr->ia_size);
inode->i_blocks = (inode->i_size + 511) >> 9;
}

View File

@ -158,7 +158,7 @@ extern const struct inode_operations jffs2_dir_inode_operations;
extern const struct file_operations jffs2_file_operations;
extern const struct inode_operations jffs2_file_inode_operations;
extern const struct address_space_operations jffs2_file_address_operations;
int jffs2_fsync(struct file *, struct dentry *, int);
int jffs2_fsync(struct file *, int);
int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
/* ioctl.c */

View File

@ -27,9 +27,9 @@
#include "jfs_acl.h"
#include "jfs_debug.h"
int jfs_fsync(struct file *file, struct dentry *dentry, int datasync)
int jfs_fsync(struct file *file, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = file->f_mapping->host;
int rc = 0;
if (!(inode->i_state & I_DIRTY) ||

View File

@ -21,7 +21,7 @@
struct fid;
extern struct inode *ialloc(struct inode *, umode_t);
extern int jfs_fsync(struct file *, struct dentry *, int);
extern int jfs_fsync(struct file *, int);
extern long jfs_ioctl(struct file *, unsigned int, unsigned long);
extern long jfs_compat_ioctl(struct file *, unsigned int, unsigned long);
extern struct inode *jfs_iget(struct super_block *, unsigned long);

View File

@ -8,6 +8,7 @@
#include <linux/slab.h>
#include <linux/mount.h>
#include <linux/vfs.h>
#include <linux/quotaops.h>
#include <linux/mutex.h>
#include <linux/exportfs.h>
#include <linux/writeback.h>
@ -58,11 +59,6 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct na
return NULL;
}
int simple_sync_file(struct file * file, struct dentry *dentry, int datasync)
{
return 0;
}
int dcache_dir_open(struct inode *inode, struct file *file)
{
static struct qstr cursor_name = {.len = 1, .name = "."};
@ -190,7 +186,7 @@ const struct file_operations simple_dir_operations = {
.llseek = dcache_dir_lseek,
.read = generic_read_dir,
.readdir = dcache_readdir,
.fsync = simple_sync_file,
.fsync = noop_fsync,
};
const struct inode_operations simple_dir_inode_operations = {
@ -330,6 +326,81 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
return 0;
}
/**
* simple_setsize - handle core mm and vfs requirements for file size change
* @inode: inode
* @newsize: new file size
*
* Returns 0 on success, -error on failure.
*
* simple_setsize must be called with inode_mutex held.
*
* simple_setsize will check that the requested new size is OK (see
* inode_newsize_ok), and then will perform the necessary i_size update
* and pagecache truncation (if necessary). It will be typically be called
* from the filesystem's setattr function when ATTR_SIZE is passed in.
*
* The inode itself must have correct permissions and attributes to allow
* i_size to be changed, this function then just checks that the new size
* requested is valid.
*
* In the case of simple in-memory filesystems with inodes stored solely
* in the inode cache, and file data in the pagecache, nothing more needs
* to be done to satisfy a truncate request. Filesystems with on-disk
* blocks for example will need to free them in the case of truncate, in
* that case it may be easier not to use simple_setsize (but each of its
* components will likely be required at some point to update pagecache
* and inode etc).
*/
int simple_setsize(struct inode *inode, loff_t newsize)
{
loff_t oldsize;
int error;
error = inode_newsize_ok(inode, newsize);
if (error)
return error;
oldsize = inode->i_size;
i_size_write(inode, newsize);
truncate_pagecache(inode, oldsize, newsize);
return error;
}
EXPORT_SYMBOL(simple_setsize);
/**
* simple_setattr - setattr for simple in-memory filesystem
* @dentry: dentry
* @iattr: iattr structure
*
* Returns 0 on success, -error on failure.
*
* simple_setattr implements setattr for an in-memory filesystem which
* does not store its own file data or metadata (eg. uses the page cache
* and inode cache as its data store).
*/
int simple_setattr(struct dentry *dentry, struct iattr *iattr)
{
struct inode *inode = dentry->d_inode;
int error;
error = inode_change_ok(inode, iattr);
if (error)
return error;
if (iattr->ia_valid & ATTR_SIZE) {
error = simple_setsize(inode, iattr->ia_size);
if (error)
return error;
}
generic_setattr(inode, iattr);
return error;
}
EXPORT_SYMBOL(simple_setattr);
int simple_readpage(struct file *file, struct page *page)
{
clear_highpage(page);
@ -851,13 +922,22 @@ struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
}
EXPORT_SYMBOL_GPL(generic_fh_to_parent);
int simple_fsync(struct file *file, struct dentry *dentry, int datasync)
/**
* generic_file_fsync - generic fsync implementation for simple filesystems
* @file: file to synchronize
* @datasync: only synchronize essential metadata if true
*
* This is a generic implementation of the fsync method for simple
* filesystems which track all non-inode metadata in the buffers list
* hanging off the address_space structure.
*/
int generic_file_fsync(struct file *file, int datasync)
{
struct writeback_control wbc = {
.sync_mode = WB_SYNC_ALL,
.nr_to_write = 0, /* metadata-only; caller takes care of data */
};
struct inode *inode = dentry->d_inode;
struct inode *inode = file->f_mapping->host;
int err;
int ret;
@ -872,7 +952,15 @@ int simple_fsync(struct file *file, struct dentry *dentry, int datasync)
ret = err;
return ret;
}
EXPORT_SYMBOL(simple_fsync);
EXPORT_SYMBOL(generic_file_fsync);
/*
* No-op implementation of ->fsync for in-memory filesystems.
*/
int noop_fsync(struct file *file, int datasync)
{
return 0;
}
EXPORT_SYMBOL(dcache_dir_close);
EXPORT_SYMBOL(dcache_dir_lseek);
@ -895,7 +983,7 @@ EXPORT_SYMBOL(simple_release_fs);
EXPORT_SYMBOL(simple_rename);
EXPORT_SYMBOL(simple_rmdir);
EXPORT_SYMBOL(simple_statfs);
EXPORT_SYMBOL(simple_sync_file);
EXPORT_SYMBOL(noop_fsync);
EXPORT_SYMBOL(simple_unlink);
EXPORT_SYMBOL(simple_read_from_buffer);
EXPORT_SYMBOL(simple_write_to_buffer);

View File

@ -219,9 +219,9 @@ int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
}
}
int logfs_fsync(struct file *file, struct dentry *dentry, int datasync)
int logfs_fsync(struct file *file, int datasync)
{
struct super_block *sb = dentry->d_inode->i_sb;
struct super_block *sb = file->f_mapping->host->i_sb;
logfs_write_anchor(sb);
return 0;

View File

@ -506,7 +506,7 @@ extern const struct address_space_operations logfs_reg_aops;
int logfs_readpage(struct file *file, struct page *page);
int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg);
int logfs_fsync(struct file *file, struct dentry *dentry, int datasync);
int logfs_fsync(struct file *file, int datasync);
/* gc.c */
u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec);

View File

@ -22,7 +22,7 @@ const struct file_operations minix_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = minix_readdir,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
};
static inline void dir_put_page(struct page *page)
@ -72,11 +72,8 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
{
struct address_space *mapping = dir->i_mapping;
struct page *page = read_mapping_page(mapping, n, NULL);
if (!IS_ERR(page)) {
if (!IS_ERR(page))
kmap(page);
if (!PageUptodate(page))
goto fail;
}
return page;
fail:

View File

@ -19,7 +19,7 @@ const struct file_operations minix_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
};

View File

@ -20,6 +20,9 @@ static inline block_t *i_data(struct inode *inode)
return (block_t *)minix_i(inode)->u.i2_data;
}
#define DIRCOUNT 7
#define INDIRCOUNT(sb) (1 << ((sb)->s_blocksize_bits - 2))
static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
{
int n = 0;
@ -34,21 +37,21 @@ static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
printk("MINIX-fs: block_to_path: "
"block %ld too big on dev %s\n",
block, bdevname(sb->s_bdev, b));
} else if (block < 7) {
} else if (block < DIRCOUNT) {
offsets[n++] = block;
} else if ((block -= 7) < 256) {
offsets[n++] = 7;
} else if ((block -= DIRCOUNT) < INDIRCOUNT(sb)) {
offsets[n++] = DIRCOUNT;
offsets[n++] = block;
} else if ((block -= 256) < 256*256) {
offsets[n++] = 8;
offsets[n++] = block>>8;
offsets[n++] = block & 255;
} else if ((block -= INDIRCOUNT(sb)) < INDIRCOUNT(sb) * INDIRCOUNT(sb)) {
offsets[n++] = DIRCOUNT + 1;
offsets[n++] = block / INDIRCOUNT(sb);
offsets[n++] = block % INDIRCOUNT(sb);
} else {
block -= 256*256;
offsets[n++] = 9;
offsets[n++] = block>>16;
offsets[n++] = (block>>8) & 255;
offsets[n++] = block & 255;
block -= INDIRCOUNT(sb) * INDIRCOUNT(sb);
offsets[n++] = DIRCOUNT + 2;
offsets[n++] = (block / INDIRCOUNT(sb)) / INDIRCOUNT(sb);
offsets[n++] = (block / INDIRCOUNT(sb)) % INDIRCOUNT(sb);
offsets[n++] = block % INDIRCOUNT(sb);
}
return n;
}

View File

@ -1621,6 +1621,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
case LAST_DOTDOT:
follow_dotdot(nd);
dir = nd->path.dentry;
case LAST_DOT:
if (nd->path.mnt->mnt_sb->s_type->fs_flags & FS_REVAL_DOT) {
if (!dir->d_op->d_revalidate(dir, nd)) {
error = -ESTALE;
@ -1628,7 +1629,6 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
}
}
/* fallthrough */
case LAST_DOT:
case LAST_ROOT:
if (open_flag & O_CREAT)
goto exit;

View File

@ -22,7 +22,7 @@
#include <linux/ncp_fs.h>
#include "ncplib_kernel.h"
static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync)
static int ncp_fsync(struct file *file, int datasync)
{
return 0;
}

View File

@ -53,7 +53,7 @@ static int nfs_link(struct dentry *, struct inode *, struct dentry *);
static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
static int nfs_rename(struct inode *, struct dentry *,
struct inode *, struct dentry *);
static int nfs_fsync_dir(struct file *, struct dentry *, int);
static int nfs_fsync_dir(struct file *, int);
static loff_t nfs_llseek_dir(struct file *, loff_t, int);
const struct file_operations nfs_dir_operations = {
@ -641,8 +641,10 @@ out:
* All directory operations under NFS are synchronous, so fsync()
* is a dummy operation.
*/
static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync)
static int nfs_fsync_dir(struct file *filp, int datasync)
{
struct dentry *dentry = filp->f_path.dentry;
dfprintk(FILE, "NFS: fsync dir(%s/%s) datasync %d\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
datasync);

View File

@ -53,7 +53,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
unsigned long nr_segs, loff_t pos);
static int nfs_file_flush(struct file *, fl_owner_t id);
static int nfs_file_fsync(struct file *, struct dentry *dentry, int datasync);
static int nfs_file_fsync(struct file *, int datasync);
static int nfs_check_flags(int flags);
static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
@ -322,8 +322,9 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
* whether any write errors occurred for this process.
*/
static int
nfs_file_fsync(struct file *file, struct dentry *dentry, int datasync)
nfs_file_fsync(struct file *file, int datasync)
{
struct dentry *dentry = file->f_path.dentry;
struct nfs_open_context *ctx = nfs_file_open_context(file);
struct inode *inode = dentry->d_inode;

View File

@ -27,7 +27,7 @@
#include "nilfs.h"
#include "segment.h"
int nilfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
int nilfs_sync_file(struct file *file, int datasync)
{
/*
* Called from fsync() system call
@ -37,7 +37,7 @@ int nilfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
* This function should be implemented when the writeback function
* will be implemented.
*/
struct inode *inode = dentry->d_inode;
struct inode *inode = file->f_mapping->host;
int err;
if (!nilfs_inode_dirty(inode))

View File

@ -228,7 +228,7 @@ extern void nilfs_set_link(struct inode *, struct nilfs_dir_entry *,
struct page *, struct inode *);
/* file.c */
extern int nilfs_sync_file(struct file *, struct dentry *, int);
extern int nilfs_sync_file(struct file *, int);
/* ioctl.c */
long nilfs_ioctl(struct file *, unsigned int, unsigned long);

View File

@ -1527,10 +1527,9 @@ static int ntfs_dir_open(struct inode *vi, struct file *filp)
* this problem for now. We do write the $BITMAP attribute if it is present
* which is the important one for a directory so things are not too bad.
*/
static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry,
int datasync)
static int ntfs_dir_fsync(struct file *filp, int datasync)
{
struct inode *bmp_vi, *vi = dentry->d_inode;
struct inode *bmp_vi, *vi = filp->f_mapping->host;
int err, ret;
ntfs_attr na;

View File

@ -2133,7 +2133,6 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
/**
* ntfs_file_fsync - sync a file to disk
* @filp: file to be synced
* @dentry: dentry describing the file to sync
* @datasync: if non-zero only flush user data and not metadata
*
* Data integrity sync of a file to disk. Used for fsync, fdatasync, and msync
@ -2149,19 +2148,15 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
* Also, if @datasync is true, we do not wait on the inode to be written out
* but we always wait on the page cache pages to be written out.
*
* Note: In the past @filp could be NULL so we ignore it as we don't need it
* anyway.
*
* Locking: Caller must hold i_mutex on the inode.
*
* TODO: We should probably also write all attribute/index inodes associated
* with this inode but since we have no simple way of getting to them we ignore
* this problem for now.
*/
static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
int datasync)
static int ntfs_file_fsync(struct file *filp, int datasync)
{
struct inode *vi = dentry->d_inode;
struct inode *vi = filp->f_mapping->host;
int err, ret = 0;
ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);

View File

@ -175,13 +175,12 @@ static int ocfs2_dir_release(struct inode *inode, struct file *file)
return 0;
}
static int ocfs2_sync_file(struct file *file,
struct dentry *dentry,
int datasync)
static int ocfs2_sync_file(struct file *file, int datasync)
{
int err = 0;
journal_t *journal;
struct inode *inode = dentry->d_inode;
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = file->f_mapping->host;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", file, dentry, datasync,
@ -1053,7 +1052,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
}
/*
* This will intentionally not wind up calling vmtruncate(),
* This will intentionally not wind up calling simple_setsize(),
* since all the work for a size change has been done above.
* Otherwise, we could get into problems with truncate as
* ip_alloc_sem is used there to protect against i_size
@ -2119,9 +2118,13 @@ relock:
* direct write may have instantiated a few
* blocks outside i_size. Trim these off again.
* Don't need i_size_read because we hold i_mutex.
*
* XXX(hch): this looks buggy because ocfs2 did not
* actually implement ->truncate. Take a look at
* the new truncate sequence and update this accordingly
*/
if (*ppos + count > inode->i_size)
vmtruncate(inode, inode->i_size);
simple_setsize(inode, inode->i_size);
ret = written;
goto out_dio;
}

View File

@ -329,7 +329,7 @@ const struct file_operations omfs_file_operations = {
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
};

View File

@ -1169,14 +1169,18 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
switch (cmd) {
case F_SETPIPE_SZ:
if (!capable(CAP_SYS_ADMIN) && arg > pipe_max_pages)
return -EINVAL;
if (!capable(CAP_SYS_ADMIN) && arg > pipe_max_pages) {
ret = -EINVAL;
goto out;
}
/*
* The pipe needs to be at least 2 pages large to
* guarantee POSIX behaviour.
*/
if (arg < 2)
return -EINVAL;
if (arg < 2) {
ret = -EINVAL;
goto out;
}
ret = pipe_set_size(pipe, arg);
break;
case F_GETPIPE_SZ:
@ -1187,6 +1191,7 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
out:
mutex_unlock(&pipe->inode->i_mutex);
return ret;
}

View File

@ -80,7 +80,7 @@ const struct file_operations qnx4_dir_operations =
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = qnx4_readdir,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
};
const struct inode_operations qnx4_dir_inode_operations =

View File

@ -43,12 +43,13 @@ const struct file_operations ramfs_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = simple_sync_file,
.fsync = noop_fsync,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
.llseek = generic_file_llseek,
};
const struct inode_operations ramfs_file_inode_operations = {
.setattr = simple_setattr,
.getattr = simple_getattr,
};

View File

@ -42,7 +42,7 @@ const struct file_operations ramfs_file_operations = {
.aio_read = generic_file_aio_read,
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.fsync = simple_sync_file,
.fsync = noop_fsync,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
.llseek = generic_file_llseek,
@ -146,7 +146,7 @@ static int ramfs_nommu_resize(struct inode *inode, loff_t newsize, loff_t size)
return ret;
}
ret = vmtruncate(inode, newsize);
ret = simple_setsize(inode, newsize);
return ret;
}
@ -169,7 +169,8 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
/* pick out size-changing events */
if (ia->ia_valid & ATTR_SIZE) {
loff_t size = i_size_read(inode);
loff_t size = inode->i_size;
if (ia->ia_size != size) {
ret = ramfs_nommu_resize(inode, ia->ia_size, size);
if (ret < 0 || ia->ia_valid == ATTR_SIZE)
@ -182,7 +183,7 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
}
}
ret = inode_setattr(inode, ia);
generic_setattr(inode, ia);
out:
ia->ia_valid = old_ia_valid;
return ret;

View File

@ -14,8 +14,7 @@
extern const struct reiserfs_key MIN_KEY;
static int reiserfs_readdir(struct file *, void *, filldir_t);
static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
int datasync);
static int reiserfs_dir_fsync(struct file *filp, int datasync);
const struct file_operations reiserfs_dir_operations = {
.llseek = generic_file_llseek,
@ -28,10 +27,9 @@ const struct file_operations reiserfs_dir_operations = {
#endif
};
static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
int datasync)
static int reiserfs_dir_fsync(struct file *filp, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = filp->f_mapping->host;
int err;
reiserfs_write_lock(inode->i_sb);
err = reiserfs_commit_for_inode(inode);

View File

@ -134,10 +134,9 @@ static void reiserfs_vfs_truncate_file(struct inode *inode)
* be removed...
*/
static int reiserfs_sync_file(struct file *filp,
struct dentry *dentry, int datasync)
static int reiserfs_sync_file(struct file *filp, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = filp->f_mapping->host;
int err;
int barrier_done;

View File

@ -28,8 +28,9 @@
#include "proto.h"
static int
smb_fsync(struct file *file, struct dentry * dentry, int datasync)
smb_fsync(struct file *file, int datasync)
{
struct dentry *dentry = file->f_path.dentry;
struct smb_sb_info *server = server_from_dentry(dentry);
int result;

View File

@ -714,7 +714,7 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
error = server->ops->truncate(inode, attr->ia_size);
if (error)
goto out;
error = vmtruncate(inode, attr->ia_size);
error = simple_setsize(inode, attr->ia_size);
if (error)
goto out;
refresh = 1;

View File

@ -946,8 +946,8 @@ out:
EXPORT_SYMBOL_GPL(vfs_kern_mount);
/**
* freeze_super -- lock the filesystem and force it into a consistent state
* @super: the super to lock
* freeze_super - lock the filesystem and force it into a consistent state
* @sb: the super to lock
*
* Syncs the super to make sure the filesystem is consistent and calls the fs's
* freeze_fs. Subsequent calls to this without first thawing the fs will return

View File

@ -130,12 +130,10 @@ void emergency_sync(void)
/*
* Generic function to fsync a file.
*
* filp may be NULL if called via the msync of a vma.
*/
int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
int file_fsync(struct file *filp, int datasync)
{
struct inode * inode = dentry->d_inode;
struct inode *inode = filp->f_mapping->host;
struct super_block * sb;
int ret, err;
@ -183,7 +181,7 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
* livelocks in fsync_buffers_list().
*/
mutex_lock(&mapping->host->i_mutex);
err = file->f_op->fsync(file, file->f_path.dentry, datasync);
err = file->f_op->fsync(file, datasync);
if (!ret)
ret = err;
mutex_unlock(&mapping->host->i_mutex);

View File

@ -117,13 +117,11 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
if (error)
goto out;
iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
error = inode_setattr(inode, iattr);
if (error)
goto out;
/* this ignores size changes */
generic_setattr(inode, iattr);
error = sysfs_sd_setattr(sd, iattr);
out:
mutex_unlock(&sysfs_mutex);
return error;

View File

@ -24,7 +24,7 @@ const struct file_operations sysv_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = sysv_readdir,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
};
static inline void dir_put_page(struct page *page)

View File

@ -26,7 +26,7 @@ const struct file_operations sysv_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
};

View File

@ -43,6 +43,7 @@ static int sysv_sync_fs(struct super_block *sb, int wait)
* then attach current time stamp.
* But if the filesystem was marked clean, keep it clean.
*/
sb->s_dirt = 0;
old_time = fs32_to_cpu(sbi, *sbi->s_sb_time);
if (sbi->s_type == FSTYPE_SYSV4) {
if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time))

View File

@ -967,12 +967,15 @@ static int do_writepage(struct page *page, int len)
* the page locked, and it locks @ui_mutex. However, write-back does take inode
* @i_mutex, which means other VFS operations may be run on this inode at the
* same time. And the problematic one is truncation to smaller size, from where
* we have to call 'vmtruncate()', which first changes @inode->i_size, then
* we have to call 'simple_setsize()', which first changes @inode->i_size, then
* drops the truncated pages. And while dropping the pages, it takes the page
* lock. This means that 'do_truncation()' cannot call 'vmtruncate()' with
* lock. This means that 'do_truncation()' cannot call 'simple_setsize()' with
* @ui_mutex locked, because it would deadlock with 'ubifs_writepage()'. This
* means that @inode->i_size is changed while @ui_mutex is unlocked.
*
* XXX: with the new truncate the above is not true anymore, the simple_setsize
* calls can be replaced with the individual components.
*
* But in 'ubifs_writepage()' we have to guarantee that we do not write beyond
* inode size. How do we do this if @inode->i_size may became smaller while we
* are in the middle of 'ubifs_writepage()'? The UBIFS solution is the
@ -1125,7 +1128,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
budgeted = 0;
}
err = vmtruncate(inode, new_size);
err = simple_setsize(inode, new_size);
if (err)
goto out_budg;
@ -1214,7 +1217,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,
if (attr->ia_valid & ATTR_SIZE) {
dbg_gen("size %lld -> %lld", inode->i_size, new_size);
err = vmtruncate(inode, new_size);
err = simple_setsize(inode, new_size);
if (err)
goto out;
}
@ -1223,7 +1226,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,
if (attr->ia_valid & ATTR_SIZE) {
/* Truncation changes inode [mc]time */
inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
/* 'vmtruncate()' changed @i_size, update @ui_size */
/* 'simple_setsize()' changed @i_size, update @ui_size */
ui->ui_size = inode->i_size;
}
@ -1304,9 +1307,9 @@ static void *ubifs_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync)
int ubifs_fsync(struct file *file, int datasync)
{
struct inode *inode = dentry->d_inode;
struct inode *inode = file->f_mapping->host;
struct ubifs_info *c = inode->i_sb->s_fs_info;
int err;

View File

@ -379,7 +379,7 @@ struct ubifs_gced_idx_leb {
* The @ui_size is a "shadow" variable for @inode->i_size and UBIFS uses
* @ui_size instead of @inode->i_size. The reason for this is that UBIFS cannot
* make sure @inode->i_size is always changed under @ui_mutex, because it
* cannot call 'vmtruncate()' with @ui_mutex locked, because it would deadlock
* cannot call 'simple_setsize()' with @ui_mutex locked, because it would deadlock
* with 'ubifs_writepage()' (see file.c). All the other inode fields are
* changed under @ui_mutex, so they do not need "shadow" fields. Note, one
* could consider to rework locking and base it on "shadow" fields.
@ -1678,7 +1678,7 @@ const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c);
int ubifs_calc_dark(const struct ubifs_info *c, int spc);
/* file.c */
int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync);
int ubifs_fsync(struct file *file, int datasync);
int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
/* dir.c */

View File

@ -211,5 +211,5 @@ const struct file_operations udf_dir_operations = {
.read = generic_read_dir,
.readdir = udf_readdir,
.unlocked_ioctl = udf_ioctl,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
};

View File

@ -224,7 +224,7 @@ const struct file_operations udf_file_operations = {
.write = do_sync_write,
.aio_write = udf_file_aio_write,
.release = udf_release_file,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
.llseek = generic_file_llseek,
};

View File

@ -666,6 +666,6 @@ not_empty:
const struct file_operations ufs_dir_operations = {
.read = generic_read_dir,
.readdir = ufs_readdir,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
.llseek = generic_file_llseek,
};

View File

@ -42,6 +42,6 @@ const struct file_operations ufs_file_operations = {
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.open = dquot_file_open,
.fsync = simple_fsync,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
};

Some files were not shown because too many files have changed in this diff Show More