patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / reiserfs / file.c
index 7eba8fd..b74f710 100644 (file)
@@ -5,12 +5,16 @@
 
 #include <linux/time.h>
 #include <linux/reiserfs_fs.h>
+#include <linux/reiserfs_acl.h>
+#include <linux/reiserfs_xattr.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <linux/pagemap.h>
+#include <linux/swap.h>
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
+#include <linux/quotaops.h>
 
 /*
 ** We pack the tails of files on file close, not at the time they are written.
@@ -97,81 +101,6 @@ static int reiserfs_sync_file(
   return ( n_err < 0 ) ? -EIO : 0;
 }
 
-int reiserfs_setattr_flags(struct inode *inode, unsigned int flags)
-{
-       unsigned int oldflags, newflags;
-
-       oldflags = REISERFS_I(inode)->i_flags;
-       newflags = oldflags & ~(REISERFS_IMMUTABLE_FL |
-               REISERFS_IUNLINK_FL | REISERFS_BARRIER_FL);
-       if (flags & ATTR_FLAG_IMMUTABLE)
-               newflags |= REISERFS_IMMUTABLE_FL;
-       if (flags & ATTR_FLAG_IUNLINK)
-               newflags |= REISERFS_IUNLINK_FL;
-       if (flags & ATTR_FLAG_BARRIER)
-               newflags |= REISERFS_BARRIER_FL;
-
-       if (oldflags ^ newflags) {
-               REISERFS_I(inode)->i_flags = newflags;
-               inode->i_ctime = CURRENT_TIME;
-       }
-       return 0;
-}
-
-int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
-    struct inode *inode = dentry->d_inode ;
-    int error ;
-
-    reiserfs_write_lock(inode->i_sb);
-    if (S_ISDIR(inode->i_mode))
-       goto is_dir;
-
-    if (attr->ia_valid & ATTR_SIZE) {
-       /* version 2 items will be caught by the s_maxbytes check
-       ** done for us in vmtruncate
-       */
-       if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
-           attr->ia_size > MAX_NON_LFS) {
-           error = -EFBIG ;
-           goto out;
-       }
-       /* fill in hole pointers in the expanding truncate case. */
-        if (attr->ia_size > inode->i_size) {
-           error = generic_cont_expand(inode, attr->ia_size) ;
-           if (REISERFS_I(inode)->i_prealloc_count > 0) {
-               struct reiserfs_transaction_handle th ;
-               /* we're changing at most 2 bitmaps, inode + super */
-               journal_begin(&th, inode->i_sb, 4) ;
-               reiserfs_discard_prealloc (&th, inode);
-               journal_end(&th, inode->i_sb, 4) ;
-           }
-           if (error)
-               goto out;
-       }
-    }
-
-    if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) ||
-        ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) &&
-       (get_inode_sd_version (inode) == STAT_DATA_V1)) {
-               /* stat data of format v3.5 has 16 bit uid and gid */
-           error = -EINVAL;
-           goto out;   
-       }
-
-is_dir:
-    error = inode_change_ok(inode, attr) ;
-
-    if (!error && attr->ia_valid & ATTR_ATTR_FLAG)
-       reiserfs_setattr_flags(inode, attr->ia_attr_flags);
-
-    if (!error)
-        inode_setattr(inode, attr) ;
-
-out:
-    reiserfs_write_unlock(inode->i_sb);
-    return error ;
-}
-
 /* I really do not want to play with memory shortage right now, so
    to simplify the code, we are not going to write more than this much pages at
    a time. This still should considerably improve performance compared to 4k
@@ -347,7 +276,7 @@ int reiserfs_allocate_blocks_for_region(
                    /* Ok, there is existing indirect item already. Need to append it */
                    /* Calculate position past inserted item */
                    make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);
-                   res = reiserfs_paste_into_item( th, &path, &key, (char *)zeros, UNFM_P_SIZE*to_paste);
+                   res = reiserfs_paste_into_item( th, &path, &key, inode, (char *)zeros, UNFM_P_SIZE*to_paste);
                    if ( res ) {
                        kfree(zeros);
                        goto error_exit_free_blocks;
@@ -370,14 +299,15 @@ int reiserfs_allocate_blocks_for_region(
                    if ( res != ITEM_NOT_FOUND ) {
                        /* item should not exist, otherwise we have error */
                        if ( res != -ENOSPC ) {
-                           reiserfs_warning ("green-9008: search_by_key (%K) returned %d\n",
-                                              &key, res);
+                           reiserfs_warning (inode->i_sb,
+                               "green-9008: search_by_key (%K) returned %d",
+                                             &key, res);
                        }
                        res = -EIO;
                        kfree(zeros);
                        goto error_exit_free_blocks;
                    }
-                   res = reiserfs_insert_item( th, &path, &key, &ins_ih, (char *)zeros);
+                   res = reiserfs_insert_item( th, &path, &key, &ins_ih, inode, (char *)zeros);
                } else {
                    reiserfs_panic(inode->i_sb, "green-9011: Unexpected key type %K\n", &key);
                }
@@ -494,7 +424,7 @@ retry:
            // position. We do not need to recalculate path as it should
            // already point to correct place.
            make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);
