diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/block_dev.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/compression.c | 39 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 26 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 6 | ||||
| -rw-r--r-- | fs/cifs/readdir.c | 1 | ||||
| -rw-r--r-- | fs/dax.c | 5 | ||||
| -rw-r--r-- | fs/fscache/cookie.c | 5 | ||||
| -rw-r--r-- | fs/fscache/netfs.c | 1 | ||||
| -rw-r--r-- | fs/fscache/object.c | 32 | ||||
| -rw-r--r-- | fs/iomap.c | 3 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 4 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 1 | ||||
| -rw-r--r-- | fs/nfs/pnfs.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfs4layouts.c | 5 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 19 | ||||
| -rw-r--r-- | fs/nfsd/state.h | 4 | ||||
| -rw-r--r-- | fs/proc/page.c | 3 | ||||
| -rw-r--r-- | fs/pstore/ram.c | 2 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_ag_resv.c | 70 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_attr.c | 6 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 48 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.h | 6 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_ialloc_btree.c | 90 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_ialloc_btree.h | 3 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_sb.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_bmap_util.c | 28 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.c | 1 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 23 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.h | 1 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm.c | 3 |
31 files changed, 334 insertions, 113 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 5db5d1340d69..3c47614a4b32 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -331,7 +331,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages) | |||
| 331 | struct blk_plug plug; | 331 | struct blk_plug plug; |
| 332 | struct blkdev_dio *dio; | 332 | struct blkdev_dio *dio; |
| 333 | struct bio *bio; | 333 | struct bio *bio; |
| 334 | bool is_read = (iov_iter_rw(iter) == READ); | 334 | bool is_read = (iov_iter_rw(iter) == READ), is_sync; |
| 335 | loff_t pos = iocb->ki_pos; | 335 | loff_t pos = iocb->ki_pos; |
| 336 | blk_qc_t qc = BLK_QC_T_NONE; | 336 | blk_qc_t qc = BLK_QC_T_NONE; |
| 337 | int ret; | 337 | int ret; |
| @@ -344,7 +344,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages) | |||
| 344 | bio_get(bio); /* extra ref for the completion handler */ | 344 | bio_get(bio); /* extra ref for the completion handler */ |
| 345 | 345 | ||
| 346 | dio = container_of(bio, struct blkdev_dio, bio); | 346 | dio = container_of(bio, struct blkdev_dio, bio); |
| 347 | dio->is_sync = is_sync_kiocb(iocb); | 347 | dio->is_sync = is_sync = is_sync_kiocb(iocb); |
| 348 | if (dio->is_sync) | 348 | if (dio->is_sync) |
| 349 | dio->waiter = current; | 349 | dio->waiter = current; |
| 350 | else | 350 | else |
| @@ -398,7 +398,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages) | |||
| 398 | } | 398 | } |
| 399 | blk_finish_plug(&plug); | 399 | blk_finish_plug(&plug); |
| 400 | 400 | ||
| 401 | if (!dio->is_sync) | 401 | if (!is_sync) |
| 402 | return -EIOCBQUEUED; | 402 | return -EIOCBQUEUED; |
| 403 | 403 | ||
| 404 | for (;;) { | 404 | for (;;) { |
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 7f390849343b..c4444d6f439f 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
| @@ -1024,6 +1024,7 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, | |||
| 1024 | unsigned long buf_offset; | 1024 | unsigned long buf_offset; |
| 1025 | unsigned long current_buf_start; | 1025 | unsigned long current_buf_start; |
| 1026 | unsigned long start_byte; | 1026 | unsigned long start_byte; |
| 1027 | unsigned long prev_start_byte; | ||
| 1027 | unsigned long working_bytes = total_out - buf_start; | 1028 | unsigned long working_bytes = total_out - buf_start; |
| 1028 | unsigned long bytes; | 1029 | unsigned long bytes; |
| 1029 | char *kaddr; | 1030 | char *kaddr; |
| @@ -1071,26 +1072,34 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, | |||
| 1071 | if (!bio->bi_iter.bi_size) | 1072 | if (!bio->bi_iter.bi_size) |
| 1072 | return 0; | 1073 | return 0; |
| 1073 | bvec = bio_iter_iovec(bio, bio->bi_iter); | 1074 | bvec = bio_iter_iovec(bio, bio->bi_iter); |
| 1074 | 1075 | prev_start_byte = start_byte; | |
| 1075 | start_byte = page_offset(bvec.bv_page) - disk_start; | 1076 | start_byte = page_offset(bvec.bv_page) - disk_start; |
| 1076 | 1077 | ||
| 1077 | /* | 1078 | /* |
| 1078 | * make sure our new page is covered by this | 1079 | * We need to make sure we're only adjusting |
| 1079 | * working buffer | 1080 | * our offset into compression working buffer when |
| 1081 | * we're switching pages. Otherwise we can incorrectly | ||
| 1082 | * keep copying when we were actually done. | ||
| 1080 | */ | 1083 | */ |
| 1081 | if (total_out <= start_byte) | 1084 | if (start_byte != prev_start_byte) { |
| 1082 | return 1; | 1085 | /* |
| 1086 | * make sure our new page is covered by this | ||
| 1087 | * working buffer | ||
| 1088 | */ | ||
| 1089 | if (total_out <= start_byte) | ||
| 1090 | return 1; | ||
| 1083 | 1091 | ||
| 1084 | /* | 1092 | /* |
| 1085 | * the next page in the biovec might not be adjacent | 1093 | * the next page in the biovec might not be adjacent |
| 1086 | * to the last page, but it might still be found | 1094 | * to the last page, but it might still be found |
| 1087 | * inside this working buffer. bump our offset pointer | 1095 | * inside this working buffer. bump our offset pointer |
| 1088 | */ | 1096 | */ |
| 1089 | if (total_out > start_byte && | 1097 | if (total_out > start_byte && |
| 1090 | current_buf_start < start_byte) { | 1098 | current_buf_start < start_byte) { |
| 1091 | buf_offset = start_byte - buf_start; | 1099 | buf_offset = start_byte - buf_start; |
| 1092 | working_bytes = total_out - start_byte; | 1100 | working_bytes = total_out - start_byte; |
| 1093 | current_buf_start = buf_start + buf_offset; | 1101 | current_buf_start = buf_start + buf_offset; |
| 1102 | } | ||
| 1094 | } | 1103 | } |
| 1095 | } | 1104 | } |
| 1096 | 1105 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 4e024260ad71..1e861a063721 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -3835,10 +3835,7 @@ cache_acl: | |||
| 3835 | break; | 3835 | break; |
| 3836 | case S_IFDIR: | 3836 | case S_IFDIR: |
| 3837 | inode->i_fop = &btrfs_dir_file_operations; | 3837 | inode->i_fop = &btrfs_dir_file_operations; |
| 3838 | if (root == fs_info->tree_root) | 3838 | inode->i_op = &btrfs_dir_inode_operations; |
| 3839 | inode->i_op = &btrfs_dir_ro_inode_operations; | ||
| 3840 | else | ||
| 3841 | inode->i_op = &btrfs_dir_inode_operations; | ||
| 3842 | break; | 3839 | break; |
| 3843 | case S_IFLNK: | 3840 | case S_IFLNK: |
| 3844 | inode->i_op = &btrfs_symlink_inode_operations; | 3841 | inode->i_op = &btrfs_symlink_inode_operations; |
| @@ -4505,8 +4502,19 @@ search_again: | |||
| 4505 | if (found_type > min_type) { | 4502 | if (found_type > min_type) { |
| 4506 | del_item = 1; | 4503 | del_item = 1; |
| 4507 | } else { | 4504 | } else { |
| 4508 | if (item_end < new_size) | 4505 | if (item_end < new_size) { |
| 4506 | /* | ||
| 4507 | * With NO_HOLES mode, for the following mapping | ||
| 4508 | * | ||
| 4509 | * [0-4k][hole][8k-12k] | ||
| 4510 | * | ||
| 4511 | * if truncating isize down to 6k, it ends up | ||
| 4512 | * isize being 8k. | ||
| 4513 | */ | ||
| 4514 | if (btrfs_fs_incompat(root->fs_info, NO_HOLES)) | ||
| 4515 | last_size = new_size; | ||
| 4509 | break; | 4516 | break; |
| 4517 | } | ||
| 4510 | if (found_key.offset >= new_size) | 4518 | if (found_key.offset >= new_size) |
| 4511 | del_item = 1; | 4519 | del_item = 1; |
| 4512 | else | 4520 | else |
| @@ -5710,6 +5718,7 @@ static struct inode *new_simple_dir(struct super_block *s, | |||
| 5710 | 5718 | ||
| 5711 | inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID; | 5719 | inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID; |
| 5712 | inode->i_op = &btrfs_dir_ro_inode_operations; | 5720 | inode->i_op = &btrfs_dir_ro_inode_operations; |
| 5721 | inode->i_opflags &= ~IOP_XATTR; | ||
| 5713 | inode->i_fop = &simple_dir_operations; | 5722 | inode->i_fop = &simple_dir_operations; |
| 5714 | inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; | 5723 | inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; |
| 5715 | inode->i_mtime = current_time(inode); | 5724 | inode->i_mtime = current_time(inode); |
| @@ -7215,7 +7224,6 @@ static struct extent_map *btrfs_create_dio_extent(struct inode *inode, | |||
| 7215 | struct extent_map *em = NULL; | 7224 | struct extent_map *em = NULL; |
| 7216 | int ret; | 7225 | int ret; |
| 7217 | 7226 | ||
| 7218 | down_read(&BTRFS_I(inode)->dio_sem); | ||
| 7219 | if (type != BTRFS_ORDERED_NOCOW) { | 7227 | if (type != BTRFS_ORDERED_NOCOW) { |
| 7220 | em = create_pinned_em(inode, start, len, orig_start, | 7228 | em = create_pinned_em(inode, start, len, orig_start, |
| 7221 | block_start, block_len, orig_block_len, | 7229 | block_start, block_len, orig_block_len, |
| @@ -7234,7 +7242,6 @@ static struct extent_map *btrfs_create_dio_extent(struct inode *inode, | |||
| 7234 | em = ERR_PTR(ret); | 7242 | em = ERR_PTR(ret); |
| 7235 | } | 7243 | } |
| 7236 | out: | 7244 | out: |
| 7237 | up_read(&BTRFS_I(inode)->dio_sem); | ||
| 7238 | 7245 | ||
| 7239 | return em; | 7246 | return em; |
| 7240 | } | 7247 | } |
| @@ -8692,6 +8699,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
| 8692 | dio_data.unsubmitted_oe_range_start = (u64)offset; | 8699 | dio_data.unsubmitted_oe_range_start = (u64)offset; |
| 8693 | dio_data.unsubmitted_oe_range_end = (u64)offset; | 8700 | dio_data.unsubmitted_oe_range_end = (u64)offset; |
| 8694 | current->journal_info = &dio_data; | 8701 | current->journal_info = &dio_data; |
| 8702 | down_read(&BTRFS_I(inode)->dio_sem); | ||
| 8695 | } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK, | 8703 | } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK, |
| 8696 | &BTRFS_I(inode)->runtime_flags)) { | 8704 | &BTRFS_I(inode)->runtime_flags)) { |
| 8697 | inode_dio_end(inode); | 8705 | inode_dio_end(inode); |
| @@ -8704,6 +8712,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
| 8704 | iter, btrfs_get_blocks_direct, NULL, | 8712 | iter, btrfs_get_blocks_direct, NULL, |
| 8705 | btrfs_submit_direct, flags); | 8713 | btrfs_submit_direct, flags); |
| 8706 | if (iov_iter_rw(iter) == WRITE) { | 8714 | if (iov_iter_rw(iter) == WRITE) { |
| 8715 | up_read(&BTRFS_I(inode)->dio_sem); | ||
| 8707 | current->journal_info = NULL; | 8716 | current->journal_info = NULL; |
| 8708 | if (ret < 0 && ret != -EIOCBQUEUED) { | 8717 | if (ret < 0 && ret != -EIOCBQUEUED) { |
| 8709 | if (dio_data.reserve) | 8718 | if (dio_data.reserve) |
| @@ -9212,6 +9221,7 @@ static int btrfs_truncate(struct inode *inode) | |||
| 9212 | break; | 9221 | break; |
| 9213 | } | 9222 | } |
| 9214 | 9223 | ||
| 9224 | btrfs_block_rsv_release(fs_info, rsv, -1); | ||
| 9215 | ret = btrfs_block_rsv_migrate(&fs_info->trans_block_rsv, | 9225 | ret = btrfs_block_rsv_migrate(&fs_info->trans_block_rsv, |
| 9216 | rsv, min_size, 0); | 9226 | rsv, min_size, 0); |
| 9217 | BUG_ON(ret); /* shouldn't happen */ | 9227 | BUG_ON(ret); /* shouldn't happen */ |
| @@ -10579,8 +10589,6 @@ static const struct inode_operations btrfs_dir_inode_operations = { | |||
| 10579 | static const struct inode_operations btrfs_dir_ro_inode_operations = { | 10589 | static const struct inode_operations btrfs_dir_ro_inode_operations = { |
| 10580 | .lookup = btrfs_lookup, | 10590 | .lookup = btrfs_lookup, |
| 10581 | .permission = btrfs_permission, | 10591 | .permission = btrfs_permission, |
| 10582 | .get_acl = btrfs_get_acl, | ||
| 10583 | .set_acl = btrfs_set_acl, | ||
| 10584 | .update_time = btrfs_update_time, | 10592 | .update_time = btrfs_update_time, |
| 10585 | }; | 10593 | }; |
| 10586 | 10594 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 33f967d30b2a..21e51b0ba188 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -5653,6 +5653,10 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 5653 | #ifdef CONFIG_COMPAT | 5653 | #ifdef CONFIG_COMPAT |
| 5654 | long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 5654 | long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 5655 | { | 5655 | { |
| 5656 | /* | ||
| 5657 | * These all access 32-bit values anyway so no further | ||
| 5658 | * handling is necessary. | ||
| 5659 | */ | ||
| 5656 | switch (cmd) { | 5660 | switch (cmd) { |
| 5657 | case FS_IOC32_GETFLAGS: | 5661 | case FS_IOC32_GETFLAGS: |
| 5658 | cmd = FS_IOC_GETFLAGS; | 5662 | cmd = FS_IOC_GETFLAGS; |
| @@ -5663,8 +5667,6 @@ long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 5663 | case FS_IOC32_GETVERSION: | 5667 | case FS_IOC32_GETVERSION: |
| 5664 | cmd = FS_IOC_GETVERSION; | 5668 | cmd = FS_IOC_GETVERSION; |
| 5665 | break; | 5669 | break; |
| 5666 | default: | ||
| 5667 | return -ENOIOCTLCMD; | ||
| 5668 | } | 5670 | } |
| 5669 | 5671 | ||
| 5670 | return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); | 5672 | return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 8f6a2a5863b9..a27fc8791551 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -285,6 +285,7 @@ initiate_cifs_search(const unsigned int xid, struct file *file) | |||
| 285 | rc = -ENOMEM; | 285 | rc = -ENOMEM; |
| 286 | goto error_exit; | 286 | goto error_exit; |
| 287 | } | 287 | } |
| 288 | spin_lock_init(&cifsFile->file_info_lock); | ||
| 288 | file->private_data = cifsFile; | 289 | file->private_data = cifsFile; |
| 289 | cifsFile->tlink = cifs_get_tlink(tlink); | 290 | cifsFile->tlink = cifs_get_tlink(tlink); |
| 290 | tcon = tlink_tcon(tlink); | 291 | tcon = tlink_tcon(tlink); |
| @@ -1031,6 +1031,11 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, | |||
| 1031 | struct blk_dax_ctl dax = { 0 }; | 1031 | struct blk_dax_ctl dax = { 0 }; |
| 1032 | ssize_t map_len; | 1032 | ssize_t map_len; |
| 1033 | 1033 | ||
| 1034 | if (fatal_signal_pending(current)) { | ||
| 1035 | ret = -EINTR; | ||
| 1036 | break; | ||
| 1037 | } | ||
| 1038 | |||
| 1034 | dax.sector = dax_iomap_sector(iomap, pos); | 1039 | dax.sector = dax_iomap_sector(iomap, pos); |
| 1035 | dax.size = (length + offset + PAGE_SIZE - 1) & PAGE_MASK; | 1040 | dax.size = (length + offset + PAGE_SIZE - 1) & PAGE_MASK; |
| 1036 | map_len = dax_map_atomic(iomap->bdev, &dax); | 1041 | map_len = dax_map_atomic(iomap->bdev, &dax); |
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index 4304072161aa..40d61077bead 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c | |||
| @@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) | |||
| 542 | hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) { | 542 | hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) { |
| 543 | if (invalidate) | 543 | if (invalidate) |
| 544 | set_bit(FSCACHE_OBJECT_RETIRED, &object->flags); | 544 | set_bit(FSCACHE_OBJECT_RETIRED, &object->flags); |
| 545 | clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); | ||
| 545 | fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL); | 546 | fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL); |
| 546 | } | 547 | } |
| 547 | } else { | 548 | } else { |
| @@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) | |||
| 560 | wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t, | 561 | wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t, |
| 561 | TASK_UNINTERRUPTIBLE); | 562 | TASK_UNINTERRUPTIBLE); |
| 562 | 563 | ||
| 564 | /* Make sure any pending writes are cancelled. */ | ||
| 565 | if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) | ||
| 566 | fscache_invalidate_writes(cookie); | ||
| 567 | |||
| 563 | /* Reset the cookie state if it wasn't relinquished */ | 568 | /* Reset the cookie state if it wasn't relinquished */ |
| 564 | if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) { | 569 | if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) { |
| 565 | atomic_inc(&cookie->n_active); | 570 | atomic_inc(&cookie->n_active); |
diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c index 9b28649df3a1..a8aa00be4444 100644 --- a/fs/fscache/netfs.c +++ b/fs/fscache/netfs.c | |||
| @@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) | |||
| 48 | cookie->flags = 1 << FSCACHE_COOKIE_ENABLED; | 48 | cookie->flags = 1 << FSCACHE_COOKIE_ENABLED; |
| 49 | 49 | ||
| 50 | spin_lock_init(&cookie->lock); | 50 | spin_lock_init(&cookie->lock); |
| 51 | spin_lock_init(&cookie->stores_lock); | ||
| 51 | INIT_HLIST_HEAD(&cookie->backing_objects); | 52 | INIT_HLIST_HEAD(&cookie->backing_objects); |
| 52 | 53 | ||
| 53 | /* check the netfs type is not already present */ | 54 | /* check the netfs type is not already present */ |
diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 9e792e30f4db..7a182c87f378 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c | |||
| @@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object | |||
| 30 | static const struct fscache_state *fscache_object_available(struct fscache_object *, int); | 30 | static const struct fscache_state *fscache_object_available(struct fscache_object *, int); |
| 31 | static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int); | 31 | static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int); |
| 32 | static const struct fscache_state *fscache_update_object(struct fscache_object *, int); | 32 | static const struct fscache_state *fscache_update_object(struct fscache_object *, int); |
| 33 | static const struct fscache_state *fscache_object_dead(struct fscache_object *, int); | ||
| 33 | 34 | ||
| 34 | #define __STATE_NAME(n) fscache_osm_##n | 35 | #define __STATE_NAME(n) fscache_osm_##n |
| 35 | #define STATE(n) (&__STATE_NAME(n)) | 36 | #define STATE(n) (&__STATE_NAME(n)) |
| @@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure); | |||
| 91 | static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object); | 92 | static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object); |
| 92 | static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents); | 93 | static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents); |
| 93 | static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object); | 94 | static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object); |
| 94 | static WORK_STATE(OBJECT_DEAD, "DEAD", (void*)2UL); | 95 | static WORK_STATE(OBJECT_DEAD, "DEAD", fscache_object_dead); |
| 95 | 96 | ||
| 96 | static WAIT_STATE(WAIT_FOR_INIT, "?INI", | 97 | static WAIT_STATE(WAIT_FOR_INIT, "?INI", |
| 97 | TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD)); | 98 | TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD)); |
| @@ -229,6 +230,10 @@ execute_work_state: | |||
| 229 | event = -1; | 230 | event = -1; |
| 230 | if (new_state == NO_TRANSIT) { | 231 | if (new_state == NO_TRANSIT) { |
| 231 | _debug("{OBJ%x} %s notrans", object->debug_id, state->name); | 232 | _debug("{OBJ%x} %s notrans", object->debug_id, state->name); |
| 233 | if (unlikely(state == STATE(OBJECT_DEAD))) { | ||
| 234 | _leave(" [dead]"); | ||
| 235 | return; | ||
| 236 | } | ||
| 232 | fscache_enqueue_object(object); | 237 | fscache_enqueue_object(object); |
| 233 | event_mask = object->oob_event_mask; | 238 | event_mask = object->oob_event_mask; |
| 234 | goto unmask_events; | 239 | goto unmask_events; |
| @@ -239,7 +244,7 @@ execute_work_state: | |||
| 239 | object->state = state = new_state; | 244 | object->state = state = new_state; |
| 240 | 245 | ||
| 241 | if (state->work) { | 246 | if (state->work) { |
| 242 | if (unlikely(state->work == ((void *)2UL))) { | 247 | if (unlikely(state == STATE(OBJECT_DEAD))) { |
| 243 | _leave(" [dead]"); | 248 | _leave(" [dead]"); |
| 244 | return; | 249 | return; |
| 245 | } | 250 | } |
| @@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob | |||
| 645 | fscache_mark_object_dead(object); | 650 | fscache_mark_object_dead(object); |
| 646 | object->oob_event_mask = 0; | 651 | object->oob_event_mask = 0; |
| 647 | 652 | ||
| 653 | if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) { | ||
| 654 | /* Reject any new read/write ops and abort any that are pending. */ | ||
| 655 | clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); | ||
| 656 | fscache_cancel_all_ops(object); | ||
| 657 | } | ||
| 658 | |||
| 648 | if (list_empty(&object->dependents) && | 659 | if (list_empty(&object->dependents) && |
| 649 | object->n_ops == 0 && | 660 | object->n_ops == 0 && |
| 650 | object->n_children == 0) | 661 | object->n_children == 0) |
| @@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object, | |||
| 1077 | } | 1088 | } |
| 1078 | } | 1089 | } |
| 1079 | EXPORT_SYMBOL(fscache_object_mark_killed); | 1090 | EXPORT_SYMBOL(fscache_object_mark_killed); |
| 1091 | |||
| 1092 | /* | ||
| 1093 | * The object is dead. We can get here if an object gets queued by an event | ||
| 1094 | * that would lead to its death (such as EV_KILL) when the dispatcher is | ||
| 1095 | * already running (and so can be requeued) but hasn't yet cleared the event | ||
| 1096 | * mask. | ||
| 1097 | */ | ||
| 1098 | static const struct fscache_state *fscache_object_dead(struct fscache_object *object, | ||
| 1099 | int event) | ||
| 1100 | { | ||
| 1101 | if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD, | ||
| 1102 | &object->flags)) | ||
| 1103 | return NO_TRANSIT; | ||
| 1104 | |||
| 1105 | WARN(true, "FS-Cache object redispatched after death"); | ||
| 1106 | return NO_TRANSIT; | ||
| 1107 | } | ||
diff --git a/fs/iomap.c b/fs/iomap.c index 354a123f170e..a51cb4c07d4d 100644 --- a/fs/iomap.c +++ b/fs/iomap.c | |||
| @@ -114,6 +114,9 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags, | |||
| 114 | 114 | ||
| 115 | BUG_ON(pos + len > iomap->offset + iomap->length); | 115 | BUG_ON(pos + len > iomap->offset + iomap->length); |
| 116 | 116 | ||
| 117 | if (fatal_signal_pending(current)) | ||
| 118 | return -EINTR; | ||
| 119 | |||
| 117 | page = grab_cache_page_write_begin(inode->i_mapping, index, flags); | 120 | page = grab_cache_page_write_begin(inode->i_mapping, index, flags); |
| 118 | if (!page) | 121 | if (!page) |
| 119 | return -ENOMEM; | 122 | return -ENOMEM; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ecc151697fd4..0a0eaecf9676 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -2700,7 +2700,8 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, | |||
| 2700 | sattr->ia_valid |= ATTR_MTIME; | 2700 | sattr->ia_valid |= ATTR_MTIME; |
| 2701 | 2701 | ||
| 2702 | /* Except MODE, it seems harmless of setting twice. */ | 2702 | /* Except MODE, it seems harmless of setting twice. */ |
| 2703 | if ((attrset[1] & FATTR4_WORD1_MODE)) | 2703 | if (opendata->o_arg.createmode != NFS4_CREATE_EXCLUSIVE && |
| 2704 | attrset[1] & FATTR4_WORD1_MODE) | ||
| 2704 | sattr->ia_valid &= ~ATTR_MODE; | 2705 | sattr->ia_valid &= ~ATTR_MODE; |
| 2705 | 2706 | ||
| 2706 | if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL) | 2707 | if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL) |
| @@ -8490,6 +8491,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, | |||
| 8490 | goto out; | 8491 | goto out; |
| 8491 | } | 8492 | } |
| 8492 | 8493 | ||
| 8494 | nfs4_sequence_free_slot(&lgp->res.seq_res); | ||
| 8493 | err = nfs4_handle_exception(server, nfs4err, exception); | 8495 | err = nfs4_handle_exception(server, nfs4err, exception); |
| 8494 | if (!status) { | 8496 | if (!status) { |
| 8495 | if (exception->retry) | 8497 | if (exception->retry) |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 90e6193ce6be..daeb94e3acd4 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -1091,6 +1091,7 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) | |||
| 1091 | case -NFS4ERR_BADXDR: | 1091 | case -NFS4ERR_BADXDR: |
| 1092 | case -NFS4ERR_RESOURCE: | 1092 | case -NFS4ERR_RESOURCE: |
| 1093 | case -NFS4ERR_NOFILEHANDLE: | 1093 | case -NFS4ERR_NOFILEHANDLE: |
| 1094 | case -NFS4ERR_MOVED: | ||
| 1094 | /* Non-seqid mutating errors */ | 1095 | /* Non-seqid mutating errors */ |
| 1095 | return; | 1096 | return; |
| 1096 | }; | 1097 | }; |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 59554f3adf29..dd042498ce7c 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -1200,10 +1200,10 @@ _pnfs_return_layout(struct inode *ino) | |||
| 1200 | 1200 | ||
| 1201 | send = pnfs_prepare_layoutreturn(lo, &stateid, NULL); | 1201 | send = pnfs_prepare_layoutreturn(lo, &stateid, NULL); |
| 1202 | spin_unlock(&ino->i_lock); | 1202 | spin_unlock(&ino->i_lock); |
| 1203 | pnfs_free_lseg_list(&tmp_list); | ||
| 1204 | if (send) | 1203 | if (send) |
| 1205 | status = pnfs_send_layoutreturn(lo, &stateid, IOMODE_ANY, true); | 1204 | status = pnfs_send_layoutreturn(lo, &stateid, IOMODE_ANY, true); |
| 1206 | out_put_layout_hdr: | 1205 | out_put_layout_hdr: |
| 1206 | pnfs_free_lseg_list(&tmp_list); | ||
| 1207 | pnfs_put_layout_hdr(lo); | 1207 | pnfs_put_layout_hdr(lo); |
| 1208 | out: | 1208 | out: |
| 1209 | dprintk("<-- %s status: %d\n", __func__, status); | 1209 | dprintk("<-- %s status: %d\n", __func__, status); |
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c index 596205d939a1..1fc07a9c70e9 100644 --- a/fs/nfsd/nfs4layouts.c +++ b/fs/nfsd/nfs4layouts.c | |||
| @@ -223,10 +223,11 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate, | |||
| 223 | struct nfs4_layout_stateid *ls; | 223 | struct nfs4_layout_stateid *ls; |
| 224 | struct nfs4_stid *stp; | 224 | struct nfs4_stid *stp; |
| 225 | 225 | ||
| 226 | stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache); | 226 | stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache, |
| 227 | nfsd4_free_layout_stateid); | ||
| 227 | if (!stp) | 228 | if (!stp) |
| 228 | return NULL; | 229 | return NULL; |
| 229 | stp->sc_free = nfsd4_free_layout_stateid; | 230 | |
| 230 | get_nfs4_file(fp); | 231 | get_nfs4_file(fp); |
| 231 | stp->sc_file = fp; | 232 | stp->sc_file = fp; |
| 232 | 233 | ||
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 4b4beaaa4eaa..a0dee8ae9f97 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -633,8 +633,8 @@ out: | |||
| 633 | return co; | 633 | return co; |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, | 636 | struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab, |
| 637 | struct kmem_cache *slab) | 637 | void (*sc_free)(struct nfs4_stid *)) |
| 638 | { | 638 | { |
| 639 | struct nfs4_stid *stid; | 639 | struct nfs4_stid *stid; |
| 640 | int new_id; | 640 | int new_id; |
| @@ -650,6 +650,8 @@ struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, | |||
| 650 | idr_preload_end(); | 650 | idr_preload_end(); |
| 651 | if (new_id < 0) | 651 | if (new_id < 0) |
| 652 | goto out_free; | 652 | goto out_free; |
| 653 | |||
| 654 | stid->sc_free = sc_free; | ||
| 653 | stid->sc_client = cl; | 655 | stid->sc_client = cl; |
| 654 | stid->sc_stateid.si_opaque.so_id = new_id; | 656 | stid->sc_stateid.si_opaque.so_id = new_id; |
| 655 | stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid; | 657 | stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid; |
| @@ -675,15 +677,12 @@ out_free: | |||
| 675 | static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp) | 677 | static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp) |
| 676 | { | 678 | { |
| 677 | struct nfs4_stid *stid; | 679 | struct nfs4_stid *stid; |
| 678 | struct nfs4_ol_stateid *stp; | ||
| 679 | 680 | ||
| 680 | stid = nfs4_alloc_stid(clp, stateid_slab); | 681 | stid = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_ol_stateid); |
| 681 | if (!stid) | 682 | if (!stid) |
| 682 | return NULL; | 683 | return NULL; |
| 683 | 684 | ||
| 684 | stp = openlockstateid(stid); | 685 | return openlockstateid(stid); |
| 685 | stp->st_stid.sc_free = nfs4_free_ol_stateid; | ||
| 686 | return stp; | ||
| 687 | } | 686 | } |
| 688 | 687 | ||
| 689 | static void nfs4_free_deleg(struct nfs4_stid *stid) | 688 | static void nfs4_free_deleg(struct nfs4_stid *stid) |
| @@ -781,11 +780,10 @@ alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh, | |||
| 781 | goto out_dec; | 780 | goto out_dec; |
| 782 | if (delegation_blocked(¤t_fh->fh_handle)) | 781 | if (delegation_blocked(¤t_fh->fh_handle)) |
| 783 | goto out_dec; | 782 | goto out_dec; |
| 784 | dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); | 783 | dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab, nfs4_free_deleg)); |
| 785 | if (dp == NULL) | 784 | if (dp == NULL) |
| 786 | goto out_dec; | 785 | goto out_dec; |
| 787 | 786 | ||
| 788 | dp->dl_stid.sc_free = nfs4_free_deleg; | ||
| 789 | /* | 787 | /* |
| 790 | * delegation seqid's are never incremented. The 4.1 special | 788 | * delegation seqid's are never incremented. The 4.1 special |
| 791 | * meaning of seqid 0 isn't meaningful, really, but let's avoid | 789 | * meaning of seqid 0 isn't meaningful, really, but let's avoid |
| @@ -5580,7 +5578,6 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo, | |||
| 5580 | stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner); | 5578 | stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner); |
| 5581 | get_nfs4_file(fp); | 5579 | get_nfs4_file(fp); |
| 5582 | stp->st_stid.sc_file = fp; | 5580 | stp->st_stid.sc_file = fp; |
| 5583 | stp->st_stid.sc_free = nfs4_free_lock_stateid; | ||
| 5584 | stp->st_access_bmap = 0; | 5581 | stp->st_access_bmap = 0; |
| 5585 | stp->st_deny_bmap = open_stp->st_deny_bmap; | 5582 | stp->st_deny_bmap = open_stp->st_deny_bmap; |
| 5586 | stp->st_openstp = open_stp; | 5583 | stp->st_openstp = open_stp; |
| @@ -5623,7 +5620,7 @@ find_or_create_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fi, | |||
| 5623 | lst = find_lock_stateid(lo, fi); | 5620 | lst = find_lock_stateid(lo, fi); |
| 5624 | if (lst == NULL) { | 5621 | if (lst == NULL) { |
| 5625 | spin_unlock(&clp->cl_lock); | 5622 | spin_unlock(&clp->cl_lock); |
| 5626 | ns = nfs4_alloc_stid(clp, stateid_slab); | 5623 | ns = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_lock_stateid); |
| 5627 | if (ns == NULL) | 5624 | if (ns == NULL) |
| 5628 | return NULL; | 5625 | return NULL; |
| 5629 | 5626 | ||
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index c9399366f9df..4516e8b7d776 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
| @@ -603,8 +603,8 @@ extern __be32 nfs4_preprocess_stateid_op(struct svc_rqst *rqstp, | |||
| 603 | __be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate, | 603 | __be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate, |
| 604 | stateid_t *stateid, unsigned char typemask, | 604 | stateid_t *stateid, unsigned char typemask, |
| 605 | struct nfs4_stid **s, struct nfsd_net *nn); | 605 | struct nfs4_stid **s, struct nfsd_net *nn); |
| 606 | struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, | 606 | struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab, |
| 607 | struct kmem_cache *slab); | 607 | void (*sc_free)(struct nfs4_stid *)); |
| 608 | void nfs4_unhash_stid(struct nfs4_stid *s); | 608 | void nfs4_unhash_stid(struct nfs4_stid *s); |
| 609 | void nfs4_put_stid(struct nfs4_stid *s); | 609 | void nfs4_put_stid(struct nfs4_stid *s); |
| 610 | void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid); | 610 | void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid); |
diff --git a/fs/proc/page.c b/fs/proc/page.c index a2066e6dee90..2726536489b1 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c | |||
| @@ -173,7 +173,8 @@ u64 stable_page_flags(struct page *page) | |||
| 173 | u |= kpf_copy_bit(k, KPF_ACTIVE, PG_active); | 173 | u |= kpf_copy_bit(k, KPF_ACTIVE, PG_active); |
| 174 | u |= kpf_copy_bit(k, KPF_RECLAIM, PG_reclaim); | 174 | u |= kpf_copy_bit(k, KPF_RECLAIM, PG_reclaim); |
| 175 | 175 | ||
| 176 | u |= kpf_copy_bit(k, KPF_SWAPCACHE, PG_swapcache); | 176 | if (PageSwapCache(page)) |
| 177 | u |= 1 << KPF_SWAPCACHE; | ||
| 177 | u |= kpf_copy_bit(k, KPF_SWAPBACKED, PG_swapbacked); | 178 | u |= kpf_copy_bit(k, KPF_SWAPBACKED, PG_swapbacked); |
| 178 | 179 | ||
| 179 | u |= kpf_copy_bit(k, KPF_UNEVICTABLE, PG_unevictable); | 180 | u |= kpf_copy_bit(k, KPF_UNEVICTABLE, PG_unevictable); |
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 27c059e1760a..1d887efaaf71 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c | |||
| @@ -280,7 +280,7 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, | |||
| 280 | 1, id, type, PSTORE_TYPE_PMSG, 0); | 280 | 1, id, type, PSTORE_TYPE_PMSG, 0); |
| 281 | 281 | ||
| 282 | /* ftrace is last since it may want to dynamically allocate memory. */ | 282 | /* ftrace is last since it may want to dynamically allocate memory. */ |
| 283 | if (!prz_ok(prz)) { | 283 | if (!prz_ok(prz) && cxt->fprzs) { |
| 284 | if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)) { | 284 | if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)) { |
| 285 | prz = ramoops_get_next_prz(cxt->fprzs, | 285 | prz = ramoops_get_next_prz(cxt->fprzs, |
| 286 | &cxt->ftrace_read_cnt, 1, id, type, | 286 | &cxt->ftrace_read_cnt, 1, id, type, |
diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c index d346d42c54d1..33db69be4832 100644 --- a/fs/xfs/libxfs/xfs_ag_resv.c +++ b/fs/xfs/libxfs/xfs_ag_resv.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include "xfs_rmap_btree.h" | 39 | #include "xfs_rmap_btree.h" |
| 40 | #include "xfs_btree.h" | 40 | #include "xfs_btree.h" |
| 41 | #include "xfs_refcount_btree.h" | 41 | #include "xfs_refcount_btree.h" |
| 42 | #include "xfs_ialloc_btree.h" | ||
| 42 | 43 | ||
| 43 | /* | 44 | /* |
| 44 | * Per-AG Block Reservations | 45 | * Per-AG Block Reservations |
| @@ -200,22 +201,30 @@ __xfs_ag_resv_init( | |||
| 200 | struct xfs_mount *mp = pag->pag_mount; | 201 | struct xfs_mount *mp = pag->pag_mount; |
| 201 | struct xfs_ag_resv *resv; | 202 | struct xfs_ag_resv *resv; |
| 202 | int error; | 203 | int error; |
| 204 | xfs_extlen_t reserved; | ||
| 203 | 205 | ||
| 204 | resv = xfs_perag_resv(pag, type); | ||
| 205 | if (used > ask) | 206 | if (used > ask) |
| 206 | ask = used; | 207 | ask = used; |
| 207 | resv->ar_asked = ask; | 208 | reserved = ask - used; |
| 208 | resv->ar_reserved = resv->ar_orig_reserved = ask - used; | ||
| 209 | mp->m_ag_max_usable -= ask; | ||
| 210 | 209 | ||
| 211 | trace_xfs_ag_resv_init(pag, type, ask); | 210 | error = xfs_mod_fdblocks(mp, -(int64_t)reserved, true); |
| 212 | 211 | if (error) { | |
| 213 | error = xfs_mod_fdblocks(mp, -(int64_t)resv->ar_reserved, true); | ||
| 214 | if (error) | ||
| 215 | trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno, | 212 | trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno, |
| 216 | error, _RET_IP_); | 213 | error, _RET_IP_); |
| 214 | xfs_warn(mp, | ||
| 215 | "Per-AG reservation for AG %u failed. Filesystem may run out of space.", | ||
| 216 | pag->pag_agno); | ||
| 217 | return error; | ||
| 218 | } | ||
| 217 | 219 | ||
| 218 | return error; | 220 | mp->m_ag_max_usable -= ask; |
| 221 | |||
| 222 | resv = xfs_perag_resv(pag, type); | ||
| 223 | resv->ar_asked = ask; | ||
| 224 | resv->ar_reserved = resv->ar_orig_reserved = reserved; | ||
| 225 | |||
| 226 | trace_xfs_ag_resv_init(pag, type, ask); | ||
| 227 | return 0; | ||
| 219 | } | 228 | } |
| 220 | 229 | ||
| 221 | /* Create a per-AG block reservation. */ | 230 | /* Create a per-AG block reservation. */ |
| @@ -223,6 +232,8 @@ int | |||
| 223 | xfs_ag_resv_init( | 232 | xfs_ag_resv_init( |
| 224 | struct xfs_perag *pag) | 233 | struct xfs_perag *pag) |
| 225 | { | 234 | { |
| 235 | struct xfs_mount *mp = pag->pag_mount; | ||
| 236 | xfs_agnumber_t agno = pag->pag_agno; | ||
| 226 | xfs_extlen_t ask; | 237 | xfs_extlen_t ask; |
| 227 | xfs_extlen_t used; | 238 | xfs_extlen_t used; |
| 228 | int error = 0; | 239 | int error = 0; |
| @@ -231,23 +242,45 @@ xfs_ag_resv_init( | |||
| 231 | if (pag->pag_meta_resv.ar_asked == 0) { | 242 | if (pag->pag_meta_resv.ar_asked == 0) { |
| 232 | ask = used = 0; | 243 | ask = used = 0; |
| 233 | 244 | ||
| 234 | error = xfs_refcountbt_calc_reserves(pag->pag_mount, | 245 | error = xfs_refcountbt_calc_reserves(mp, agno, &ask, &used); |
| 235 | pag->pag_agno, &ask, &used); | ||
| 236 | if (error) | 246 | if (error) |
| 237 | goto out; | 247 | goto out; |
| 238 | 248 | ||
| 239 | error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, | 249 | error = xfs_finobt_calc_reserves(mp, agno, &ask, &used); |
| 240 | ask, used); | ||
| 241 | if (error) | 250 | if (error) |
| 242 | goto out; | 251 | goto out; |
| 252 | |||
| 253 | error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, | ||
| 254 | ask, used); | ||
| 255 | if (error) { | ||
| 256 | /* | ||
| 257 | * Because we didn't have per-AG reservations when the | ||
| 258 | * finobt feature was added we might not be able to | ||
| 259 | * reserve all needed blocks. Warn and fall back to the | ||
| 260 | * old and potentially buggy code in that case, but | ||
| 261 | * ensure we do have the reservation for the refcountbt. | ||
| 262 | */ | ||
| 263 | ask = used = 0; | ||
| 264 | |||
| 265 | mp->m_inotbt_nores = true; | ||
| 266 | |||
| 267 | error = xfs_refcountbt_calc_reserves(mp, agno, &ask, | ||
| 268 | &used); | ||
| 269 | if (error) | ||
| 270 | goto out; | ||
| 271 | |||
| 272 | error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, | ||
| 273 | ask, used); | ||
| 274 | if (error) | ||
| 275 | goto out; | ||
| 276 | } | ||
| 243 | } | 277 | } |
| 244 | 278 | ||
| 245 | /* Create the AGFL metadata reservation */ | 279 | /* Create the AGFL metadata reservation */ |
| 246 | if (pag->pag_agfl_resv.ar_asked == 0) { | 280 | if (pag->pag_agfl_resv.ar_asked == 0) { |
| 247 | ask = used = 0; | 281 | ask = used = 0; |
| 248 | 282 | ||
| 249 | error = xfs_rmapbt_calc_reserves(pag->pag_mount, pag->pag_agno, | 283 | error = xfs_rmapbt_calc_reserves(mp, agno, &ask, &used); |
| 250 | &ask, &used); | ||
| 251 | if (error) | 284 | if (error) |
| 252 | goto out; | 285 | goto out; |
| 253 | 286 | ||
| @@ -256,9 +289,16 @@ xfs_ag_resv_init( | |||
| 256 | goto out; | 289 | goto out; |
| 257 | } | 290 | } |
| 258 | 291 | ||
| 292 | #ifdef DEBUG | ||
| 293 | /* need to read in the AGF for the ASSERT below to work */ | ||
| 294 | error = xfs_alloc_pagf_init(pag->pag_mount, NULL, pag->pag_agno, 0); | ||
| 295 | if (error) | ||
| 296 | return error; | ||
| 297 | |||
| 259 | ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved + | 298 | ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved + |
| 260 | xfs_perag_resv(pag, XFS_AG_RESV_AGFL)->ar_reserved <= | 299 | xfs_perag_resv(pag, XFS_AG_RESV_AGFL)->ar_reserved <= |
| 261 | pag->pagf_freeblks + pag->pagf_flcount); | 300 | pag->pagf_freeblks + pag->pagf_flcount); |
| 301 | #endif | ||
| 262 | out: | 302 | out: |
| 263 | return error; | 303 | return error; |
| 264 | } | 304 | } |
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index af1ecb19121e..6622d46ddec3 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c | |||
| @@ -131,9 +131,6 @@ xfs_attr_get( | |||
| 131 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 131 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) |
| 132 | return -EIO; | 132 | return -EIO; |
| 133 | 133 | ||
| 134 | if (!xfs_inode_hasattr(ip)) | ||
| 135 | return -ENOATTR; | ||
| 136 | |||
| 137 | error = xfs_attr_args_init(&args, ip, name, flags); | 134 | error = xfs_attr_args_init(&args, ip, name, flags); |
| 138 | if (error) | 135 | if (error) |
| 139 | return error; | 136 | return error; |
| @@ -392,9 +389,6 @@ xfs_attr_remove( | |||
| 392 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | 389 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) |
| 393 | return -EIO; | 390 | return -EIO; |
| 394 | 391 | ||
| 395 | if (!xfs_inode_hasattr(dp)) | ||
| 396 | return -ENOATTR; | ||
| 397 | |||
| 398 | error = xfs_attr_args_init(&args, dp, name, flags); | 392 | error = xfs_attr_args_init(&args, dp, name, flags); |
| 399 | if (error) | 393 | if (error) |
| 400 | return error; | 394 | return error; |
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 44773c9eb957..bfc00de5c6f1 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
| @@ -3629,7 +3629,7 @@ xfs_bmap_btalloc( | |||
| 3629 | align = xfs_get_cowextsz_hint(ap->ip); | 3629 | align = xfs_get_cowextsz_hint(ap->ip); |
| 3630 | else if (xfs_alloc_is_userdata(ap->datatype)) | 3630 | else if (xfs_alloc_is_userdata(ap->datatype)) |
| 3631 | align = xfs_get_extsz_hint(ap->ip); | 3631 | align = xfs_get_extsz_hint(ap->ip); |
| 3632 | if (unlikely(align)) { | 3632 | if (align) { |
| 3633 | error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, | 3633 | error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, |
| 3634 | align, 0, ap->eof, 0, ap->conv, | 3634 | align, 0, ap->eof, 0, ap->conv, |
| 3635 | &ap->offset, &ap->length); | 3635 | &ap->offset, &ap->length); |
| @@ -3701,7 +3701,7 @@ xfs_bmap_btalloc( | |||
| 3701 | args.minlen = ap->minlen; | 3701 | args.minlen = ap->minlen; |
| 3702 | } | 3702 | } |
| 3703 | /* apply extent size hints if obtained earlier */ | 3703 | /* apply extent size hints if obtained earlier */ |
| 3704 | if (unlikely(align)) { | 3704 | if (align) { |
| 3705 | args.prod = align; | 3705 | args.prod = align; |
| 3706 | if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod))) | 3706 | if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod))) |
| 3707 | args.mod = (xfs_extlen_t)(args.prod - args.mod); | 3707 | args.mod = (xfs_extlen_t)(args.prod - args.mod); |
| @@ -4514,8 +4514,6 @@ xfs_bmapi_write( | |||
| 4514 | int n; /* current extent index */ | 4514 | int n; /* current extent index */ |
| 4515 | xfs_fileoff_t obno; /* old block number (offset) */ | 4515 | xfs_fileoff_t obno; /* old block number (offset) */ |
| 4516 | int whichfork; /* data or attr fork */ | 4516 | int whichfork; /* data or attr fork */ |
| 4517 | char inhole; /* current location is hole in file */ | ||
| 4518 | char wasdelay; /* old extent was delayed */ | ||
| 4519 | 4517 | ||
| 4520 | #ifdef DEBUG | 4518 | #ifdef DEBUG |
| 4521 | xfs_fileoff_t orig_bno; /* original block number value */ | 4519 | xfs_fileoff_t orig_bno; /* original block number value */ |
| @@ -4603,22 +4601,44 @@ xfs_bmapi_write( | |||
| 4603 | bma.firstblock = firstblock; | 4601 | bma.firstblock = firstblock; |
| 4604 | 4602 | ||
| 4605 | while (bno < end && n < *nmap) { | 4603 | while (bno < end && n < *nmap) { |
| 4606 | inhole = eof || bma.got.br_startoff > bno; | 4604 | bool need_alloc = false, wasdelay = false; |
| 4607 | wasdelay = !inhole && isnullstartblock(bma.got.br_startblock); | ||
| 4608 | 4605 | ||
| 4609 | /* | 4606 | /* in hole or beyoned EOF? */ |
| 4610 | * Make sure we only reflink into a hole. | 4607 | if (eof || bma.got.br_startoff > bno) { |
| 4611 | */ | 4608 | if (flags & XFS_BMAPI_DELALLOC) { |
| 4612 | if (flags & XFS_BMAPI_REMAP) | 4609 | /* |
| 4613 | ASSERT(inhole); | 4610 | * For the COW fork we can reasonably get a |
| 4614 | if (flags & XFS_BMAPI_COWFORK) | 4611 | * request for converting an extent that races |
| 4615 | ASSERT(!inhole); | 4612 | * with other threads already having converted |
| 4613 | * part of it, as there converting COW to | ||
| 4614 | * regular blocks is not protected using the | ||
| 4615 | * IOLOCK. | ||
| 4616 | */ | ||
| 4617 | ASSERT(flags & XFS_BMAPI_COWFORK); | ||
| 4618 | if (!(flags & XFS_BMAPI_COWFORK)) { | ||
| 4619 | error = -EIO; | ||
| 4620 | goto error0; | ||
| 4621 | } | ||
| 4622 | |||
| 4623 | if (eof || bno >= end) | ||
| 4624 | break; | ||
| 4625 | } else { | ||
| 4626 | need_alloc = true; | ||
| 4627 | } | ||
| 4628 | } else { | ||
| 4629 | /* | ||
| 4630 | * Make sure we only reflink into a hole. | ||
| 4631 | */ | ||
| 4632 | ASSERT(!(flags & XFS_BMAPI_REMAP)); | ||
| 4633 | if (isnullstartblock(bma.got.br_startblock)) | ||
| 4634 | wasdelay = true; | ||
| 4635 | } | ||
| 4616 | 4636 | ||
| 4617 | /* | 4637 | /* |
| 4618 | * First, deal with the hole before the allocated space | 4638 | * First, deal with the hole before the allocated space |
| 4619 | * that we found, if any. | 4639 | * that we found, if any. |
| 4620 | */ | 4640 | */ |
| 4621 | if (inhole || wasdelay) { | 4641 | if (need_alloc || wasdelay) { |
| 4622 | bma.eof = eof; | 4642 | bma.eof = eof; |
| 4623 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); | 4643 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); |
| 4624 | bma.wasdel = wasdelay; | 4644 | bma.wasdel = wasdelay; |
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index cecd094404cc..cdef87db5262 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h | |||
| @@ -110,6 +110,9 @@ struct xfs_extent_free_item | |||
| 110 | /* Map something in the CoW fork. */ | 110 | /* Map something in the CoW fork. */ |
| 111 | #define XFS_BMAPI_COWFORK 0x200 | 111 | #define XFS_BMAPI_COWFORK 0x200 |
| 112 | 112 | ||
| 113 | /* Only convert delalloc space, don't allocate entirely new extents */ | ||
| 114 | #define XFS_BMAPI_DELALLOC 0x400 | ||
| 115 | |||
| 113 | #define XFS_BMAPI_FLAGS \ | 116 | #define XFS_BMAPI_FLAGS \ |
| 114 | { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ | 117 | { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ |
| 115 | { XFS_BMAPI_METADATA, "METADATA" }, \ | 118 | { XFS_BMAPI_METADATA, "METADATA" }, \ |
| @@ -120,7 +123,8 @@ struct xfs_extent_free_item | |||
| 120 | { XFS_BMAPI_CONVERT, "CONVERT" }, \ | 123 | { XFS_BMAPI_CONVERT, "CONVERT" }, \ |
| 121 | { XFS_BMAPI_ZERO, "ZERO" }, \ | 124 | { XFS_BMAPI_ZERO, "ZERO" }, \ |
| 122 | { XFS_BMAPI_REMAP, "REMAP" }, \ | 125 | { XFS_BMAPI_REMAP, "REMAP" }, \ |
| 123 | { XFS_BMAPI_COWFORK, "COWFORK" } | 126 | { XFS_BMAPI_COWFORK, "COWFORK" }, \ |
| 127 | { XFS_BMAPI_DELALLOC, "DELALLOC" } | ||
| 124 | 128 | ||
| 125 | 129 | ||
| 126 | static inline int xfs_bmapi_aflag(int w) | 130 | static inline int xfs_bmapi_aflag(int w) |
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c index 0fd086d03d41..7c471881c9a6 100644 --- a/fs/xfs/libxfs/xfs_ialloc_btree.c +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c | |||
| @@ -82,11 +82,12 @@ xfs_finobt_set_root( | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | STATIC int | 84 | STATIC int |
| 85 | xfs_inobt_alloc_block( | 85 | __xfs_inobt_alloc_block( |
| 86 | struct xfs_btree_cur *cur, | 86 | struct xfs_btree_cur *cur, |
| 87 | union xfs_btree_ptr *start, | 87 | union xfs_btree_ptr *start, |
| 88 | union xfs_btree_ptr *new, | 88 | union xfs_btree_ptr *new, |
| 89 | int *stat) | 89 | int *stat, |
| 90 | enum xfs_ag_resv_type resv) | ||
| 90 | { | 91 | { |
| 91 | xfs_alloc_arg_t args; /* block allocation args */ | 92 | xfs_alloc_arg_t args; /* block allocation args */ |
| 92 | int error; /* error return value */ | 93 | int error; /* error return value */ |
| @@ -103,6 +104,7 @@ xfs_inobt_alloc_block( | |||
| 103 | args.maxlen = 1; | 104 | args.maxlen = 1; |
| 104 | args.prod = 1; | 105 | args.prod = 1; |
| 105 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 106 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
| 107 | args.resv = resv; | ||
| 106 | 108 | ||
| 107 | error = xfs_alloc_vextent(&args); | 109 | error = xfs_alloc_vextent(&args); |
| 108 | if (error) { | 110 | if (error) { |
| @@ -123,6 +125,27 @@ xfs_inobt_alloc_block( | |||
| 123 | } | 125 | } |
| 124 | 126 | ||
| 125 | STATIC int | 127 | STATIC int |
| 128 | xfs_inobt_alloc_block( | ||
| 129 | struct xfs_btree_cur *cur, | ||
| 130 | union xfs_btree_ptr *start, | ||
| 131 | union xfs_btree_ptr *new, | ||
| 132 | int *stat) | ||
| 133 | { | ||
| 134 | return __xfs_inobt_alloc_block(cur, start, new, stat, XFS_AG_RESV_NONE); | ||
| 135 | } | ||
| 136 | |||
| 137 | STATIC int | ||
| 138 | xfs_finobt_alloc_block( | ||
| 139 | struct xfs_btree_cur *cur, | ||
| 140 | union xfs_btree_ptr *start, | ||
| 141 | union xfs_btree_ptr *new, | ||
| 142 | int *stat) | ||
| 143 | { | ||
| 144 | return __xfs_inobt_alloc_block(cur, start, new, stat, | ||
| 145 | XFS_AG_RESV_METADATA); | ||
| 146 | } | ||
| 147 | |||
| 148 | STATIC int | ||
| 126 | xfs_inobt_free_block( | 149 | xfs_inobt_free_block( |
| 127 | struct xfs_btree_cur *cur, | 150 | struct xfs_btree_cur *cur, |
| 128 | struct xfs_buf *bp) | 151 | struct xfs_buf *bp) |
| @@ -328,7 +351,7 @@ static const struct xfs_btree_ops xfs_finobt_ops = { | |||
| 328 | 351 | ||
| 329 | .dup_cursor = xfs_inobt_dup_cursor, | 352 | .dup_cursor = xfs_inobt_dup_cursor, |
| 330 | .set_root = xfs_finobt_set_root, | 353 | .set_root = xfs_finobt_set_root, |
| 331 | .alloc_block = xfs_inobt_alloc_block, | 354 | .alloc_block = xfs_finobt_alloc_block, |
| 332 | .free_block = xfs_inobt_free_block, | 355 | .free_block = xfs_inobt_free_block, |
| 333 | .get_minrecs = xfs_inobt_get_minrecs, | 356 | .get_minrecs = xfs_inobt_get_minrecs, |
| 334 | .get_maxrecs = xfs_inobt_get_maxrecs, | 357 | .get_maxrecs = xfs_inobt_get_maxrecs, |
| @@ -480,3 +503,64 @@ xfs_inobt_rec_check_count( | |||
| 480 | return 0; | 503 | return 0; |
| 481 | } | 504 | } |
| 482 | #endif /* DEBUG */ | 505 | #endif /* DEBUG */ |
| 506 | |||
| 507 | static xfs_extlen_t | ||
| 508 | xfs_inobt_max_size( | ||
| 509 | struct xfs_mount *mp) | ||
| 510 | { | ||
| 511 | /* Bail out if we're uninitialized, which can happen in mkfs. */ | ||
| 512 | if (mp->m_inobt_mxr[0] == 0) | ||
| 513 | return 0; | ||
| 514 | |||
| 515 | return xfs_btree_calc_size(mp, mp->m_inobt_mnr, | ||
| 516 | (uint64_t)mp->m_sb.sb_agblocks * mp->m_sb.sb_inopblock / | ||
| 517 | XFS_INODES_PER_CHUNK); | ||
| 518 | } | ||
| 519 | |||
| 520 | static int | ||
| 521 | xfs_inobt_count_blocks( | ||
| 522 | struct xfs_mount *mp, | ||
| 523 | xfs_agnumber_t agno, | ||
| 524 | xfs_btnum_t btnum, | ||
| 525 | xfs_extlen_t *tree_blocks) | ||
| 526 | { | ||
| 527 | struct xfs_buf *agbp; | ||
| 528 | struct xfs_btree_cur *cur; | ||
| 529 | int error; | ||
| 530 | |||
| 531 | error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); | ||
| 532 | if (error) | ||
| 533 | return error; | ||
| 534 | |||
| 535 | cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno, btnum); | ||
| 536 | error = xfs_btree_count_blocks(cur, tree_blocks); | ||
| 537 | xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); | ||
| 538 | xfs_buf_relse(agbp); | ||
| 539 | |||
| 540 | return error; | ||
| 541 | } | ||
| 542 | |||
| 543 | /* | ||
| 544 | * Figure out how many blocks to reserve and how many are used by this btree. | ||
| 545 | */ | ||
| 546 | int | ||
| 547 | xfs_finobt_calc_reserves( | ||
| 548 | struct xfs_mount *mp, | ||
| 549 | xfs_agnumber_t agno, | ||
| 550 | xfs_extlen_t *ask, | ||
| 551 | xfs_extlen_t *used) | ||
| 552 | { | ||
| 553 | xfs_extlen_t tree_len = 0; | ||
| 554 | int error; | ||
| 555 | |||
| 556 | if (!xfs_sb_version_hasfinobt(&mp->m_sb)) | ||
| 557 | return 0; | ||
| 558 | |||
| 559 | error = xfs_inobt_count_blocks(mp, agno, XFS_BTNUM_FINO, &tree_len); | ||
| 560 | if (error) | ||
| 561 | return error; | ||
| 562 | |||
| 563 | *ask += xfs_inobt_max_size(mp); | ||
| 564 | *used += tree_len; | ||
| 565 | return 0; | ||
| 566 | } | ||
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.h b/fs/xfs/libxfs/xfs_ialloc_btree.h index bd88453217ce..aa81e2e63f3f 100644 --- a/fs/xfs/libxfs/xfs_ialloc_btree.h +++ b/fs/xfs/libxfs/xfs_ialloc_btree.h | |||
| @@ -72,4 +72,7 @@ int xfs_inobt_rec_check_count(struct xfs_mount *, | |||
| 72 | #define xfs_inobt_rec_check_count(mp, rec) 0 | 72 | #define xfs_inobt_rec_check_count(mp, rec) 0 |
| 73 | #endif /* DEBUG */ | 73 | #endif /* DEBUG */ |
| 74 | 74 | ||
| 75 | int xfs_finobt_calc_reserves(struct xfs_mount *mp, xfs_agnumber_t agno, | ||
| 76 | xfs_extlen_t *ask, xfs_extlen_t *used); | ||
| 77 | |||
| 75 | #endif /* __XFS_IALLOC_BTREE_H__ */ | 78 | #endif /* __XFS_IALLOC_BTREE_H__ */ |
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 2580262e4ea0..584ec896a533 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c | |||
| @@ -242,7 +242,7 @@ xfs_mount_validate_sb( | |||
| 242 | sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG || | 242 | sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG || |
| 243 | sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || | 243 | sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || |
| 244 | sbp->sb_blocksize != (1 << sbp->sb_blocklog) || | 244 | sbp->sb_blocksize != (1 << sbp->sb_blocklog) || |
| 245 | sbp->sb_dirblklog > XFS_MAX_BLOCKSIZE_LOG || | 245 | sbp->sb_dirblklog + sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || |
| 246 | sbp->sb_inodesize < XFS_DINODE_MIN_SIZE || | 246 | sbp->sb_inodesize < XFS_DINODE_MIN_SIZE || |
| 247 | sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || | 247 | sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || |
| 248 | sbp->sb_inodelog < XFS_DINODE_MIN_LOG || | 248 | sbp->sb_inodelog < XFS_DINODE_MIN_LOG || |
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index b9abce524c33..c1417919ab0a 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
| @@ -528,7 +528,6 @@ xfs_getbmap( | |||
| 528 | xfs_bmbt_irec_t *map; /* buffer for user's data */ | 528 | xfs_bmbt_irec_t *map; /* buffer for user's data */ |
| 529 | xfs_mount_t *mp; /* file system mount point */ | 529 | xfs_mount_t *mp; /* file system mount point */ |
| 530 | int nex; /* # of user extents can do */ | 530 | int nex; /* # of user extents can do */ |
| 531 | int nexleft; /* # of user extents left */ | ||
| 532 | int subnex; /* # of bmapi's can do */ | 531 | int subnex; /* # of bmapi's can do */ |
| 533 | int nmap; /* number of map entries */ | 532 | int nmap; /* number of map entries */ |
| 534 | struct getbmapx *out; /* output structure */ | 533 | struct getbmapx *out; /* output structure */ |
| @@ -686,10 +685,8 @@ xfs_getbmap( | |||
| 686 | goto out_free_map; | 685 | goto out_free_map; |
| 687 | } | 686 | } |
| 688 | 687 | ||
| 689 | nexleft = nex; | ||
| 690 | |||
| 691 | do { | 688 | do { |
| 692 | nmap = (nexleft > subnex) ? subnex : nexleft; | 689 | nmap = (nex> subnex) ? subnex : nex; |
| 693 | error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), | 690 | error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), |
| 694 | XFS_BB_TO_FSB(mp, bmv->bmv_length), | 691 | XFS_BB_TO_FSB(mp, bmv->bmv_length), |
| 695 | map, &nmap, bmapi_flags); | 692 | map, &nmap, bmapi_flags); |
| @@ -697,8 +694,8 @@ xfs_getbmap( | |||
| 697 | goto out_free_map; | 694 | goto out_free_map; |
| 698 | ASSERT(nmap <= subnex); | 695 | ASSERT(nmap <= subnex); |
| 699 | 696 | ||
| 700 | for (i = 0; i < nmap && nexleft && bmv->bmv_length && | 697 | for (i = 0; i < nmap && bmv->bmv_length && |
| 701 | cur_ext < bmv->bmv_count; i++) { | 698 | cur_ext < bmv->bmv_count - 1; i++) { |
| 702 | out[cur_ext].bmv_oflags = 0; | 699 | out[cur_ext].bmv_oflags = 0; |
| 703 | if (map[i].br_state == XFS_EXT_UNWRITTEN) | 700 | if (map[i].br_state == XFS_EXT_UNWRITTEN) |
| 704 | out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC; | 701 | out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC; |
| @@ -760,16 +757,27 @@ xfs_getbmap( | |||
| 760 | continue; | 757 | continue; |
| 761 | } | 758 | } |
| 762 | 759 | ||
| 760 | /* | ||
| 761 | * In order to report shared extents accurately, | ||
| 762 | * we report each distinct shared/unshared part | ||
| 763 | * of a single bmbt record using multiple bmap | ||
| 764 | * extents. To make that happen, we iterate the | ||
| 765 | * same map array item multiple times, each | ||
| 766 | * time trimming out the subextent that we just | ||
| 767 | * reported. | ||
| 768 | * | ||
| 769 | * Because of this, we must check the out array | ||
| 770 | * index (cur_ext) directly against bmv_count-1 | ||
| 771 | * to avoid overflows. | ||
| 772 | */ | ||
| 763 | if (inject_map.br_startblock != NULLFSBLOCK) { | 773 | if (inject_map.br_startblock != NULLFSBLOCK) { |
| 764 | map[i] = inject_map; | 774 | map[i] = inject_map; |
| 765 | i--; | 775 | i--; |
| 766 | } else | 776 | } |
| 767 | nexleft--; | ||
| 768 | bmv->bmv_entries++; | 777 | bmv->bmv_entries++; |
| 769 | cur_ext++; | 778 | cur_ext++; |
| 770 | } | 779 | } |
| 771 | } while (nmap && nexleft && bmv->bmv_length && | 780 | } while (nmap && bmv->bmv_length && cur_ext < bmv->bmv_count - 1); |
| 772 | cur_ext < bmv->bmv_count); | ||
| 773 | 781 | ||
| 774 | out_free_map: | 782 | out_free_map: |
| 775 | kmem_free(map); | 783 | kmem_free(map); |
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 7f0a01f7b592..ac3b4db519df 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
| @@ -422,6 +422,7 @@ retry: | |||
| 422 | out_free_pages: | 422 | out_free_pages: |
| 423 | for (i = 0; i < bp->b_page_count; i++) | 423 | for (i = 0; i < bp->b_page_count; i++) |
| 424 | __free_page(bp->b_pages[i]); | 424 | __free_page(bp->b_pages[i]); |
| 425 | bp->b_flags &= ~_XBF_PAGES; | ||
| 425 | return error; | 426 | return error; |
| 426 | } | 427 | } |
| 427 | 428 | ||
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index b9557795eb74..de32f0fe47c8 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -1792,22 +1792,23 @@ xfs_inactive_ifree( | |||
| 1792 | int error; | 1792 | int error; |
| 1793 | 1793 | ||
| 1794 | /* | 1794 | /* |
| 1795 | * The ifree transaction might need to allocate blocks for record | 1795 | * We try to use a per-AG reservation for any block needed by the finobt |
| 1796 | * insertion to the finobt. We don't want to fail here at ENOSPC, so | 1796 | * tree, but as the finobt feature predates the per-AG reservation |
| 1797 | * allow ifree to dip into the reserved block pool if necessary. | 1797 | * support a degraded file system might not have enough space for the |
| 1798 | * | 1798 | * reservation at mount time. In that case try to dip into the reserved |
| 1799 | * Freeing large sets of inodes generally means freeing inode chunks, | 1799 | * pool and pray. |
| 1800 | * directory and file data blocks, so this should be relatively safe. | ||
| 1801 | * Only under severe circumstances should it be possible to free enough | ||
| 1802 | * inodes to exhaust the reserve block pool via finobt expansion while | ||
| 1803 | * at the same time not creating free space in the filesystem. | ||
| 1804 | * | 1800 | * |
| 1805 | * Send a warning if the reservation does happen to fail, as the inode | 1801 | * Send a warning if the reservation does happen to fail, as the inode |
| 1806 | * now remains allocated and sits on the unlinked list until the fs is | 1802 | * now remains allocated and sits on the unlinked list until the fs is |
| 1807 | * repaired. | 1803 | * repaired. |
| 1808 | */ | 1804 | */ |
| 1809 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ifree, | 1805 | if (unlikely(mp->m_inotbt_nores)) { |
| 1810 | XFS_IFREE_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp); | 1806 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ifree, |
| 1807 | XFS_IFREE_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, | ||
| 1808 | &tp); | ||
| 1809 | } else { | ||
| 1810 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ifree, 0, 0, 0, &tp); | ||
| 1811 | } | ||
| 1811 | if (error) { | 1812 | if (error) { |
| 1812 | if (error == -ENOSPC) { | 1813 | if (error == -ENOSPC) { |
| 1813 | xfs_warn_ratelimited(mp, | 1814 | xfs_warn_ratelimited(mp, |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 0d147428971e..1aa3abd67b36 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
| @@ -681,7 +681,7 @@ xfs_iomap_write_allocate( | |||
| 681 | xfs_trans_t *tp; | 681 | xfs_trans_t *tp; |
| 682 | int nimaps; | 682 | int nimaps; |
| 683 | int error = 0; | 683 | int error = 0; |
| 684 | int flags = 0; | 684 | int flags = XFS_BMAPI_DELALLOC; |
| 685 | int nres; | 685 | int nres; |
| 686 | 686 | ||
| 687 | if (whichfork == XFS_COW_FORK) | 687 | if (whichfork == XFS_COW_FORK) |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 84f785218907..7f351f706b7a 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
| @@ -140,6 +140,7 @@ typedef struct xfs_mount { | |||
| 140 | int m_fixedfsid[2]; /* unchanged for life of FS */ | 140 | int m_fixedfsid[2]; /* unchanged for life of FS */ |
| 141 | uint m_dmevmask; /* DMI events for this FS */ | 141 | uint m_dmevmask; /* DMI events for this FS */ |
| 142 | __uint64_t m_flags; /* global mount flags */ | 142 | __uint64_t m_flags; /* global mount flags */ |
| 143 | bool m_inotbt_nores; /* no per-AG finobt resv. */ | ||
| 143 | int m_ialloc_inos; /* inodes in inode allocation */ | 144 | int m_ialloc_inos; /* inodes in inode allocation */ |
| 144 | int m_ialloc_blks; /* blocks in inode allocation */ | 145 | int m_ialloc_blks; /* blocks in inode allocation */ |
| 145 | int m_ialloc_min_blks;/* min blocks in sparse inode | 146 | int m_ialloc_min_blks;/* min blocks in sparse inode |
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 45e50ea90769..b669b123287b 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c | |||
| @@ -1177,7 +1177,8 @@ xfs_qm_dqusage_adjust( | |||
| 1177 | * the case in all other instances. It's OK that we do this because | 1177 | * the case in all other instances. It's OK that we do this because |
| 1178 | * quotacheck is done only at mount time. | 1178 | * quotacheck is done only at mount time. |
| 1179 | */ | 1179 | */ |
| 1180 | error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip); | 1180 | error = xfs_iget(mp, NULL, ino, XFS_IGET_DONTCACHE, XFS_ILOCK_EXCL, |
| 1181 | &ip); | ||
| 1181 | if (error) { | 1182 | if (error) { |
| 1182 | *res = BULKSTAT_RV_NOTHING; | 1183 | *res = BULKSTAT_RV_NOTHING; |
| 1183 | return error; | 1184 | return error; |
