diff options
| -rw-r--r-- | fs/btrfs/inode.c | 33 |
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 | } | ||
| 5181 | nopos: | 5198 | nopos: |
| 5182 | ret = 0; | 5199 | ret = 0; |
| 5183 | err: | 5200 | err: |
