Merge branch 'for-linus-unmerged' of git://git.kernel.org/pub/scm/linux/kernel/git...
Linus Torvalds [Mon, 28 Mar 2011 22:31:05 +0000 (15:31 -0700)]
* 'for-linus-unmerged' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (45 commits)
  Btrfs: fix __btrfs_map_block on 32 bit machines
  btrfs: fix possible deadlock by clearing __GFP_FS flag
  btrfs: check link counter overflow in link(2)
  btrfs: don't mess with i_nlink of unlocked inode in rename()
  Btrfs: check return value of btrfs_alloc_path()
  Btrfs: fix OOPS of empty filesystem after balance
  Btrfs: fix memory leak of empty filesystem after balance
  Btrfs: fix return value of setflags ioctl
  Btrfs: fix uncheck memory allocations
  btrfs: make inode ref log recovery faster
  Btrfs: add btrfs_trim_fs() to handle FITRIM
  Btrfs: adjust btrfs_discard_extent() return errors and trimmed bytes
  Btrfs: make btrfs_map_block() return entire free extent for each device of RAID0/1/10/DUP
  Btrfs: make update_reserved_bytes() public
  btrfs: return EXDEV when linking from different subvolumes
  Btrfs: Per file/directory controls for COW and compression
  Btrfs: add datacow flag in inode flag
  btrfs: use GFP_NOFS instead of GFP_KERNEL
  Btrfs: check return value of read_tree_block()
  btrfs: properly access unaligned checksum buffer
  ...

Fix up trivial conflicts in fs/btrfs/volumes.c due to plug removal in
the block layer.

1  2 
fs/btrfs/disk-io.c
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/volumes.c
fs/btrfs/xattr.c
include/linux/fs.h

Simple merge
Simple merge
@@@ -4807,9 -4831,15 +4832,12 @@@ static int btrfs_link(struct dentry *ol
        int err;
        int drop_inode = 0;
  
 -      if (inode->i_nlink == 0)
 -              return -ENOENT;
 -
        /* do not allow sys_link's with other subvols of the same device */
        if (root->objectid != BTRFS_I(inode)->root->objectid)
-               return -EPERM;
+               return -EXDEV;
+       if (inode->i_nlink == ~0U)
+               return -EMLINK;
  
        btrfs_inc_nlink(inode);
        inode->i_ctime = CURRENT_TIME;
@@@ -153,12 -172,11 +172,11 @@@ static int btrfs_ioctl_setflags(struct 
        if (copy_from_user(&flags, arg, sizeof(flags)))
                return -EFAULT;
  
-       if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
-                     FS_NOATIME_FL | FS_NODUMP_FL | \
-                     FS_SYNC_FL | FS_DIRSYNC_FL))
-               return -EOPNOTSUPP;
+       ret = check_flags(flags);
+       if (ret)
+               return ret;
  
 -      if (!is_owner_or_cap(inode))
 +      if (!inode_owner_or_capable(inode))
                return -EACCES;
  
        mutex_lock(&inode->i_mutex);
@@@ -3003,8 -3060,19 +3011,19 @@@ again
  
        num_stripes = 1;
        stripe_index = 0;
