diff options
Diffstat (limited to 'fs/hfs/inode.c')
| -rw-r--r-- | fs/hfs/inode.c | 103 | 
1 files changed, 61 insertions, 42 deletions
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index dffb4e99664..d0929bc8178 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -14,6 +14,7 @@  #include <linux/pagemap.h>  #include <linux/mpage.h>  #include <linux/sched.h> +#include <linux/aio.h>  #include "hfs_fs.h"  #include "btree.h" @@ -35,6 +36,16 @@ static int hfs_readpage(struct file *file, struct page *page)  	return block_read_full_page(page, hfs_get_block);  } +static void hfs_write_failed(struct address_space *mapping, loff_t to) +{ +	struct inode *inode = mapping->host; + +	if (to > inode->i_size) { +		truncate_pagecache(inode, inode->i_size); +		hfs_file_truncate(inode); +	} +} +  static int hfs_write_begin(struct file *file, struct address_space *mapping,  			loff_t pos, unsigned len, unsigned flags,  			struct page **pagep, void **fsdata) @@ -45,11 +56,8 @@ static int hfs_write_begin(struct file *file, struct address_space *mapping,  	ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,  				hfs_get_block,  				&HFS_I(mapping->host)->phys_size); -	if (unlikely(ret)) { -		loff_t isize = mapping->host->i_size; -		if (pos + len > isize) -			vmtruncate(mapping->host, isize); -	} +	if (unlikely(ret)) +		hfs_write_failed(mapping, pos + len);  	return ret;  } @@ -117,14 +125,15 @@ static int hfs_releasepage(struct page *page, gfp_t mask)  }  static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb, -		const struct iovec *iov, loff_t offset, unsigned long nr_segs) +		struct iov_iter *iter, loff_t offset)  {  	struct file *file = iocb->ki_filp; -	struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; +	struct address_space *mapping = file->f_mapping; +	struct inode *inode = file_inode(file)->i_mapping->host; +	size_t count = iov_iter_count(iter);  	ssize_t ret; -	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, -				  offset, nr_segs, hfs_get_block, NULL); +	ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, hfs_get_block);  	/*  	 * In case of error extending write may have instantiated a few @@ -132,10 +141,10 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,  	 */  	if (unlikely((rw & WRITE) && ret < 0)) {  		loff_t isize = i_size_read(inode); -		loff_t end = offset + iov_length(iov, nr_segs); +		loff_t end = offset + count;  		if (end > isize) -			vmtruncate(inode, isize); +			hfs_write_failed(mapping, end);  	}  	return ret; @@ -150,7 +159,6 @@ static int hfs_writepages(struct address_space *mapping,  const struct address_space_operations hfs_btree_aops = {  	.readpage	= hfs_readpage,  	.writepage	= hfs_writepage, -	.sync_page	= block_sync_page,  	.write_begin	= hfs_write_begin,  	.write_end	= generic_write_end,  	.bmap		= hfs_bmap, @@ -160,7 +168,6 @@ const struct address_space_operations hfs_btree_aops = {  const struct address_space_operations hfs_aops = {  	.readpage	= hfs_readpage,  	.writepage	= hfs_writepage, -	.sync_page	= block_sync_page,  	.write_begin	= hfs_write_begin,  	.write_end	= generic_write_end,  	.bmap		= hfs_bmap, @@ -171,7 +178,7 @@ const struct address_space_operations hfs_aops = {  /*   * hfs_new_inode   */ -struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode) +struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode)  {  	struct super_block *sb = dir->i_sb;  	struct inode *inode = new_inode(sb); @@ -185,7 +192,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)  	inode->i_mode = mode;  	inode->i_uid = current_fsuid();  	inode->i_gid = current_fsgid(); -	inode->i_nlink = 1; +	set_nlink(inode, 1);  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;  	HFS_I(inode)->flags = 0;  	HFS_I(inode)->rsrc_inode = NULL; @@ -222,7 +229,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)  	insert_inode_hash(inode);  	mark_inode_dirty(inode);  	set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); -	sb->s_dirt = 1; +	hfs_mark_mdb_dirty(sb);  	return inode;  } @@ -231,13 +238,13 @@ void hfs_delete_inode(struct inode *inode)  {  	struct super_block *sb = inode->i_sb; -	dprint(DBG_INODE, "delete_inode: %lu\n", inode->i_ino); +	hfs_dbg(INODE, "delete_inode: %lu\n", inode->i_ino);  	if (S_ISDIR(inode->i_mode)) {  		HFS_SB(sb)->folder_count--;  		if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))  			HFS_SB(sb)->root_dirs--;  		set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); -		sb->s_dirt = 1; +		hfs_mark_mdb_dirty(sb);  		return;  	}  	HFS_SB(sb)->file_count--; @@ -250,7 +257,7 @@ void hfs_delete_inode(struct inode *inode)  		}  	}  	set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); -	sb->s_dirt = 1; +	hfs_mark_mdb_dirty(sb);  }  void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext, @@ -315,7 +322,7 @@ static int hfs_read_inode(struct inode *inode, void *data)  	/* Initialize the inode */  	inode->i_uid = hsb->s_uid;  	inode->i_gid = hsb->s_gid; -	inode->i_nlink = 1; +	set_nlink(inode, 1);  	if (idata->key)  		HFS_I(inode)->cat_key = *idata->key; @@ -410,9 +417,12 @@ int hfs_write_inode(struct inode *inode, struct writeback_control *wbc)  	struct inode *main_inode = inode;  	struct hfs_find_data fd;  	hfs_cat_rec rec; +	int res; -	dprint(DBG_INODE, "hfs_write_inode: %lu\n", inode->i_ino); -	hfs_ext_write_extent(inode); +	hfs_dbg(INODE, "hfs_write_inode: %lu\n", inode->i_ino); +	res = hfs_ext_write_extent(inode); +	if (res) +		return res;  	if (inode->i_ino < HFS_FIRSTUSER_CNID) {  		switch (inode->i_ino) { @@ -491,7 +501,7 @@ out:  }  static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry, -				      struct nameidata *nd) +				      unsigned int flags)  {  	struct inode *inode = NULL;  	hfs_cat_rec rec; @@ -509,7 +519,11 @@ static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,  	if (!inode)  		return ERR_PTR(-ENOMEM); -	hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd); +	res = hfs_find_init(HFS_SB(dir->i_sb)->cat_tree, &fd); +	if (res) { +		iput(inode); +		return ERR_PTR(res); +	}  	fd.search_key->cat = HFS_I(dir)->cat_key;  	res = hfs_brec_read(&fd, &rec, sizeof(rec));  	if (!res) { @@ -533,8 +547,8 @@ out:  void hfs_evict_inode(struct inode *inode)  { -	truncate_inode_pages(&inode->i_data, 0); -	end_writeback(inode); +	truncate_inode_pages_final(&inode->i_data); +	clear_inode(inode);  	if (HFS_IS_RSRC(inode) && HFS_I(inode)->rsrc_inode) {  		HFS_I(HFS_I(inode)->rsrc_inode)->rsrc_inode = NULL;  		iput(HFS_I(inode)->rsrc_inode); @@ -596,9 +610,9 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)  	/* no uig/gid changes and limit which mode bits can be set */  	if (((attr->ia_valid & ATTR_UID) && -	     (attr->ia_uid != hsb->s_uid)) || +	     (!uid_eq(attr->ia_uid, hsb->s_uid))) ||  	    ((attr->ia_valid & ATTR_GID) && -	     (attr->ia_gid != hsb->s_gid)) || +	     (!gid_eq(attr->ia_gid, hsb->s_gid))) ||  	    ((attr->ia_valid & ATTR_MODE) &&  	     ((S_ISDIR(inode->i_mode) &&  	       (attr->ia_mode != inode->i_mode)) || @@ -617,9 +631,14 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)  	if ((attr->ia_valid & ATTR_SIZE) &&  	    attr->ia_size != i_size_read(inode)) { -		error = vmtruncate(inode, attr->ia_size); +		inode_dio_wait(inode); + +		error = inode_newsize_ok(inode, attr->ia_size);  		if (error)  			return error; + +		truncate_setsize(inode, attr->ia_size); +		hfs_file_truncate(inode);  	}  	setattr_copy(inode, attr); @@ -627,37 +646,38 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)  	return 0;  } -static int hfs_file_fsync(struct file *filp, int datasync) +static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end, +			  int datasync)  {  	struct inode *inode = filp->f_mapping->host;  	struct super_block * sb;  	int ret, err; +	ret = filemap_write_and_wait_range(inode->i_mapping, start, end); +	if (ret) +		return ret; +	mutex_lock(&inode->i_mutex); +  	/* sync the inode to buffers */  	ret = write_inode_now(inode, 0);  	/* sync the superblock to buffers */  	sb = inode->i_sb; -	if (sb->s_dirt) { -		lock_super(sb); -		sb->s_dirt = 0; -		if (!(sb->s_flags & MS_RDONLY)) -			hfs_mdb_commit(sb); -		unlock_super(sb); -	} +	flush_delayed_work(&HFS_SB(sb)->mdb_work);  	/* .. finally sync the buffers to disk */  	err = sync_blockdev(sb->s_bdev);  	if (!ret)  		ret = err; +	mutex_unlock(&inode->i_mutex);  	return ret;  }  static const struct file_operations hfs_file_operations = {  	.llseek		= generic_file_llseek, -	.read		= do_sync_read, -	.aio_read	= generic_file_aio_read, -	.write		= do_sync_write, -	.aio_write	= generic_file_aio_write, +	.read		= new_sync_read, +	.read_iter	= generic_file_read_iter, +	.write		= new_sync_write, +	.write_iter	= generic_file_write_iter,  	.mmap		= generic_file_mmap,  	.splice_read	= generic_file_splice_read,  	.fsync		= hfs_file_fsync, @@ -667,7 +687,6 @@ static const struct file_operations hfs_file_operations = {  static const struct inode_operations hfs_file_inode_operations = {  	.lookup		= hfs_file_lookup, -	.truncate	= hfs_file_truncate,  	.setattr	= hfs_inode_setattr,  	.setxattr	= hfs_setxattr,  	.getxattr	= hfs_getxattr,  | 