-           res = reiserfs_paste_into_item( th, &path, &key, (char *)(allocated_blocks+curr_block), UNFM_P_SIZE*(blocks_to_allocate-curr_block));
+           res = reiserfs_paste_into_item( th, &path, &key, inode, (char *)(allocated_blocks+curr_block), UNFM_P_SIZE*(blocks_to_allocate-curr_block));
            if ( res ) {
                goto error_exit_free_blocks;
            }
@@ -518,14 +448,15 @@ retry:
                /* Well, if we have found such item already, or some error
                   occured, we need to warn user and return error */
                if ( res != -ENOSPC ) {
-                   reiserfs_warning ("green-9009: search_by_key (%K) returned %d\n",
-                                     &key, res);
+                   reiserfs_warning (inode->i_sb,
+                                     "green-9009: search_by_key (%K) "
+                                     "returned %d", &key, res);
                }
                res = -EIO;
                goto error_exit_free_blocks;
            }
            /* Insert item into the tree with the data as its body */
-           res = reiserfs_insert_item( th, &path, &key, &ins_ih, (char *)(allocated_blocks+curr_block));
+           res = reiserfs_insert_item( th, &path, &key, &ins_ih, inode, (char *)(allocated_blocks+curr_block));
        } else {
            reiserfs_panic(inode->i_sb, "green-9010: unexpected item type for key %K\n",&key);
        }
@@ -535,7 +466,6 @@ retry:
     // unless we return an error, they are also responsible for logging
     // the inode.
     //
-    inode->i_blocks += blocks_to_allocate << (inode->i_blkbits - 9);
     pathrelse(&path);
     reiserfs_write_unlock(inode->i_sb);
 
@@ -581,7 +511,7 @@ error_exit_free_blocks:
     pathrelse(&path);
     // free blocks
     for( i = 0; i < blocks_to_allocate; i++ )
-       reiserfs_free_block(th, le32_to_cpu(allocated_blocks[i]));
+       reiserfs_free_block(th, inode, le32_to_cpu(allocated_blocks[i]), 1);
 
 error_exit:
     reiserfs_update_sd(th, inode); // update any changes we made to blk count
@@ -615,7 +545,7 @@ int reiserfs_copy_from_user_to_file_region(
                                                                 array to
                                                                 prepared pages
                                                                */
-                               const char *buf /* Pointer to user-supplied
+                               const char __user *buf /* Pointer to user-supplied
                                                   data*/
                                )
 {
@@ -726,10 +656,6 @@ int reiserfs_submit_file_region_for_write(
                             // we only remember error status to report it on
                             // exit.
        write_bytes-=count;
-       SetPageReferenced(page);
-       unlock_page(page); // We unlock the page as it was locked by earlier call
-                         // to grab_cache_page
-       page_cache_release(page);
     }
     /* now that we've gotten all the ordered buffers marked dirty,
      * we can safely update i_size and close any running transaction
@@ -766,6 +692,17 @@ int reiserfs_submit_file_region_for_write(
        reiserfs_write_unlock(inode->i_sb);
     }
     th->t_trans_id = 0;
+
+    /* 
+     * we have to unlock the pages after updating i_size, otherwise
+     * we race with writepage
+     */
+    for ( i = 0; i < num_pages ; i++) {
+       struct page *page=prepared_pages[i];
+       unlock_page(page); 
+       mark_page_accessed(page);
+       page_cache_release(page);
+    }
     return retval;
 }
 
@@ -872,7 +809,9 @@ int reiserfs_prepare_file_region_for_write(
 
 
     if ( num_pages < 1 ) {
-       reiserfs_warning("green-9001: reiserfs_prepare_file_region_for_write called with zero number of pages to process\n");
+       reiserfs_warning (inode->i_sb,
+                         "green-9001: reiserfs_prepare_file_region_for_write "
+                         "called with zero number of pages to process");
        return -EFAULT;
     }
 
@@ -1123,7 +1062,7 @@ failed_read:
 
 */
 ssize_t reiserfs_file_write( struct file *file, /* the file we are going to write into */
-                             const char *buf, /*  pointer to user supplied data
+                             const char __user *buf, /*  pointer to user supplied data
 (in userspace) */
                              size_t count, /* amount of bytes to write */
                              loff_t *ppos /* pointer to position in file that we start writing at. Should be updated to
@@ -1351,6 +1290,11 @@ struct file_operations reiserfs_file_operations = {
 struct  inode_operations reiserfs_file_inode_operations = {
     .truncate  = reiserfs_vfs_truncate_file,
     .setattr    = reiserfs_setattr,
+    .setxattr   = reiserfs_setxattr,
+    .getxattr   = reiserfs_getxattr,
+    .listxattr  = reiserfs_listxattr,
+    .removexattr = reiserfs_removexattr,
+    .permission = reiserfs_permission,
 };