-       if (map->type & BTRFS_BLOCK_GROUP_RAID1) {
-               if (rw & REQ_WRITE)
+       stripe_nr_orig = stripe_nr;
+       stripe_nr_end = (offset + *length + map->stripe_len - 1) &
+                       (~(map->stripe_len - 1));
+       do_div(stripe_nr_end, map->stripe_len);
+       stripe_end_offset = stripe_nr_end * map->stripe_len -
+                           (offset + *length);
+       if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
+               if (rw & REQ_DISCARD)
+                       num_stripes = min_t(u64, map->num_stripes,
+                                           stripe_nr_end - stripe_nr_orig);
+               stripe_index = do_div(stripe_nr, map->num_stripes);
+       } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) {
 -              if (unplug_page || (rw & (REQ_WRITE | REQ_DISCARD)))
++              if (rw & (REQ_WRITE | REQ_DISCARD))
                        num_stripes = map->num_stripes;
                else if (mirror_num)
                        stripe_index = mirror_num - 1;
                stripe_index = do_div(stripe_nr, factor);
                stripe_index *= map->sub_stripes;
  
 -              if (unplug_page || (rw & REQ_WRITE))
 +              if (rw & REQ_WRITE)
                        num_stripes = map->sub_stripes;
+               else if (rw & REQ_DISCARD)
+                       num_stripes = min_t(u64, map->sub_stripes *
+                                           (stripe_nr_end - stripe_nr_orig),
+                                           map->num_stripes);
                else if (mirror_num)
                        stripe_index += mirror_num - 1;
                else {
        }
        BUG_ON(stripe_index >= map->num_stripes);
  
-       for (i = 0; i < num_stripes; i++) {
-               multi->stripes[i].physical =
-                       map->stripes[stripe_index].physical +
-                       stripe_offset + stripe_nr * map->stripe_len;
-               multi->stripes[i].dev = map->stripes[stripe_index].dev;
-               stripe_index++;
+       if (rw & REQ_DISCARD) {
+               for (i = 0; i < num_stripes; i++) {
+                       multi->stripes[i].physical =
+                               map->stripes[stripe_index].physical +
+                               stripe_offset + stripe_nr * map->stripe_len;
+                       multi->stripes[i].dev = map->stripes[stripe_index].dev;
+                       if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
+                               u64 stripes;
+                               u32 last_stripe = 0;
+                               int j;
+                               div_u64_rem(stripe_nr_end - 1,
+                                           map->num_stripes,
+                                           &last_stripe);
+                               for (j = 0; j < map->num_stripes; j++) {
+                                       u32 test;
+                                       div_u64_rem(stripe_nr_end - 1 - j,
+                                                   map->num_stripes, &test);
+                                       if (test == stripe_index)
+                                               break;
+                               }
+                               stripes = stripe_nr_end - 1 - j;
+                               do_div(stripes, map->num_stripes);
+                               multi->stripes[i].length = map->stripe_len *
+                                       (stripes - stripe_nr + 1);
+                               if (i == 0) {
+                                       multi->stripes[i].length -=
+                                               stripe_offset;
+                                       stripe_offset = 0;
+                               }
+                               if (stripe_index == last_stripe)
+                                       multi->stripes[i].length -=
+                                               stripe_end_offset;
+                       } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
+                               u64 stripes;
+                               int j;
+                               int factor = map->num_stripes /
+                                            map->sub_stripes;
+                               u32 last_stripe = 0;
+                               div_u64_rem(stripe_nr_end - 1,
+                                           factor, &last_stripe);
+                               last_stripe *= map->sub_stripes;
+                               for (j = 0; j < factor; j++) {
+                                       u32 test;
+                                       div_u64_rem(stripe_nr_end - 1 - j,
+                                                   factor, &test);
+                                       if (test ==
+                                           stripe_index / map->sub_stripes)
+                                               break;
+                               }
+                               stripes = stripe_nr_end - 1 - j;
+                               do_div(stripes, factor);
+                               multi->stripes[i].length = map->stripe_len *
+                                       (stripes - stripe_nr + 1);
+                               if (i < map->sub_stripes) {
+                                       multi->stripes[i].length -=
+                                               stripe_offset;
+                                       if (i == map->sub_stripes - 1)
+                                               stripe_offset = 0;
+                               }
+                               if (stripe_index >= last_stripe &&
+                                   stripe_index <= (last_stripe +
+                                                    map->sub_stripes - 1)) {
+                                       multi->stripes[i].length -=
+                                               stripe_end_offset;
+                               }
+                       } else
+                               multi->stripes[i].length = *length;
+                       stripe_index++;
+                       if (stripe_index == map->num_stripes) {
+                               /* This could only happen for RAID0/10 */
+                               stripe_index = 0;
+                               stripe_nr++;
+                       }
+               }
+       } else {
+               for (i = 0; i < num_stripes; i++) {
 -                      if (unplug_page) {
 -                              struct btrfs_device *device;
 -                              struct backing_dev_info *bdi;
 -
 -                              device = map->stripes[stripe_index].dev;
 -                              if (device->bdev) {
 -                                      bdi = blk_get_backing_dev_info(device->
 -                                                                     bdev);
 -                                      if (bdi->unplug_io_fn)
 -                                              bdi->unplug_io_fn(bdi,
 -                                                                unplug_page);
 -                              }
 -                      } else {
 -                              multi->stripes[i].physical =
 -                                      map->stripes[stripe_index].physical +
 -                                      stripe_offset +
 -                                      stripe_nr * map->stripe_len;
 -                              multi->stripes[i].dev =
 -                                      map->stripes[stripe_index].dev;
 -                      }
++                      multi->stripes[i].physical =
++                              map->stripes[stripe_index].physical +
++                              stripe_offset +
++                              stripe_nr * map->stripe_len;
++                      multi->stripes[i].dev =
++                              map->stripes[stripe_index].dev;
+                       stripe_index++;
+               }
        }
        if (multi_ret) {
                *multi_ret = multi;
Simple merge
Simple merge