aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 6d1b93c8aafb..021694c08181 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2166,16 +2166,23 @@ static noinline int record_one_backref(u64 inum, u64 offset, u64 root_id,
2166 if (btrfs_file_extent_disk_bytenr(leaf, extent) != old->bytenr) 2166 if (btrfs_file_extent_disk_bytenr(leaf, extent) != old->bytenr)
2167 continue; 2167 continue;
2168 2168
2169 extent_offset = btrfs_file_extent_offset(leaf, extent); 2169 /*
2170 if (key.offset - extent_offset != offset) 2170 * 'offset' refers to the exact key.offset,
2171 * NOT the 'offset' field in btrfs_extent_data_ref, ie.
2172 * (key.offset - extent_offset).
2173 */
2174 if (key.offset != offset)
2171 continue; 2175 continue;
2172 2176
2177 extent_offset = btrfs_file_extent_offset(leaf, extent);
2173 num_bytes = btrfs_file_extent_num_bytes(leaf, extent); 2178 num_bytes = btrfs_file_extent_num_bytes(leaf, extent);
2179
2174 if (extent_offset >= old->extent_offset + old->offset + 2180 if (extent_offset >= old->extent_offset + old->offset +
2175 old->len || extent_offset + num_bytes <= 2181 old->len || extent_offset + num_bytes <=
2176 old->extent_offset + old->offset) 2182 old->extent_offset + old->offset)
2177 continue; 2183 continue;
2178 2184
2185 ret = 0;
2179 break; 2186 break;
2180 } 2187 }
2181 2188
@@ -2187,7 +2194,7 @@ static noinline int record_one_backref(u64 inum, u64 offset, u64 root_id,
2187 2194
2188 backref->root_id = root_id; 2195 backref->root_id = root_id;
2189 backref->inum = inum; 2196 backref->inum = inum;
2190 backref->file_pos = offset + extent_offset; 2197 backref->file_pos = offset;
2191 backref->num_bytes = num_bytes; 2198 backref->num_bytes = num_bytes;
2192 backref->extent_offset = extent_offset; 2199 backref->extent_offset = extent_offset;
2193 backref->generation = btrfs_file_extent_generation(leaf, extent); 2200 backref->generation = btrfs_file_extent_generation(leaf, extent);
@@ -2210,7 +2217,8 @@ static noinline bool record_extent_backrefs(struct btrfs_path *path,
2210 new->path = path; 2217 new->path = path;
2211 2218
2212 list_for_each_entry_safe(old, tmp, &new->head, list) { 2219 list_for_each_entry_safe(old, tmp, &new->head, list) {
2213 ret = iterate_inodes_from_logical(old->bytenr, fs_info, 2220 ret = iterate_inodes_from_logical(old->bytenr +
2221 old->extent_offset, fs_info,
2214 path, record_one_backref, 2222 path, record_one_backref,
2215 old); 2223 old);
2216 BUG_ON(ret < 0 && ret != -ENOENT); 2224 BUG_ON(ret < 0 && ret != -ENOENT);
@@ -4391,9 +4399,6 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
4391 int mask = attr->ia_valid; 4399 int mask = attr->ia_valid;
4392 int ret; 4400 int ret;
4393 4401
4394 if (newsize == oldsize)
4395 return 0;
4396
4397 /* 4402 /*
4398 * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a 4403 * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a
4399 * special case where we need to update the times despite not having 4404 * special case where we need to update the times despite not having
@@ -5165,14 +5170,31 @@ next:
5165 } 5170 }
5166 5171
5167 /* Reached end of directory/root. Bump pos past the last item. */ 5172 /* Reached end of directory/root. Bump pos past the last item. */
5168 if (key_type == BTRFS_DIR_INDEX_KEY) 5173 ctx->pos++;
5169 /* 5174
5170 * 32-bit glibc will use getdents64, but then strtol - 5175 /*
5171 * so the last number we can serve is this. 5176 * Stop new entries from being returned after we return the last
5172 */ 5177 * entry.
5173 ctx->pos = 0x7fffffff; 5178 *
5174 else 5179 * New directory entries are assigned a strictly increasing
5175 ctx->pos++; 5180 * offset. This means that new entries created during readdir
5181 * are *guaranteed* to be seen in the future by that readdir.
5182 * This has broken buggy programs which operate on names as
5183 * they're returned by readdir. Until we re-use freed offsets
5184 * we have this hack to stop new entries from being returned
5185 * under the assumption that they'll never reach this huge
5186 * offset.
5187 *
5188 * This is being careful not to overflow 32bit loff_t unless the
5189 * last entry requires it because doing so has broken 32bit apps
5190 * in the past.
5191 */
5192 if (key_type == BTRFS_DIR_INDEX_KEY) {
5193 if (ctx->pos >= INT_MAX)
5194 ctx->pos = LLONG_MAX;
5195 else
5196 ctx->pos = INT_MAX;
5197 }
5176nopos: 5198nopos:
5177 ret = 0; 5199 ret = 0;
5178err: 5200err: