]> err.no Git - linux-2.6/blobdiff - fs/ntfs/file.c
[PATCH] fuse: move INIT handling to inode.c
[linux-2.6] / fs / ntfs / file.c
index cf2a0e2330dfdca288f08cbba86b9bc87b83ab55..fb413d3d861875932742b3ccea65d40ac99ef47b 100644 (file)
@@ -78,12 +78,8 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
  * 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
@@ -98,10 +94,10 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
  * 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
@@ -110,9 +106,8 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
  * 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)
@@ -478,7 +473,7 @@ static inline int ntfs_submit_bh_for_read(struct buffer_head *bh)
  * @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.
  * 
@@ -531,7 +526,7 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **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;
@@ -673,10 +668,10 @@ map_buffer_cached:
                                 * 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
@@ -787,11 +782,13 @@ retry_remap:
                                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) {
@@ -1640,7 +1637,7 @@ err_out:
  * @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
@@ -1692,7 +1689,7 @@ static int ntfs_commit_pages_after_write(struct page **pages,
        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))
@@ -1817,7 +1814,7 @@ err_out:
 /**
  * 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,
@@ -1835,7 +1832,7 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
        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;
@@ -1857,10 +1854,24 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
        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;
@@ -1973,8 +1984,6 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
        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;
@@ -2164,7 +2173,7 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
        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:
@@ -2187,9 +2196,9 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const char __user *buf,
 
        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)
@@ -2212,12 +2221,12 @@ static ssize_t ntfs_file_writev(struct file *file, const struct iovec *iov,
        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)
@@ -2260,7 +2269,7 @@ static ssize_t ntfs_file_write(struct file *file, const char __user *buf,
  * 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