vserver 1.9.3
[linux-2.6.git] / fs / ntfs / file.c
index f034d82..c7880d5 100644 (file)
@@ -48,26 +48,101 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
        return generic_file_open(vi, filp);
 }
 
+#ifdef NTFS_RW
+
+/**
+ * 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
+ * system calls.  This function is inspired by fs/buffer.c::file_fsync().
+ *
+ * If @datasync is false, write the mft record and all associated extent mft
+ * records as well as the $DATA attribute and then sync the block device.
+ *
+ * If @datasync is true and the attribute is non-resident, we skip the writing
+ * of the mft record and all associated extent mft records (this might still
+ * happen due to the write_inode_now() call).
+ *
+ * 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_sem 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)
+{
+       struct inode *vi = dentry->d_inode;
+       int err, ret = 0;
+
+       ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+       BUG_ON(S_ISDIR(vi->i_mode));
+       if (!datasync || !NInoNonResident(NTFS_I(vi)))
+               ret = ntfs_write_inode(vi, 1);
+       write_inode_now(vi, !datasync);
+       err = sync_blockdev(vi->i_sb->s_bdev);
+       if (unlikely(err && !ret))
+               ret = err;
+       if (likely(!ret))
+               ntfs_debug("Done.");
+       else
+               ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
+                               "%u.", datasync ? "data" : "", vi->i_ino, -ret);
+       return ret;
+}
+
+#endif /* NTFS_RW */
+
 struct file_operations ntfs_file_ops = {
-       .llseek         = generic_file_llseek,  /* Seek inside file. */
-       .read           = generic_file_read,    /* Read from file. */
+       .llseek         = generic_file_llseek,    /* Seek inside file. */
+       .read           = generic_file_read,      /* Read from file. */
+       .aio_read       = generic_file_aio_read,  /* Async read from file. */
+       .readv          = generic_file_readv,     /* Read from file. */
 #ifdef NTFS_RW
-       .write          = generic_file_write,   /* Write to a file. */
-#endif
-       .mmap           = generic_file_mmap,    /* Mmap file. */
-       .sendfile       = generic_file_sendfile,/* Zero-copy data send with the
-                                                  data source being on the
-                                                  ntfs partition. We don't
-                                                  need to care about the data
-                                                  destination. */
-       .open           = ntfs_file_open,       /* Open file. */
+       .write          = generic_file_write,     /* Write to file. */
+       .aio_write      = generic_file_aio_write, /* Async write to file. */
+       .writev         = generic_file_writev,    /* Write to file. */
+       /*.release      = ,*/                     /* Last file is closed.  See
+                                                    fs/ext2/file.c::
+                                                    ext2_release_file() for
+                                                    how to use this to discard
+                                                    preallocated space for
+                                                    write opened files. */
+       .fsync          = ntfs_file_fsync,        /* Sync a file to disk. */
+       /*.aio_fsync    = ,*/                     /* Sync all outstanding async
+                                                    i/o operations on a
+                                                    kiocb. */
+#endif /* NTFS_RW */
+       /*.ioctl        = ,*/                     /* Perform function on the
+                                                    mounted filesystem. */
+       .mmap           = generic_file_mmap,      /* Mmap file. */
+       .open           = ntfs_file_open,         /* Open file. */
+       .sendfile       = generic_file_sendfile,  /* Zero-copy data send with
+                                                    the data source being on
+                                                    the ntfs partition.  We
+                                                    do not need to care about
+                                                    the data destination. */
+       /*.sendpage     = ,*/                     /* Zero-copy data send with
+                                                    the data destination being
+                                                    on the ntfs partition.  We
+                                                    do not need to care about
+                                                    the data source. */
 };
 
 struct inode_operations ntfs_file_inode_ops = {
 #ifdef NTFS_RW
        .truncate       = ntfs_truncate,
        .setattr        = ntfs_setattr,
-#endif
+#endif /* NTFS_RW */
 };
 
 struct file_operations ntfs_empty_file_ops = {};