diff options
Diffstat (limited to 'fs/ntfs3/file.c')
| -rw-r--r-- | fs/ntfs3/file.c | 76 | 
1 files changed, 59 insertions, 17 deletions
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index a5a30a24ce5d..5418662c80d8 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -48,7 +48,7 @@ static int ntfs_ioctl_fitrim(struct ntfs_sb_info *sbi, unsigned long arg)  	return 0;  } -static long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg) +long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg)  {  	struct inode *inode = file_inode(filp);  	struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info; @@ -61,7 +61,7 @@ static long ntfs_ioctl(struct file *filp, u32 cmd, unsigned long arg)  }  #ifdef CONFIG_COMPAT -static long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg) +long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg)  {  	return ntfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); @@ -188,6 +188,7 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)  	u32 bh_next, bh_off, to;  	sector_t iblock;  	struct folio *folio; +	bool dirty = false;  	for (; idx < idx_end; idx += 1, from = 0) {  		page_off = (loff_t)idx << PAGE_SHIFT; @@ -223,29 +224,27 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)  			/* Ok, it's mapped. Make sure it's up-to-date. */  			if (folio_test_uptodate(folio))  				set_buffer_uptodate(bh); - -			if (!buffer_uptodate(bh)) { -				err = bh_read(bh, 0); -				if (err < 0) { -					folio_unlock(folio); -					folio_put(folio); -					goto out; -				} +			else if (bh_read(bh, 0) < 0) { +				err = -EIO; +				folio_unlock(folio); +				folio_put(folio); +				goto out;  			}  			mark_buffer_dirty(bh); -  		} while (bh_off = bh_next, iblock += 1,  			 head != (bh = bh->b_this_page));  		folio_zero_segment(folio, from, to); +		dirty = true;  		folio_unlock(folio);  		folio_put(folio);  		cond_resched();  	}  out: -	mark_inode_dirty(inode); +	if (dirty) +		mark_inode_dirty(inode);  	return err;  } @@ -261,6 +260,9 @@ static int ntfs_file_mmap(struct file *file, struct vm_area_struct *vma)  	bool rw = vma->vm_flags & VM_WRITE;  	int err; +	if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) +		return -EIO; +  	if (is_encrypted(ni)) {  		ntfs_inode_warn(inode, "mmap encrypted not supported");  		return -EOPNOTSUPP; @@ -499,10 +501,14 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)  		ni_lock(ni);  		err = attr_punch_hole(ni, vbo, len, &frame_size);  		ni_unlock(ni); +		if (!err) +			goto ok; +  		if (err != E_NTFS_NOTALIGNED)  			goto out;  		/* Process not aligned punch. */ +		err = 0;  		mask = frame_size - 1;  		vbo_a = (vbo + mask) & ~mask;  		end_a = end & ~mask; @@ -525,6 +531,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)  			ni_lock(ni);  			err = attr_punch_hole(ni, vbo_a, end_a - vbo_a, NULL);  			ni_unlock(ni); +			if (err) +				goto out;  		}  	} else if (mode & FALLOC_FL_COLLAPSE_RANGE) {  		/* @@ -564,6 +572,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)  		ni_lock(ni);  		err = attr_insert_range(ni, vbo, len);  		ni_unlock(ni); +		if (err) +			goto out;  	} else {  		/* Check new size. */  		u8 cluster_bits = sbi->cluster_bits; @@ -633,11 +643,18 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)  					    &ni->file.run, i_size, &ni->i_valid,  					    true, NULL);  			ni_unlock(ni); +			if (err) +				goto out;  		} else if (new_size > i_size) { -			inode->i_size = new_size; +			i_size_write(inode, new_size);  		}  	} +ok: +	err = file_modified(file); +	if (err) +		goto out; +  out:  	if (map_locked)  		filemap_invalidate_unlock(mapping); @@ -663,6 +680,9 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry,  	umode_t mode = inode->i_mode;  	int err; +	if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) +		return -EIO; +  	err = setattr_prepare(idmap, dentry, attr);  	if (err)  		goto out; @@ -676,7 +696,7 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry,  			goto out;  		}  		inode_dio_wait(inode); -		oldsize = inode->i_size; +		oldsize = i_size_read(inode);  		newsize = attr->ia_size;  		if (newsize <= oldsize) @@ -688,7 +708,7 @@ int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry,  			goto out;  		ni->ni_flags |= NI_FLAG_UPDATE_PARENT; -		inode->i_size = newsize; +		i_size_write(inode, newsize);  	}  	setattr_copy(idmap, inode, attr); @@ -718,6 +738,9 @@ static ssize_t ntfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)  	struct inode *inode = file->f_mapping->host;  	struct ntfs_inode *ni = ntfs_i(inode); +	if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) +		return -EIO; +  	if (is_encrypted(ni)) {  		ntfs_inode_warn(inode, "encrypted i/o not supported");  		return -EOPNOTSUPP; @@ -752,6 +775,9 @@ static ssize_t ntfs_file_splice_read(struct file *in, loff_t *ppos,  	struct inode *inode = in->f_mapping->host;  	struct ntfs_inode *ni = ntfs_i(inode); +	if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) +		return -EIO; +  	if (is_encrypted(ni)) {  		ntfs_inode_warn(inode, "encrypted i/o not supported");  		return -EOPNOTSUPP; @@ -821,7 +847,7 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)  	size_t count = iov_iter_count(from);  	loff_t pos = iocb->ki_pos;  	struct inode *inode = file_inode(file); -	loff_t i_size = inode->i_size; +	loff_t i_size = i_size_read(inode);  	struct address_space *mapping = inode->i_mapping;  	struct ntfs_inode *ni = ntfs_i(inode);  	u64 valid = ni->i_valid; @@ -1028,6 +1054,8 @@ out:  	iocb->ki_pos += written;  	if (iocb->ki_pos > ni->i_valid)  		ni->i_valid = iocb->ki_pos; +	if (iocb->ki_pos > i_size) +		i_size_write(inode, iocb->ki_pos);  	return written;  } @@ -1041,8 +1069,12 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)  	struct address_space *mapping = file->f_mapping;  	struct inode *inode = mapping->host;  	ssize_t ret; +	int err;  	struct ntfs_inode *ni = ntfs_i(inode); +	if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) +		return -EIO; +  	if (is_encrypted(ni)) {  		ntfs_inode_warn(inode, "encrypted i/o not supported");  		return -EOPNOTSUPP; @@ -1068,6 +1100,12 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)  	if (ret <= 0)  		goto out; +	err = file_modified(iocb->ki_filp); +	if (err) { +		ret = err; +		goto out; +	} +  	if (WARN_ON(ni->ni_flags & NI_FLAG_COMPRESSED_MASK)) {  		/* Should never be here, see ntfs_file_open(). */  		ret = -EOPNOTSUPP; @@ -1097,6 +1135,9 @@ int ntfs_file_open(struct inode *inode, struct file *file)  {  	struct ntfs_inode *ni = ntfs_i(inode); +	if (unlikely(ntfs3_forced_shutdown(inode->i_sb))) +		return -EIO; +  	if (unlikely((is_compressed(ni) || is_encrypted(ni)) &&  		     (file->f_flags & O_DIRECT))) {  		return -EOPNOTSUPP; @@ -1138,7 +1179,8 @@ static int ntfs_file_release(struct inode *inode, struct file *file)  		down_write(&ni->file.run_lock);  		err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, -				    inode->i_size, &ni->i_valid, false, NULL); +				    i_size_read(inode), &ni->i_valid, false, +				    NULL);  		up_write(&ni->file.run_lock);  		ni_unlock(ni);  | 
