aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/inode.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c72033ee6017..021694c08181 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5170,14 +5170,31 @@ next:
5170 } 5170 }
5171 5171
5172 /* Reached end of directory/root. Bump pos past the last item. */ 5172 /* Reached end of directory/root. Bump pos past the last item. */
5173 if (key_type == BTRFS_DIR_INDEX_KEY) 5173 ctx->pos++;
5174 /* 5174
5175 * 32-bit glibc will use getdents64, but then strtol - 5175 /*
5176 * so the last number we can serve is this. 5176 * Stop new entries from being returned after we return the last
5177 */ 5177 * entry.
5178 ctx->pos = 0x7fffffff; 5178 *
5179 else 5179 * New directory entries are assigned a strictly increasing
5180 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 }
5181nopos: 5198nopos:
5182 ret = 0; 5199 ret = 0;
5183err: 5200err: