* Extend the initialized size of an attribute described by the ntfs inode @ni
* to @new_init_size bytes. This involves zeroing any non-sparse space between
* the old initialized size and @new_init_size both in the page cache and on
- * disk (if relevant complete pages are zeroed in the page cache then these may
- * simply be marked dirty for later writeout). There is one caveat and that is
- * that if any uptodate page cache pages between the old initialized size and
- * the smaller of @new_init_size and the file size (vfs inode->i_size) are in
- * memory, these need to be marked dirty without being zeroed since they could
- * be non-zero due to mmap() based writes.
+ * disk (if relevant complete pages are already uptodate in the page cache then
+ * these are simply marked dirty).
*
* As a side-effect, the file size (vfs inode->i_size) may be incremented as,
* in the resident attribute case, it is tied to the initialized size and, in
* with new data via mmap() based writes, so we cannot just zero it. And since
* POSIX specifies that the behaviour of resizing a file whilst it is mmap()ped
* is unspecified, we choose not to do zeroing and thus we do not need to touch
- * the page at all. For a more detailed explanation see ntfs_truncate() which
- * is in fs/ntfs/inode.c.
+ * the page at all. For a more detailed explanation see ntfs_truncate() in
+ * fs/ntfs/inode.c.
*
- * @cached_page and @lru_pvec are just optimisations for dealing with multiple
+ * @cached_page and @lru_pvec are just optimizations for dealing with multiple
* pages.
*
* Return 0 on success and -errno on error. In the case that an error is
* this is the case, the necessary zeroing will also have happened and that all
* metadata is self-consistent.
*
- * Locking: This function locks the mft record of the base ntfs inode and
- * maintains the lock throughout execution of the function. This is required
- * so that the initialized size of the attribute can be modified safely.
+ * Locking: i_mutex on the vfs inode corrseponsind to the ntfs inode @ni must be
+ * held by the caller.
*/
static int ntfs_attr_extend_initialized(ntfs_inode *ni, const s64 new_init_size,
struct page **cached_page, struct pagevec *lru_pvec)
* @bytes: number of bytes to be written
*
* This is called for non-resident attributes from ntfs_file_buffered_write()
- * with i_sem held on the inode (@pages[0]->mapping->host). There are
+ * with i_mutex held on the inode (@pages[0]->mapping->host). There are
* @nr_pages pages in @pages which are locked but not kmap()ped. The source
* data has not yet been copied into the @pages.
*
ni = NTFS_I(vi);
vol = ni->vol;
ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, start page "
- "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%x.",
+ "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.",
vi->i_ino, ni->type, pages[0]->index, nr_pages,
(long long)pos, bytes);
blocksize_bits = vi->i_blkbits;
* to, we need to read it in before the write,
* i.e. now.
*/
- if (!buffer_uptodate(bh) && ((bh_pos < pos &&
- bh_end > pos) ||
- (bh_end > end &&
- bh_end > end))) {
+ if (!buffer_uptodate(bh) && bh_pos < end &&
+ bh_end > pos &&
+ (bh_pos < pos ||
+ bh_end > end)) {
/*
* If the buffer is fully or partially
* within the initialized size, do an
vcn_len = rl[1].vcn - vcn;
lcn_block = lcn << (vol->cluster_size_bits -
blocksize_bits);
+ cdelta = 0;
/*
- * If the number of remaining clusters in the
- * @pages is smaller or equal to the number of
- * cached clusters, unlock the runlist as the
- * map cache will be used from now on.
+ * If the number of remaining clusters touched
+ * by the write is smaller or equal to the
+ * number of cached clusters, unlock the
+ * runlist as the map cache will be used from
+ * now on.
*/
if (likely(vcn + vcn_len >= cend)) {
if (rl_write_locked) {
* @pos: byte position in file at which the write begins
* @bytes: number of bytes to be written
*
- * This is called from ntfs_file_buffered_write() with i_sem held on the inode
+ * This is called from ntfs_file_buffered_write() with i_mutex held on the inode
* (@pages[0]->mapping->host). There are @nr_pages pages in @pages which are
* locked but not kmap()ped. The source data has already been copied into the
* @page. ntfs_prepare_pages_for_non_resident_write() has been called before
vi = page->mapping->host;
ni = NTFS_I(vi);
ntfs_debug("Entering for inode 0x%lx, attribute type 0x%x, start page "
- "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%x.",
+ "index 0x%lx, nr_pages 0x%x, pos 0x%llx, bytes 0x%zx.",
vi->i_ino, ni->type, page->index, nr_pages,
(long long)pos, bytes);
if (NInoNonResident(ni))
/**
* ntfs_file_buffered_write -
*
- * Locking: The vfs is holding ->i_sem on the inode.
+ * Locking: The vfs is holding ->i_mutex on the inode.
*/
static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
const struct iovec *iov, unsigned long nr_segs,
VCN last_vcn;
LCN lcn;
unsigned long flags;
- size_t bytes, iov_ofs;
+ size_t bytes, iov_ofs = 0; /* Offset in the current iovec. */
ssize_t status, written;
unsigned nr_pages;
int err;
if (ni->type != AT_INDEX_ALLOCATION) {
/* If file is encrypted, deny access, just like NT4. */
if (NInoEncrypted(ni)) {
+ /*
+ * Reminder for later: Encrypted files are _always_
+ * non-resident so that the content can always be
+ * encrypted.
+ */
ntfs_debug("Denying write access to encrypted file.");
return -EACCES;
}
if (NInoCompressed(ni)) {
+ /* Only unnamed $DATA attribute can be compressed. */
+ BUG_ON(ni->type != AT_DATA);
+ BUG_ON(ni->name_len);
+ /*
+ * Reminder for later: If resident, the data is not
+ * actually compressed. Only on the switch to non-
+ * resident does compression kick in. This is in
+ * contrast to encrypted files (see above).
+ */
ntfs_error(vi->i_sb, "Writing to compressed files is "
"not implemented yet. Sorry.");
return -EOPNOTSUPP;
last_vcn = -1;
if (likely(nr_segs == 1))
buf = iov->iov_base;
- else
- iov_ofs = 0; /* Offset in the current iovec. */
do {
VCN vcn;
pgoff_t idx, start_idx;
err = remove_suid(file->f_dentry);
if (err)
goto out;
- inode_update_time(inode, 1);
+ file_update_time(file);
written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos,
count);
out:
BUG_ON(iocb->ki_pos != pos);
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
ret = ntfs_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
int err = sync_page_range(inode, mapping, pos, ret);
if (err < 0)
struct kiocb kiocb;
ssize_t ret;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
init_sync_kiocb(&kiocb, file);
ret = ntfs_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
if (ret == -EIOCBQUEUED)
ret = wait_on_sync_kiocb(&kiocb);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
int err = sync_page_range(inode, mapping, *ppos - ret, ret);
if (err < 0)
* Note: In the past @filp could be NULL so we ignore it as we don't need it
* anyway.
*
- * Locking: Caller must hold i_sem on the inode.
+ * 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