patch-2.4.1 linux/fs/reiserfs/file.c

Next file: linux/fs/reiserfs/fix_node.c
Previous file: linux/fs/reiserfs/do_balan.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0/linux/fs/reiserfs/file.c linux/fs/reiserfs/file.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ */
+
+
+#ifdef __KERNEL__
+
+#include <linux/sched.h>
+#include <linux/reiserfs_fs.h>
+#include <linux/smp_lock.h>
+
+#else
+
+#include "nokernel.h"
+
+#endif
+
+/*
+** We pack the tails of files on file close, not at the time they are written.
+** This implies an unnecessary copy of the tail and an unnecessary indirect item
+** insertion/balancing, for files that are written in one write.
+** It avoids unnecessary tail packings (balances) for files that are written in
+** multiple writes and are small enough to have tails.
+** 
+** file_release is called by the VFS layer when the file is closed.  If
+** this is the last open file descriptor, and the file
+** small enough to have a tail, and the tail is currently in an
+** unformatted node, the tail is converted back into a direct item.
+** 
+** We use reiserfs_truncate_file to pack the tail, since it already has
+** all the conditions coded.  
+*/
+static int reiserfs_file_release (struct inode * inode, struct file * filp)
+{
+
+    struct reiserfs_transaction_handle th ;
+    int windex ;
+
+    if (!S_ISREG (inode->i_mode))
+	BUG ();
+
+    /* fast out for when nothing needs to be done */
+    if ((atomic_read(&inode->i_count) > 1 ||
+         !inode->u.reiserfs_i.i_pack_on_close || 
+         !tail_has_to_be_packed(inode))       && 
+	inode->u.reiserfs_i.i_prealloc_count <= 0) {
+	return 0;
+    }    
+    
+    lock_kernel() ;
+    down (&inode->i_sem); 
+    journal_begin(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3) ;
+
+#ifdef REISERFS_PREALLOCATE
+    reiserfs_discard_prealloc (&th, inode);
+#endif
+    journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3) ;
+
+    if (atomic_read(&inode->i_count) <= 1 &&
+	inode->u.reiserfs_i.i_pack_on_close &&
+        tail_has_to_be_packed (inode)) {
+	/* if regular file is released by last holder and it has been
+	   appended (we append by unformatted node only) or its direct
+	   item(s) had to be converted, then it may have to be
+	   indirect2direct converted */
+	windex = push_journal_writer("file_release") ;
+	reiserfs_truncate_file(inode, 0) ;
+	pop_journal_writer(windex) ;
+    }
+    up (&inode->i_sem); 
+    unlock_kernel() ;
+    return 0;
+}
+
+static void reiserfs_vfs_truncate_file(struct inode *inode) {
+    reiserfs_truncate_file(inode, 1) ;
+}
+
+/* Sync a reiserfs file. */
+static int reiserfs_sync_file(
+			      struct file   * p_s_filp,
+			      struct dentry * p_s_dentry,
+			      int datasync
+			      ) {
+  struct inode * p_s_inode = p_s_dentry->d_inode;
+  struct reiserfs_transaction_handle th ;
+  int n_err = 0;
+  int windex ;
+  int jbegin_count = 1 ;
+
+  lock_kernel() ;
+
+  if (!S_ISREG(p_s_inode->i_mode))
+      BUG ();
+
+  n_err = fsync_inode_buffers(p_s_inode) ;
+  /* commit the current transaction to flush any metadata
+  ** changes.  sys_fsync takes care of flushing the dirty pages for us
+  */
+  journal_begin(&th, p_s_inode->i_sb, jbegin_count) ;
+  windex = push_journal_writer("sync_file") ;
+  reiserfs_update_sd(&th, p_s_inode);
+  pop_journal_writer(windex) ;
+  journal_end_sync(&th, p_s_inode->i_sb,jbegin_count) ;
+  unlock_kernel() ;
+  return ( n_err < 0 ) ? -EIO : 0;
+}
+
+
+struct file_operations reiserfs_file_operations = {
+    read:	generic_file_read,
+    write:	generic_file_write,
+    ioctl:	reiserfs_ioctl,
+    mmap:	generic_file_mmap,
+    release:	reiserfs_file_release,
+    fsync:	reiserfs_sync_file,
+};
+
+
+struct  inode_operations reiserfs_file_inode_operations = {
+    truncate:	reiserfs_vfs_truncate_file,
+};
+
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)