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

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

diff -u --recursive --new-file v2.4.0/linux/fs/reiserfs/ioctl.c linux/fs/reiserfs/ioctl.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/reiserfs_fs.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+#include <linux/locks.h>
+
+#else
+
+#include "nokernel.h"
+
+#endif
+
+/*
+** reiserfs_ioctl - handler for ioctl for inode
+** supported commands:
+**  1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
+**                           and prevent packing file (argument arg has to be non-zero)
+**  2) That's all for a while ...
+*/
+int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+		unsigned long arg)
+{
+	switch (cmd) {
+	    case REISERFS_IOC_UNPACK:
+		if (arg)
+		    return reiserfs_unpack (inode, filp);
+			
+	    default:
+		return -ENOTTY;
+	}
+}
+
+/*
+** reiserfs_unpack
+** Function try to convert tail from direct item into indirect.
+** It set up nopack attribute in the inode.u.reiserfs_i.nopack
+*/
+int reiserfs_unpack (struct inode * inode, struct file * filp)
+{
+    int retval = 0;
+    int index ;
+    struct page *page ;
+    unsigned long write_from ;
+    unsigned long blocksize = inode->i_sb->s_blocksize ;
+    	
+    if (inode->i_size == 0) {
+        return -EINVAL ;
+    }
+    /* ioctl already done */
+    if (inode->u.reiserfs_i.nopack) {
+        return 0 ;
+    }
+    lock_kernel();
+
+    /* we need to make sure nobody is changing the file size beneath
+    ** us
+    */
+    down(&inode->i_sem) ;
+
+    write_from = inode->i_size & (blocksize - 1) ;
+    /* if we are on a block boundary, we are already unpacked.  */
+    if ( write_from == 0) {
+	inode->u.reiserfs_i.nopack = 1;
+	goto out ;
+    }
+
+    /* we unpack by finding the page with the tail, and calling
+    ** reiserfs_prepare_write on that page.  This will force a 
+    ** reiserfs_get_block to unpack the tail for us.
+    */
+    index = inode->i_size >> PAGE_CACHE_SHIFT ;
+    page = grab_cache_page(inode->i_mapping, index) ;
+    retval = PTR_ERR(page) ;
+    if (IS_ERR(page)) {
+        goto out ;
+    }
+    retval = reiserfs_prepare_write(NULL, page, write_from, blocksize) ;
+    if (retval)
+        goto out_unlock ;
+
+    /* conversion can change page contents, must flush */
+    flush_dcache_page(page) ;
+    inode->u.reiserfs_i.nopack = 1;
+    kunmap(page) ; /* mapped by prepare_write */
+
+out_unlock:
+    UnlockPage(page) ;
+    page_cache_release(page) ;
+
+out:
+    up(&inode->i_sem) ;
+    unlock_kernel();    
+    return retval;
+}

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