vserver 1.9.3
[linux-2.6.git] / fs / ntfs / file.c
index 234be72..c7880d5 100644 (file)
@@ -1,20 +1,20 @@
 /*
  * file.c - NTFS kernel file operations. Part of the Linux-NTFS project.
  *
- * Copyright (c) 2001 Anton Altaparmakov.
+ * Copyright (c) 2001-2004 Anton Altaparmakov
  *
  * This program/include file is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as published
  * by the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * This program/include file is distributed in the hope that it will be 
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 
+ * This program/include file is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program (in the main directory of the Linux-NTFS 
+ * along with this program (in the main directory of the Linux-NTFS
  * distribution in the file COPYING); if not, write to the Free Software
  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
@@ -48,29 +48,103 @@ 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 = {};
 
 struct inode_operations ntfs_empty_inode_ops = {};
-