]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/btrfs/inode.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs...
[net-next-2.6.git] / fs / btrfs / inode.c
index 5ab120d544bc6c2f44269cf709e7556df040e4cf..1bff92ad474434a535b711abebb14d7a692cabca 100644 (file)
@@ -2673,7 +2673,7 @@ static int check_path_shared(struct btrfs_root *root,
        struct extent_buffer *eb;
        int level;
        int ret;
-       u64 refs;
+       u64 refs = 1;
 
        for (level = 0; level < BTRFS_MAX_LEVEL; level++) {
                if (!path->nodes[level])
@@ -4312,12 +4312,23 @@ void btrfs_dirty_inode(struct inode *inode)
                /* whoops, lets try again with the full transaction */
                btrfs_end_transaction(trans, root);
                trans = btrfs_start_transaction(root, 1);
+               if (IS_ERR(trans)) {
+                       if (printk_ratelimit()) {
+                               printk(KERN_ERR "btrfs: fail to "
+                                      "dirty  inode %lu error %ld\n",
+                                      inode->i_ino, PTR_ERR(trans));
+                       }
+                       return;
+               }
                btrfs_set_trans_block_group(trans, inode);
 
                ret = btrfs_update_inode(trans, root, inode);
                if (ret) {
-                       printk(KERN_ERR"btrfs: fail to dirty inode %lu error %d\n",
-                               inode->i_ino, ret);
+                       if (printk_ratelimit()) {
+                               printk(KERN_ERR "btrfs: fail to "
+                                      "dirty  inode %lu error %d\n",
+                                      inode->i_ino, ret);
+                       }
                }
        }
        btrfs_end_transaction(trans, root);
@@ -4465,16 +4476,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        if (ret != 0)
                goto fail;
 
-       inode->i_uid = current_fsuid();
-
-       if (dir && (dir->i_mode & S_ISGID)) {
-               inode->i_gid = dir->i_gid;
-               if (S_ISDIR(mode))
-                       mode |= S_ISGID;
-       } else
-               inode->i_gid = current_fsgid();
-
-       inode->i_mode = mode;
+       inode_init_owner(inode, dir, mode);
        inode->i_ino = objectid;
        inode_set_bytes(inode, 0);
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
@@ -5722,6 +5724,32 @@ free_ordered:
        bio_endio(bio, ret);
 }
 
+static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb,
+                       const struct iovec *iov, loff_t offset,
+                       unsigned long nr_segs)
+{
+       int seg;
+       size_t size;
+       unsigned long addr;
+       unsigned blocksize_mask = root->sectorsize - 1;
+       ssize_t retval = -EINVAL;
+       loff_t end = offset;
+
+       if (offset & blocksize_mask)
+               goto out;
+
+       /* Check the memory alignment.  Blocks cannot straddle pages */
+       for (seg = 0; seg < nr_segs; seg++) {
+               addr = (unsigned long)iov[seg].iov_base;
+               size = iov[seg].iov_len;
+               end += size;
+               if ((addr & blocksize_mask) || (size & blocksize_mask)) 
+                       goto out;
+       }
+       retval = 0;
+out:
+       return retval;
+}
 static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
                        const struct iovec *iov, loff_t offset,
                        unsigned long nr_segs)
@@ -5736,6 +5764,11 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
        int write_bits = 0;
        size_t count = iov_length(iov, nr_segs);
 
+       if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov,
+                           offset, nr_segs)) {
+               return 0;
+       }
+
        lockstart = offset;
        lockend = offset + count - 1;
 
@@ -5784,9 +5817,10 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
        free_extent_state(cached_state);
        cached_state = NULL;
 
-       ret = __blockdev_direct_IO(rw, iocb, inode, NULL, iov, offset, nr_segs,
-                                  btrfs_get_blocks_direct, NULL,
-                                  btrfs_submit_direct, 0);
+       ret = __blockdev_direct_IO(rw, iocb, inode,
+                  BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
+                  iov, offset, nr_segs, btrfs_get_blocks_direct, NULL,
+                  btrfs_submit_direct, 0);
 
        if (ret < 0 && ret != -EIOCBQUEUED) {
                clear_extent_bit(&BTRFS_I(inode)->io_tree, offset,
@@ -6850,7 +6884,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                if (em->block_start == EXTENT_MAP_HOLE ||
                    (cur_offset >= inode->i_size &&
                     !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
-                       ret = btrfs_prealloc_file_range(inode, 0, cur_offset,
+                       ret = btrfs_prealloc_file_range(inode, mode, cur_offset,
                                                        last_byte - cur_offset,
                                                        1 << inode->i_blkbits,
                                                        offset + len,