Blame view
fs/ext4/namei.c
102 KB
ac27a0ec1 [PATCH] ext4: ini... |
1 |
/* |
617ba13b3 [PATCH] ext4: ren... |
2 |
* linux/fs/ext4/namei.c |
ac27a0ec1 [PATCH] ext4: ini... |
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
* * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) * Laboratoire MASI - Institut Blaise Pascal * Universite Pierre et Marie Curie (Paris VI) * * from * * linux/fs/minix/namei.c * * Copyright (C) 1991, 1992 Linus Torvalds * * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 * Directory entry file type support and forward compatibility hooks * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 * Hash Tree Directory indexing (c) * Daniel Phillips, 2001 * Hash Tree Directory indexing porting * Christopher Li, 2002 * Hash Tree Directory indexing cleanup * Theodore Ts'o, 2002 */ #include <linux/fs.h> #include <linux/pagemap.h> |
ac27a0ec1 [PATCH] ext4: ini... |
29 |
#include <linux/time.h> |
ac27a0ec1 [PATCH] ext4: ini... |
30 31 32 33 34 35 |
#include <linux/fcntl.h> #include <linux/stat.h> #include <linux/string.h> #include <linux/quotaops.h> #include <linux/buffer_head.h> #include <linux/bio.h> |
3dcf54515 ext4: move header... |
36 37 |
#include "ext4.h" #include "ext4_jbd2.h" |
ac27a0ec1 [PATCH] ext4: ini... |
38 |
|
ac27a0ec1 [PATCH] ext4: ini... |
39 40 |
#include "xattr.h" #include "acl.h" |
0562e0bad ext4: add more tr... |
41 |
#include <trace/events/ext4.h> |
ac27a0ec1 [PATCH] ext4: ini... |
42 43 44 45 46 |
/* * define how far ahead to read directories while searching them. */ #define NAMEI_RA_CHUNKS 2 #define NAMEI_RA_BLOCKS 4 |
8c55e2041 EXT4: Fix whitespace |
47 |
#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) |
ac27a0ec1 [PATCH] ext4: ini... |
48 |
|
617ba13b3 [PATCH] ext4: ren... |
49 |
static struct buffer_head *ext4_append(handle_t *handle, |
ac27a0ec1 [PATCH] ext4: ini... |
50 |
struct inode *inode, |
0f70b4061 ext4: use ERR_PTR... |
51 |
ext4_lblk_t *block) |
ac27a0ec1 [PATCH] ext4: ini... |
52 53 |
{ struct buffer_head *bh; |
1c2150283 ext4: convert ext... |
54 |
int err; |
ac27a0ec1 [PATCH] ext4: ini... |
55 |
|
df981d03e ext4: add max_dir... |
56 57 |
if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb && ((inode->i_size >> 10) >= |
0f70b4061 ext4: use ERR_PTR... |
58 59 |
EXT4_SB(inode->i_sb)->s_max_dir_size_kb))) return ERR_PTR(-ENOSPC); |
df981d03e ext4: add max_dir... |
60 |
|
ac27a0ec1 [PATCH] ext4: ini... |
61 |
*block = inode->i_size >> inode->i_sb->s_blocksize_bits; |
c5e298ae5 ext4: prevent ext... |
62 |
bh = ext4_bread(handle, inode, *block, EXT4_GET_BLOCKS_CREATE); |
1c2150283 ext4: convert ext... |
63 64 |
if (IS_ERR(bh)) return bh; |
0f70b4061 ext4: use ERR_PTR... |
65 66 |
inode->i_size += inode->i_sb->s_blocksize; EXT4_I(inode)->i_disksize = inode->i_size; |
5d6012553 ext4: add missing... |
67 |
BUFFER_TRACE(bh, "get_write_access"); |
0f70b4061 ext4: use ERR_PTR... |
68 69 70 71 72 |
err = ext4_journal_get_write_access(handle, bh); if (err) { brelse(bh); ext4_std_error(inode->i_sb, err); return ERR_PTR(err); |
6d1ab10e6 ext4: ext4_bread ... |
73 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
74 75 |
return bh; } |
dc6982ff4 ext4: refactor co... |
76 77 78 79 80 81 82 83 |
static int ext4_dx_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent); typedef enum { EITHER, INDEX, DIRENT } dirblock_type_t; #define ext4_read_dirblock(inode, block, type) \ |
b03a2f7eb ext4: improve war... |
84 |
__ext4_read_dirblock((inode), (block), (type), __func__, __LINE__) |
dc6982ff4 ext4: refactor co... |
85 86 |
static struct buffer_head *__ext4_read_dirblock(struct inode *inode, |
b03a2f7eb ext4: improve war... |
87 88 89 90 |
ext4_lblk_t block, dirblock_type_t type, const char *func, unsigned int line) |
dc6982ff4 ext4: refactor co... |
91 92 93 |
{ struct buffer_head *bh; struct ext4_dir_entry *dirent; |
1c2150283 ext4: convert ext... |
94 |
int is_dx_block = 0; |
dc6982ff4 ext4: refactor co... |
95 |
|
1c2150283 ext4: convert ext... |
96 97 |
bh = ext4_bread(NULL, inode, block, 0); if (IS_ERR(bh)) { |
b03a2f7eb ext4: improve war... |
98 99 100 101 102 |
__ext4_warning(inode->i_sb, func, line, "inode #%lu: lblock %lu: comm %s: " "error %ld reading directory block", inode->i_ino, (unsigned long)block, current->comm, PTR_ERR(bh)); |
1c2150283 ext4: convert ext... |
103 104 105 106 |
return bh; } if (!bh) { |
b03a2f7eb ext4: improve war... |
107 108 |
ext4_error_inode(inode, func, line, block, "Directory hole found"); |
6a797d273 ext4: call out CR... |
109 |
return ERR_PTR(-EFSCORRUPTED); |
dc6982ff4 ext4: refactor co... |
110 111 112 113 114 115 116 117 118 119 120 121 |
} dirent = (struct ext4_dir_entry *) bh->b_data; /* Determine whether or not we have an index block */ if (is_dx(inode)) { if (block == 0) is_dx_block = 1; else if (ext4_rec_len_from_disk(dirent->rec_len, inode->i_sb->s_blocksize) == inode->i_sb->s_blocksize) is_dx_block = 1; } if (!is_dx_block && type == INDEX) { |
b03a2f7eb ext4: improve war... |
122 |
ext4_error_inode(inode, func, line, block, |
dc6982ff4 ext4: refactor co... |
123 |
"directory leaf block found instead of index block"); |
6a797d273 ext4: call out CR... |
124 |
return ERR_PTR(-EFSCORRUPTED); |
dc6982ff4 ext4: refactor co... |
125 |
} |
9aa5d32ba ext4: Replace ope... |
126 |
if (!ext4_has_metadata_csum(inode->i_sb) || |
dc6982ff4 ext4: refactor co... |
127 128 129 130 131 132 133 134 135 136 137 138 |
buffer_verified(bh)) return bh; /* * An empty leaf block can get mistaken for a index block; for * this reason, we can only check the index checksum when the * caller is sure it should be an index block. */ if (is_dx_block && type == INDEX) { if (ext4_dx_csum_verify(inode, dirent)) set_buffer_verified(bh); else { |
b03a2f7eb ext4: improve war... |
139 140 |
ext4_error_inode(inode, func, line, block, "Directory index failed checksum"); |
a871611b4 ext4: check ext4_... |
141 |
brelse(bh); |
6a797d273 ext4: call out CR... |
142 |
return ERR_PTR(-EFSBADCRC); |
a871611b4 ext4: check ext4_... |
143 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
144 |
} |
dc6982ff4 ext4: refactor co... |
145 146 147 148 |
if (!is_dx_block) { if (ext4_dirent_csum_verify(inode, dirent)) set_buffer_verified(bh); else { |
b03a2f7eb ext4: improve war... |
149 150 |
ext4_error_inode(inode, func, line, block, "Directory block failed checksum"); |
dc6982ff4 ext4: refactor co... |
151 |
brelse(bh); |
6a797d273 ext4: call out CR... |
152 |
return ERR_PTR(-EFSBADCRC); |
dc6982ff4 ext4: refactor co... |
153 |
} |
6d1ab10e6 ext4: ext4_bread ... |
154 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
155 156 157 158 159 160 |
return bh; } #ifndef assert #define assert(test) J_ASSERT(test) #endif |
ac27a0ec1 [PATCH] ext4: ini... |
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
#ifdef DX_DEBUG #define dxtrace(command) command #else #define dxtrace(command) #endif struct fake_dirent { __le32 inode; __le16 rec_len; u8 name_len; u8 file_type; }; struct dx_countlimit { __le16 limit; __le16 count; }; struct dx_entry { __le32 hash; __le32 block; }; /* * dx_root_info is laid out so that if it should somehow get overlaid by a * dirent the two low bits of the hash version will be zero. Therefore, the * hash version mod 4 should never be 0. Sincerely, the paranoia department. */ struct dx_root { struct fake_dirent dot; char dot_name[4]; struct fake_dirent dotdot; char dotdot_name[4]; struct dx_root_info { __le32 reserved_zero; u8 hash_version; u8 info_length; /* 8 */ u8 indirect_levels; u8 unused_flags; } info; struct dx_entry entries[0]; }; struct dx_node { struct fake_dirent fake; struct dx_entry entries[0]; }; struct dx_frame { struct buffer_head *bh; struct dx_entry *entries; struct dx_entry *at; }; struct dx_map_entry { u32 hash; |
ef2b02d3e ext34: ensure do_... |
228 229 |
u16 offs; u16 size; |
ac27a0ec1 [PATCH] ext4: ini... |
230 |
}; |
e61539189 ext4: change on-d... |
231 232 233 234 235 236 237 |
/* * This goes at the end of each htree block. */ struct dx_tail { u32 dt_reserved; __le32 dt_checksum; /* crc32c(uuid+inum+dirblock) */ }; |
725d26d3f ext4: Introduce e... |
238 239 |
static inline ext4_lblk_t dx_get_block(struct dx_entry *entry); static void dx_set_block(struct dx_entry *entry, ext4_lblk_t value); |
af5bc92dd ext4: Fix whitesp... |
240 241 242 243 244 245 246 247 |
static inline unsigned dx_get_hash(struct dx_entry *entry); static void dx_set_hash(struct dx_entry *entry, unsigned value); static unsigned dx_get_count(struct dx_entry *entries); static unsigned dx_get_limit(struct dx_entry *entries); static void dx_set_count(struct dx_entry *entries, unsigned value); static void dx_set_limit(struct dx_entry *entries, unsigned value); static unsigned dx_root_limit(struct inode *dir, unsigned infosize); static unsigned dx_node_limit(struct inode *dir); |
5b643f9ce ext4 crypto: opti... |
248 |
static struct dx_frame *dx_probe(struct ext4_filename *fname, |
ac27a0ec1 [PATCH] ext4: ini... |
249 250 |
struct inode *dir, struct dx_hash_info *hinfo, |
dd73b5d5c ext4: convert dx_... |
251 |
struct dx_frame *frame); |
af5bc92dd ext4: Fix whitesp... |
252 |
static void dx_release(struct dx_frame *frames); |
1f3862b55 ext4 crypto: file... |
253 254 255 |
static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de, unsigned blocksize, struct dx_hash_info *hinfo, struct dx_map_entry map[]); |
ac27a0ec1 [PATCH] ext4: ini... |
256 |
static void dx_sort_map(struct dx_map_entry *map, unsigned count); |
af5bc92dd ext4: Fix whitesp... |
257 |
static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to, |
3d0518f47 ext4: New rec_len... |
258 |
struct dx_map_entry *offsets, int count, unsigned blocksize); |
8bad4597c ext4: Use unsigne... |
259 |
static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize); |
725d26d3f ext4: Introduce e... |
260 261 |
static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block); |
617ba13b3 [PATCH] ext4: ren... |
262 |
static int ext4_htree_next_block(struct inode *dir, __u32 hash, |
ac27a0ec1 [PATCH] ext4: ini... |
263 264 265 |
struct dx_frame *frame, struct dx_frame *frames, __u32 *start_hash); |
f702ba0fd ext4: Don't use '... |
266 |
static struct buffer_head * ext4_dx_find_entry(struct inode *dir, |
5b643f9ce ext4 crypto: opti... |
267 |
struct ext4_filename *fname, |
537d8f938 ext4: convert ext... |
268 |
struct ext4_dir_entry_2 **res_dir); |
5b643f9ce ext4 crypto: opti... |
269 |
static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname, |
56a04915d ext4 crypto: simp... |
270 |
struct inode *dir, struct inode *inode); |
ac27a0ec1 [PATCH] ext4: ini... |
271 |
|
dbe894440 ext4: Calculate a... |
272 |
/* checksumming functions */ |
3c47d5417 ext4: let add_dir... |
273 274 |
void initialize_dirent_tail(struct ext4_dir_entry_tail *t, unsigned int blocksize) |
b0336e8d2 ext4: calculate a... |
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
{ memset(t, 0, sizeof(struct ext4_dir_entry_tail)); t->det_rec_len = ext4_rec_len_to_disk( sizeof(struct ext4_dir_entry_tail), blocksize); t->det_reserved_ft = EXT4_FT_DIR_CSUM; } /* Walk through a dirent block to find a checksum "dirent" at the tail */ static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode, struct ext4_dir_entry *de) { struct ext4_dir_entry_tail *t; #ifdef PARANOID struct ext4_dir_entry *d, *top; d = de; top = (struct ext4_dir_entry *)(((void *)de) + (EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct ext4_dir_entry_tail))); while (d < top && d->rec_len) d = (struct ext4_dir_entry *)(((void *)d) + le16_to_cpu(d->rec_len)); if (d != top) return NULL; t = (struct ext4_dir_entry_tail *)d; #else t = EXT4_DIRENT_TAIL(de, EXT4_BLOCK_SIZE(inode->i_sb)); #endif if (t->det_reserved_zero1 || le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) || t->det_reserved_zero2 || t->det_reserved_ft != EXT4_FT_DIR_CSUM) return NULL; return t; } static __le32 ext4_dirent_csum(struct inode *inode, struct ext4_dir_entry *dirent, int size) { struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct ext4_inode_info *ei = EXT4_I(inode); __u32 csum; csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)dirent, size); return cpu_to_le32(csum); } |
b03a2f7eb ext4: improve war... |
326 327 328 329 330 |
#define warn_no_space_for_csum(inode) \ __warn_no_space_for_csum((inode), __func__, __LINE__) static void __warn_no_space_for_csum(struct inode *inode, const char *func, unsigned int line) |
dffe9d8da ext4: do not use ... |
331 |
{ |
b03a2f7eb ext4: improve war... |
332 333 |
__ext4_warning_inode(inode, func, line, "No space for directory leaf checksum. Please run e2fsck -D."); |
dffe9d8da ext4: do not use ... |
334 |
} |
b0336e8d2 ext4: calculate a... |
335 336 337 |
int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent) { struct ext4_dir_entry_tail *t; |
9aa5d32ba ext4: Replace ope... |
338 |
if (!ext4_has_metadata_csum(inode->i_sb)) |
b0336e8d2 ext4: calculate a... |
339 340 341 342 |
return 1; t = get_dirent_tail(inode, dirent); if (!t) { |
dffe9d8da ext4: do not use ... |
343 |
warn_no_space_for_csum(inode); |
b0336e8d2 ext4: calculate a... |
344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
return 0; } if (t->det_checksum != ext4_dirent_csum(inode, dirent, (void *)t - (void *)dirent)) return 0; return 1; } static void ext4_dirent_csum_set(struct inode *inode, struct ext4_dir_entry *dirent) { struct ext4_dir_entry_tail *t; |
9aa5d32ba ext4: Replace ope... |
358 |
if (!ext4_has_metadata_csum(inode->i_sb)) |
b0336e8d2 ext4: calculate a... |
359 360 361 362 |
return; t = get_dirent_tail(inode, dirent); if (!t) { |
dffe9d8da ext4: do not use ... |
363 |
warn_no_space_for_csum(inode); |
b0336e8d2 ext4: calculate a... |
364 365 366 367 368 369 |
return; } t->det_checksum = ext4_dirent_csum(inode, dirent, (void *)t - (void *)dirent); } |
3c47d5417 ext4: let add_dir... |
370 371 372 |
int ext4_handle_dirty_dirent_node(handle_t *handle, struct inode *inode, struct buffer_head *bh) |
b0336e8d2 ext4: calculate a... |
373 374 375 376 |
{ ext4_dirent_csum_set(inode, (struct ext4_dir_entry *)bh->b_data); return ext4_handle_dirty_metadata(handle, inode, bh); } |
dbe894440 ext4: Calculate a... |
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
static struct dx_countlimit *get_dx_countlimit(struct inode *inode, struct ext4_dir_entry *dirent, int *offset) { struct ext4_dir_entry *dp; struct dx_root_info *root; int count_offset; if (le16_to_cpu(dirent->rec_len) == EXT4_BLOCK_SIZE(inode->i_sb)) count_offset = 8; else if (le16_to_cpu(dirent->rec_len) == 12) { dp = (struct ext4_dir_entry *)(((void *)dirent) + 12); if (le16_to_cpu(dp->rec_len) != EXT4_BLOCK_SIZE(inode->i_sb) - 12) return NULL; root = (struct dx_root_info *)(((void *)dp + 12)); if (root->reserved_zero || root->info_length != sizeof(struct dx_root_info)) return NULL; count_offset = 32; } else return NULL; if (offset) *offset = count_offset; return (struct dx_countlimit *)(((void *)dirent) + count_offset); } static __le32 ext4_dx_csum(struct inode *inode, struct ext4_dir_entry *dirent, int count_offset, int count, struct dx_tail *t) { struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct ext4_inode_info *ei = EXT4_I(inode); |
d6a771056 ext4: fix miscell... |
410 |
__u32 csum; |
dbe894440 ext4: Calculate a... |
411 |
int size; |
b47820edd ext4: avoid modif... |
412 413 |
__u32 dummy_csum = 0; int offset = offsetof(struct dx_tail, dt_checksum); |
dbe894440 ext4: Calculate a... |
414 415 |
size = count_offset + (count * sizeof(struct dx_entry)); |
dbe894440 ext4: Calculate a... |
416 |
csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)dirent, size); |
b47820edd ext4: avoid modif... |
417 418 |
csum = ext4_chksum(sbi, csum, (__u8 *)t, offset); csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum)); |
dbe894440 ext4: Calculate a... |
419 420 421 422 423 424 425 426 427 428 |
return cpu_to_le32(csum); } static int ext4_dx_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent) { struct dx_countlimit *c; struct dx_tail *t; int count_offset, limit, count; |
9aa5d32ba ext4: Replace ope... |
429 |
if (!ext4_has_metadata_csum(inode->i_sb)) |
dbe894440 ext4: Calculate a... |
430 431 432 433 434 |
return 1; c = get_dx_countlimit(inode, dirent, &count_offset); if (!c) { EXT4_ERROR_INODE(inode, "dir seems corrupt? Run e2fsck -D."); |
fa9645406 ext4: correct err... |
435 |
return 0; |
dbe894440 ext4: Calculate a... |
436 437 438 439 440 |
} limit = le16_to_cpu(c->limit); count = le16_to_cpu(c->count); if (count_offset + (limit * sizeof(struct dx_entry)) > EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) { |
dffe9d8da ext4: do not use ... |
441 |
warn_no_space_for_csum(inode); |
fa9645406 ext4: correct err... |
442 |
return 0; |
dbe894440 ext4: Calculate a... |
443 444 445 446 447 448 449 450 451 452 453 454 455 456 |
} t = (struct dx_tail *)(((struct dx_entry *)c) + limit); if (t->dt_checksum != ext4_dx_csum(inode, dirent, count_offset, count, t)) return 0; return 1; } static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent) { struct dx_countlimit *c; struct dx_tail *t; int count_offset, limit, count; |
9aa5d32ba ext4: Replace ope... |
457 |
if (!ext4_has_metadata_csum(inode->i_sb)) |
dbe894440 ext4: Calculate a... |
458 459 460 461 462 463 464 465 466 467 468 |
return; c = get_dx_countlimit(inode, dirent, &count_offset); if (!c) { EXT4_ERROR_INODE(inode, "dir seems corrupt? Run e2fsck -D."); return; } limit = le16_to_cpu(c->limit); count = le16_to_cpu(c->count); if (count_offset + (limit * sizeof(struct dx_entry)) > EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) { |
dffe9d8da ext4: do not use ... |
469 |
warn_no_space_for_csum(inode); |
dbe894440 ext4: Calculate a... |
470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
return; } t = (struct dx_tail *)(((struct dx_entry *)c) + limit); t->dt_checksum = ext4_dx_csum(inode, dirent, count_offset, count, t); } static inline int ext4_handle_dirty_dx_node(handle_t *handle, struct inode *inode, struct buffer_head *bh) { ext4_dx_csum_set(inode, (struct ext4_dir_entry *)bh->b_data); return ext4_handle_dirty_metadata(handle, inode, bh); } |
ac27a0ec1 [PATCH] ext4: ini... |
484 |
/* |
f795e1407 ext4: fix build f... |
485 486 487 |
* p is at least 6 bytes before the end of page */ static inline struct ext4_dir_entry_2 * |
3d0518f47 ext4: New rec_len... |
488 |
ext4_next_entry(struct ext4_dir_entry_2 *p, unsigned long blocksize) |
f795e1407 ext4: fix build f... |
489 490 |
{ return (struct ext4_dir_entry_2 *)((char *)p + |
3d0518f47 ext4: New rec_len... |
491 |
ext4_rec_len_from_disk(p->rec_len, blocksize)); |
f795e1407 ext4: fix build f... |
492 493 494 |
} /* |
ac27a0ec1 [PATCH] ext4: ini... |
495 496 497 |
* Future: use high four bits of block for coalesce-on-delete flags * Mask them off for now. */ |
725d26d3f ext4: Introduce e... |
498 |
static inline ext4_lblk_t dx_get_block(struct dx_entry *entry) |
ac27a0ec1 [PATCH] ext4: ini... |
499 500 501 |
{ return le32_to_cpu(entry->block) & 0x00ffffff; } |
725d26d3f ext4: Introduce e... |
502 |
static inline void dx_set_block(struct dx_entry *entry, ext4_lblk_t value) |
ac27a0ec1 [PATCH] ext4: ini... |
503 504 505 |
{ entry->block = cpu_to_le32(value); } |
af5bc92dd ext4: Fix whitesp... |
506 |
static inline unsigned dx_get_hash(struct dx_entry *entry) |
ac27a0ec1 [PATCH] ext4: ini... |
507 508 509 |
{ return le32_to_cpu(entry->hash); } |
af5bc92dd ext4: Fix whitesp... |
510 |
static inline void dx_set_hash(struct dx_entry *entry, unsigned value) |
ac27a0ec1 [PATCH] ext4: ini... |
511 512 513 |
{ entry->hash = cpu_to_le32(value); } |
af5bc92dd ext4: Fix whitesp... |
514 |
static inline unsigned dx_get_count(struct dx_entry *entries) |
ac27a0ec1 [PATCH] ext4: ini... |
515 516 517 |
{ return le16_to_cpu(((struct dx_countlimit *) entries)->count); } |
af5bc92dd ext4: Fix whitesp... |
518 |
static inline unsigned dx_get_limit(struct dx_entry *entries) |
ac27a0ec1 [PATCH] ext4: ini... |
519 520 521 |
{ return le16_to_cpu(((struct dx_countlimit *) entries)->limit); } |
af5bc92dd ext4: Fix whitesp... |
522 |
static inline void dx_set_count(struct dx_entry *entries, unsigned value) |
ac27a0ec1 [PATCH] ext4: ini... |
523 524 525 |
{ ((struct dx_countlimit *) entries)->count = cpu_to_le16(value); } |
af5bc92dd ext4: Fix whitesp... |
526 |
static inline void dx_set_limit(struct dx_entry *entries, unsigned value) |
ac27a0ec1 [PATCH] ext4: ini... |
527 528 529 |
{ ((struct dx_countlimit *) entries)->limit = cpu_to_le16(value); } |
af5bc92dd ext4: Fix whitesp... |
530 |
static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize) |
ac27a0ec1 [PATCH] ext4: ini... |
531 |
{ |
617ba13b3 [PATCH] ext4: ren... |
532 533 |
unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) - EXT4_DIR_REC_LEN(2) - infosize; |
dbe894440 ext4: Calculate a... |
534 |
|
9aa5d32ba ext4: Replace ope... |
535 |
if (ext4_has_metadata_csum(dir->i_sb)) |
dbe894440 ext4: Calculate a... |
536 |
entry_space -= sizeof(struct dx_tail); |
d9c769b76 ext4: cleanup nev... |
537 |
return entry_space / sizeof(struct dx_entry); |
ac27a0ec1 [PATCH] ext4: ini... |
538 |
} |
af5bc92dd ext4: Fix whitesp... |
539 |
static inline unsigned dx_node_limit(struct inode *dir) |
ac27a0ec1 [PATCH] ext4: ini... |
540 |
{ |
617ba13b3 [PATCH] ext4: ren... |
541 |
unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0); |
dbe894440 ext4: Calculate a... |
542 |
|
9aa5d32ba ext4: Replace ope... |
543 |
if (ext4_has_metadata_csum(dir->i_sb)) |
dbe894440 ext4: Calculate a... |
544 |
entry_space -= sizeof(struct dx_tail); |
d9c769b76 ext4: cleanup nev... |
545 |
return entry_space / sizeof(struct dx_entry); |
ac27a0ec1 [PATCH] ext4: ini... |
546 547 548 549 550 551 |
} /* * Debug */ #ifdef DX_DEBUG |
4776004f5 ext4: Add printk ... |
552 |
static void dx_show_index(char * label, struct dx_entry *entries) |
ac27a0ec1 [PATCH] ext4: ini... |
553 |
{ |
63f579335 [PATCH] ext4 whit... |
554 |
int i, n = dx_get_count (entries); |
d74f3d252 ext4: add missing... |
555 |
printk(KERN_DEBUG "%s index", label); |
63f579335 [PATCH] ext4 whit... |
556 |
for (i = 0; i < n; i++) { |
d74f3d252 ext4: add missing... |
557 558 559 |
printk(KERN_CONT " %x->%lu", i ? dx_get_hash(entries + i) : 0, (unsigned long)dx_get_block(entries + i)); |
63f579335 [PATCH] ext4 whit... |
560 |
} |
d74f3d252 ext4: add missing... |
561 562 |
printk(KERN_CONT " "); |
ac27a0ec1 [PATCH] ext4: ini... |
563 564 565 566 567 568 569 570 |
} struct stats { unsigned names; unsigned space; unsigned bcount; }; |
b30984864 ext4 crypto: part... |
571 572 573 574 |
static struct stats dx_show_leaf(struct inode *dir, struct dx_hash_info *hinfo, struct ext4_dir_entry_2 *de, int size, int show_names) |
ac27a0ec1 [PATCH] ext4: ini... |
575 576 577 578 579 580 581 582 583 584 585 586 |
{ unsigned names = 0, space = 0; char *base = (char *) de; struct dx_hash_info h = *hinfo; printk("names: "); while ((char *) de < base + size) { if (de->inode) { if (show_names) { |
b30984864 ext4 crypto: part... |
587 588 589 |
#ifdef CONFIG_EXT4_FS_ENCRYPTION int len; char *name; |
a7550b30a ext4 crypto: migr... |
590 591 |
struct fscrypt_str fname_crypto_str = FSTR_INIT(NULL, 0); |
c936e1ec2 ext4 crypto: use ... |
592 |
int res = 0; |
b30984864 ext4 crypto: part... |
593 594 595 |
name = de->name; len = de->name_len; |
a7550b30a ext4 crypto: migr... |
596 597 |
if (ext4_encrypted_inode(dir)) res = fscrypt_get_encryption_info(dir); |
b7236e21d ext4 crypto: reor... |
598 599 600 601 |
if (res) { printk(KERN_WARNING "Error setting up" " fname crypto: %d ", res); |
b30984864 ext4 crypto: part... |
602 |
} |
a7550b30a ext4 crypto: migr... |
603 |
if (!fscrypt_has_encryption_key(dir)) { |
b30984864 ext4 crypto: part... |
604 605 606 607 608 609 610 611 |
/* Directory is not encrypted */ ext4fs_dirhash(de->name, de->name_len, &h); printk("%*.s:(U)%x.%u ", len, name, h.hash, (unsigned) ((char *) de - base)); } else { |
a7550b30a ext4 crypto: migr... |
612 613 |
struct fscrypt_str de_name = FSTR_INIT(name, len); |
b30984864 ext4 crypto: part... |
614 |
/* Directory is encrypted */ |
a7550b30a ext4 crypto: migr... |
615 616 |
res = fscrypt_fname_alloc_buffer( dir, len, |
b30984864 ext4 crypto: part... |
617 |
&fname_crypto_str); |
ef1eb3aa5 fscrypto: make fi... |
618 |
if (res) |
b30984864 ext4 crypto: part... |
619 620 621 622 623 |
printk(KERN_WARNING "Error " "allocating crypto " "buffer--skipping " "crypto "); |
a7550b30a ext4 crypto: migr... |
624 625 626 |
res = fscrypt_fname_disk_to_usr(dir, 0, 0, &de_name, &fname_crypto_str); |
ef1eb3aa5 fscrypto: make fi... |
627 |
if (res) { |
b30984864 ext4 crypto: part... |
628 629 630 631 632 633 634 635 636 637 638 |
printk(KERN_WARNING "Error " "converting filename " "from disk to usr" " "); name = "??"; len = 2; } else { name = fname_crypto_str.name; len = fname_crypto_str.len; } |
5de0b4d0c ext4 crypto: simp... |
639 640 |
ext4fs_dirhash(de->name, de->name_len, &h); |
b30984864 ext4 crypto: part... |
641 642 643 |
printk("%*.s:(E)%x.%u ", len, name, h.hash, (unsigned) ((char *) de - base)); |
a7550b30a ext4 crypto: migr... |
644 645 |
fscrypt_fname_free_buffer( &fname_crypto_str); |
b30984864 ext4 crypto: part... |
646 647 |
} #else |
ac27a0ec1 [PATCH] ext4: ini... |
648 649 |
int len = de->name_len; char *name = de->name; |
617ba13b3 [PATCH] ext4: ren... |
650 |
ext4fs_dirhash(de->name, de->name_len, &h); |
b30984864 ext4 crypto: part... |
651 |
printk("%*.s:%x.%u ", len, name, h.hash, |
265c6a0f9 ext4: fix compila... |
652 |
(unsigned) ((char *) de - base)); |
b30984864 ext4 crypto: part... |
653 |
#endif |
ac27a0ec1 [PATCH] ext4: ini... |
654 |
} |
617ba13b3 [PATCH] ext4: ren... |
655 |
space += EXT4_DIR_REC_LEN(de->name_len); |
ac27a0ec1 [PATCH] ext4: ini... |
656 657 |
names++; } |
3d0518f47 ext4: New rec_len... |
658 |
de = ext4_next_entry(de, size); |
ac27a0ec1 [PATCH] ext4: ini... |
659 |
} |
d74f3d252 ext4: add missing... |
660 661 |
printk(KERN_CONT "(%i) ", names); |
ac27a0ec1 [PATCH] ext4: ini... |
662 663 664 665 666 667 668 |
return (struct stats) { names, space, 1 }; } struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, struct dx_entry *entries, int levels) { unsigned blocksize = dir->i_sb->s_blocksize; |
af5bc92dd ext4: Fix whitesp... |
669 |
unsigned count = dx_get_count(entries), names = 0, space = 0, i; |
ac27a0ec1 [PATCH] ext4: ini... |
670 671 |
unsigned bcount = 0; struct buffer_head *bh; |
ac27a0ec1 [PATCH] ext4: ini... |
672 673 674 675 |
printk("%i indexed blocks... ", count); for (i = 0; i < count; i++, entries++) { |
725d26d3f ext4: Introduce e... |
676 677 |
ext4_lblk_t block = dx_get_block(entries); ext4_lblk_t hash = i ? dx_get_hash(entries): 0; |
ac27a0ec1 [PATCH] ext4: ini... |
678 679 680 |
u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; struct stats stats; printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); |
1c2150283 ext4: convert ext... |
681 682 683 |
bh = ext4_bread(NULL,dir, block, 0); if (!bh || IS_ERR(bh)) continue; |
ac27a0ec1 [PATCH] ext4: ini... |
684 685 |
stats = levels? dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): |
b30984864 ext4 crypto: part... |
686 687 |
dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0); |
ac27a0ec1 [PATCH] ext4: ini... |
688 689 690 |
names += stats.names; space += stats.space; bcount += stats.bcount; |
af5bc92dd ext4: Fix whitesp... |
691 |
brelse(bh); |
ac27a0ec1 [PATCH] ext4: ini... |
692 693 |
} if (bcount) |
60e6679e2 ext4: Drop whites... |
694 695 |
printk(KERN_DEBUG "%snames %u, fullness %u (%u%%) ", |
4776004f5 ext4: Add printk ... |
696 697 |
levels ? "" : " ", names, space/bcount, (space/bcount)*100/blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
698 699 700 701 702 703 704 705 706 707 708 709 710 711 |
return (struct stats) { names, space, bcount}; } #endif /* DX_DEBUG */ /* * Probe for a directory leaf block to search. * * dx_probe can return ERR_BAD_DX_DIR, which means there was a format * error in the directory index, and the caller should fall back to * searching the directory normally. The callers of dx_probe **MUST** * check for this error code, and make sure it never gets reflected * back to userspace. */ static struct dx_frame * |
5b643f9ce ext4 crypto: opti... |
712 |
dx_probe(struct ext4_filename *fname, struct inode *dir, |
dd73b5d5c ext4: convert dx_... |
713 |
struct dx_hash_info *hinfo, struct dx_frame *frame_in) |
ac27a0ec1 [PATCH] ext4: ini... |
714 715 716 717 |
{ unsigned count, indirect; struct dx_entry *at, *entries, *p, *q, *m; struct dx_root *root; |
ac27a0ec1 [PATCH] ext4: ini... |
718 |
struct dx_frame *frame = frame_in; |
dd73b5d5c ext4: convert dx_... |
719 |
struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR); |
ac27a0ec1 [PATCH] ext4: ini... |
720 |
u32 hash; |
dd73b5d5c ext4: convert dx_... |
721 722 723 724 725 |
frame->bh = ext4_read_dirblock(dir, 0, INDEX); if (IS_ERR(frame->bh)) return (struct dx_frame *) frame->bh; root = (struct dx_root *) frame->bh->b_data; |
ac27a0ec1 [PATCH] ext4: ini... |
726 727 728 |
if (root->info.hash_version != DX_HASH_TEA && root->info.hash_version != DX_HASH_HALF_MD4 && root->info.hash_version != DX_HASH_LEGACY) { |
b03a2f7eb ext4: improve war... |
729 730 |
ext4_warning_inode(dir, "Unrecognised inode hash code %u", root->info.hash_version); |
ac27a0ec1 [PATCH] ext4: ini... |
731 732 |
goto fail; } |
5b643f9ce ext4 crypto: opti... |
733 734 |
if (fname) hinfo = &fname->hinfo; |
ac27a0ec1 [PATCH] ext4: ini... |
735 |
hinfo->hash_version = root->info.hash_version; |
f99b25897 ext4: Add support... |
736 737 |
if (hinfo->hash_version <= DX_HASH_TEA) hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; |
617ba13b3 [PATCH] ext4: ren... |
738 |
hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed; |
5b643f9ce ext4 crypto: opti... |
739 740 |
if (fname && fname_name(fname)) ext4fs_dirhash(fname_name(fname), fname_len(fname), hinfo); |
ac27a0ec1 [PATCH] ext4: ini... |
741 742 743 |
hash = hinfo->hash; if (root->info.unused_flags & 1) { |
b03a2f7eb ext4: improve war... |
744 745 |
ext4_warning_inode(dir, "Unimplemented hash flags: %#06x", root->info.unused_flags); |
ac27a0ec1 [PATCH] ext4: ini... |
746 747 |
goto fail; } |
b03a2f7eb ext4: improve war... |
748 749 750 751 |
indirect = root->info.indirect_levels; if (indirect > 1) { ext4_warning_inode(dir, "Unimplemented hash depth: %#06x", root->info.indirect_levels); |
ac27a0ec1 [PATCH] ext4: ini... |
752 753 |
goto fail; } |
b03a2f7eb ext4: improve war... |
754 755 |
entries = (struct dx_entry *)(((char *)&root->info) + root->info.info_length); |
3d82abae9 dir_index: error ... |
756 757 758 |
if (dx_get_limit(entries) != dx_root_limit(dir, root->info.info_length)) { |
b03a2f7eb ext4: improve war... |
759 760 761 |
ext4_warning_inode(dir, "dx entry: limit %u != root limit %u", dx_get_limit(entries), dx_root_limit(dir, root->info.info_length)); |
3d82abae9 dir_index: error ... |
762 763 |
goto fail; } |
af5bc92dd ext4: Fix whitesp... |
764 |
dxtrace(printk("Look up %x", hash)); |
dd73b5d5c ext4: convert dx_... |
765 |
while (1) { |
ac27a0ec1 [PATCH] ext4: ini... |
766 |
count = dx_get_count(entries); |
3d82abae9 dir_index: error ... |
767 |
if (!count || count > dx_get_limit(entries)) { |
b03a2f7eb ext4: improve war... |
768 769 770 |
ext4_warning_inode(dir, "dx entry: count %u beyond limit %u", count, dx_get_limit(entries)); |
dd73b5d5c ext4: convert dx_... |
771 |
goto fail; |
3d82abae9 dir_index: error ... |
772 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
773 774 |
p = entries + 1; q = entries + count - 1; |
dd73b5d5c ext4: convert dx_... |
775 |
while (p <= q) { |
b03a2f7eb ext4: improve war... |
776 |
m = p + (q - p) / 2; |
d74f3d252 ext4: add missing... |
777 |
dxtrace(printk(KERN_CONT ".")); |
ac27a0ec1 [PATCH] ext4: ini... |
778 779 780 781 782 |
if (dx_get_hash(m) > hash) q = m - 1; else p = m + 1; } |
dd73b5d5c ext4: convert dx_... |
783 |
if (0) { // linear search cross check |
ac27a0ec1 [PATCH] ext4: ini... |
784 785 786 787 |
unsigned n = count - 1; at = entries; while (n--) { |
d74f3d252 ext4: add missing... |
788 |
dxtrace(printk(KERN_CONT ",")); |
ac27a0ec1 [PATCH] ext4: ini... |
789 790 791 792 793 794 795 796 797 798 |
if (dx_get_hash(++at) > hash) { at--; break; } } assert (at == p - 1); } at = p - 1; |
d74f3d252 ext4: add missing... |
799 800 801 |
dxtrace(printk(KERN_CONT " %x->%u ", at == entries ? 0 : dx_get_hash(at), |
b03a2f7eb ext4: improve war... |
802 |
dx_get_block(at))); |
ac27a0ec1 [PATCH] ext4: ini... |
803 804 |
frame->entries = entries; frame->at = at; |
dd73b5d5c ext4: convert dx_... |
805 806 807 808 809 810 811 812 |
if (!indirect--) return frame; frame++; frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX); if (IS_ERR(frame->bh)) { ret_err = (struct dx_frame *) frame->bh; frame->bh = NULL; goto fail; |
dbe894440 ext4: Calculate a... |
813 |
} |
dd73b5d5c ext4: convert dx_... |
814 |
entries = ((struct dx_node *) frame->bh->b_data)->entries; |
dbe894440 ext4: Calculate a... |
815 |
|
b03a2f7eb ext4: improve war... |
816 817 818 819 |
if (dx_get_limit(entries) != dx_node_limit(dir)) { ext4_warning_inode(dir, "dx entry: limit %u != node limit %u", dx_get_limit(entries), dx_node_limit(dir)); |
dd73b5d5c ext4: convert dx_... |
820 |
goto fail; |
3d82abae9 dir_index: error ... |
821 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
822 |
} |
dd73b5d5c ext4: convert dx_... |
823 |
fail: |
ac27a0ec1 [PATCH] ext4: ini... |
824 825 826 827 |
while (frame >= frame_in) { brelse(frame->bh); frame--; } |
b30984864 ext4 crypto: part... |
828 |
|
dd73b5d5c ext4: convert dx_... |
829 |
if (ret_err == ERR_PTR(ERR_BAD_DX_DIR)) |
b03a2f7eb ext4: improve war... |
830 831 |
ext4_warning_inode(dir, "Corrupt directory, running e2fsck is recommended"); |
dd73b5d5c ext4: convert dx_... |
832 |
return ret_err; |
ac27a0ec1 [PATCH] ext4: ini... |
833 |
} |
b03a2f7eb ext4: improve war... |
834 |
static void dx_release(struct dx_frame *frames) |
ac27a0ec1 [PATCH] ext4: ini... |
835 836 837 |
{ if (frames[0].bh == NULL) return; |
b03a2f7eb ext4: improve war... |
838 |
if (((struct dx_root *)frames[0].bh->b_data)->info.indirect_levels) |
ac27a0ec1 [PATCH] ext4: ini... |
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 |
brelse(frames[1].bh); brelse(frames[0].bh); } /* * This function increments the frame pointer to search the next leaf * block, and reads in the necessary intervening nodes if the search * should be necessary. Whether or not the search is necessary is * controlled by the hash parameter. If the hash value is even, then * the search is only continued if the next block starts with that * hash value. This is used if we are searching for a specific file. * * If the hash value is HASH_NB_ALWAYS, then always go to the next block. * * This function returns 1 if the caller should continue to search, * or 0 if it should not. If there is an error reading one of the * index blocks, it will a negative error code. * * If start_hash is non-null, it will be filled in with the starting * hash of the next page. */ |
617ba13b3 [PATCH] ext4: ren... |
860 |
static int ext4_htree_next_block(struct inode *dir, __u32 hash, |
ac27a0ec1 [PATCH] ext4: ini... |
861 862 863 864 865 866 |
struct dx_frame *frame, struct dx_frame *frames, __u32 *start_hash) { struct dx_frame *p; struct buffer_head *bh; |
dc6982ff4 ext4: refactor co... |
867 |
int num_frames = 0; |
ac27a0ec1 [PATCH] ext4: ini... |
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 |
__u32 bhash; p = frame; /* * Find the next leaf page by incrementing the frame pointer. * If we run out of entries in the interior node, loop around and * increment pointer in the parent node. When we break out of * this loop, num_frames indicates the number of interior * nodes need to be read. */ while (1) { if (++(p->at) < p->entries + dx_get_count(p->entries)) break; if (p == frames) return 0; num_frames++; p--; } /* * If the hash is 1, then continue only if the next page has a * continuation hash of any value. This is used for readdir * handling. Otherwise, check to see if the hash matches the * desired contiuation hash. If it doesn't, return since * there's no point to read in the successive index pages. */ bhash = dx_get_hash(p->at); if (start_hash) *start_hash = bhash; if ((hash & 1) == 0) { if ((bhash & ~1) != hash) return 0; } /* * If the hash is HASH_NB_ALWAYS, we always go to the next * block so no check is necessary */ while (num_frames--) { |
dc6982ff4 ext4: refactor co... |
906 907 908 |
bh = ext4_read_dirblock(dir, dx_get_block(p->at), INDEX); if (IS_ERR(bh)) return PTR_ERR(bh); |
ac27a0ec1 [PATCH] ext4: ini... |
909 |
p++; |
af5bc92dd ext4: Fix whitesp... |
910 |
brelse(p->bh); |
ac27a0ec1 [PATCH] ext4: ini... |
911 912 913 914 915 916 917 918 |
p->bh = bh; p->at = p->entries = ((struct dx_node *) bh->b_data)->entries; } return 1; } /* |
ac27a0ec1 [PATCH] ext4: ini... |
919 920 921 922 923 |
* This function fills a red-black tree with information from a * directory block. It returns the number directory entries loaded * into the tree. If there is an error it is returned in err. */ static int htree_dirblock_to_tree(struct file *dir_file, |
725d26d3f ext4: Introduce e... |
924 |
struct inode *dir, ext4_lblk_t block, |
ac27a0ec1 [PATCH] ext4: ini... |
925 926 927 928 |
struct dx_hash_info *hinfo, __u32 start_hash, __u32 start_minor_hash) { struct buffer_head *bh; |
617ba13b3 [PATCH] ext4: ren... |
929 |
struct ext4_dir_entry_2 *de, *top; |
90b0a9732 ext4: fix possibl... |
930 |
int err = 0, count = 0; |
a7550b30a ext4 crypto: migr... |
931 |
struct fscrypt_str fname_crypto_str = FSTR_INIT(NULL, 0), tmp_str; |
ac27a0ec1 [PATCH] ext4: ini... |
932 |
|
725d26d3f ext4: Introduce e... |
933 934 935 |
dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu ", (unsigned long)block)); |
dc6982ff4 ext4: refactor co... |
936 937 938 |
bh = ext4_read_dirblock(dir, block, DIRENT); if (IS_ERR(bh)) return PTR_ERR(bh); |
b0336e8d2 ext4: calculate a... |
939 |
|
617ba13b3 [PATCH] ext4: ren... |
940 941 |
de = (struct ext4_dir_entry_2 *) bh->b_data; top = (struct ext4_dir_entry_2 *) ((char *) de + |
ac27a0ec1 [PATCH] ext4: ini... |
942 |
dir->i_sb->s_blocksize - |
617ba13b3 [PATCH] ext4: ren... |
943 |
EXT4_DIR_REC_LEN(0)); |
1f3862b55 ext4 crypto: file... |
944 945 |
#ifdef CONFIG_EXT4_FS_ENCRYPTION /* Check if the directory is encrypted */ |
b7236e21d ext4 crypto: reor... |
946 |
if (ext4_encrypted_inode(dir)) { |
a7550b30a ext4 crypto: migr... |
947 |
err = fscrypt_get_encryption_info(dir); |
c936e1ec2 ext4 crypto: use ... |
948 949 950 951 |
if (err < 0) { brelse(bh); return err; } |
a7550b30a ext4 crypto: migr... |
952 |
err = fscrypt_fname_alloc_buffer(dir, EXT4_NAME_LEN, |
1f3862b55 ext4 crypto: file... |
953 954 |
&fname_crypto_str); if (err < 0) { |
1f3862b55 ext4 crypto: file... |
955 956 957 958 959 |
brelse(bh); return err; } } #endif |
3d0518f47 ext4: New rec_len... |
960 |
for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { |
f7c21177a ext4: Use ext4_er... |
961 |
if (ext4_check_dir_entry(dir, NULL, de, bh, |
226ba972b ext4: refactor __... |
962 |
bh->b_data, bh->b_size, |
cad3f0076 ext4: optimize ex... |
963 964 |
(block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb)) + ((char *)de - bh->b_data))) { |
64cb92737 ext3,ext4: don't ... |
965 966 |
/* silently ignore the rest of the block */ break; |
e6c402119 [PATCH] handle ex... |
967 |
} |
617ba13b3 [PATCH] ext4: ren... |
968 |
ext4fs_dirhash(de->name, de->name_len, hinfo); |
ac27a0ec1 [PATCH] ext4: ini... |
969 970 971 972 973 974 |
if ((hinfo->hash < start_hash) || ((hinfo->hash == start_hash) && (hinfo->minor_hash < start_minor_hash))) continue; if (de->inode == 0) continue; |
b7236e21d ext4 crypto: reor... |
975 |
if (!ext4_encrypted_inode(dir)) { |
1f3862b55 ext4 crypto: file... |
976 977 978 979 980 981 |
tmp_str.name = de->name; tmp_str.len = de->name_len; err = ext4_htree_store_dirent(dir_file, hinfo->hash, hinfo->minor_hash, de, &tmp_str); } else { |
d22995907 ext4 crypto: don'... |
982 |
int save_len = fname_crypto_str.len; |
a7550b30a ext4 crypto: migr... |
983 984 |
struct fscrypt_str de_name = FSTR_INIT(de->name, de->name_len); |
d22995907 ext4 crypto: don'... |
985 |
|
1f3862b55 ext4 crypto: file... |
986 |
/* Directory is encrypted */ |
a7550b30a ext4 crypto: migr... |
987 988 989 |
err = fscrypt_fname_disk_to_usr(dir, hinfo->hash, hinfo->minor_hash, &de_name, &fname_crypto_str); |
ef1eb3aa5 fscrypto: make fi... |
990 |
if (err) { |
1f3862b55 ext4 crypto: file... |
991 992 993 994 995 996 |
count = err; goto errout; } err = ext4_htree_store_dirent(dir_file, hinfo->hash, hinfo->minor_hash, de, &fname_crypto_str); |
d22995907 ext4 crypto: don'... |
997 |
fname_crypto_str.len = save_len; |
1f3862b55 ext4 crypto: file... |
998 |
} |
2f61830ae ext4 crypto: teac... |
999 |
if (err != 0) { |
1f3862b55 ext4 crypto: file... |
1000 1001 |
count = err; goto errout; |
ac27a0ec1 [PATCH] ext4: ini... |
1002 1003 1004 |
} count++; } |
1f3862b55 ext4 crypto: file... |
1005 |
errout: |
ac27a0ec1 [PATCH] ext4: ini... |
1006 |
brelse(bh); |
1f3862b55 ext4 crypto: file... |
1007 |
#ifdef CONFIG_EXT4_FS_ENCRYPTION |
a7550b30a ext4 crypto: migr... |
1008 |
fscrypt_fname_free_buffer(&fname_crypto_str); |
1f3862b55 ext4 crypto: file... |
1009 |
#endif |
ac27a0ec1 [PATCH] ext4: ini... |
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 |
return count; } /* * This function fills a red-black tree with information from a * directory. We start scanning the directory in hash order, starting * at start_hash and start_minor_hash. * * This function returns the number of entries inserted into the tree, * or a negative error code. */ |
617ba13b3 [PATCH] ext4: ren... |
1022 |
int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, |
ac27a0ec1 [PATCH] ext4: ini... |
1023 1024 1025 |
__u32 start_minor_hash, __u32 *next_hash) { struct dx_hash_info hinfo; |
617ba13b3 [PATCH] ext4: ren... |
1026 |
struct ext4_dir_entry_2 *de; |
ac27a0ec1 [PATCH] ext4: ini... |
1027 1028 |
struct dx_frame frames[2], *frame; struct inode *dir; |
725d26d3f ext4: Introduce e... |
1029 |
ext4_lblk_t block; |
ac27a0ec1 [PATCH] ext4: ini... |
1030 |
int count = 0; |
725d26d3f ext4: Introduce e... |
1031 |
int ret, err; |
ac27a0ec1 [PATCH] ext4: ini... |
1032 |
__u32 hashval; |
a7550b30a ext4 crypto: migr... |
1033 |
struct fscrypt_str tmp_str; |
ac27a0ec1 [PATCH] ext4: ini... |
1034 |
|
60e6679e2 ext4: Drop whites... |
1035 1036 |
dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x ", |
4776004f5 ext4: Add printk ... |
1037 |
start_hash, start_minor_hash)); |
496ad9aa8 new helper: file_... |
1038 |
dir = file_inode(dir_file); |
12e9b8920 ext4: Use bitops ... |
1039 |
if (!(ext4_test_inode_flag(dir, EXT4_INODE_INDEX))) { |
617ba13b3 [PATCH] ext4: ren... |
1040 |
hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; |
f99b25897 ext4: Add support... |
1041 1042 1043 |
if (hinfo.hash_version <= DX_HASH_TEA) hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; |
617ba13b3 [PATCH] ext4: ren... |
1044 |
hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; |
8af0f0822 ext4: fix readdir... |
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 |
if (ext4_has_inline_data(dir)) { int has_inline_data = 1; count = htree_inlinedir_to_tree(dir_file, dir, 0, &hinfo, start_hash, start_minor_hash, &has_inline_data); if (has_inline_data) { *next_hash = ~0; return count; } } |
ac27a0ec1 [PATCH] ext4: ini... |
1056 1057 1058 1059 1060 1061 1062 |
count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo, start_hash, start_minor_hash); *next_hash = ~0; return count; } hinfo.hash = start_hash; hinfo.minor_hash = 0; |
dd73b5d5c ext4: convert dx_... |
1063 1064 1065 |
frame = dx_probe(NULL, dir, &hinfo, frames); if (IS_ERR(frame)) return PTR_ERR(frame); |
ac27a0ec1 [PATCH] ext4: ini... |
1066 1067 1068 |
/* Add '.' and '..' from the htree header */ if (!start_hash && !start_minor_hash) { |
617ba13b3 [PATCH] ext4: ren... |
1069 |
de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data; |
2f61830ae ext4 crypto: teac... |
1070 1071 1072 1073 1074 |
tmp_str.name = de->name; tmp_str.len = de->name_len; err = ext4_htree_store_dirent(dir_file, 0, 0, de, &tmp_str); if (err != 0) |
ac27a0ec1 [PATCH] ext4: ini... |
1075 1076 1077 1078 |
goto errout; count++; } if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) { |
617ba13b3 [PATCH] ext4: ren... |
1079 |
de = (struct ext4_dir_entry_2 *) frames[0].bh->b_data; |
3d0518f47 ext4: New rec_len... |
1080 |
de = ext4_next_entry(de, dir->i_sb->s_blocksize); |
2f61830ae ext4 crypto: teac... |
1081 1082 1083 1084 1085 |
tmp_str.name = de->name; tmp_str.len = de->name_len; err = ext4_htree_store_dirent(dir_file, 2, 0, de, &tmp_str); if (err != 0) |
ac27a0ec1 [PATCH] ext4: ini... |
1086 1087 1088 1089 1090 |
goto errout; count++; } while (1) { |
1f60fbe72 ext4: allow readd... |
1091 1092 1093 1094 1095 |
if (fatal_signal_pending(current)) { err = -ERESTARTSYS; goto errout; } cond_resched(); |
ac27a0ec1 [PATCH] ext4: ini... |
1096 1097 1098 1099 1100 1101 1102 1103 1104 |
block = dx_get_block(frame->at); ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo, start_hash, start_minor_hash); if (ret < 0) { err = ret; goto errout; } count += ret; hashval = ~0; |
617ba13b3 [PATCH] ext4: ren... |
1105 |
ret = ext4_htree_next_block(dir, HASH_NB_ALWAYS, |
ac27a0ec1 [PATCH] ext4: ini... |
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 |
frame, frames, &hashval); *next_hash = hashval; if (ret < 0) { err = ret; goto errout; } /* * Stop if: (a) there are no more entries, or * (b) we have inserted at least one entry and the * next hash value is not a continuation */ if ((ret == 0) || (count && ((hashval & 1) == 0))) break; } dx_release(frames); |
4776004f5 ext4: Add printk ... |
1122 1123 1124 |
dxtrace(printk(KERN_DEBUG "Fill tree: returned %d entries, " "next hash: %x ", count, *next_hash)); |
ac27a0ec1 [PATCH] ext4: ini... |
1125 1126 1127 1128 1129 |
return count; errout: dx_release(frames); return (err); } |
7335cd3b4 ext4: create a ne... |
1130 1131 |
static inline int search_dirblock(struct buffer_head *bh, struct inode *dir, |
5b643f9ce ext4 crypto: opti... |
1132 |
struct ext4_filename *fname, |
7335cd3b4 ext4: create a ne... |
1133 1134 1135 1136 |
const struct qstr *d_name, unsigned int offset, struct ext4_dir_entry_2 **res_dir) { |
5b643f9ce ext4 crypto: opti... |
1137 1138 |
return ext4_search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir, fname, d_name, offset, res_dir); |
7335cd3b4 ext4: create a ne... |
1139 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
1140 1141 1142 |
/* * Directory block splitting, compacting */ |
ef2b02d3e ext34: ensure do_... |
1143 1144 1145 1146 |
/* * Create map of hash values, offsets, and sizes, stored at end of block. * Returns number of entries mapped. */ |
1f3862b55 ext4 crypto: file... |
1147 1148 |
static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de, unsigned blocksize, struct dx_hash_info *hinfo, |
8bad4597c ext4: Use unsigne... |
1149 |
struct dx_map_entry *map_tail) |
ac27a0ec1 [PATCH] ext4: ini... |
1150 1151 1152 1153 |
{ int count = 0; char *base = (char *) de; struct dx_hash_info h = *hinfo; |
8bad4597c ext4: Use unsigne... |
1154 |
while ((char *) de < base + blocksize) { |
ac27a0ec1 [PATCH] ext4: ini... |
1155 |
if (de->name_len && de->inode) { |
617ba13b3 [PATCH] ext4: ren... |
1156 |
ext4fs_dirhash(de->name, de->name_len, &h); |
ac27a0ec1 [PATCH] ext4: ini... |
1157 1158 |
map_tail--; map_tail->hash = h.hash; |
9aee22860 ext4: fix dx_map_... |
1159 |
map_tail->offs = ((char *) de - base)>>2; |
ef2b02d3e ext34: ensure do_... |
1160 |
map_tail->size = le16_to_cpu(de->rec_len); |
ac27a0ec1 [PATCH] ext4: ini... |
1161 1162 1163 1164 |
count++; cond_resched(); } /* XXX: do we need to check rec_len == 0 case? -Chris */ |
3d0518f47 ext4: New rec_len... |
1165 |
de = ext4_next_entry(de, blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
1166 1167 1168 |
} return count; } |
ef2b02d3e ext34: ensure do_... |
1169 |
/* Sort map by hash value */ |
ac27a0ec1 [PATCH] ext4: ini... |
1170 1171 |
static void dx_sort_map (struct dx_map_entry *map, unsigned count) { |
63f579335 [PATCH] ext4 whit... |
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 |
struct dx_map_entry *p, *q, *top = map + count - 1; int more; /* Combsort until bubble sort doesn't suck */ while (count > 2) { count = count*10/13; if (count - 9 < 2) /* 9, 10 -> 11 */ count = 11; for (p = top, q = p - count; q >= map; p--, q--) if (p->hash < q->hash) swap(*p, *q); } /* Garden variety bubble sort */ do { more = 0; q = top; while (q-- > map) { if (q[1].hash >= q[0].hash) |
ac27a0ec1 [PATCH] ext4: ini... |
1189 |
continue; |
63f579335 [PATCH] ext4 whit... |
1190 1191 |
swap(*(q+1), *q); more = 1; |
ac27a0ec1 [PATCH] ext4: ini... |
1192 1193 1194 |
} } while(more); } |
725d26d3f ext4: Introduce e... |
1195 |
static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block) |
ac27a0ec1 [PATCH] ext4: ini... |
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 |
{ struct dx_entry *entries = frame->entries; struct dx_entry *old = frame->at, *new = old + 1; int count = dx_get_count(entries); assert(count < dx_get_limit(entries)); assert(old < entries + count); memmove(new + 1, new, (char *)(entries + count) - (char *)(new)); dx_set_hash(new, hash); dx_set_block(new, block); dx_set_count(entries, count + 1); } |
ac27a0ec1 [PATCH] ext4: ini... |
1208 |
|
ac27a0ec1 [PATCH] ext4: ini... |
1209 |
/* |
617ba13b3 [PATCH] ext4: ren... |
1210 |
* NOTE! unlike strncmp, ext4_match returns 1 for success, 0 for failure. |
ac27a0ec1 [PATCH] ext4: ini... |
1211 |
* |
617ba13b3 [PATCH] ext4: ren... |
1212 |
* `len <= EXT4_NAME_LEN' is guaranteed by caller. |
ac27a0ec1 [PATCH] ext4: ini... |
1213 1214 |
* `de != NULL' is guaranteed by caller. */ |
5b643f9ce ext4 crypto: opti... |
1215 |
static inline int ext4_match(struct ext4_filename *fname, |
1f3862b55 ext4 crypto: file... |
1216 |
struct ext4_dir_entry_2 *de) |
ac27a0ec1 [PATCH] ext4: ini... |
1217 |
{ |
5b643f9ce ext4 crypto: opti... |
1218 1219 |
const void *name = fname_name(fname); u32 len = fname_len(fname); |
1f3862b55 ext4 crypto: file... |
1220 |
|
ac27a0ec1 [PATCH] ext4: ini... |
1221 1222 |
if (!de->inode) return 0; |
1f3862b55 ext4 crypto: file... |
1223 1224 |
#ifdef CONFIG_EXT4_FS_ENCRYPTION |
5b643f9ce ext4 crypto: opti... |
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 |
if (unlikely(!name)) { if (fname->usr_fname->name[0] == '_') { int ret; if (de->name_len < 16) return 0; ret = memcmp(de->name + de->name_len - 16, fname->crypto_buf.name + 8, 16); return (ret == 0) ? 1 : 0; } name = fname->crypto_buf.name; len = fname->crypto_buf.len; } |
1f3862b55 ext4 crypto: file... |
1237 |
#endif |
5b643f9ce ext4 crypto: opti... |
1238 |
if (de->name_len != len) |
1f3862b55 ext4 crypto: file... |
1239 |
return 0; |
5b643f9ce ext4 crypto: opti... |
1240 |
return (memcmp(de->name, name, len) == 0) ? 1 : 0; |
ac27a0ec1 [PATCH] ext4: ini... |
1241 1242 1243 1244 1245 |
} /* * Returns 0 if not found, -1 on failure, and 1 on success */ |
5b643f9ce ext4 crypto: opti... |
1246 1247 1248 1249 |
int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size, struct inode *dir, struct ext4_filename *fname, const struct qstr *d_name, unsigned int offset, struct ext4_dir_entry_2 **res_dir) |
ac27a0ec1 [PATCH] ext4: ini... |
1250 |
{ |
617ba13b3 [PATCH] ext4: ren... |
1251 |
struct ext4_dir_entry_2 * de; |
ac27a0ec1 [PATCH] ext4: ini... |
1252 1253 |
char * dlimit; int de_len; |
1f3862b55 ext4 crypto: file... |
1254 |
int res; |
7335cd3b4 ext4: create a ne... |
1255 1256 |
de = (struct ext4_dir_entry_2 *)search_buf; dlimit = search_buf + buf_size; |
ac27a0ec1 [PATCH] ext4: ini... |
1257 1258 1259 |
while ((char *) de < dlimit) { /* this code is executed quadratically often */ /* do minimal checking `by hand' */ |
1f3862b55 ext4 crypto: file... |
1260 |
if ((char *) de + de->name_len <= dlimit) { |
5b643f9ce ext4 crypto: opti... |
1261 |
res = ext4_match(fname, de); |
1f3862b55 ext4 crypto: file... |
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 |
if (res < 0) { res = -1; goto return_result; } if (res > 0) { /* found a match - just to be sure, do * a full check */ if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data, bh->b_size, offset)) { res = -1; goto return_result; } *res_dir = de; res = 1; goto return_result; } |
ac27a0ec1 [PATCH] ext4: ini... |
1279 |
|
ac27a0ec1 [PATCH] ext4: ini... |
1280 1281 |
} /* prevent looping on a bad block */ |
3d0518f47 ext4: New rec_len... |
1282 1283 |
de_len = ext4_rec_len_from_disk(de->rec_len, dir->i_sb->s_blocksize); |
1f3862b55 ext4 crypto: file... |
1284 1285 1286 1287 |
if (de_len <= 0) { res = -1; goto return_result; } |
ac27a0ec1 [PATCH] ext4: ini... |
1288 |
offset += de_len; |
617ba13b3 [PATCH] ext4: ren... |
1289 |
de = (struct ext4_dir_entry_2 *) ((char *) de + de_len); |
ac27a0ec1 [PATCH] ext4: ini... |
1290 |
} |
1f3862b55 ext4 crypto: file... |
1291 1292 1293 |
res = 0; return_result: |
1f3862b55 ext4 crypto: file... |
1294 |
return res; |
ac27a0ec1 [PATCH] ext4: ini... |
1295 |
} |
c6af8803c ext4: don't verif... |
1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 |
static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block, struct ext4_dir_entry *de) { struct super_block *sb = dir->i_sb; if (!is_dx(dir)) return 0; if (block == 0) return 1; if (de->inode == 0 && ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) == sb->s_blocksize) return 1; return 0; } |
ac27a0ec1 [PATCH] ext4: ini... |
1311 1312 |
/* |
617ba13b3 [PATCH] ext4: ren... |
1313 |
* ext4_find_entry() |
ac27a0ec1 [PATCH] ext4: ini... |
1314 1315 1316 1317 1318 1319 1320 1321 1322 |
* * finds an entry in the specified directory with the wanted name. It * returns the cache buffer in which the entry was found, and the entry * itself (as a parameter - res_dir). It does NOT read the inode of the * entry - you'll have to do that yourself if you want to. * * The returned buffer_head has ->b_count elevated. The caller is expected * to brelse() it when appropriate. */ |
f702ba0fd ext4: Don't use '... |
1323 1324 |
static struct buffer_head * ext4_find_entry (struct inode *dir, const struct qstr *d_name, |
32f7f22c0 ext4: let ext4_re... |
1325 1326 |
struct ext4_dir_entry_2 **res_dir, int *inlined) |
ac27a0ec1 [PATCH] ext4: ini... |
1327 |
{ |
af5bc92dd ext4: Fix whitesp... |
1328 1329 1330 |
struct super_block *sb; struct buffer_head *bh_use[NAMEI_RA_SIZE]; struct buffer_head *bh, *ret = NULL; |
725d26d3f ext4: Introduce e... |
1331 |
ext4_lblk_t start, block, b; |
8941ec8bb ext4: avoid unini... |
1332 |
const u8 *name = d_name->name; |
ac27a0ec1 [PATCH] ext4: ini... |
1333 1334 1335 1336 1337 |
int ra_max = 0; /* Number of bh's in the readahead buffer, bh_use[] */ int ra_ptr = 0; /* Current index into readahead buffer */ int num = 0; |
725d26d3f ext4: Introduce e... |
1338 |
ext4_lblk_t nblocks; |
5b643f9ce ext4 crypto: opti... |
1339 1340 |
int i, namelen, retval; struct ext4_filename fname; |
ac27a0ec1 [PATCH] ext4: ini... |
1341 1342 1343 |
*res_dir = NULL; sb = dir->i_sb; |
f702ba0fd ext4: Don't use '... |
1344 |
namelen = d_name->len; |
617ba13b3 [PATCH] ext4: ren... |
1345 |
if (namelen > EXT4_NAME_LEN) |
ac27a0ec1 [PATCH] ext4: ini... |
1346 |
return NULL; |
e8e948e78 ext4: let ext4_fi... |
1347 |
|
5b643f9ce ext4 crypto: opti... |
1348 1349 1350 |
retval = ext4_fname_setup_filename(dir, d_name, 1, &fname); if (retval) return ERR_PTR(retval); |
e8e948e78 ext4: let ext4_fi... |
1351 1352 |
if (ext4_has_inline_data(dir)) { int has_inline_data = 1; |
5b643f9ce ext4 crypto: opti... |
1353 |
ret = ext4_find_inline_entry(dir, &fname, d_name, res_dir, |
e8e948e78 ext4: let ext4_fi... |
1354 |
&has_inline_data); |
32f7f22c0 ext4: let ext4_re... |
1355 1356 1357 |
if (has_inline_data) { if (inlined) *inlined = 1; |
5b643f9ce ext4 crypto: opti... |
1358 |
goto cleanup_and_exit; |
32f7f22c0 ext4: let ext4_re... |
1359 |
} |
e8e948e78 ext4: let ext4_fi... |
1360 |
} |
8941ec8bb ext4: avoid unini... |
1361 |
if ((namelen <= 2) && (name[0] == '.') && |
6d5c3aa84 ext4: fix typo wh... |
1362 |
(name[1] == '.' || name[1] == '\0')) { |
8941ec8bb ext4: avoid unini... |
1363 1364 1365 1366 1367 1368 1369 1370 |
/* * "." or ".." will only be in the first block * NFS may look up ".."; "." should be handled by the VFS */ block = start = 0; nblocks = 1; goto restart; } |
ac27a0ec1 [PATCH] ext4: ini... |
1371 |
if (is_dx(dir)) { |
5b643f9ce ext4 crypto: opti... |
1372 |
ret = ext4_dx_find_entry(dir, &fname, res_dir); |
ac27a0ec1 [PATCH] ext4: ini... |
1373 1374 1375 1376 1377 |
/* * On success, or if the error was file not found, * return. Otherwise, fall back to doing a search the * old fashioned way. */ |
5b643f9ce ext4 crypto: opti... |
1378 1379 |
if (!IS_ERR(ret) || PTR_ERR(ret) != ERR_BAD_DX_DIR) goto cleanup_and_exit; |
4776004f5 ext4: Add printk ... |
1380 1381 1382 |
dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, " "falling back ")); |
ac27a0ec1 [PATCH] ext4: ini... |
1383 |
} |
617ba13b3 [PATCH] ext4: ren... |
1384 1385 |
nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb); start = EXT4_I(dir)->i_dir_start_lookup; |
ac27a0ec1 [PATCH] ext4: ini... |
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 |
if (start >= nblocks) start = 0; block = start; restart: do { /* * We deal with the read-ahead logic here. */ if (ra_ptr >= ra_max) { /* Refill the readahead buffer */ ra_ptr = 0; b = block; for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) { /* * Terminate if we reach the end of the * directory and must wrap, or if our * search has finished at this block. */ if (b >= nblocks || (num && block == start)) { bh_use[ra_max] = NULL; break; } num++; |
105600822 ext4: convert ext... |
1409 |
bh = ext4_getblk(NULL, dir, b++, 0); |
a1c83681d fs: Drop unlikely... |
1410 |
if (IS_ERR(bh)) { |
5b643f9ce ext4 crypto: opti... |
1411 1412 1413 1414 |
if (ra_max == 0) { ret = bh; goto cleanup_and_exit; } |
36de92864 ext4: propagate e... |
1415 1416 |
break; } |
ac27a0ec1 [PATCH] ext4: ini... |
1417 1418 |
bh_use[ra_max] = bh; if (bh) |
dfec8a14f fs: have ll_rw_bl... |
1419 1420 |
ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, |
65299a3b7 block: separate p... |
1421 |
1, &bh); |
ac27a0ec1 [PATCH] ext4: ini... |
1422 1423 1424 1425 1426 1427 1428 |
} } if ((bh = bh_use[ra_ptr++]) == NULL) goto next; wait_on_buffer(bh); if (!buffer_uptodate(bh)) { /* read error, skip block & hope for the best */ |
24676da46 ext4: Convert cal... |
1429 1430 |
EXT4_ERROR_INODE(dir, "reading directory lblock %lu", (unsigned long) block); |
ac27a0ec1 [PATCH] ext4: ini... |
1431 1432 1433 |
brelse(bh); goto next; } |
b0336e8d2 ext4: calculate a... |
1434 |
if (!buffer_verified(bh) && |
c6af8803c ext4: don't verif... |
1435 1436 |
!is_dx_internal_node(dir, block, (struct ext4_dir_entry *)bh->b_data) && |
b0336e8d2 ext4: calculate a... |
1437 1438 1439 1440 1441 1442 1443 1444 |
!ext4_dirent_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data)) { EXT4_ERROR_INODE(dir, "checksumming directory " "block %lu", (unsigned long)block); brelse(bh); goto next; } set_buffer_verified(bh); |
5b643f9ce ext4 crypto: opti... |
1445 |
i = search_dirblock(bh, dir, &fname, d_name, |
617ba13b3 [PATCH] ext4: ren... |
1446 |
block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); |
ac27a0ec1 [PATCH] ext4: ini... |
1447 |
if (i == 1) { |
617ba13b3 [PATCH] ext4: ren... |
1448 |
EXT4_I(dir)->i_dir_start_lookup = block; |
ac27a0ec1 [PATCH] ext4: ini... |
1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 |
ret = bh; goto cleanup_and_exit; } else { brelse(bh); if (i < 0) goto cleanup_and_exit; } next: if (++block >= nblocks) block = 0; } while (block != start); /* * If the directory has grown while we were searching, then * search the last part of the directory before giving up. */ block = nblocks; |
617ba13b3 [PATCH] ext4: ren... |
1466 |
nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb); |
ac27a0ec1 [PATCH] ext4: ini... |
1467 1468 1469 1470 1471 1472 1473 1474 |
if (block < nblocks) { start = 0; goto restart; } cleanup_and_exit: /* Clean up the read-ahead blocks */ for (; ra_ptr < ra_max; ra_ptr++) |
af5bc92dd ext4: Fix whitesp... |
1475 |
brelse(bh_use[ra_ptr]); |
5b643f9ce ext4 crypto: opti... |
1476 |
ext4_fname_free_filename(&fname); |
ac27a0ec1 [PATCH] ext4: ini... |
1477 1478 |
return ret; } |
5b643f9ce ext4 crypto: opti... |
1479 1480 1481 |
static struct buffer_head * ext4_dx_find_entry(struct inode *dir, struct ext4_filename *fname, struct ext4_dir_entry_2 **res_dir) |
ac27a0ec1 [PATCH] ext4: ini... |
1482 |
{ |
8941ec8bb ext4: avoid unini... |
1483 |
struct super_block * sb = dir->i_sb; |
ac27a0ec1 [PATCH] ext4: ini... |
1484 |
struct dx_frame frames[2], *frame; |
5b643f9ce ext4 crypto: opti... |
1485 |
const struct qstr *d_name = fname->usr_fname; |
ac27a0ec1 [PATCH] ext4: ini... |
1486 |
struct buffer_head *bh; |
725d26d3f ext4: Introduce e... |
1487 |
ext4_lblk_t block; |
ac27a0ec1 [PATCH] ext4: ini... |
1488 |
int retval; |
ac27a0ec1 [PATCH] ext4: ini... |
1489 |
|
1f3862b55 ext4 crypto: file... |
1490 1491 1492 |
#ifdef CONFIG_EXT4_FS_ENCRYPTION *res_dir = NULL; #endif |
5b643f9ce ext4 crypto: opti... |
1493 |
frame = dx_probe(fname, dir, NULL, frames); |
dd73b5d5c ext4: convert dx_... |
1494 1495 |
if (IS_ERR(frame)) return (struct buffer_head *) frame; |
ac27a0ec1 [PATCH] ext4: ini... |
1496 1497 |
do { block = dx_get_block(frame->at); |
dc6982ff4 ext4: refactor co... |
1498 |
bh = ext4_read_dirblock(dir, block, DIRENT); |
537d8f938 ext4: convert ext... |
1499 |
if (IS_ERR(bh)) |
b0336e8d2 ext4: calculate a... |
1500 |
goto errout; |
537d8f938 ext4: convert ext... |
1501 |
|
5b643f9ce ext4 crypto: opti... |
1502 |
retval = search_dirblock(bh, dir, fname, d_name, |
7845c0497 ext4: use search_... |
1503 1504 |
block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); |
537d8f938 ext4: convert ext... |
1505 1506 |
if (retval == 1) goto success; |
af5bc92dd ext4: Fix whitesp... |
1507 |
brelse(bh); |
7845c0497 ext4: use search_... |
1508 |
if (retval == -1) { |
537d8f938 ext4: convert ext... |
1509 |
bh = ERR_PTR(ERR_BAD_DX_DIR); |
7845c0497 ext4: use search_... |
1510 1511 |
goto errout; } |
ac27a0ec1 [PATCH] ext4: ini... |
1512 |
/* Check to see if we should continue to search */ |
5b643f9ce ext4 crypto: opti... |
1513 |
retval = ext4_htree_next_block(dir, fname->hinfo.hash, frame, |
ac27a0ec1 [PATCH] ext4: ini... |
1514 1515 |
frames, NULL); if (retval < 0) { |
b03a2f7eb ext4: improve war... |
1516 1517 1518 |
ext4_warning_inode(dir, "error %d reading directory index block", retval); |
537d8f938 ext4: convert ext... |
1519 |
bh = ERR_PTR(retval); |
ac27a0ec1 [PATCH] ext4: ini... |
1520 1521 1522 |
goto errout; } } while (retval == 1); |
537d8f938 ext4: convert ext... |
1523 |
bh = NULL; |
ac27a0ec1 [PATCH] ext4: ini... |
1524 |
errout: |
265c6a0f9 ext4: fix compila... |
1525 1526 |
dxtrace(printk(KERN_DEBUG "%s not found ", d_name->name)); |
537d8f938 ext4: convert ext... |
1527 1528 1529 |
success: dx_release(frames); return bh; |
ac27a0ec1 [PATCH] ext4: ini... |
1530 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
1531 |
|
00cd8dd3b stop passing name... |
1532 |
static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
ac27a0ec1 [PATCH] ext4: ini... |
1533 |
{ |
af5bc92dd ext4: Fix whitesp... |
1534 1535 1536 |
struct inode *inode; struct ext4_dir_entry_2 *de; struct buffer_head *bh; |
ac27a0ec1 [PATCH] ext4: ini... |
1537 |
|
a7550b30a ext4 crypto: migr... |
1538 1539 |
if (ext4_encrypted_inode(dir)) { int res = fscrypt_get_encryption_info(dir); |
28b4c2639 ext4 crypto: reva... |
1540 1541 |
/* |
a7550b30a ext4 crypto: migr... |
1542 |
* DCACHE_ENCRYPTED_WITH_KEY is set if the dentry is |
28b4c2639 ext4 crypto: reva... |
1543 |
* created while the directory was encrypted and we |
a7550b30a ext4 crypto: migr... |
1544 |
* have access to the key. |
28b4c2639 ext4 crypto: reva... |
1545 |
*/ |
a7550b30a ext4 crypto: migr... |
1546 1547 1548 1549 1550 1551 |
if (fscrypt_has_encryption_key(dir)) fscrypt_set_encrypted_dentry(dentry); fscrypt_set_d_op(dentry); if (res && res != -ENOKEY) return ERR_PTR(res); } |
28b4c2639 ext4 crypto: reva... |
1552 |
|
a7550b30a ext4 crypto: migr... |
1553 1554 |
if (dentry->d_name.len > EXT4_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); |
ac27a0ec1 [PATCH] ext4: ini... |
1555 |
|
32f7f22c0 ext4: let ext4_re... |
1556 |
bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); |
36de92864 ext4: propagate e... |
1557 1558 |
if (IS_ERR(bh)) return (struct dentry *) bh; |
ac27a0ec1 [PATCH] ext4: ini... |
1559 1560 |
inode = NULL; if (bh) { |
498e5f241 ext4: Change unsi... |
1561 |
__u32 ino = le32_to_cpu(de->inode); |
af5bc92dd ext4: Fix whitesp... |
1562 |
brelse(bh); |
617ba13b3 [PATCH] ext4: ren... |
1563 |
if (!ext4_valid_inum(dir->i_sb, ino)) { |
24676da46 ext4: Convert cal... |
1564 |
EXT4_ERROR_INODE(dir, "bad inode number: %u", ino); |
6a797d273 ext4: call out CR... |
1565 |
return ERR_PTR(-EFSCORRUPTED); |
a6c15c2b0 ext3/ext4: orphan... |
1566 |
} |
7e936b737 ext4: disallow ha... |
1567 |
if (unlikely(ino == dir->i_ino)) { |
a34e15cc3 ext4: use %pd pri... |
1568 1569 |
EXT4_ERROR_INODE(dir, "'%pd' linked to parent dir", dentry); |
6a797d273 ext4: call out CR... |
1570 |
return ERR_PTR(-EFSCORRUPTED); |
7e936b737 ext4: disallow ha... |
1571 |
} |
f4bb29810 ext4: add ext4_ig... |
1572 |
inode = ext4_iget_normal(dir->i_sb, ino); |
a9049376e make d_splice_ali... |
1573 1574 1575 1576 |
if (inode == ERR_PTR(-ESTALE)) { EXT4_ERROR_INODE(dir, "deleted inode referenced: %u", ino); |
6a797d273 ext4: call out CR... |
1577 |
return ERR_PTR(-EFSCORRUPTED); |
e6f009b0b ext4: return -EIO... |
1578 |
} |
d9cdc9033 ext4 crypto: enfo... |
1579 |
if (!IS_ERR(inode) && ext4_encrypted_inode(dir) && |
ff978b09f ext4 crypto: move... |
1580 |
(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) && |
a7550b30a ext4 crypto: migr... |
1581 |
!fscrypt_has_permitted_context(dir, inode)) { |
ff978b09f ext4 crypto: move... |
1582 |
int nokey = ext4_encrypted_inode(inode) && |
a7550b30a ext4 crypto: migr... |
1583 |
!fscrypt_has_encryption_key(inode); |
d9cdc9033 ext4 crypto: enfo... |
1584 |
iput(inode); |
ff978b09f ext4 crypto: move... |
1585 1586 |
if (nokey) return ERR_PTR(-ENOKEY); |
d9cdc9033 ext4 crypto: enfo... |
1587 |
ext4_warning(inode->i_sb, |
8d2ae1cbe ext4: remove trai... |
1588 |
"Inconsistent encryption contexts: %lu/%lu", |
d9cdc9033 ext4 crypto: enfo... |
1589 1590 1591 1592 |
(unsigned long) dir->i_ino, (unsigned long) inode->i_ino); return ERR_PTR(-EPERM); } |
ac27a0ec1 [PATCH] ext4: ini... |
1593 1594 1595 |
} return d_splice_alias(inode, dentry); } |
617ba13b3 [PATCH] ext4: ren... |
1596 |
struct dentry *ext4_get_parent(struct dentry *child) |
ac27a0ec1 [PATCH] ext4: ini... |
1597 |
{ |
498e5f241 ext4: Change unsi... |
1598 |
__u32 ino; |
26fe57502 vfs: make it poss... |
1599 |
static const struct qstr dotdot = QSTR_INIT("..", 2); |
617ba13b3 [PATCH] ext4: ren... |
1600 |
struct ext4_dir_entry_2 * de; |
ac27a0ec1 [PATCH] ext4: ini... |
1601 |
struct buffer_head *bh; |
2b0143b5c VFS: normal files... |
1602 |
bh = ext4_find_entry(d_inode(child), &dotdot, &de, NULL); |
36de92864 ext4: propagate e... |
1603 1604 |
if (IS_ERR(bh)) return (struct dentry *) bh; |
ac27a0ec1 [PATCH] ext4: ini... |
1605 1606 1607 1608 |
if (!bh) return ERR_PTR(-ENOENT); ino = le32_to_cpu(de->inode); brelse(bh); |
fc64005c9 don't bother with... |
1609 |
if (!ext4_valid_inum(child->d_sb, ino)) { |
2b0143b5c VFS: normal files... |
1610 |
EXT4_ERROR_INODE(d_inode(child), |
24676da46 ext4: Convert cal... |
1611 |
"bad parent inode number: %u", ino); |
6a797d273 ext4: call out CR... |
1612 |
return ERR_PTR(-EFSCORRUPTED); |
a6c15c2b0 ext3/ext4: orphan... |
1613 |
} |
fc64005c9 don't bother with... |
1614 |
return d_obtain_alias(ext4_iget_normal(child->d_sb, ino)); |
ac27a0ec1 [PATCH] ext4: ini... |
1615 |
} |
ef2b02d3e ext34: ensure do_... |
1616 1617 1618 1619 |
/* * Move count entries from end of map between two memory locations. * Returns pointer to last entry moved. */ |
617ba13b3 [PATCH] ext4: ren... |
1620 |
static struct ext4_dir_entry_2 * |
3d0518f47 ext4: New rec_len... |
1621 1622 |
dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count, unsigned blocksize) |
ac27a0ec1 [PATCH] ext4: ini... |
1623 1624 1625 1626 |
{ unsigned rec_len = 0; while (count--) { |
60e6679e2 ext4: Drop whites... |
1627 |
struct ext4_dir_entry_2 *de = (struct ext4_dir_entry_2 *) |
9aee22860 ext4: fix dx_map_... |
1628 |
(from + (map->offs<<2)); |
617ba13b3 [PATCH] ext4: ren... |
1629 |
rec_len = EXT4_DIR_REC_LEN(de->name_len); |
ac27a0ec1 [PATCH] ext4: ini... |
1630 |
memcpy (to, de, rec_len); |
617ba13b3 [PATCH] ext4: ren... |
1631 |
((struct ext4_dir_entry_2 *) to)->rec_len = |
3d0518f47 ext4: New rec_len... |
1632 |
ext4_rec_len_to_disk(rec_len, blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
1633 1634 1635 1636 |
de->inode = 0; map++; to += rec_len; } |
617ba13b3 [PATCH] ext4: ren... |
1637 |
return (struct ext4_dir_entry_2 *) (to - rec_len); |
ac27a0ec1 [PATCH] ext4: ini... |
1638 |
} |
ef2b02d3e ext34: ensure do_... |
1639 1640 1641 1642 |
/* * Compact each dir entry in the range to the minimal rec_len. * Returns pointer to last entry in range. */ |
8bad4597c ext4: Use unsigne... |
1643 |
static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize) |
ac27a0ec1 [PATCH] ext4: ini... |
1644 |
{ |
617ba13b3 [PATCH] ext4: ren... |
1645 |
struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base; |
ac27a0ec1 [PATCH] ext4: ini... |
1646 1647 1648 |
unsigned rec_len = 0; prev = to = de; |
8bad4597c ext4: Use unsigne... |
1649 |
while ((char*)de < base + blocksize) { |
3d0518f47 ext4: New rec_len... |
1650 |
next = ext4_next_entry(de, blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
1651 |
if (de->inode && de->name_len) { |
617ba13b3 [PATCH] ext4: ren... |
1652 |
rec_len = EXT4_DIR_REC_LEN(de->name_len); |
ac27a0ec1 [PATCH] ext4: ini... |
1653 1654 |
if (de > to) memmove(to, de, rec_len); |
3d0518f47 ext4: New rec_len... |
1655 |
to->rec_len = ext4_rec_len_to_disk(rec_len, blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
1656 |
prev = to; |
617ba13b3 [PATCH] ext4: ren... |
1657 |
to = (struct ext4_dir_entry_2 *) (((char *) to) + rec_len); |
ac27a0ec1 [PATCH] ext4: ini... |
1658 1659 1660 1661 1662 |
} de = next; } return prev; } |
ef2b02d3e ext34: ensure do_... |
1663 1664 1665 1666 1667 |
/* * Split a full leaf block to make room for a new dir entry. * Allocate a new block, and move entries so that they are approx. equally full. * Returns pointer to de in block into which the new entry will be inserted. */ |
617ba13b3 [PATCH] ext4: ren... |
1668 |
static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, |
ac27a0ec1 [PATCH] ext4: ini... |
1669 |
struct buffer_head **bh,struct dx_frame *frame, |
f8b3b59d4 ext4: convert do_... |
1670 |
struct dx_hash_info *hinfo) |
ac27a0ec1 [PATCH] ext4: ini... |
1671 1672 1673 1674 |
{ unsigned blocksize = dir->i_sb->s_blocksize; unsigned count, continued; struct buffer_head *bh2; |
725d26d3f ext4: Introduce e... |
1675 |
ext4_lblk_t newblock; |
ac27a0ec1 [PATCH] ext4: ini... |
1676 1677 1678 |
u32 hash2; struct dx_map_entry *map; char *data1 = (*bh)->b_data, *data2; |
59e315b4c ext3/4: Fix loop ... |
1679 |
unsigned split, move, size; |
617ba13b3 [PATCH] ext4: ren... |
1680 |
struct ext4_dir_entry_2 *de = NULL, *de2; |
b0336e8d2 ext4: calculate a... |
1681 1682 |
struct ext4_dir_entry_tail *t; int csum_size = 0; |
59e315b4c ext3/4: Fix loop ... |
1683 |
int err = 0, i; |
ac27a0ec1 [PATCH] ext4: ini... |
1684 |
|
9aa5d32ba ext4: Replace ope... |
1685 |
if (ext4_has_metadata_csum(dir->i_sb)) |
b0336e8d2 ext4: calculate a... |
1686 |
csum_size = sizeof(struct ext4_dir_entry_tail); |
0f70b4061 ext4: use ERR_PTR... |
1687 1688 |
bh2 = ext4_append(handle, dir, &newblock); if (IS_ERR(bh2)) { |
ac27a0ec1 [PATCH] ext4: ini... |
1689 1690 |
brelse(*bh); *bh = NULL; |
f8b3b59d4 ext4: convert do_... |
1691 |
return (struct ext4_dir_entry_2 *) bh2; |
ac27a0ec1 [PATCH] ext4: ini... |
1692 1693 1694 |
} BUFFER_TRACE(*bh, "get_write_access"); |
617ba13b3 [PATCH] ext4: ren... |
1695 |
err = ext4_journal_get_write_access(handle, *bh); |
fedee54d8 ext3: dirindex er... |
1696 1697 |
if (err) goto journal_error; |
ac27a0ec1 [PATCH] ext4: ini... |
1698 |
BUFFER_TRACE(frame->bh, "get_write_access"); |
617ba13b3 [PATCH] ext4: ren... |
1699 |
err = ext4_journal_get_write_access(handle, frame->bh); |
ac27a0ec1 [PATCH] ext4: ini... |
1700 1701 1702 1703 1704 1705 1706 |
if (err) goto journal_error; data2 = bh2->b_data; /* create map in the end of data2 block */ map = (struct dx_map_entry *) (data2 + blocksize); |
1f3862b55 ext4 crypto: file... |
1707 |
count = dx_make_map(dir, (struct ext4_dir_entry_2 *) data1, |
ac27a0ec1 [PATCH] ext4: ini... |
1708 1709 |
blocksize, hinfo, map); map -= count; |
af5bc92dd ext4: Fix whitesp... |
1710 |
dx_sort_map(map, count); |
ef2b02d3e ext34: ensure do_... |
1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 |
/* Split the existing block in the middle, size-wise */ size = 0; move = 0; for (i = count-1; i >= 0; i--) { /* is more than half of this entry in 2nd half of the block? */ if (size + map[i].size/2 > blocksize/2) break; size += map[i].size; move++; } /* map index at which we will split */ split = count - move; |
ac27a0ec1 [PATCH] ext4: ini... |
1723 1724 |
hash2 = map[split].hash; continued = hash2 == map[split - 1].hash; |
725d26d3f ext4: Introduce e... |
1725 1726 1727 1728 |
dxtrace(printk(KERN_INFO "Split block %lu at %x, %i/%i ", (unsigned long)dx_get_block(frame->at), hash2, split, count-split)); |
ac27a0ec1 [PATCH] ext4: ini... |
1729 1730 |
/* Fancy dance to stay within two buffers */ |
1f3862b55 ext4 crypto: file... |
1731 1732 |
de2 = dx_move_dirents(data1, data2, map + split, count - split, blocksize); |
af5bc92dd ext4: Fix whitesp... |
1733 |
de = dx_pack_dirents(data1, blocksize); |
b0336e8d2 ext4: calculate a... |
1734 1735 |
de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) - (char *) de, |
3d0518f47 ext4: New rec_len... |
1736 |
blocksize); |
b0336e8d2 ext4: calculate a... |
1737 1738 |
de2->rec_len = ext4_rec_len_to_disk(data2 + (blocksize - csum_size) - (char *) de2, |
3d0518f47 ext4: New rec_len... |
1739 |
blocksize); |
b0336e8d2 ext4: calculate a... |
1740 1741 1742 1743 1744 1745 1746 |
if (csum_size) { t = EXT4_DIRENT_TAIL(data2, blocksize); initialize_dirent_tail(t, blocksize); t = EXT4_DIRENT_TAIL(data1, blocksize); initialize_dirent_tail(t, blocksize); } |
b30984864 ext4 crypto: part... |
1747 1748 1749 1750 |
dxtrace(dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1)); dxtrace(dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); |
ac27a0ec1 [PATCH] ext4: ini... |
1751 1752 |
/* Which block gets the new entry? */ |
f8b3b59d4 ext4: convert do_... |
1753 |
if (hinfo->hash >= hash2) { |
ac27a0ec1 [PATCH] ext4: ini... |
1754 1755 1756 |
swap(*bh, bh2); de = de2; } |
af5bc92dd ext4: Fix whitesp... |
1757 |
dx_insert_block(frame, hash2 + continued, newblock); |
b0336e8d2 ext4: calculate a... |
1758 |
err = ext4_handle_dirty_dirent_node(handle, dir, bh2); |
ac27a0ec1 [PATCH] ext4: ini... |
1759 1760 |
if (err) goto journal_error; |
dbe894440 ext4: Calculate a... |
1761 |
err = ext4_handle_dirty_dx_node(handle, dir, frame->bh); |
ac27a0ec1 [PATCH] ext4: ini... |
1762 1763 |
if (err) goto journal_error; |
af5bc92dd ext4: Fix whitesp... |
1764 1765 |
brelse(bh2); dxtrace(dx_show_index("frame", frame->entries)); |
ac27a0ec1 [PATCH] ext4: ini... |
1766 |
return de; |
fedee54d8 ext3: dirindex er... |
1767 1768 1769 1770 1771 1772 |
journal_error: brelse(*bh); brelse(bh2); *bh = NULL; ext4_std_error(dir->i_sb, err); |
f8b3b59d4 ext4: convert do_... |
1773 |
return ERR_PTR(err); |
ac27a0ec1 [PATCH] ext4: ini... |
1774 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
1775 |
|
978fef914 ext4: create __ex... |
1776 1777 1778 |
int ext4_find_dest_de(struct inode *dir, struct inode *inode, struct buffer_head *bh, void *buf, int buf_size, |
5b643f9ce ext4 crypto: opti... |
1779 |
struct ext4_filename *fname, |
978fef914 ext4: create __ex... |
1780 1781 1782 |
struct ext4_dir_entry_2 **dest_de) { struct ext4_dir_entry_2 *de; |
5b643f9ce ext4 crypto: opti... |
1783 |
unsigned short reclen = EXT4_DIR_REC_LEN(fname_len(fname)); |
978fef914 ext4: create __ex... |
1784 1785 1786 |
int nlen, rlen; unsigned int offset = 0; char *top; |
1f3862b55 ext4 crypto: file... |
1787 |
int res; |
978fef914 ext4: create __ex... |
1788 1789 1790 1791 |
de = (struct ext4_dir_entry_2 *)buf; top = buf + buf_size - reclen; while ((char *) de <= top) { if (ext4_check_dir_entry(dir, NULL, de, bh, |
1f3862b55 ext4 crypto: file... |
1792 |
buf, buf_size, offset)) { |
6a797d273 ext4: call out CR... |
1793 |
res = -EFSCORRUPTED; |
1f3862b55 ext4 crypto: file... |
1794 1795 1796 |
goto return_result; } /* Provide crypto context and crypto buffer to ext4 match */ |
5b643f9ce ext4 crypto: opti... |
1797 |
res = ext4_match(fname, de); |
1f3862b55 ext4 crypto: file... |
1798 1799 1800 1801 1802 1803 |
if (res < 0) goto return_result; if (res > 0) { res = -EEXIST; goto return_result; } |
978fef914 ext4: create __ex... |
1804 1805 1806 1807 1808 1809 1810 |
nlen = EXT4_DIR_REC_LEN(de->name_len); rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); if ((de->inode ? rlen - nlen : rlen) >= reclen) break; de = (struct ext4_dir_entry_2 *)((char *)de + rlen); offset += rlen; } |
978fef914 ext4: create __ex... |
1811 |
|
1f3862b55 ext4 crypto: file... |
1812 1813 1814 1815 1816 1817 1818 |
if ((char *) de > top) res = -ENOSPC; else { *dest_de = de; res = 0; } return_result: |
1f3862b55 ext4 crypto: file... |
1819 |
return res; |
978fef914 ext4: create __ex... |
1820 |
} |
4bdfc873b ext4 crypto: inse... |
1821 1822 1823 1824 |
int ext4_insert_dentry(struct inode *dir, struct inode *inode, struct ext4_dir_entry_2 *de, int buf_size, |
5b643f9ce ext4 crypto: opti... |
1825 |
struct ext4_filename *fname) |
978fef914 ext4: create __ex... |
1826 1827 1828 1829 1830 1831 1832 1833 |
{ int nlen, rlen; nlen = EXT4_DIR_REC_LEN(de->name_len); rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); if (de->inode) { struct ext4_dir_entry_2 *de1 = |
4bdfc873b ext4 crypto: inse... |
1834 |
(struct ext4_dir_entry_2 *)((char *)de + nlen); |
978fef914 ext4: create __ex... |
1835 1836 1837 1838 1839 1840 1841 |
de1->rec_len = ext4_rec_len_to_disk(rlen - nlen, buf_size); de->rec_len = ext4_rec_len_to_disk(nlen, buf_size); de = de1; } de->file_type = EXT4_FT_UNKNOWN; de->inode = cpu_to_le32(inode->i_ino); ext4_set_de_type(inode->i_sb, de, inode->i_mode); |
5b643f9ce ext4 crypto: opti... |
1842 1843 |
de->name_len = fname_len(fname); memcpy(de->name, fname_name(fname), fname_len(fname)); |
4bdfc873b ext4 crypto: inse... |
1844 |
return 0; |
978fef914 ext4: create __ex... |
1845 |
} |
4bdfc873b ext4 crypto: inse... |
1846 |
|
ac27a0ec1 [PATCH] ext4: ini... |
1847 1848 1849 1850 1851 1852 1853 |
/* * Add a new entry into a directory (leaf) block. If de is non-NULL, * it points to a directory entry which is guaranteed to be large * enough for new directory entry. If de is NULL, then * add_dirent_to_buf will attempt search the directory block for * space. It will return -ENOSPC if no space is available, and -EIO * and -EEXIST if directory entry already exists. |
ac27a0ec1 [PATCH] ext4: ini... |
1854 |
*/ |
5b643f9ce ext4 crypto: opti... |
1855 1856 |
static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname, struct inode *dir, |
617ba13b3 [PATCH] ext4: ren... |
1857 |
struct inode *inode, struct ext4_dir_entry_2 *de, |
af5bc92dd ext4: Fix whitesp... |
1858 |
struct buffer_head *bh) |
ac27a0ec1 [PATCH] ext4: ini... |
1859 |
{ |
3d0518f47 ext4: New rec_len... |
1860 |
unsigned int blocksize = dir->i_sb->s_blocksize; |
b0336e8d2 ext4: calculate a... |
1861 |
int csum_size = 0; |
978fef914 ext4: create __ex... |
1862 |
int err; |
b0336e8d2 ext4: calculate a... |
1863 |
|
9aa5d32ba ext4: Replace ope... |
1864 |
if (ext4_has_metadata_csum(inode->i_sb)) |
b0336e8d2 ext4: calculate a... |
1865 |
csum_size = sizeof(struct ext4_dir_entry_tail); |
ac27a0ec1 [PATCH] ext4: ini... |
1866 |
|
ac27a0ec1 [PATCH] ext4: ini... |
1867 |
if (!de) { |
5b643f9ce ext4 crypto: opti... |
1868 1869 |
err = ext4_find_dest_de(dir, inode, bh, bh->b_data, blocksize - csum_size, fname, &de); |
978fef914 ext4: create __ex... |
1870 1871 |
if (err) return err; |
ac27a0ec1 [PATCH] ext4: ini... |
1872 1873 |
} BUFFER_TRACE(bh, "get_write_access"); |
617ba13b3 [PATCH] ext4: ren... |
1874 |
err = ext4_journal_get_write_access(handle, bh); |
ac27a0ec1 [PATCH] ext4: ini... |
1875 |
if (err) { |
617ba13b3 [PATCH] ext4: ren... |
1876 |
ext4_std_error(dir->i_sb, err); |
ac27a0ec1 [PATCH] ext4: ini... |
1877 1878 |
return err; } |
4bdfc873b ext4 crypto: inse... |
1879 1880 |
/* By now the buffer is marked for journaling. Due to crypto operations, * the following function call may fail */ |
5b643f9ce ext4 crypto: opti... |
1881 |
err = ext4_insert_dentry(dir, inode, de, blocksize, fname); |
4bdfc873b ext4 crypto: inse... |
1882 1883 |
if (err < 0) return err; |
978fef914 ext4: create __ex... |
1884 |
|
ac27a0ec1 [PATCH] ext4: ini... |
1885 1886 1887 1888 1889 1890 |
/* * XXX shouldn't update any times until successful * completion of syscall, but too many callers depend * on this. * * XXX similarly, too many callers depend on |
617ba13b3 [PATCH] ext4: ren... |
1891 |
* ext4_new_inode() setting the times, but error |
ac27a0ec1 [PATCH] ext4: ini... |
1892 1893 1894 1895 |
* recovery deletes the inode, so the worst that can * happen is that the times are slightly out of date * and/or different from the directory change time. */ |
ef7f38359 ext4: Add nanosec... |
1896 |
dir->i_mtime = dir->i_ctime = ext4_current_time(dir); |
617ba13b3 [PATCH] ext4: ren... |
1897 |
ext4_update_dx_flag(dir); |
ac27a0ec1 [PATCH] ext4: ini... |
1898 |
dir->i_version++; |
617ba13b3 [PATCH] ext4: ren... |
1899 |
ext4_mark_inode_dirty(handle, dir); |
0390131ba ext4: Allow ext4 ... |
1900 |
BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
b0336e8d2 ext4: calculate a... |
1901 |
err = ext4_handle_dirty_dirent_node(handle, dir, bh); |
ac27a0ec1 [PATCH] ext4: ini... |
1902 |
if (err) |
617ba13b3 [PATCH] ext4: ren... |
1903 |
ext4_std_error(dir->i_sb, err); |
ac27a0ec1 [PATCH] ext4: ini... |
1904 1905 |
return 0; } |
ac27a0ec1 [PATCH] ext4: ini... |
1906 1907 1908 1909 |
/* * This converts a one block unindexed directory to a 3 block indexed * directory, and adds the dentry to the indexed directory. */ |
5b643f9ce ext4 crypto: opti... |
1910 |
static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname, |
56a04915d ext4 crypto: simp... |
1911 |
struct inode *dir, |
ac27a0ec1 [PATCH] ext4: ini... |
1912 1913 |
struct inode *inode, struct buffer_head *bh) { |
ac27a0ec1 [PATCH] ext4: ini... |
1914 1915 1916 1917 |
struct buffer_head *bh2; struct dx_root *root; struct dx_frame frames[2], *frame; struct dx_entry *entries; |
617ba13b3 [PATCH] ext4: ren... |
1918 |
struct ext4_dir_entry_2 *de, *de2; |
b0336e8d2 ext4: calculate a... |
1919 |
struct ext4_dir_entry_tail *t; |
ac27a0ec1 [PATCH] ext4: ini... |
1920 1921 1922 1923 |
char *data1, *top; unsigned len; int retval; unsigned blocksize; |
725d26d3f ext4: Introduce e... |
1924 |
ext4_lblk_t block; |
ac27a0ec1 [PATCH] ext4: ini... |
1925 |
struct fake_dirent *fde; |
4bdfc873b ext4 crypto: inse... |
1926 |
int csum_size = 0; |
9aa5d32ba ext4: Replace ope... |
1927 |
if (ext4_has_metadata_csum(inode->i_sb)) |
b0336e8d2 ext4: calculate a... |
1928 |
csum_size = sizeof(struct ext4_dir_entry_tail); |
ac27a0ec1 [PATCH] ext4: ini... |
1929 1930 |
blocksize = dir->i_sb->s_blocksize; |
e6b8bc09b ext4: Add sanity ... |
1931 1932 |
dxtrace(printk(KERN_DEBUG "Creating index: inode %lu ", dir->i_ino)); |
5d6012553 ext4: add missing... |
1933 |
BUFFER_TRACE(bh, "get_write_access"); |
617ba13b3 [PATCH] ext4: ren... |
1934 |
retval = ext4_journal_get_write_access(handle, bh); |
ac27a0ec1 [PATCH] ext4: ini... |
1935 |
if (retval) { |
617ba13b3 [PATCH] ext4: ren... |
1936 |
ext4_std_error(dir->i_sb, retval); |
ac27a0ec1 [PATCH] ext4: ini... |
1937 1938 1939 1940 |
brelse(bh); return retval; } root = (struct dx_root *) bh->b_data; |
e6b8bc09b ext4: Add sanity ... |
1941 1942 1943 |
/* The 0th block becomes the root, move the dirents out */ fde = &root->dotdot; de = (struct ext4_dir_entry_2 *)((char *)fde + |
3d0518f47 ext4: New rec_len... |
1944 |
ext4_rec_len_from_disk(fde->rec_len, blocksize)); |
e6b8bc09b ext4: Add sanity ... |
1945 |
if ((char *) de >= (((char *) root) + blocksize)) { |
24676da46 ext4: Convert cal... |
1946 |
EXT4_ERROR_INODE(dir, "invalid rec_len for '..'"); |
e6b8bc09b ext4: Add sanity ... |
1947 |
brelse(bh); |
6a797d273 ext4: call out CR... |
1948 |
return -EFSCORRUPTED; |
e6b8bc09b ext4: Add sanity ... |
1949 |
} |
b0336e8d2 ext4: calculate a... |
1950 |
len = ((char *) root) + (blocksize - csum_size) - (char *) de; |
e6b8bc09b ext4: Add sanity ... |
1951 1952 |
/* Allocate new block for the 0th block's dirents */ |
0f70b4061 ext4: use ERR_PTR... |
1953 1954 |
bh2 = ext4_append(handle, dir, &block); if (IS_ERR(bh2)) { |
ac27a0ec1 [PATCH] ext4: ini... |
1955 |
brelse(bh); |
0f70b4061 ext4: use ERR_PTR... |
1956 |
return PTR_ERR(bh2); |
ac27a0ec1 [PATCH] ext4: ini... |
1957 |
} |
12e9b8920 ext4: Use bitops ... |
1958 |
ext4_set_inode_flag(dir, EXT4_INODE_INDEX); |
ac27a0ec1 [PATCH] ext4: ini... |
1959 |
data1 = bh2->b_data; |
ac27a0ec1 [PATCH] ext4: ini... |
1960 |
memcpy (data1, de, len); |
617ba13b3 [PATCH] ext4: ren... |
1961 |
de = (struct ext4_dir_entry_2 *) data1; |
ac27a0ec1 [PATCH] ext4: ini... |
1962 |
top = data1 + len; |
3d0518f47 ext4: New rec_len... |
1963 |
while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) |
ac27a0ec1 [PATCH] ext4: ini... |
1964 |
de = de2; |
b0336e8d2 ext4: calculate a... |
1965 1966 |
de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) - (char *) de, |
3d0518f47 ext4: New rec_len... |
1967 |
blocksize); |
b0336e8d2 ext4: calculate a... |
1968 1969 1970 1971 1972 |
if (csum_size) { t = EXT4_DIRENT_TAIL(data1, blocksize); initialize_dirent_tail(t, blocksize); } |
ac27a0ec1 [PATCH] ext4: ini... |
1973 |
/* Initialize the root; the dot dirents already exist */ |
617ba13b3 [PATCH] ext4: ren... |
1974 |
de = (struct ext4_dir_entry_2 *) (&root->dotdot); |
3d0518f47 ext4: New rec_len... |
1975 1976 |
de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2), blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
1977 1978 |
memset (&root->info, 0, sizeof(root->info)); root->info.info_length = sizeof(root->info); |
617ba13b3 [PATCH] ext4: ren... |
1979 |
root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; |
ac27a0ec1 [PATCH] ext4: ini... |
1980 |
entries = root->entries; |
af5bc92dd ext4: Fix whitesp... |
1981 1982 1983 |
dx_set_block(entries, 1); dx_set_count(entries, 1); dx_set_limit(entries, dx_root_limit(dir, sizeof(root->info))); |
ac27a0ec1 [PATCH] ext4: ini... |
1984 1985 |
/* Initialize as for dx_probe */ |
5b643f9ce ext4 crypto: opti... |
1986 1987 1988 1989 1990 |
fname->hinfo.hash_version = root->info.hash_version; if (fname->hinfo.hash_version <= DX_HASH_TEA) fname->hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; ext4fs_dirhash(fname_name(fname), fname_len(fname), &fname->hinfo); |
6050d47ad ext4: bail out fr... |
1991 |
memset(frames, 0, sizeof(frames)); |
ac27a0ec1 [PATCH] ext4: ini... |
1992 1993 1994 1995 |
frame = frames; frame->entries = entries; frame->at = entries; frame->bh = bh; |
6976a6f2a ext4: don't deref... |
1996 |
|
6050d47ad ext4: bail out fr... |
1997 1998 1999 |
retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh); if (retval) goto out_frames; |
e81d44778 ext4: release bh ... |
2000 |
retval = ext4_handle_dirty_dirent_node(handle, dir, bh2); |
6050d47ad ext4: bail out fr... |
2001 2002 |
if (retval) goto out_frames; |
6976a6f2a ext4: don't deref... |
2003 |
|
e81d44778 ext4: release bh ... |
2004 |
de = do_split(handle,dir, &bh2, frame, &fname->hinfo); |
f8b3b59d4 ext4: convert do_... |
2005 |
if (IS_ERR(de)) { |
6050d47ad ext4: bail out fr... |
2006 2007 |
retval = PTR_ERR(de); goto out_frames; |
7ad8e4e6a ext4: Fix fs corr... |
2008 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2009 |
|
e81d44778 ext4: release bh ... |
2010 |
retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh2); |
6050d47ad ext4: bail out fr... |
2011 2012 2013 2014 2015 2016 |
out_frames: /* * Even if the block split failed, we have to properly write * out all the changes we did so far. Otherwise we can end up * with corrupted filesystem. */ |
e81d44778 ext4: release bh ... |
2017 2018 |
if (retval) ext4_mark_inode_dirty(handle, dir); |
6050d47ad ext4: bail out fr... |
2019 |
dx_release(frames); |
e81d44778 ext4: release bh ... |
2020 |
brelse(bh2); |
6050d47ad ext4: bail out fr... |
2021 |
return retval; |
ac27a0ec1 [PATCH] ext4: ini... |
2022 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2023 2024 |
/* |
617ba13b3 [PATCH] ext4: ren... |
2025 |
* ext4_add_entry() |
ac27a0ec1 [PATCH] ext4: ini... |
2026 2027 |
* * adds a file entry to the specified directory, using the same |
617ba13b3 [PATCH] ext4: ren... |
2028 |
* semantics as ext4_find_entry(). It returns NULL if it failed. |
ac27a0ec1 [PATCH] ext4: ini... |
2029 2030 2031 2032 2033 |
* * NOTE!! The inode part of 'de' is left at 0 - which means you * may not sleep between calling this and putting something into * the entry, as someone else might have used it while you slept. */ |
af5bc92dd ext4: Fix whitesp... |
2034 2035 |
static int ext4_add_entry(handle_t *handle, struct dentry *dentry, struct inode *inode) |
ac27a0ec1 [PATCH] ext4: ini... |
2036 |
{ |
2b0143b5c VFS: normal files... |
2037 |
struct inode *dir = d_inode(dentry->d_parent); |
e12fb9722 ext4: make fsync ... |
2038 |
struct buffer_head *bh = NULL; |
617ba13b3 [PATCH] ext4: ren... |
2039 |
struct ext4_dir_entry_2 *de; |
b0336e8d2 ext4: calculate a... |
2040 |
struct ext4_dir_entry_tail *t; |
af5bc92dd ext4: Fix whitesp... |
2041 |
struct super_block *sb; |
5b643f9ce ext4 crypto: opti... |
2042 |
struct ext4_filename fname; |
ac27a0ec1 [PATCH] ext4: ini... |
2043 |
int retval; |
ac27a0ec1 [PATCH] ext4: ini... |
2044 |
int dx_fallback=0; |
ac27a0ec1 [PATCH] ext4: ini... |
2045 |
unsigned blocksize; |
725d26d3f ext4: Introduce e... |
2046 |
ext4_lblk_t block, blocks; |
b0336e8d2 ext4: calculate a... |
2047 |
int csum_size = 0; |
9aa5d32ba ext4: Replace ope... |
2048 |
if (ext4_has_metadata_csum(inode->i_sb)) |
b0336e8d2 ext4: calculate a... |
2049 |
csum_size = sizeof(struct ext4_dir_entry_tail); |
ac27a0ec1 [PATCH] ext4: ini... |
2050 2051 2052 2053 2054 |
sb = dir->i_sb; blocksize = sb->s_blocksize; if (!dentry->d_name.len) return -EINVAL; |
3c47d5417 ext4: let add_dir... |
2055 |
|
5b643f9ce ext4 crypto: opti... |
2056 2057 2058 |
retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname); if (retval) return retval; |
3c47d5417 ext4: let add_dir... |
2059 |
if (ext4_has_inline_data(dir)) { |
56a04915d ext4 crypto: simp... |
2060 |
retval = ext4_try_add_inline_entry(handle, &fname, dir, inode); |
3c47d5417 ext4: let add_dir... |
2061 |
if (retval < 0) |
5b643f9ce ext4 crypto: opti... |
2062 |
goto out; |
3c47d5417 ext4: let add_dir... |
2063 2064 |
if (retval == 1) { retval = 0; |
e12fb9722 ext4: make fsync ... |
2065 |
goto out; |
3c47d5417 ext4: let add_dir... |
2066 2067 |
} } |
ac27a0ec1 [PATCH] ext4: ini... |
2068 |
if (is_dx(dir)) { |
56a04915d ext4 crypto: simp... |
2069 |
retval = ext4_dx_add_entry(handle, &fname, dir, inode); |
ac27a0ec1 [PATCH] ext4: ini... |
2070 |
if (!retval || (retval != ERR_BAD_DX_DIR)) |
e12fb9722 ext4: make fsync ... |
2071 |
goto out; |
12e9b8920 ext4: Use bitops ... |
2072 |
ext4_clear_inode_flag(dir, EXT4_INODE_INDEX); |
ac27a0ec1 [PATCH] ext4: ini... |
2073 |
dx_fallback++; |
617ba13b3 [PATCH] ext4: ren... |
2074 |
ext4_mark_inode_dirty(handle, dir); |
ac27a0ec1 [PATCH] ext4: ini... |
2075 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2076 |
blocks = dir->i_size >> sb->s_blocksize_bits; |
498e5f241 ext4: Change unsi... |
2077 |
for (block = 0; block < blocks; block++) { |
dc6982ff4 ext4: refactor co... |
2078 |
bh = ext4_read_dirblock(dir, block, DIRENT); |
5b643f9ce ext4 crypto: opti... |
2079 2080 2081 2082 2083 2084 2085 |
if (IS_ERR(bh)) { retval = PTR_ERR(bh); bh = NULL; goto out; } retval = add_dirent_to_buf(handle, &fname, dir, inode, NULL, bh); |
e12fb9722 ext4: make fsync ... |
2086 2087 |
if (retval != -ENOSPC) goto out; |
ac27a0ec1 [PATCH] ext4: ini... |
2088 |
|
ac27a0ec1 [PATCH] ext4: ini... |
2089 |
if (blocks == 1 && !dx_fallback && |
e2b911c53 ext4: clean up fe... |
2090 |
ext4_has_feature_dir_index(sb)) { |
56a04915d ext4 crypto: simp... |
2091 |
retval = make_indexed_dir(handle, &fname, dir, |
5b643f9ce ext4 crypto: opti... |
2092 |
inode, bh); |
e12fb9722 ext4: make fsync ... |
2093 2094 2095 |
bh = NULL; /* make_indexed_dir releases bh */ goto out; } |
ac27a0ec1 [PATCH] ext4: ini... |
2096 2097 |
brelse(bh); } |
0f70b4061 ext4: use ERR_PTR... |
2098 |
bh = ext4_append(handle, dir, &block); |
5b643f9ce ext4 crypto: opti... |
2099 2100 2101 2102 2103 |
if (IS_ERR(bh)) { retval = PTR_ERR(bh); bh = NULL; goto out; } |
617ba13b3 [PATCH] ext4: ren... |
2104 |
de = (struct ext4_dir_entry_2 *) bh->b_data; |
ac27a0ec1 [PATCH] ext4: ini... |
2105 |
de->inode = 0; |
b0336e8d2 ext4: calculate a... |
2106 2107 2108 2109 2110 2111 |
de->rec_len = ext4_rec_len_to_disk(blocksize - csum_size, blocksize); if (csum_size) { t = EXT4_DIRENT_TAIL(bh->b_data, blocksize); initialize_dirent_tail(t, blocksize); } |
5b643f9ce ext4 crypto: opti... |
2112 |
retval = add_dirent_to_buf(handle, &fname, dir, inode, de, bh); |
e12fb9722 ext4: make fsync ... |
2113 |
out: |
5b643f9ce ext4 crypto: opti... |
2114 |
ext4_fname_free_filename(&fname); |
2de770a40 ext4: fix potenti... |
2115 |
brelse(bh); |
14ece1028 ext4: Make fsync ... |
2116 2117 |
if (retval == 0) ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY); |
2de770a40 ext4: fix potenti... |
2118 |
return retval; |
ac27a0ec1 [PATCH] ext4: ini... |
2119 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2120 2121 2122 |
/* * Returns 0 for success, or a negative error value */ |
5b643f9ce ext4 crypto: opti... |
2123 |
static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname, |
56a04915d ext4 crypto: simp... |
2124 |
struct inode *dir, struct inode *inode) |
ac27a0ec1 [PATCH] ext4: ini... |
2125 2126 2127 |
{ struct dx_frame frames[2], *frame; struct dx_entry *entries, *at; |
af5bc92dd ext4: Fix whitesp... |
2128 |
struct buffer_head *bh; |
af5bc92dd ext4: Fix whitesp... |
2129 |
struct super_block *sb = dir->i_sb; |
617ba13b3 [PATCH] ext4: ren... |
2130 |
struct ext4_dir_entry_2 *de; |
ac27a0ec1 [PATCH] ext4: ini... |
2131 |
int err; |
5b643f9ce ext4 crypto: opti... |
2132 |
frame = dx_probe(fname, dir, NULL, frames); |
dd73b5d5c ext4: convert dx_... |
2133 2134 |
if (IS_ERR(frame)) return PTR_ERR(frame); |
ac27a0ec1 [PATCH] ext4: ini... |
2135 2136 |
entries = frame->entries; at = frame->at; |
dc6982ff4 ext4: refactor co... |
2137 2138 2139 2140 |
bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT); if (IS_ERR(bh)) { err = PTR_ERR(bh); bh = NULL; |
ac27a0ec1 [PATCH] ext4: ini... |
2141 |
goto cleanup; |
6d1ab10e6 ext4: ext4_bread ... |
2142 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2143 2144 |
BUFFER_TRACE(bh, "get_write_access"); |
617ba13b3 [PATCH] ext4: ren... |
2145 |
err = ext4_journal_get_write_access(handle, bh); |
ac27a0ec1 [PATCH] ext4: ini... |
2146 2147 |
if (err) goto journal_error; |
5b643f9ce ext4 crypto: opti... |
2148 |
err = add_dirent_to_buf(handle, fname, dir, inode, NULL, bh); |
2de770a40 ext4: fix potenti... |
2149 |
if (err != -ENOSPC) |
ac27a0ec1 [PATCH] ext4: ini... |
2150 |
goto cleanup; |
ac27a0ec1 [PATCH] ext4: ini... |
2151 2152 |
/* Block full, should compress but for now just split */ |
4776004f5 ext4: Add printk ... |
2153 2154 |
dxtrace(printk(KERN_DEBUG "using %u of %u node entries ", |
ac27a0ec1 [PATCH] ext4: ini... |
2155 2156 2157 |
dx_get_count(entries), dx_get_limit(entries))); /* Need to split index? */ if (dx_get_count(entries) == dx_get_limit(entries)) { |
725d26d3f ext4: Introduce e... |
2158 |
ext4_lblk_t newblock; |
ac27a0ec1 [PATCH] ext4: ini... |
2159 2160 2161 2162 2163 2164 2165 2166 |
unsigned icount = dx_get_count(entries); int levels = frame - frames; struct dx_entry *entries2; struct dx_node *node2; struct buffer_head *bh2; if (levels && (dx_get_count(frames->entries) == dx_get_limit(frames->entries))) { |
b03a2f7eb ext4: improve war... |
2167 |
ext4_warning_inode(dir, "Directory index full!"); |
ac27a0ec1 [PATCH] ext4: ini... |
2168 2169 2170 |
err = -ENOSPC; goto cleanup; } |
0f70b4061 ext4: use ERR_PTR... |
2171 2172 2173 |
bh2 = ext4_append(handle, dir, &newblock); if (IS_ERR(bh2)) { err = PTR_ERR(bh2); |
ac27a0ec1 [PATCH] ext4: ini... |
2174 |
goto cleanup; |
0f70b4061 ext4: use ERR_PTR... |
2175 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2176 2177 |
node2 = (struct dx_node *)(bh2->b_data); entries2 = node2->entries; |
1f7bebb9e ext4: Always set ... |
2178 |
memset(&node2->fake, 0, sizeof(struct fake_dirent)); |
3d0518f47 ext4: New rec_len... |
2179 2180 |
node2->fake.rec_len = ext4_rec_len_to_disk(sb->s_blocksize, sb->s_blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
2181 |
BUFFER_TRACE(frame->bh, "get_write_access"); |
617ba13b3 [PATCH] ext4: ren... |
2182 |
err = ext4_journal_get_write_access(handle, frame->bh); |
ac27a0ec1 [PATCH] ext4: ini... |
2183 2184 2185 2186 2187 |
if (err) goto journal_error; if (levels) { unsigned icount1 = icount/2, icount2 = icount - icount1; unsigned hash2 = dx_get_hash(entries + icount1); |
4776004f5 ext4: Add printk ... |
2188 2189 2190 |
dxtrace(printk(KERN_DEBUG "Split index %i/%i ", icount1, icount2)); |
ac27a0ec1 [PATCH] ext4: ini... |
2191 2192 |
BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */ |
617ba13b3 [PATCH] ext4: ren... |
2193 |
err = ext4_journal_get_write_access(handle, |
ac27a0ec1 [PATCH] ext4: ini... |
2194 2195 2196 |
frames[0].bh); if (err) goto journal_error; |
af5bc92dd ext4: Fix whitesp... |
2197 2198 2199 2200 2201 |
memcpy((char *) entries2, (char *) (entries + icount1), icount2 * sizeof(struct dx_entry)); dx_set_count(entries, icount1); dx_set_count(entries2, icount2); dx_set_limit(entries2, dx_node_limit(dir)); |
ac27a0ec1 [PATCH] ext4: ini... |
2202 2203 2204 2205 2206 2207 2208 |
/* Which index block gets the new entry? */ if (at - entries >= icount1) { frame->at = at = at - entries - icount1 + entries2; frame->entries = entries = entries2; swap(frame->bh, bh2); } |
af5bc92dd ext4: Fix whitesp... |
2209 2210 2211 |
dx_insert_block(frames + 0, hash2, newblock); dxtrace(dx_show_index("node", frames[1].entries)); dxtrace(dx_show_index("node", |
ac27a0ec1 [PATCH] ext4: ini... |
2212 |
((struct dx_node *) bh2->b_data)->entries)); |
dbe894440 ext4: Calculate a... |
2213 |
err = ext4_handle_dirty_dx_node(handle, dir, bh2); |
ac27a0ec1 [PATCH] ext4: ini... |
2214 2215 2216 2217 |
if (err) goto journal_error; brelse (bh2); } else { |
4776004f5 ext4: Add printk ... |
2218 2219 2220 |
dxtrace(printk(KERN_DEBUG "Creating second level index... ")); |
ac27a0ec1 [PATCH] ext4: ini... |
2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 |
memcpy((char *) entries2, (char *) entries, icount * sizeof(struct dx_entry)); dx_set_limit(entries2, dx_node_limit(dir)); /* Set up root */ dx_set_count(entries, 1); dx_set_block(entries + 0, newblock); ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1; /* Add new access path frame */ frame = frames + 1; frame->at = at = at - entries + entries2; frame->entries = entries = entries2; frame->bh = bh2; |
617ba13b3 [PATCH] ext4: ren... |
2235 |
err = ext4_journal_get_write_access(handle, |
ac27a0ec1 [PATCH] ext4: ini... |
2236 2237 2238 2239 |
frame->bh); if (err) goto journal_error; } |
dbe894440 ext4: Calculate a... |
2240 |
err = ext4_handle_dirty_dx_node(handle, dir, frames[0].bh); |
b40971426 ext4: add error c... |
2241 2242 2243 2244 |
if (err) { ext4_std_error(inode->i_sb, err); goto cleanup; } |
ac27a0ec1 [PATCH] ext4: ini... |
2245 |
} |
5b643f9ce ext4 crypto: opti... |
2246 |
de = do_split(handle, dir, &bh, frame, &fname->hinfo); |
f8b3b59d4 ext4: convert do_... |
2247 2248 |
if (IS_ERR(de)) { err = PTR_ERR(de); |
ac27a0ec1 [PATCH] ext4: ini... |
2249 |
goto cleanup; |
f8b3b59d4 ext4: convert do_... |
2250 |
} |
5b643f9ce ext4 crypto: opti... |
2251 |
err = add_dirent_to_buf(handle, fname, dir, inode, de, bh); |
ac27a0ec1 [PATCH] ext4: ini... |
2252 2253 2254 |
goto cleanup; journal_error: |
617ba13b3 [PATCH] ext4: ren... |
2255 |
ext4_std_error(dir->i_sb, err); |
ac27a0ec1 [PATCH] ext4: ini... |
2256 |
cleanup: |
b1deefc99 ext4: remove unne... |
2257 |
brelse(bh); |
ac27a0ec1 [PATCH] ext4: ini... |
2258 2259 2260 |
dx_release(frames); return err; } |
ac27a0ec1 [PATCH] ext4: ini... |
2261 2262 |
/* |
05019a9e7 ext4: make ext4_d... |
2263 2264 |
* ext4_generic_delete_entry deletes a directory entry by merging it * with the previous entry |
ac27a0ec1 [PATCH] ext4: ini... |
2265 |
*/ |
05019a9e7 ext4: make ext4_d... |
2266 2267 2268 2269 2270 2271 2272 |
int ext4_generic_delete_entry(handle_t *handle, struct inode *dir, struct ext4_dir_entry_2 *de_del, struct buffer_head *bh, void *entry_buf, int buf_size, int csum_size) |
ac27a0ec1 [PATCH] ext4: ini... |
2273 |
{ |
af5bc92dd ext4: Fix whitesp... |
2274 |
struct ext4_dir_entry_2 *de, *pde; |
3d0518f47 ext4: New rec_len... |
2275 |
unsigned int blocksize = dir->i_sb->s_blocksize; |
05019a9e7 ext4: make ext4_d... |
2276 |
int i; |
b0336e8d2 ext4: calculate a... |
2277 |
|
ac27a0ec1 [PATCH] ext4: ini... |
2278 2279 |
i = 0; pde = NULL; |
05019a9e7 ext4: make ext4_d... |
2280 2281 |
de = (struct ext4_dir_entry_2 *)entry_buf; while (i < buf_size - csum_size) { |
226ba972b ext4: refactor __... |
2282 2283 |
if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data, bh->b_size, i)) |
6a797d273 ext4: call out CR... |
2284 |
return -EFSCORRUPTED; |
ac27a0ec1 [PATCH] ext4: ini... |
2285 |
if (de == de_del) { |
ac27a0ec1 [PATCH] ext4: ini... |
2286 |
if (pde) |
a72d7f834 ext4: Avoid rec_l... |
2287 |
pde->rec_len = ext4_rec_len_to_disk( |
3d0518f47 ext4: New rec_len... |
2288 2289 2290 2291 2292 |
ext4_rec_len_from_disk(pde->rec_len, blocksize) + ext4_rec_len_from_disk(de->rec_len, blocksize), blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
2293 2294 2295 |
else de->inode = 0; dir->i_version++; |
ac27a0ec1 [PATCH] ext4: ini... |
2296 2297 |
return 0; } |
3d0518f47 ext4: New rec_len... |
2298 |
i += ext4_rec_len_from_disk(de->rec_len, blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
2299 |
pde = de; |
3d0518f47 ext4: New rec_len... |
2300 |
de = ext4_next_entry(de, blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
2301 2302 2303 |
} return -ENOENT; } |
05019a9e7 ext4: make ext4_d... |
2304 2305 2306 2307 2308 2309 |
static int ext4_delete_entry(handle_t *handle, struct inode *dir, struct ext4_dir_entry_2 *de_del, struct buffer_head *bh) { int err, csum_size = 0; |
9f40fe546 ext4: let ext4_de... |
2310 2311 2312 2313 2314 2315 2316 |
if (ext4_has_inline_data(dir)) { int has_inline_data = 1; err = ext4_delete_inline_entry(handle, dir, de_del, bh, &has_inline_data); if (has_inline_data) return err; } |
9aa5d32ba ext4: Replace ope... |
2317 |
if (ext4_has_metadata_csum(dir->i_sb)) |
05019a9e7 ext4: make ext4_d... |
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 |
csum_size = sizeof(struct ext4_dir_entry_tail); BUFFER_TRACE(bh, "get_write_access"); err = ext4_journal_get_write_access(handle, bh); if (unlikely(err)) goto out; err = ext4_generic_delete_entry(handle, dir, de_del, bh, bh->b_data, dir->i_sb->s_blocksize, csum_size); if (err) goto out; BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); err = ext4_handle_dirty_dirent_node(handle, dir, bh); if (unlikely(err)) goto out; return 0; out: if (err != -ENOENT) ext4_std_error(dir->i_sb, err); return err; } |
f8628a14a ext4: Remove 6500... |
2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 |
/* * DIR_NLINK feature is set if 1) nlinks > EXT4_LINK_MAX or 2) nlinks == 2, * since this indicates that nlinks count was previously 1. */ static void ext4_inc_count(handle_t *handle, struct inode *inode) { inc_nlink(inode); if (is_dx(inode) && inode->i_nlink > 1) { /* limit is 16-bit i_links_count */ if (inode->i_nlink >= EXT4_LINK_MAX || inode->i_nlink == 2) { |
bfe868486 filesystems: add ... |
2352 |
set_nlink(inode, 1); |
e2b911c53 ext4: clean up fe... |
2353 |
ext4_set_feature_dir_nlink(inode->i_sb); |
f8628a14a ext4: Remove 6500... |
2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 |
} } } /* * If a directory had nlink == 1, then we should let it be 1. This indicates * directory has >EXT4_LINK_MAX subdirs. */ static void ext4_dec_count(handle_t *handle, struct inode *inode) { |
909a4cf1f ext4: avoid setti... |
2364 2365 |
if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) drop_nlink(inode); |
f8628a14a ext4: Remove 6500... |
2366 |
} |
617ba13b3 [PATCH] ext4: ren... |
2367 |
static int ext4_add_nondir(handle_t *handle, |
ac27a0ec1 [PATCH] ext4: ini... |
2368 2369 |
struct dentry *dentry, struct inode *inode) { |
617ba13b3 [PATCH] ext4: ren... |
2370 |
int err = ext4_add_entry(handle, dentry, inode); |
ac27a0ec1 [PATCH] ext4: ini... |
2371 |
if (!err) { |
617ba13b3 [PATCH] ext4: ren... |
2372 |
ext4_mark_inode_dirty(handle, inode); |
6b38e842b nfsd race fixes: ... |
2373 |
unlock_new_inode(inode); |
8fc37ec54 don't expose I_NE... |
2374 |
d_instantiate(dentry, inode); |
ac27a0ec1 [PATCH] ext4: ini... |
2375 2376 |
return 0; } |
731b9a549 [PATCH] remove ex... |
2377 |
drop_nlink(inode); |
6b38e842b nfsd race fixes: ... |
2378 |
unlock_new_inode(inode); |
ac27a0ec1 [PATCH] ext4: ini... |
2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 |
iput(inode); return err; } /* * By the time this is called, we already have created * the directory cache entry for the new file, but it * is so far negative - it has no inode. * * If the create succeeds, we fill in the inode information * with d_instantiate(). */ |
4acdaf27e switch ->create()... |
2391 |
static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
ebfc3b49a don't pass nameid... |
2392 |
bool excl) |
ac27a0ec1 [PATCH] ext4: ini... |
2393 2394 |
{ handle_t *handle; |
af5bc92dd ext4: Fix whitesp... |
2395 |
struct inode *inode; |
1139575a9 ext4: start handl... |
2396 |
int err, credits, retries = 0; |
ac27a0ec1 [PATCH] ext4: ini... |
2397 |
|
a7cdadee0 ext4: Handle erro... |
2398 2399 2400 |
err = dquot_initialize(dir); if (err) return err; |
907f4554e dquot: move dquot... |
2401 |
|
1139575a9 ext4: start handl... |
2402 |
credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + |
eb9cc7e16 ext4: move quota ... |
2403 |
EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3); |
ac27a0ec1 [PATCH] ext4: ini... |
2404 |
retry: |
1139575a9 ext4: start handl... |
2405 2406 2407 |
inode = ext4_new_inode_start_handle(dir, mode, &dentry->d_name, 0, NULL, EXT4_HT_DIR, credits); handle = ext4_journal_current_handle(); |
ac27a0ec1 [PATCH] ext4: ini... |
2408 2409 |
err = PTR_ERR(inode); if (!IS_ERR(inode)) { |
617ba13b3 [PATCH] ext4: ren... |
2410 |
inode->i_op = &ext4_file_inode_operations; |
be64f884b dax: unify ext2/4... |
2411 |
inode->i_fop = &ext4_file_operations; |
617ba13b3 [PATCH] ext4: ren... |
2412 |
ext4_set_aops(inode); |
e709e9df6 ext4 crypto: encr... |
2413 |
err = ext4_add_nondir(handle, dentry, inode); |
1139575a9 ext4: start handl... |
2414 2415 |
if (!err && IS_DIRSYNC(dir)) ext4_handle_sync(handle); |
ac27a0ec1 [PATCH] ext4: ini... |
2416 |
} |
1139575a9 ext4: start handl... |
2417 2418 |
if (handle) ext4_journal_stop(handle); |
617ba13b3 [PATCH] ext4: ren... |
2419 |
if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
ac27a0ec1 [PATCH] ext4: ini... |
2420 2421 2422 |
goto retry; return err; } |
af5bc92dd ext4: Fix whitesp... |
2423 |
static int ext4_mknod(struct inode *dir, struct dentry *dentry, |
1a67aafb5 switch ->mknod() ... |
2424 |
umode_t mode, dev_t rdev) |
ac27a0ec1 [PATCH] ext4: ini... |
2425 2426 2427 |
{ handle_t *handle; struct inode *inode; |
1139575a9 ext4: start handl... |
2428 |
int err, credits, retries = 0; |
ac27a0ec1 [PATCH] ext4: ini... |
2429 |
|
a7cdadee0 ext4: Handle erro... |
2430 2431 2432 |
err = dquot_initialize(dir); if (err) return err; |
907f4554e dquot: move dquot... |
2433 |
|
1139575a9 ext4: start handl... |
2434 |
credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + |
eb9cc7e16 ext4: move quota ... |
2435 |
EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3); |
ac27a0ec1 [PATCH] ext4: ini... |
2436 |
retry: |
1139575a9 ext4: start handl... |
2437 2438 2439 |
inode = ext4_new_inode_start_handle(dir, mode, &dentry->d_name, 0, NULL, EXT4_HT_DIR, credits); handle = ext4_journal_current_handle(); |
ac27a0ec1 [PATCH] ext4: ini... |
2440 2441 2442 |
err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); |
617ba13b3 [PATCH] ext4: ren... |
2443 |
inode->i_op = &ext4_special_inode_operations; |
617ba13b3 [PATCH] ext4: ren... |
2444 |
err = ext4_add_nondir(handle, dentry, inode); |
1139575a9 ext4: start handl... |
2445 2446 |
if (!err && IS_DIRSYNC(dir)) ext4_handle_sync(handle); |
ac27a0ec1 [PATCH] ext4: ini... |
2447 |
} |
1139575a9 ext4: start handl... |
2448 2449 |
if (handle) ext4_journal_stop(handle); |
617ba13b3 [PATCH] ext4: ren... |
2450 |
if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
ac27a0ec1 [PATCH] ext4: ini... |
2451 2452 2453 |
goto retry; return err; } |
af51a2ac3 ext4: ->tmpfile()... |
2454 2455 2456 2457 2458 |
static int ext4_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) { handle_t *handle; struct inode *inode; int err, retries = 0; |
a7cdadee0 ext4: Handle erro... |
2459 2460 2461 |
err = dquot_initialize(dir); if (err) return err; |
af51a2ac3 ext4: ->tmpfile()... |
2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 |
retry: inode = ext4_new_inode_start_handle(dir, mode, NULL, 0, NULL, EXT4_HT_DIR, EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) + 4 + EXT4_XATTR_TRANS_BLOCKS); handle = ext4_journal_current_handle(); err = PTR_ERR(inode); if (!IS_ERR(inode)) { inode->i_op = &ext4_file_inode_operations; |
be64f884b dax: unify ext2/4... |
2473 |
inode->i_fop = &ext4_file_operations; |
af51a2ac3 ext4: ->tmpfile()... |
2474 |
ext4_set_aops(inode); |
e94bd3490 ext4: fix a BUG w... |
2475 |
d_tmpfile(dentry, inode); |
af51a2ac3 ext4: ->tmpfile()... |
2476 2477 |
err = ext4_orphan_add(handle, inode); if (err) |
43ae9e3fc ext[34]: fix doub... |
2478 |
goto err_unlock_inode; |
af51a2ac3 ext4: ->tmpfile()... |
2479 |
mark_inode_dirty(inode); |
af51a2ac3 ext4: ->tmpfile()... |
2480 2481 2482 2483 2484 2485 2486 |
unlock_new_inode(inode); } if (handle) ext4_journal_stop(handle); if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) goto retry; return err; |
43ae9e3fc ext[34]: fix doub... |
2487 |
err_unlock_inode: |
af51a2ac3 ext4: ->tmpfile()... |
2488 2489 |
ext4_journal_stop(handle); unlock_new_inode(inode); |
af51a2ac3 ext4: ->tmpfile()... |
2490 2491 |
return err; } |
a774f9c20 ext4: make ext4_i... |
2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 |
struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode, struct ext4_dir_entry_2 *de, int blocksize, int csum_size, unsigned int parent_ino, int dotdot_real_len) { de->inode = cpu_to_le32(inode->i_ino); de->name_len = 1; de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len), blocksize); strcpy(de->name, "."); ext4_set_de_type(inode->i_sb, de, S_IFDIR); de = ext4_next_entry(de, blocksize); de->inode = cpu_to_le32(parent_ino); de->name_len = 2; if (!dotdot_real_len) de->rec_len = ext4_rec_len_to_disk(blocksize - (csum_size + EXT4_DIR_REC_LEN(1)), blocksize); else de->rec_len = ext4_rec_len_to_disk( EXT4_DIR_REC_LEN(de->name_len), blocksize); strcpy(de->name, ".."); ext4_set_de_type(inode->i_sb, de, S_IFDIR); return ext4_next_entry(de, blocksize); } static int ext4_init_new_dir(handle_t *handle, struct inode *dir, struct inode *inode) |
ac27a0ec1 [PATCH] ext4: ini... |
2522 |
{ |
dabd991f9 ext4: add more er... |
2523 |
struct buffer_head *dir_block = NULL; |
af5bc92dd ext4: Fix whitesp... |
2524 |
struct ext4_dir_entry_2 *de; |
b0336e8d2 ext4: calculate a... |
2525 |
struct ext4_dir_entry_tail *t; |
dc6982ff4 ext4: refactor co... |
2526 |
ext4_lblk_t block = 0; |
3d0518f47 ext4: New rec_len... |
2527 |
unsigned int blocksize = dir->i_sb->s_blocksize; |
b0336e8d2 ext4: calculate a... |
2528 |
int csum_size = 0; |
a774f9c20 ext4: make ext4_i... |
2529 |
int err; |
ac27a0ec1 [PATCH] ext4: ini... |
2530 |
|
9aa5d32ba ext4: Replace ope... |
2531 |
if (ext4_has_metadata_csum(dir->i_sb)) |
b0336e8d2 ext4: calculate a... |
2532 |
csum_size = sizeof(struct ext4_dir_entry_tail); |
3c47d5417 ext4: let add_dir... |
2533 2534 2535 2536 2537 2538 2539 |
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { err = ext4_try_create_inline_dir(handle, dir, inode); if (err < 0 && err != -ENOSPC) goto out; if (!err) goto out; } |
dc6982ff4 ext4: refactor co... |
2540 |
inode->i_size = 0; |
0f70b4061 ext4: use ERR_PTR... |
2541 2542 2543 |
dir_block = ext4_append(handle, inode, &block); if (IS_ERR(dir_block)) return PTR_ERR(dir_block); |
a774f9c20 ext4: make ext4_i... |
2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 |
de = (struct ext4_dir_entry_2 *)dir_block->b_data; ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0); set_nlink(inode, 2); if (csum_size) { t = EXT4_DIRENT_TAIL(dir_block->b_data, blocksize); initialize_dirent_tail(t, blocksize); } BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata"); err = ext4_handle_dirty_dirent_node(handle, inode, dir_block); if (err) goto out; set_buffer_verified(dir_block); out: brelse(dir_block); return err; } static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { handle_t *handle; struct inode *inode; |
1139575a9 ext4: start handl... |
2566 |
int err, credits, retries = 0; |
a774f9c20 ext4: make ext4_i... |
2567 |
|
f8628a14a ext4: Remove 6500... |
2568 |
if (EXT4_DIR_LINK_MAX(dir)) |
ac27a0ec1 [PATCH] ext4: ini... |
2569 |
return -EMLINK; |
a7cdadee0 ext4: Handle erro... |
2570 2571 2572 |
err = dquot_initialize(dir); if (err) return err; |
907f4554e dquot: move dquot... |
2573 |
|
1139575a9 ext4: start handl... |
2574 |
credits = (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + |
eb9cc7e16 ext4: move quota ... |
2575 |
EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3); |
ac27a0ec1 [PATCH] ext4: ini... |
2576 |
retry: |
1139575a9 ext4: start handl... |
2577 2578 2579 2580 |
inode = ext4_new_inode_start_handle(dir, S_IFDIR | mode, &dentry->d_name, 0, NULL, EXT4_HT_DIR, credits); handle = ext4_journal_current_handle(); |
ac27a0ec1 [PATCH] ext4: ini... |
2581 2582 2583 |
err = PTR_ERR(inode); if (IS_ERR(inode)) goto out_stop; |
617ba13b3 [PATCH] ext4: ren... |
2584 2585 |
inode->i_op = &ext4_dir_inode_operations; inode->i_fop = &ext4_dir_operations; |
a774f9c20 ext4: make ext4_i... |
2586 |
err = ext4_init_new_dir(handle, dir, inode); |
dabd991f9 ext4: add more er... |
2587 2588 2589 2590 2591 |
if (err) goto out_clear_inode; err = ext4_mark_inode_dirty(handle, inode); if (!err) err = ext4_add_entry(handle, dentry, inode); |
ac27a0ec1 [PATCH] ext4: ini... |
2592 |
if (err) { |
4cdeed861 ext4: Don't leave... |
2593 2594 |
out_clear_inode: clear_nlink(inode); |
6b38e842b nfsd race fixes: ... |
2595 |
unlock_new_inode(inode); |
617ba13b3 [PATCH] ext4: ren... |
2596 |
ext4_mark_inode_dirty(handle, inode); |
af5bc92dd ext4: Fix whitesp... |
2597 |
iput(inode); |
ac27a0ec1 [PATCH] ext4: ini... |
2598 2599 |
goto out_stop; } |
f8628a14a ext4: Remove 6500... |
2600 |
ext4_inc_count(handle, dir); |
617ba13b3 [PATCH] ext4: ren... |
2601 |
ext4_update_dx_flag(dir); |
dabd991f9 ext4: add more er... |
2602 2603 2604 |
err = ext4_mark_inode_dirty(handle, dir); if (err) goto out_clear_inode; |
6b38e842b nfsd race fixes: ... |
2605 |
unlock_new_inode(inode); |
8fc37ec54 don't expose I_NE... |
2606 |
d_instantiate(dentry, inode); |
1139575a9 ext4: start handl... |
2607 2608 |
if (IS_DIRSYNC(dir)) ext4_handle_sync(handle); |
ac27a0ec1 [PATCH] ext4: ini... |
2609 |
out_stop: |
1139575a9 ext4: start handl... |
2610 2611 |
if (handle) ext4_journal_stop(handle); |
617ba13b3 [PATCH] ext4: ren... |
2612 |
if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
ac27a0ec1 [PATCH] ext4: ini... |
2613 2614 2615 2616 2617 2618 2619 |
goto retry; return err; } /* * routine to check that the specified directory is empty (for rmdir) */ |
a7550b30a ext4 crypto: migr... |
2620 |
bool ext4_empty_dir(struct inode *inode) |
ac27a0ec1 [PATCH] ext4: ini... |
2621 |
{ |
498e5f241 ext4: Change unsi... |
2622 |
unsigned int offset; |
af5bc92dd ext4: Fix whitesp... |
2623 2624 2625 |
struct buffer_head *bh; struct ext4_dir_entry_2 *de, *de1; struct super_block *sb; |
ac27a0ec1 [PATCH] ext4: ini... |
2626 |
|
61f86638d ext4: let empty_d... |
2627 2628 |
if (ext4_has_inline_data(inode)) { int has_inline_data = 1; |
a7550b30a ext4 crypto: migr... |
2629 |
int ret; |
61f86638d ext4: let empty_d... |
2630 |
|
a7550b30a ext4 crypto: migr... |
2631 |
ret = empty_inline_dir(inode, &has_inline_data); |
61f86638d ext4: let empty_d... |
2632 |
if (has_inline_data) |
a7550b30a ext4 crypto: migr... |
2633 |
return ret; |
61f86638d ext4: let empty_d... |
2634 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2635 |
sb = inode->i_sb; |
dc6982ff4 ext4: refactor co... |
2636 2637 |
if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2)) { EXT4_ERROR_INODE(inode, "invalid size"); |
a7550b30a ext4 crypto: migr... |
2638 |
return true; |
ac27a0ec1 [PATCH] ext4: ini... |
2639 |
} |
dc6982ff4 ext4: refactor co... |
2640 2641 |
bh = ext4_read_dirblock(inode, 0, EITHER); if (IS_ERR(bh)) |
a7550b30a ext4 crypto: migr... |
2642 |
return true; |
dc6982ff4 ext4: refactor co... |
2643 |
|
617ba13b3 [PATCH] ext4: ren... |
2644 |
de = (struct ext4_dir_entry_2 *) bh->b_data; |
3d0518f47 ext4: New rec_len... |
2645 |
de1 = ext4_next_entry(de, sb->s_blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
2646 |
if (le32_to_cpu(de->inode) != inode->i_ino || |
b03a2f7eb ext4: improve war... |
2647 2648 2649 |
le32_to_cpu(de1->inode) == 0 || strcmp(".", de->name) || strcmp("..", de1->name)) { ext4_warning_inode(inode, "directory missing '.' and/or '..'"); |
af5bc92dd ext4: Fix whitesp... |
2650 |
brelse(bh); |
a7550b30a ext4 crypto: migr... |
2651 |
return true; |
ac27a0ec1 [PATCH] ext4: ini... |
2652 |
} |
3d0518f47 ext4: New rec_len... |
2653 2654 2655 |
offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) + ext4_rec_len_from_disk(de1->rec_len, sb->s_blocksize); de = ext4_next_entry(de1, sb->s_blocksize); |
af5bc92dd ext4: Fix whitesp... |
2656 |
while (offset < inode->i_size) { |
236f5ecb4 ext4: remove obso... |
2657 |
if ((void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { |
24676da46 ext4: Convert cal... |
2658 |
unsigned int lblock; |
af5bc92dd ext4: Fix whitesp... |
2659 |
brelse(bh); |
24676da46 ext4: Convert cal... |
2660 |
lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb); |
dc6982ff4 ext4: refactor co... |
2661 2662 |
bh = ext4_read_dirblock(inode, lblock, EITHER); if (IS_ERR(bh)) |
a7550b30a ext4 crypto: migr... |
2663 |
return true; |
617ba13b3 [PATCH] ext4: ren... |
2664 |
de = (struct ext4_dir_entry_2 *) bh->b_data; |
ac27a0ec1 [PATCH] ext4: ini... |
2665 |
} |
226ba972b ext4: refactor __... |
2666 2667 |
if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, offset)) { |
617ba13b3 [PATCH] ext4: ren... |
2668 |
de = (struct ext4_dir_entry_2 *)(bh->b_data + |
ac27a0ec1 [PATCH] ext4: ini... |
2669 2670 2671 2672 2673 |
sb->s_blocksize); offset = (offset | (sb->s_blocksize - 1)) + 1; continue; } if (le32_to_cpu(de->inode)) { |
af5bc92dd ext4: Fix whitesp... |
2674 |
brelse(bh); |
a7550b30a ext4 crypto: migr... |
2675 |
return false; |
ac27a0ec1 [PATCH] ext4: ini... |
2676 |
} |
3d0518f47 ext4: New rec_len... |
2677 2678 |
offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); de = ext4_next_entry(de, sb->s_blocksize); |
ac27a0ec1 [PATCH] ext4: ini... |
2679 |
} |
af5bc92dd ext4: Fix whitesp... |
2680 |
brelse(bh); |
a7550b30a ext4 crypto: migr... |
2681 |
return true; |
ac27a0ec1 [PATCH] ext4: ini... |
2682 |
} |
d745a8c20 ext4: reduce cont... |
2683 2684 |
/* * ext4_orphan_add() links an unlinked or truncated inode into a list of |
ac27a0ec1 [PATCH] ext4: ini... |
2685 2686 2687 2688 2689 |
* such inodes, starting at the superblock, in case we crash before the * file is closed/deleted, or in case the inode truncate spans multiple * transactions and the last transaction is not recovered after a crash. * * At filesystem recovery time, we walk this list deleting unlinked |
617ba13b3 [PATCH] ext4: ren... |
2690 |
* inodes and truncating linked inodes in ext4_orphan_cleanup(). |
d745a8c20 ext4: reduce cont... |
2691 2692 2693 |
* * Orphan list manipulation functions must be called under i_mutex unless * we are just creating the inode or deleting it. |
ac27a0ec1 [PATCH] ext4: ini... |
2694 |
*/ |
617ba13b3 [PATCH] ext4: ren... |
2695 |
int ext4_orphan_add(handle_t *handle, struct inode *inode) |
ac27a0ec1 [PATCH] ext4: ini... |
2696 2697 |
{ struct super_block *sb = inode->i_sb; |
cd2c080c3 ext4: use sbi in ... |
2698 |
struct ext4_sb_info *sbi = EXT4_SB(sb); |
617ba13b3 [PATCH] ext4: ren... |
2699 |
struct ext4_iloc iloc; |
ac27a0ec1 [PATCH] ext4: ini... |
2700 |
int err = 0, rc; |
d745a8c20 ext4: reduce cont... |
2701 |
bool dirty = false; |
ac27a0ec1 [PATCH] ext4: ini... |
2702 |
|
e2bfb088f ext4: don't orpha... |
2703 |
if (!sbi->s_journal || is_bad_inode(inode)) |
0390131ba ext4: Allow ext4 ... |
2704 |
return 0; |
d745a8c20 ext4: reduce cont... |
2705 |
WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) && |
5955102c9 wrappers for ->i_... |
2706 |
!inode_is_locked(inode)); |
d745a8c20 ext4: reduce cont... |
2707 2708 2709 2710 |
/* * Exit early if inode already is on orphan list. This is a big speedup * since we don't have to contend on the global s_orphan_lock. */ |
617ba13b3 [PATCH] ext4: ren... |
2711 |
if (!list_empty(&EXT4_I(inode)->i_orphan)) |
d745a8c20 ext4: reduce cont... |
2712 |
return 0; |
ac27a0ec1 [PATCH] ext4: ini... |
2713 |
|
afb86178c ext4: remove unne... |
2714 2715 2716 2717 2718 |
/* * Orphan handling is only valid for files with data blocks * being truncated, or files being unlinked. Note that we either * hold i_mutex, or the inode can not be referenced from outside, * so i_nlink should not be bumped due to race |
ac27a0ec1 [PATCH] ext4: ini... |
2719 |
*/ |
af5bc92dd ext4: Fix whitesp... |
2720 2721 |
J_ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) || inode->i_nlink == 0); |
ac27a0ec1 [PATCH] ext4: ini... |
2722 |
|
cd2c080c3 ext4: use sbi in ... |
2723 2724 |
BUFFER_TRACE(sbi->s_sbh, "get_write_access"); err = ext4_journal_get_write_access(handle, sbi->s_sbh); |
ac27a0ec1 [PATCH] ext4: ini... |
2725 |
if (err) |
d745a8c20 ext4: reduce cont... |
2726 |
goto out; |
ac27a0ec1 [PATCH] ext4: ini... |
2727 |
|
617ba13b3 [PATCH] ext4: ren... |
2728 |
err = ext4_reserve_inode_write(handle, inode, &iloc); |
ac27a0ec1 [PATCH] ext4: ini... |
2729 |
if (err) |
d745a8c20 ext4: reduce cont... |
2730 2731 2732 |
goto out; mutex_lock(&sbi->s_orphan_lock); |
6e3617e57 ext4: Handle non ... |
2733 2734 2735 2736 |
/* * Due to previous errors inode may be already a part of on-disk * orphan list. If so skip on-disk list modification. */ |
d745a8c20 ext4: reduce cont... |
2737 2738 2739 2740 2741 2742 2743 2744 2745 |
if (!NEXT_ORPHAN(inode) || NEXT_ORPHAN(inode) > (le32_to_cpu(sbi->s_es->s_inodes_count))) { /* Insert this inode at the head of the on-disk orphan list */ NEXT_ORPHAN(inode) = le32_to_cpu(sbi->s_es->s_last_orphan); sbi->s_es->s_last_orphan = cpu_to_le32(inode->i_ino); dirty = true; } list_add(&EXT4_I(inode)->i_orphan, &sbi->s_orphan); mutex_unlock(&sbi->s_orphan_lock); |
ac27a0ec1 [PATCH] ext4: ini... |
2746 |
|
d745a8c20 ext4: reduce cont... |
2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 |
if (dirty) { err = ext4_handle_dirty_super(handle, sb); rc = ext4_mark_iloc_dirty(handle, inode, &iloc); if (!err) err = rc; if (err) { /* * We have to remove inode from in-memory list if * addition to on disk orphan list failed. Stray orphan * list entries can cause panics at unmount time. */ mutex_lock(&sbi->s_orphan_lock); |
74177f55b ext4: fix oops on... |
2759 |
list_del_init(&EXT4_I(inode)->i_orphan); |
d745a8c20 ext4: reduce cont... |
2760 2761 2762 |
mutex_unlock(&sbi->s_orphan_lock); } } |
ac27a0ec1 [PATCH] ext4: ini... |
2763 2764 2765 2766 2767 |
jbd_debug(4, "superblock will point to %lu ", inode->i_ino); jbd_debug(4, "orphan inode %lu will point to %d ", inode->i_ino, NEXT_ORPHAN(inode)); |
d745a8c20 ext4: reduce cont... |
2768 |
out: |
cd2c080c3 ext4: use sbi in ... |
2769 |
ext4_std_error(sb, err); |
ac27a0ec1 [PATCH] ext4: ini... |
2770 2771 2772 2773 |
return err; } /* |
617ba13b3 [PATCH] ext4: ren... |
2774 |
* ext4_orphan_del() removes an unlinked or truncated inode from the list |
ac27a0ec1 [PATCH] ext4: ini... |
2775 2776 |
* of such inodes stored on disk, because it is finally being cleaned up. */ |
617ba13b3 [PATCH] ext4: ren... |
2777 |
int ext4_orphan_del(handle_t *handle, struct inode *inode) |
ac27a0ec1 [PATCH] ext4: ini... |
2778 2779 |
{ struct list_head *prev; |
617ba13b3 [PATCH] ext4: ren... |
2780 |
struct ext4_inode_info *ei = EXT4_I(inode); |
cd2c080c3 ext4: use sbi in ... |
2781 |
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
498e5f241 ext4: Change unsi... |
2782 |
__u32 ino_next; |
617ba13b3 [PATCH] ext4: ren... |
2783 |
struct ext4_iloc iloc; |
ac27a0ec1 [PATCH] ext4: ini... |
2784 |
int err = 0; |
cd2c080c3 ext4: use sbi in ... |
2785 |
if (!sbi->s_journal && !(sbi->s_mount_state & EXT4_ORPHAN_FS)) |
0390131ba ext4: Allow ext4 ... |
2786 |
return 0; |
d745a8c20 ext4: reduce cont... |
2787 |
WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) && |
5955102c9 wrappers for ->i_... |
2788 |
!inode_is_locked(inode)); |
d745a8c20 ext4: reduce cont... |
2789 |
/* Do this quick check before taking global s_orphan_lock. */ |
3b9d4ed26 ext4: Replace loc... |
2790 |
if (list_empty(&ei->i_orphan)) |
d745a8c20 ext4: reduce cont... |
2791 |
return 0; |
ac27a0ec1 [PATCH] ext4: ini... |
2792 |
|
d745a8c20 ext4: reduce cont... |
2793 2794 2795 2796 |
if (handle) { /* Grab inode buffer early before taking global s_orphan_lock */ err = ext4_reserve_inode_write(handle, inode, &iloc); } |
ac27a0ec1 [PATCH] ext4: ini... |
2797 |
|
d745a8c20 ext4: reduce cont... |
2798 |
mutex_lock(&sbi->s_orphan_lock); |
ac27a0ec1 [PATCH] ext4: ini... |
2799 2800 |
jbd_debug(4, "remove inode %lu from orphan list ", inode->i_ino); |
d745a8c20 ext4: reduce cont... |
2801 |
prev = ei->i_orphan.prev; |
ac27a0ec1 [PATCH] ext4: ini... |
2802 2803 2804 2805 2806 2807 |
list_del_init(&ei->i_orphan); /* If we're on an error path, we may not have a valid * transaction handle with which to update the orphan list on * disk, but we still need to remove the inode from the linked * list in memory. */ |
d745a8c20 ext4: reduce cont... |
2808 2809 |
if (!handle || err) { mutex_unlock(&sbi->s_orphan_lock); |
ac27a0ec1 [PATCH] ext4: ini... |
2810 |
goto out_err; |
d745a8c20 ext4: reduce cont... |
2811 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2812 |
|
d745a8c20 ext4: reduce cont... |
2813 |
ino_next = NEXT_ORPHAN(inode); |
ac27a0ec1 [PATCH] ext4: ini... |
2814 |
if (prev == &sbi->s_orphan) { |
498e5f241 ext4: Change unsi... |
2815 2816 |
jbd_debug(4, "superblock will point to %u ", ino_next); |
ac27a0ec1 [PATCH] ext4: ini... |
2817 |
BUFFER_TRACE(sbi->s_sbh, "get_write_access"); |
617ba13b3 [PATCH] ext4: ren... |
2818 |
err = ext4_journal_get_write_access(handle, sbi->s_sbh); |
d745a8c20 ext4: reduce cont... |
2819 2820 |
if (err) { mutex_unlock(&sbi->s_orphan_lock); |
ac27a0ec1 [PATCH] ext4: ini... |
2821 |
goto out_brelse; |
d745a8c20 ext4: reduce cont... |
2822 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2823 |
sbi->s_es->s_last_orphan = cpu_to_le32(ino_next); |
d745a8c20 ext4: reduce cont... |
2824 |
mutex_unlock(&sbi->s_orphan_lock); |
b50924c2c ext4: remove unne... |
2825 |
err = ext4_handle_dirty_super(handle, inode->i_sb); |
ac27a0ec1 [PATCH] ext4: ini... |
2826 |
} else { |
617ba13b3 [PATCH] ext4: ren... |
2827 |
struct ext4_iloc iloc2; |
ac27a0ec1 [PATCH] ext4: ini... |
2828 |
struct inode *i_prev = |
617ba13b3 [PATCH] ext4: ren... |
2829 |
&list_entry(prev, struct ext4_inode_info, i_orphan)->vfs_inode; |
ac27a0ec1 [PATCH] ext4: ini... |
2830 |
|
498e5f241 ext4: Change unsi... |
2831 2832 |
jbd_debug(4, "orphan inode %lu will point to %u ", |
ac27a0ec1 [PATCH] ext4: ini... |
2833 |
i_prev->i_ino, ino_next); |
617ba13b3 [PATCH] ext4: ren... |
2834 |
err = ext4_reserve_inode_write(handle, i_prev, &iloc2); |
d745a8c20 ext4: reduce cont... |
2835 2836 |
if (err) { mutex_unlock(&sbi->s_orphan_lock); |
ac27a0ec1 [PATCH] ext4: ini... |
2837 |
goto out_brelse; |
d745a8c20 ext4: reduce cont... |
2838 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
2839 |
NEXT_ORPHAN(i_prev) = ino_next; |
617ba13b3 [PATCH] ext4: ren... |
2840 |
err = ext4_mark_iloc_dirty(handle, i_prev, &iloc2); |
d745a8c20 ext4: reduce cont... |
2841 |
mutex_unlock(&sbi->s_orphan_lock); |
ac27a0ec1 [PATCH] ext4: ini... |
2842 2843 2844 2845 |
} if (err) goto out_brelse; NEXT_ORPHAN(inode) = 0; |
617ba13b3 [PATCH] ext4: ren... |
2846 |
err = ext4_mark_iloc_dirty(handle, inode, &iloc); |
ac27a0ec1 [PATCH] ext4: ini... |
2847 |
out_err: |
617ba13b3 [PATCH] ext4: ren... |
2848 |
ext4_std_error(inode->i_sb, err); |
ac27a0ec1 [PATCH] ext4: ini... |
2849 2850 2851 2852 2853 2854 |
return err; out_brelse: brelse(iloc.bh); goto out_err; } |
af5bc92dd ext4: Fix whitesp... |
2855 |
static int ext4_rmdir(struct inode *dir, struct dentry *dentry) |
ac27a0ec1 [PATCH] ext4: ini... |
2856 2857 |
{ int retval; |
af5bc92dd ext4: Fix whitesp... |
2858 2859 2860 |
struct inode *inode; struct buffer_head *bh; struct ext4_dir_entry_2 *de; |
8dcfaad24 ext4: start handl... |
2861 |
handle_t *handle = NULL; |
ac27a0ec1 [PATCH] ext4: ini... |
2862 2863 2864 |
/* Initialize quotas before so that eventual writes go in * separate transaction */ |
a7cdadee0 ext4: Handle erro... |
2865 2866 2867 2868 2869 2870 |
retval = dquot_initialize(dir); if (retval) return retval; retval = dquot_initialize(d_inode(dentry)); if (retval) return retval; |
907f4554e dquot: move dquot... |
2871 |
|
ac27a0ec1 [PATCH] ext4: ini... |
2872 |
retval = -ENOENT; |
32f7f22c0 ext4: let ext4_re... |
2873 |
bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); |
36de92864 ext4: propagate e... |
2874 2875 |
if (IS_ERR(bh)) return PTR_ERR(bh); |
ac27a0ec1 [PATCH] ext4: ini... |
2876 2877 |
if (!bh) goto end_rmdir; |
2b0143b5c VFS: normal files... |
2878 |
inode = d_inode(dentry); |
ac27a0ec1 [PATCH] ext4: ini... |
2879 |
|
6a797d273 ext4: call out CR... |
2880 |
retval = -EFSCORRUPTED; |
ac27a0ec1 [PATCH] ext4: ini... |
2881 2882 2883 2884 |
if (le32_to_cpu(de->inode) != inode->i_ino) goto end_rmdir; retval = -ENOTEMPTY; |
e875a2ddb ext4 crypto: expo... |
2885 |
if (!ext4_empty_dir(inode)) |
ac27a0ec1 [PATCH] ext4: ini... |
2886 |
goto end_rmdir; |
8dcfaad24 ext4: start handl... |
2887 |
handle = ext4_journal_start(dir, EXT4_HT_DIR, |
64044abf0 ext4: fix the num... |
2888 |
EXT4_DATA_TRANS_BLOCKS(dir->i_sb)); |
8dcfaad24 ext4: start handl... |
2889 2890 2891 2892 2893 2894 2895 2896 |
if (IS_ERR(handle)) { retval = PTR_ERR(handle); handle = NULL; goto end_rmdir; } if (IS_DIRSYNC(dir)) ext4_handle_sync(handle); |
617ba13b3 [PATCH] ext4: ren... |
2897 |
retval = ext4_delete_entry(handle, dir, de, bh); |
ac27a0ec1 [PATCH] ext4: ini... |
2898 2899 |
if (retval) goto end_rmdir; |
f8628a14a ext4: Remove 6500... |
2900 |
if (!EXT4_DIR_LINK_EMPTY(inode)) |
b03a2f7eb ext4: improve war... |
2901 2902 2903 |
ext4_warning_inode(inode, "empty directory '%.*s' has too many links (%u)", dentry->d_name.len, dentry->d_name.name, |
af5bc92dd ext4: Fix whitesp... |
2904 |
inode->i_nlink); |
ac27a0ec1 [PATCH] ext4: ini... |
2905 2906 2907 2908 2909 2910 |
inode->i_version++; clear_nlink(inode); /* There's no need to set i_disksize: the fact that i_nlink is * zero will ensure that the right thing happens during any * recovery. */ inode->i_size = 0; |
617ba13b3 [PATCH] ext4: ren... |
2911 |
ext4_orphan_add(handle, inode); |
ef7f38359 ext4: Add nanosec... |
2912 |
inode->i_ctime = dir->i_ctime = dir->i_mtime = ext4_current_time(inode); |
617ba13b3 [PATCH] ext4: ren... |
2913 |
ext4_mark_inode_dirty(handle, inode); |
f8628a14a ext4: Remove 6500... |
2914 |
ext4_dec_count(handle, dir); |
617ba13b3 [PATCH] ext4: ren... |
2915 2916 |
ext4_update_dx_flag(dir); ext4_mark_inode_dirty(handle, dir); |
ac27a0ec1 [PATCH] ext4: ini... |
2917 2918 |
end_rmdir: |
af5bc92dd ext4: Fix whitesp... |
2919 |
brelse(bh); |
8dcfaad24 ext4: start handl... |
2920 2921 |
if (handle) ext4_journal_stop(handle); |
ac27a0ec1 [PATCH] ext4: ini... |
2922 2923 |
return retval; } |
af5bc92dd ext4: Fix whitesp... |
2924 |
static int ext4_unlink(struct inode *dir, struct dentry *dentry) |
ac27a0ec1 [PATCH] ext4: ini... |
2925 2926 |
{ int retval; |
af5bc92dd ext4: Fix whitesp... |
2927 2928 2929 |
struct inode *inode; struct buffer_head *bh; struct ext4_dir_entry_2 *de; |
931b68649 ext4: start handl... |
2930 |
handle_t *handle = NULL; |
ac27a0ec1 [PATCH] ext4: ini... |
2931 |
|
0562e0bad ext4: add more tr... |
2932 |
trace_ext4_unlink_enter(dir, dentry); |
ac27a0ec1 [PATCH] ext4: ini... |
2933 2934 |
/* Initialize quotas before so that eventual writes go * in separate transaction */ |
a7cdadee0 ext4: Handle erro... |
2935 2936 2937 2938 2939 2940 |
retval = dquot_initialize(dir); if (retval) return retval; retval = dquot_initialize(d_inode(dentry)); if (retval) return retval; |
907f4554e dquot: move dquot... |
2941 |
|
ac27a0ec1 [PATCH] ext4: ini... |
2942 |
retval = -ENOENT; |
32f7f22c0 ext4: let ext4_re... |
2943 |
bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); |
36de92864 ext4: propagate e... |
2944 2945 |
if (IS_ERR(bh)) return PTR_ERR(bh); |
ac27a0ec1 [PATCH] ext4: ini... |
2946 2947 |
if (!bh) goto end_unlink; |
2b0143b5c VFS: normal files... |
2948 |
inode = d_inode(dentry); |
ac27a0ec1 [PATCH] ext4: ini... |
2949 |
|
6a797d273 ext4: call out CR... |
2950 |
retval = -EFSCORRUPTED; |
ac27a0ec1 [PATCH] ext4: ini... |
2951 2952 |
if (le32_to_cpu(de->inode) != inode->i_ino) goto end_unlink; |
931b68649 ext4: start handl... |
2953 |
handle = ext4_journal_start(dir, EXT4_HT_DIR, |
64044abf0 ext4: fix the num... |
2954 |
EXT4_DATA_TRANS_BLOCKS(dir->i_sb)); |
931b68649 ext4: start handl... |
2955 2956 2957 2958 2959 2960 2961 2962 |
if (IS_ERR(handle)) { retval = PTR_ERR(handle); handle = NULL; goto end_unlink; } if (IS_DIRSYNC(dir)) ext4_handle_sync(handle); |
b03a2f7eb ext4: improve war... |
2963 2964 2965 |
if (inode->i_nlink == 0) { ext4_warning_inode(inode, "Deleting file '%.*s' with no links", dentry->d_name.len, dentry->d_name.name); |
bfe868486 filesystems: add ... |
2966 |
set_nlink(inode, 1); |
ac27a0ec1 [PATCH] ext4: ini... |
2967 |
} |
617ba13b3 [PATCH] ext4: ren... |
2968 |
retval = ext4_delete_entry(handle, dir, de, bh); |
ac27a0ec1 [PATCH] ext4: ini... |
2969 2970 |
if (retval) goto end_unlink; |
ef7f38359 ext4: Add nanosec... |
2971 |
dir->i_ctime = dir->i_mtime = ext4_current_time(dir); |
617ba13b3 [PATCH] ext4: ren... |
2972 2973 |
ext4_update_dx_flag(dir); ext4_mark_inode_dirty(handle, dir); |
825f1481e ext4: Don't use e... |
2974 |
drop_nlink(inode); |
ac27a0ec1 [PATCH] ext4: ini... |
2975 |
if (!inode->i_nlink) |
617ba13b3 [PATCH] ext4: ren... |
2976 |
ext4_orphan_add(handle, inode); |
ef7f38359 ext4: Add nanosec... |
2977 |
inode->i_ctime = ext4_current_time(inode); |
617ba13b3 [PATCH] ext4: ren... |
2978 |
ext4_mark_inode_dirty(handle, inode); |
ac27a0ec1 [PATCH] ext4: ini... |
2979 2980 |
end_unlink: |
af5bc92dd ext4: Fix whitesp... |
2981 |
brelse(bh); |
931b68649 ext4: start handl... |
2982 2983 |
if (handle) ext4_journal_stop(handle); |
0562e0bad ext4: add more tr... |
2984 |
trace_ext4_unlink_exit(dentry, retval); |
ac27a0ec1 [PATCH] ext4: ini... |
2985 2986 |
return retval; } |
af5bc92dd ext4: Fix whitesp... |
2987 2988 |
static int ext4_symlink(struct inode *dir, struct dentry *dentry, const char *symname) |
ac27a0ec1 [PATCH] ext4: ini... |
2989 2990 |
{ handle_t *handle; |
af5bc92dd ext4: Fix whitesp... |
2991 |
struct inode *inode; |
f348c2523 ext4 crypto: add ... |
2992 |
int err, len = strlen(symname); |
df5e62234 ext4: fix deadloc... |
2993 |
int credits; |
f348c2523 ext4 crypto: add ... |
2994 |
bool encryption_required; |
a7550b30a ext4 crypto: migr... |
2995 2996 |
struct fscrypt_str disk_link; struct fscrypt_symlink_data *sd = NULL; |
ac27a0ec1 [PATCH] ext4: ini... |
2997 |
|
f348c2523 ext4 crypto: add ... |
2998 2999 |
disk_link.len = len + 1; disk_link.name = (char *) symname; |
6ddb24478 ext4 crypto: enab... |
3000 3001 |
encryption_required = (ext4_encrypted_inode(dir) || DUMMY_ENCRYPTION_ENABLED(EXT4_SB(dir->i_sb))); |
4d3c4e5b8 ext4 crypto: allo... |
3002 |
if (encryption_required) { |
a7550b30a ext4 crypto: migr... |
3003 |
err = fscrypt_get_encryption_info(dir); |
4d3c4e5b8 ext4 crypto: allo... |
3004 3005 |
if (err) return err; |
a7550b30a ext4 crypto: migr... |
3006 |
if (!fscrypt_has_encryption_key(dir)) |
4d3c4e5b8 ext4 crypto: allo... |
3007 |
return -EPERM; |
a7550b30a ext4 crypto: migr... |
3008 3009 |
disk_link.len = (fscrypt_fname_encrypted_size(dir, len) + sizeof(struct fscrypt_symlink_data)); |
4d3c4e5b8 ext4 crypto: allo... |
3010 3011 3012 3013 3014 3015 3016 3017 3018 |
sd = kzalloc(disk_link.len, GFP_KERNEL); if (!sd) return -ENOMEM; } if (disk_link.len > dir->i_sb->s_blocksize) { err = -ENAMETOOLONG; goto err_free_sd; } |
ac27a0ec1 [PATCH] ext4: ini... |
3019 |
|
a7cdadee0 ext4: Handle erro... |
3020 3021 |
err = dquot_initialize(dir); if (err) |
926631c20 ext4: memory leak... |
3022 |
goto err_free_sd; |
907f4554e dquot: move dquot... |
3023 |
|
f348c2523 ext4 crypto: add ... |
3024 |
if ((disk_link.len > EXT4_N_BLOCKS * 4)) { |
df5e62234 ext4: fix deadloc... |
3025 3026 3027 |
/* * For non-fast symlinks, we just allocate inode and put it on * orphan list in the first transaction => we need bitmap, |
8c2087199 ext4: Properly co... |
3028 3029 |
* group descriptor, sb, inode block, quota blocks, and * possibly selinux xattr blocks. |
df5e62234 ext4: fix deadloc... |
3030 |
*/ |
8c2087199 ext4: Properly co... |
3031 3032 |
credits = 4 + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) + EXT4_XATTR_TRANS_BLOCKS; |
df5e62234 ext4: fix deadloc... |
3033 3034 3035 3036 3037 3038 3039 3040 |
} else { /* * Fast symlink. We have to add entry to directory * (EXT4_DATA_TRANS_BLOCKS + EXT4_INDEX_EXTRA_TRANS_BLOCKS), * allocate new inode (bitmap, group descriptor, inode block, * quota blocks, sb is already counted in previous macros). */ credits = EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + |
eb9cc7e16 ext4: move quota ... |
3041 |
EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3; |
df5e62234 ext4: fix deadloc... |
3042 |
} |
f348c2523 ext4 crypto: add ... |
3043 |
|
1139575a9 ext4: start handl... |
3044 3045 3046 3047 |
inode = ext4_new_inode_start_handle(dir, S_IFLNK|S_IRWXUGO, &dentry->d_name, 0, NULL, EXT4_HT_DIR, credits); handle = ext4_journal_current_handle(); |
f348c2523 ext4 crypto: add ... |
3048 3049 3050 |
if (IS_ERR(inode)) { if (handle) ext4_journal_stop(handle); |
4d3c4e5b8 ext4 crypto: allo... |
3051 3052 |
err = PTR_ERR(inode); goto err_free_sd; |
f348c2523 ext4 crypto: add ... |
3053 3054 3055 |
} if (encryption_required) { |
f348c2523 ext4 crypto: add ... |
3056 |
struct qstr istr; |
a7550b30a ext4 crypto: migr... |
3057 3058 |
struct fscrypt_str ostr = FSTR_INIT(sd->encrypted_path, disk_link.len); |
f348c2523 ext4 crypto: add ... |
3059 |
|
f348c2523 ext4 crypto: add ... |
3060 3061 |
istr.name = (const unsigned char *) symname; istr.len = len; |
a7550b30a ext4 crypto: migr... |
3062 |
err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr); |
ef1eb3aa5 fscrypto: make fi... |
3063 |
if (err) |
f348c2523 ext4 crypto: add ... |
3064 3065 3066 |
goto err_drop_inode; sd->len = cpu_to_le16(ostr.len); disk_link.name = (char *) sd; |
a7a67e8a0 ext4: split inode... |
3067 |
inode->i_op = &ext4_encrypted_symlink_inode_operations; |
f348c2523 ext4 crypto: add ... |
3068 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
3069 |
|
f348c2523 ext4 crypto: add ... |
3070 |
if ((disk_link.len > EXT4_N_BLOCKS * 4)) { |
a7a67e8a0 ext4: split inode... |
3071 3072 |
if (!encryption_required) inode->i_op = &ext4_symlink_inode_operations; |
21fc61c73 don't put symlink... |
3073 |
inode_nohighmem(inode); |
617ba13b3 [PATCH] ext4: ren... |
3074 |
ext4_set_aops(inode); |
ac27a0ec1 [PATCH] ext4: ini... |
3075 |
/* |
df5e62234 ext4: fix deadloc... |
3076 3077 3078 3079 3080 3081 3082 3083 |
* We cannot call page_symlink() with transaction started * because it calls into ext4_write_begin() which can wait * for transaction commit if we are running out of space * and thus we deadlock. So we have to stop transaction now * and restart it when symlink contents is written. * * To keep fs consistent in case of crash, we have to put inode * to orphan list in the mean time. |
ac27a0ec1 [PATCH] ext4: ini... |
3084 |
*/ |
df5e62234 ext4: fix deadloc... |
3085 3086 3087 |
drop_nlink(inode); err = ext4_orphan_add(handle, inode); ext4_journal_stop(handle); |
f348c2523 ext4 crypto: add ... |
3088 |
handle = NULL; |
df5e62234 ext4: fix deadloc... |
3089 3090 |
if (err) goto err_drop_inode; |
f348c2523 ext4 crypto: add ... |
3091 |
err = __page_symlink(inode, disk_link.name, disk_link.len, 1); |
df5e62234 ext4: fix deadloc... |
3092 3093 3094 3095 3096 3097 |
if (err) goto err_drop_inode; /* * Now inode is being linked into dir (EXT4_DATA_TRANS_BLOCKS * + EXT4_INDEX_EXTRA_TRANS_BLOCKS), inode is also modified */ |
9924a92a8 ext4: pass contex... |
3098 |
handle = ext4_journal_start(dir, EXT4_HT_DIR, |
df5e62234 ext4: fix deadloc... |
3099 3100 3101 3102 |
EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 1); if (IS_ERR(handle)) { err = PTR_ERR(handle); |
f348c2523 ext4 crypto: add ... |
3103 |
handle = NULL; |
df5e62234 ext4: fix deadloc... |
3104 3105 |
goto err_drop_inode; } |
0ce8c0109 ext[34]: avoid i_... |
3106 |
set_nlink(inode, 1); |
df5e62234 ext4: fix deadloc... |
3107 |
err = ext4_orphan_del(handle, inode); |
f348c2523 ext4 crypto: add ... |
3108 |
if (err) |
df5e62234 ext4: fix deadloc... |
3109 |
goto err_drop_inode; |
ac27a0ec1 [PATCH] ext4: ini... |
3110 |
} else { |
e65187e6d ext4: Enable exte... |
3111 |
/* clear the extent format for fast symlink */ |
12e9b8920 ext4: Use bitops ... |
3112 |
ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); |
75e7566be ext4: switch to s... |
3113 |
if (!encryption_required) { |
a7a67e8a0 ext4: split inode... |
3114 |
inode->i_op = &ext4_fast_symlink_inode_operations; |
75e7566be ext4: switch to s... |
3115 3116 |
inode->i_link = (char *)&EXT4_I(inode)->i_data; } |
f348c2523 ext4 crypto: add ... |
3117 3118 3119 |
memcpy((char *)&EXT4_I(inode)->i_data, disk_link.name, disk_link.len); inode->i_size = disk_link.len - 1; |
ac27a0ec1 [PATCH] ext4: ini... |
3120 |
} |
617ba13b3 [PATCH] ext4: ren... |
3121 3122 |
EXT4_I(inode)->i_disksize = inode->i_size; err = ext4_add_nondir(handle, dentry, inode); |
1139575a9 ext4: start handl... |
3123 3124 |
if (!err && IS_DIRSYNC(dir)) ext4_handle_sync(handle); |
1139575a9 ext4: start handl... |
3125 3126 |
if (handle) ext4_journal_stop(handle); |
f348c2523 ext4 crypto: add ... |
3127 |
kfree(sd); |
ac27a0ec1 [PATCH] ext4: ini... |
3128 |
return err; |
df5e62234 ext4: fix deadloc... |
3129 |
err_drop_inode: |
f348c2523 ext4 crypto: add ... |
3130 3131 |
if (handle) ext4_journal_stop(handle); |
f348c2523 ext4 crypto: add ... |
3132 |
clear_nlink(inode); |
df5e62234 ext4: fix deadloc... |
3133 3134 |
unlock_new_inode(inode); iput(inode); |
4d3c4e5b8 ext4 crypto: allo... |
3135 3136 |
err_free_sd: kfree(sd); |
df5e62234 ext4: fix deadloc... |
3137 |
return err; |
ac27a0ec1 [PATCH] ext4: ini... |
3138 |
} |
af5bc92dd ext4: Fix whitesp... |
3139 3140 |
static int ext4_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) |
ac27a0ec1 [PATCH] ext4: ini... |
3141 3142 |
{ handle_t *handle; |
2b0143b5c VFS: normal files... |
3143 |
struct inode *inode = d_inode(old_dentry); |
ac27a0ec1 [PATCH] ext4: ini... |
3144 |
int err, retries = 0; |
b05ab1dc3 ext4: Limit numbe... |
3145 |
if (inode->i_nlink >= EXT4_LINK_MAX) |
ac27a0ec1 [PATCH] ext4: ini... |
3146 |
return -EMLINK; |
d9cdc9033 ext4 crypto: enfo... |
3147 |
if (ext4_encrypted_inode(dir) && |
a7550b30a ext4 crypto: migr... |
3148 |
!fscrypt_has_permitted_context(dir, inode)) |
d9cdc9033 ext4 crypto: enfo... |
3149 |
return -EPERM; |
040cb3786 ext4: adds projec... |
3150 3151 3152 3153 3154 |
if ((ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT)) && (!projid_eq(EXT4_I(dir)->i_projid, EXT4_I(old_dentry->d_inode)->i_projid))) return -EXDEV; |
a7cdadee0 ext4: Handle erro... |
3155 3156 3157 |
err = dquot_initialize(dir); if (err) return err; |
907f4554e dquot: move dquot... |
3158 |
|
ac27a0ec1 [PATCH] ext4: ini... |
3159 |
retry: |
9924a92a8 ext4: pass contex... |
3160 3161 |
handle = ext4_journal_start(dir, EXT4_HT_DIR, (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + |
af51a2ac3 ext4: ->tmpfile()... |
3162 |
EXT4_INDEX_EXTRA_TRANS_BLOCKS) + 1); |
ac27a0ec1 [PATCH] ext4: ini... |
3163 3164 3165 3166 |
if (IS_ERR(handle)) return PTR_ERR(handle); if (IS_DIRSYNC(dir)) |
0390131ba ext4: Allow ext4 ... |
3167 |
ext4_handle_sync(handle); |
ac27a0ec1 [PATCH] ext4: ini... |
3168 |
|
ef7f38359 ext4: Add nanosec... |
3169 |
inode->i_ctime = ext4_current_time(inode); |
f8628a14a ext4: Remove 6500... |
3170 |
ext4_inc_count(handle, inode); |
7de9c6ee3 new helper: ihold() |
3171 |
ihold(inode); |
ac27a0ec1 [PATCH] ext4: ini... |
3172 |
|
6b38e842b nfsd race fixes: ... |
3173 3174 3175 |
err = ext4_add_entry(handle, dentry, inode); if (!err) { ext4_mark_inode_dirty(handle, inode); |
af51a2ac3 ext4: ->tmpfile()... |
3176 3177 3178 3179 3180 |
/* this can happen only for tmpfile being * linked the first time */ if (inode->i_nlink == 1) ext4_orphan_del(handle, inode); |
6b38e842b nfsd race fixes: ... |
3181 3182 3183 3184 3185 |
d_instantiate(dentry, inode); } else { drop_nlink(inode); iput(inode); } |
617ba13b3 [PATCH] ext4: ren... |
3186 3187 |
ext4_journal_stop(handle); if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
ac27a0ec1 [PATCH] ext4: ini... |
3188 3189 3190 |
goto retry; return err; } |
32f7f22c0 ext4: let ext4_re... |
3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 |
/* * Try to find buffer head where contains the parent block. * It should be the inode block if it is inlined or the 1st block * if it is a normal dir. */ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle, struct inode *inode, int *retval, struct ext4_dir_entry_2 **parent_de, int *inlined) { struct buffer_head *bh; if (!ext4_has_inline_data(inode)) { |
dc6982ff4 ext4: refactor co... |
3206 3207 3208 |
bh = ext4_read_dirblock(inode, 0, EITHER); if (IS_ERR(bh)) { *retval = PTR_ERR(bh); |
32f7f22c0 ext4: let ext4_re... |
3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 |
return NULL; } *parent_de = ext4_next_entry( (struct ext4_dir_entry_2 *)bh->b_data, inode->i_sb->s_blocksize); return bh; } *inlined = 1; return ext4_get_first_inline_block(inode, parent_de, retval); } |
ac27a0ec1 [PATCH] ext4: ini... |
3220 |
|
c0d268c36 ext4: rename: cre... |
3221 3222 3223 3224 |
struct ext4_renament { struct inode *dir; struct dentry *dentry; struct inode *inode; |
bd42998a6 ext4: add cross r... |
3225 3226 |
bool is_dir; int dir_nlink_delta; |
c0d268c36 ext4: rename: cre... |
3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 |
/* entry for "dentry" */ struct buffer_head *bh; struct ext4_dir_entry_2 *de; int inlined; /* entry for ".." in inode if it's a directory */ struct buffer_head *dir_bh; struct ext4_dir_entry_2 *parent_de; int dir_inlined; }; |
bd1af145b ext4: rename: spl... |
3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 |
static int ext4_rename_dir_prepare(handle_t *handle, struct ext4_renament *ent) { int retval; ent->dir_bh = ext4_get_first_dir_block(handle, ent->inode, &retval, &ent->parent_de, &ent->dir_inlined); if (!ent->dir_bh) return retval; if (le32_to_cpu(ent->parent_de->inode) != ent->dir->i_ino) |
6a797d273 ext4: call out CR... |
3248 |
return -EFSCORRUPTED; |
bd1af145b ext4: rename: spl... |
3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 |
BUFFER_TRACE(ent->dir_bh, "get_write_access"); return ext4_journal_get_write_access(handle, ent->dir_bh); } static int ext4_rename_dir_finish(handle_t *handle, struct ext4_renament *ent, unsigned dir_ino) { int retval; ent->parent_de->inode = cpu_to_le32(dir_ino); BUFFER_TRACE(ent->dir_bh, "call ext4_handle_dirty_metadata"); if (!ent->dir_inlined) { if (is_dx(ent->inode)) { retval = ext4_handle_dirty_dx_node(handle, ent->inode, ent->dir_bh); } else { retval = ext4_handle_dirty_dirent_node(handle, ent->inode, ent->dir_bh); } } else { retval = ext4_mark_inode_dirty(handle, ent->inode); } if (retval) { ext4_std_error(ent->dir->i_sb, retval); return retval; } return 0; } static int ext4_setent(handle_t *handle, struct ext4_renament *ent, unsigned ino, unsigned file_type) { int retval; BUFFER_TRACE(ent->bh, "get write access"); retval = ext4_journal_get_write_access(handle, ent->bh); if (retval) return retval; ent->de->inode = cpu_to_le32(ino); |
e2b911c53 ext4: clean up fe... |
3290 |
if (ext4_has_feature_filetype(ent->dir->i_sb)) |
bd1af145b ext4: rename: spl... |
3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 |
ent->de->file_type = file_type; ent->dir->i_version++; ent->dir->i_ctime = ent->dir->i_mtime = ext4_current_time(ent->dir); ext4_mark_inode_dirty(handle, ent->dir); BUFFER_TRACE(ent->bh, "call ext4_handle_dirty_metadata"); if (!ent->inlined) { retval = ext4_handle_dirty_dirent_node(handle, ent->dir, ent->bh); if (unlikely(retval)) { ext4_std_error(ent->dir->i_sb, retval); return retval; } } brelse(ent->bh); ent->bh = NULL; return 0; } static int ext4_find_delete_entry(handle_t *handle, struct inode *dir, const struct qstr *d_name) { int retval = -ENOENT; struct buffer_head *bh; struct ext4_dir_entry_2 *de; bh = ext4_find_entry(dir, d_name, &de, NULL); |
36de92864 ext4: propagate e... |
3319 3320 |
if (IS_ERR(bh)) return PTR_ERR(bh); |
bd1af145b ext4: rename: spl... |
3321 3322 3323 3324 3325 3326 |
if (bh) { retval = ext4_delete_entry(handle, dir, de, bh); brelse(bh); } return retval; } |
d80d448c6 ext4: fix same-di... |
3327 3328 |
static void ext4_rename_delete(handle_t *handle, struct ext4_renament *ent, int force_reread) |
bd1af145b ext4: rename: spl... |
3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 |
{ int retval; /* * ent->de could have moved from under us during htree split, so make * sure that we are deleting the right entry. We might also be pointing * to a stale entry in the unused part of ent->bh so just checking inum * and the name isn't enough. */ if (le32_to_cpu(ent->de->inode) != ent->inode->i_ino || ent->de->name_len != ent->dentry->d_name.len || strncmp(ent->de->name, ent->dentry->d_name.name, |
d80d448c6 ext4: fix same-di... |
3340 3341 |
ent->de->name_len) || force_reread) { |
bd1af145b ext4: rename: spl... |
3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 |
retval = ext4_find_delete_entry(handle, ent->dir, &ent->dentry->d_name); } else { retval = ext4_delete_entry(handle, ent->dir, ent->de, ent->bh); if (retval == -ENOENT) { retval = ext4_find_delete_entry(handle, ent->dir, &ent->dentry->d_name); } } if (retval) { |
b03a2f7eb ext4: improve war... |
3353 3354 3355 |
ext4_warning_inode(ent->dir, "Deleting old file: nlink %d, error=%d", ent->dir->i_nlink, retval); |
bd1af145b ext4: rename: spl... |
3356 3357 |
} } |
bd42998a6 ext4: add cross r... |
3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 |
static void ext4_update_dir_count(handle_t *handle, struct ext4_renament *ent) { if (ent->dir_nlink_delta) { if (ent->dir_nlink_delta == -1) ext4_dec_count(handle, ent->dir); else ext4_inc_count(handle, ent->dir); ext4_mark_inode_dirty(handle, ent->dir); } } |
cd808dece ext4: support REN... |
3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 |
static struct inode *ext4_whiteout_for_rename(struct ext4_renament *ent, int credits, handle_t **h) { struct inode *wh; handle_t *handle; int retries = 0; /* * for inode block, sb block, group summaries, * and inode bitmap */ credits += (EXT4_MAXQUOTAS_TRANS_BLOCKS(ent->dir->i_sb) + EXT4_XATTR_TRANS_BLOCKS + 4); retry: wh = ext4_new_inode_start_handle(ent->dir, S_IFCHR | WHITEOUT_MODE, &ent->dentry->d_name, 0, NULL, EXT4_HT_DIR, credits); handle = ext4_journal_current_handle(); if (IS_ERR(wh)) { if (handle) ext4_journal_stop(handle); if (PTR_ERR(wh) == -ENOSPC && ext4_should_retry_alloc(ent->dir->i_sb, &retries)) goto retry; } else { *h = handle; init_special_inode(wh, wh->i_mode, WHITEOUT_DEV); wh->i_op = &ext4_special_inode_operations; } return wh; } |
ac27a0ec1 [PATCH] ext4: ini... |
3400 3401 3402 |
/* * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. |
0e2027045 ext4: allocate de... |
3403 3404 3405 3406 |
* * n.b. old_{dentry,inode) refers to the source dentry/inode * while new_{dentry,inode) refers to the destination dentry/inode * This comes from rename(const char *oldpath, const char *newpath) |
ac27a0ec1 [PATCH] ext4: ini... |
3407 |
*/ |
af5bc92dd ext4: Fix whitesp... |
3408 |
static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, |
cd808dece ext4: support REN... |
3409 3410 |
struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) |
ac27a0ec1 [PATCH] ext4: ini... |
3411 |
{ |
5b61de757 ext4: start handl... |
3412 |
handle_t *handle = NULL; |
c0d268c36 ext4: rename: cre... |
3413 3414 3415 |
struct ext4_renament old = { .dir = old_dir, .dentry = old_dentry, |
2b0143b5c VFS: normal files... |
3416 |
.inode = d_inode(old_dentry), |
c0d268c36 ext4: rename: cre... |
3417 3418 3419 3420 |
}; struct ext4_renament new = { .dir = new_dir, .dentry = new_dentry, |
2b0143b5c VFS: normal files... |
3421 |
.inode = d_inode(new_dentry), |
c0d268c36 ext4: rename: cre... |
3422 |
}; |
d80d448c6 ext4: fix same-di... |
3423 |
int force_reread; |
0e2027045 ext4: allocate de... |
3424 |
int retval; |
cd808dece ext4: support REN... |
3425 3426 3427 |
struct inode *whiteout = NULL; int credits; u8 old_file_type; |
907f4554e dquot: move dquot... |
3428 |
|
040cb3786 ext4: adds projec... |
3429 3430 3431 3432 |
if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT)) && (!projid_eq(EXT4_I(new_dir)->i_projid, EXT4_I(old_dentry->d_inode)->i_projid))) return -EXDEV; |
a7cdadee0 ext4: Handle erro... |
3433 3434 3435 3436 3437 3438 |
retval = dquot_initialize(old.dir); if (retval) return retval; retval = dquot_initialize(new.dir); if (retval) return retval; |
ac27a0ec1 [PATCH] ext4: ini... |
3439 3440 3441 |
/* Initialize quotas before so that eventual writes go * in separate transaction */ |
a7cdadee0 ext4: Handle erro... |
3442 3443 3444 3445 3446 |
if (new.inode) { retval = dquot_initialize(new.inode); if (retval) return retval; } |
ac27a0ec1 [PATCH] ext4: ini... |
3447 |
|
c0d268c36 ext4: rename: cre... |
3448 |
old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL); |
36de92864 ext4: propagate e... |
3449 3450 |
if (IS_ERR(old.bh)) return PTR_ERR(old.bh); |
ac27a0ec1 [PATCH] ext4: ini... |
3451 3452 3453 3454 3455 3456 |
/* * Check for inode number is _not_ due to possible IO errors. * We might rmdir the source, keep it as pwd of some process * and merrily kill the link to whatever was created under the * same name. Goodbye sticky bit ;-< */ |
ac27a0ec1 [PATCH] ext4: ini... |
3457 |
retval = -ENOENT; |
c0d268c36 ext4: rename: cre... |
3458 |
if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino) |
ac27a0ec1 [PATCH] ext4: ini... |
3459 |
goto end_rename; |
d9cdc9033 ext4 crypto: enfo... |
3460 3461 |
if ((old.dir != new.dir) && ext4_encrypted_inode(new.dir) && |
a7550b30a ext4 crypto: migr... |
3462 |
!fscrypt_has_permitted_context(new.dir, old.inode)) { |
d9cdc9033 ext4 crypto: enfo... |
3463 3464 3465 |
retval = -EPERM; goto end_rename; } |
c0d268c36 ext4: rename: cre... |
3466 3467 |
new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, &new.de, &new.inlined); |
36de92864 ext4: propagate e... |
3468 3469 |
if (IS_ERR(new.bh)) { retval = PTR_ERR(new.bh); |
a9cfcd63e ext4: avoid tryin... |
3470 |
new.bh = NULL; |
36de92864 ext4: propagate e... |
3471 3472 |
goto end_rename; } |
c0d268c36 ext4: rename: cre... |
3473 3474 3475 3476 |
if (new.bh) { if (!new.inode) { brelse(new.bh); new.bh = NULL; |
ac27a0ec1 [PATCH] ext4: ini... |
3477 3478 |
} } |
c0d268c36 ext4: rename: cre... |
3479 3480 |
if (new.inode && !test_opt(new.dir->i_sb, NO_AUTO_DA_ALLOC)) ext4_alloc_da_blocks(old.inode); |
5b61de757 ext4: start handl... |
3481 |
|
cd808dece ext4: support REN... |
3482 3483 3484 3485 |
credits = (2 * EXT4_DATA_TRANS_BLOCKS(old.dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2); if (!(flags & RENAME_WHITEOUT)) { handle = ext4_journal_start(old.dir, EXT4_HT_DIR, credits); |
7071b7158 ext4: fix bh leak... |
3486 3487 3488 3489 3490 |
if (IS_ERR(handle)) { retval = PTR_ERR(handle); handle = NULL; goto end_rename; } |
cd808dece ext4: support REN... |
3491 3492 |
} else { whiteout = ext4_whiteout_for_rename(&old, credits, &handle); |
7071b7158 ext4: fix bh leak... |
3493 3494 3495 3496 3497 |
if (IS_ERR(whiteout)) { retval = PTR_ERR(whiteout); whiteout = NULL; goto end_rename; } |
cd808dece ext4: support REN... |
3498 |
} |
5b61de757 ext4: start handl... |
3499 |
|
c0d268c36 ext4: rename: cre... |
3500 |
if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir)) |
5b61de757 ext4: start handl... |
3501 |
ext4_handle_sync(handle); |
c0d268c36 ext4: rename: cre... |
3502 3503 |
if (S_ISDIR(old.inode->i_mode)) { if (new.inode) { |
ac27a0ec1 [PATCH] ext4: ini... |
3504 |
retval = -ENOTEMPTY; |
e875a2ddb ext4 crypto: expo... |
3505 |
if (!ext4_empty_dir(new.inode)) |
ac27a0ec1 [PATCH] ext4: ini... |
3506 |
goto end_rename; |
0d7d5d678 ext4: rename: mov... |
3507 3508 3509 3510 |
} else { retval = -EMLINK; if (new.dir != old.dir && EXT4_DIR_LINK_MAX(new.dir)) goto end_rename; |
ac27a0ec1 [PATCH] ext4: ini... |
3511 |
} |
bd1af145b ext4: rename: spl... |
3512 |
retval = ext4_rename_dir_prepare(handle, &old); |
ef6078930 ext4: handle erro... |
3513 3514 |
if (retval) goto end_rename; |
ac27a0ec1 [PATCH] ext4: ini... |
3515 |
} |
d80d448c6 ext4: fix same-di... |
3516 3517 3518 3519 3520 3521 3522 3523 3524 |
/* * If we're renaming a file within an inline_data dir and adding or * setting the new dirent causes a conversion from inline_data to * extents/blockmap, we need to force the dirent delete code to * re-read the directory, or else we end up trying to delete a dirent * from what is now the extent tree root (or a block map). */ force_reread = (new.dir->i_ino == old.dir->i_ino && ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA)); |
cd808dece ext4: support REN... |
3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 |
old_file_type = old.de->file_type; if (whiteout) { /* * Do this before adding a new entry, so the old entry is sure * to be still pointing to the valid old entry. */ retval = ext4_setent(handle, &old, whiteout->i_ino, EXT4_FT_CHRDEV); if (retval) goto end_rename; ext4_mark_inode_dirty(handle, whiteout); } |
c0d268c36 ext4: rename: cre... |
3538 3539 |
if (!new.bh) { retval = ext4_add_entry(handle, new.dentry, old.inode); |
ac27a0ec1 [PATCH] ext4: ini... |
3540 3541 3542 |
if (retval) goto end_rename; } else { |
bd1af145b ext4: rename: spl... |
3543 |
retval = ext4_setent(handle, &new, |
cd808dece ext4: support REN... |
3544 |
old.inode->i_ino, old_file_type); |
ef6078930 ext4: handle erro... |
3545 3546 |
if (retval) goto end_rename; |
ac27a0ec1 [PATCH] ext4: ini... |
3547 |
} |
d80d448c6 ext4: fix same-di... |
3548 3549 3550 |
if (force_reread) force_reread = !ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA); |
ac27a0ec1 [PATCH] ext4: ini... |
3551 3552 3553 3554 3555 |
/* * Like most other Unix systems, set the ctime for inodes on a * rename. */ |
c0d268c36 ext4: rename: cre... |
3556 3557 |
old.inode->i_ctime = ext4_current_time(old.inode); ext4_mark_inode_dirty(handle, old.inode); |
ac27a0ec1 [PATCH] ext4: ini... |
3558 |
|
cd808dece ext4: support REN... |
3559 3560 3561 3562 3563 3564 |
if (!whiteout) { /* * ok, that's it */ ext4_rename_delete(handle, &old, force_reread); } |
ac27a0ec1 [PATCH] ext4: ini... |
3565 |
|
c0d268c36 ext4: rename: cre... |
3566 3567 3568 |
if (new.inode) { ext4_dec_count(handle, new.inode); new.inode->i_ctime = ext4_current_time(new.inode); |
ac27a0ec1 [PATCH] ext4: ini... |
3569 |
} |
c0d268c36 ext4: rename: cre... |
3570 3571 3572 |
old.dir->i_ctime = old.dir->i_mtime = ext4_current_time(old.dir); ext4_update_dx_flag(old.dir); if (old.dir_bh) { |
bd1af145b ext4: rename: spl... |
3573 3574 |
retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); if (retval) |
b40971426 ext4: add error c... |
3575 |
goto end_rename; |
bd1af145b ext4: rename: spl... |
3576 |
|
c0d268c36 ext4: rename: cre... |
3577 3578 |
ext4_dec_count(handle, old.dir); if (new.inode) { |
e875a2ddb ext4 crypto: expo... |
3579 3580 3581 |
/* checked ext4_empty_dir above, can't have another * parent, ext4_dec_count() won't work for many-linked * dirs */ |
c0d268c36 ext4: rename: cre... |
3582 |
clear_nlink(new.inode); |
ac27a0ec1 [PATCH] ext4: ini... |
3583 |
} else { |
c0d268c36 ext4: rename: cre... |
3584 3585 3586 |
ext4_inc_count(handle, new.dir); ext4_update_dx_flag(new.dir); ext4_mark_inode_dirty(handle, new.dir); |
ac27a0ec1 [PATCH] ext4: ini... |
3587 3588 |
} } |
c0d268c36 ext4: rename: cre... |
3589 3590 3591 3592 3593 |
ext4_mark_inode_dirty(handle, old.dir); if (new.inode) { ext4_mark_inode_dirty(handle, new.inode); if (!new.inode->i_nlink) ext4_orphan_add(handle, new.inode); |
ac27a0ec1 [PATCH] ext4: ini... |
3594 3595 3596 3597 |
} retval = 0; end_rename: |
c0d268c36 ext4: rename: cre... |
3598 3599 3600 |
brelse(old.dir_bh); brelse(old.bh); brelse(new.bh); |
cd808dece ext4: support REN... |
3601 3602 3603 3604 3605 3606 |
if (whiteout) { if (retval) drop_nlink(whiteout); unlock_new_inode(whiteout); iput(whiteout); } |
5b61de757 ext4: start handl... |
3607 3608 |
if (handle) ext4_journal_stop(handle); |
ac27a0ec1 [PATCH] ext4: ini... |
3609 3610 |
return retval; } |
bd42998a6 ext4: add cross r... |
3611 3612 3613 3614 3615 3616 3617 |
static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { handle_t *handle = NULL; struct ext4_renament old = { .dir = old_dir, .dentry = old_dentry, |
2b0143b5c VFS: normal files... |
3618 |
.inode = d_inode(old_dentry), |
bd42998a6 ext4: add cross r... |
3619 3620 3621 3622 |
}; struct ext4_renament new = { .dir = new_dir, .dentry = new_dentry, |
2b0143b5c VFS: normal files... |
3623 |
.inode = d_inode(new_dentry), |
bd42998a6 ext4: add cross r... |
3624 3625 3626 |
}; u8 new_file_type; int retval; |
c2faccaff ext4 crypto: enfo... |
3627 3628 3629 |
if ((ext4_encrypted_inode(old_dir) || ext4_encrypted_inode(new_dir)) && (old_dir != new_dir) && |
a7550b30a ext4 crypto: migr... |
3630 3631 |
(!fscrypt_has_permitted_context(new_dir, old.inode) || !fscrypt_has_permitted_context(old_dir, new.inode))) |
c2faccaff ext4 crypto: enfo... |
3632 |
return -EPERM; |
040cb3786 ext4: adds projec... |
3633 3634 3635 3636 3637 3638 3639 |
if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT) && !projid_eq(EXT4_I(new_dir)->i_projid, EXT4_I(old_dentry->d_inode)->i_projid)) || (ext4_test_inode_flag(old_dir, EXT4_INODE_PROJINHERIT) && !projid_eq(EXT4_I(old_dir)->i_projid, EXT4_I(new_dentry->d_inode)->i_projid))) return -EXDEV; |
a7cdadee0 ext4: Handle erro... |
3640 3641 3642 3643 3644 3645 |
retval = dquot_initialize(old.dir); if (retval) return retval; retval = dquot_initialize(new.dir); if (retval) return retval; |
bd42998a6 ext4: add cross r... |
3646 3647 3648 |
old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, &old.inlined); |
36de92864 ext4: propagate e... |
3649 3650 |
if (IS_ERR(old.bh)) return PTR_ERR(old.bh); |
bd42998a6 ext4: add cross r... |
3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 |
/* * Check for inode number is _not_ due to possible IO errors. * We might rmdir the source, keep it as pwd of some process * and merrily kill the link to whatever was created under the * same name. Goodbye sticky bit ;-< */ retval = -ENOENT; if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino) goto end_rename; new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, &new.de, &new.inlined); |
36de92864 ext4: propagate e... |
3663 3664 |
if (IS_ERR(new.bh)) { retval = PTR_ERR(new.bh); |
a9cfcd63e ext4: avoid tryin... |
3665 |
new.bh = NULL; |
36de92864 ext4: propagate e... |
3666 3667 |
goto end_rename; } |
bd42998a6 ext4: add cross r... |
3668 3669 3670 3671 3672 3673 3674 3675 |
/* RENAME_EXCHANGE case: old *and* new must both exist */ if (!new.bh || le32_to_cpu(new.de->inode) != new.inode->i_ino) goto end_rename; handle = ext4_journal_start(old.dir, EXT4_HT_DIR, (2 * EXT4_DATA_TRANS_BLOCKS(old.dir->i_sb) + 2 * EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2)); |
7071b7158 ext4: fix bh leak... |
3676 3677 3678 3679 3680 |
if (IS_ERR(handle)) { retval = PTR_ERR(handle); handle = NULL; goto end_rename; } |
bd42998a6 ext4: add cross r... |
3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 |
if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir)) ext4_handle_sync(handle); if (S_ISDIR(old.inode->i_mode)) { old.is_dir = true; retval = ext4_rename_dir_prepare(handle, &old); if (retval) goto end_rename; } if (S_ISDIR(new.inode->i_mode)) { new.is_dir = true; retval = ext4_rename_dir_prepare(handle, &new); if (retval) goto end_rename; } /* * Other than the special case of overwriting a directory, parents' * nlink only needs to be modified if this is a cross directory rename. */ if (old.dir != new.dir && old.is_dir != new.is_dir) { old.dir_nlink_delta = old.is_dir ? -1 : 1; new.dir_nlink_delta = -old.dir_nlink_delta; retval = -EMLINK; if ((old.dir_nlink_delta > 0 && EXT4_DIR_LINK_MAX(old.dir)) || (new.dir_nlink_delta > 0 && EXT4_DIR_LINK_MAX(new.dir))) goto end_rename; } new_file_type = new.de->file_type; retval = ext4_setent(handle, &new, old.inode->i_ino, old.de->file_type); if (retval) goto end_rename; retval = ext4_setent(handle, &old, new.inode->i_ino, new_file_type); if (retval) goto end_rename; /* * Like most other Unix systems, set the ctime for inodes on a * rename. */ old.inode->i_ctime = ext4_current_time(old.inode); new.inode->i_ctime = ext4_current_time(new.inode); ext4_mark_inode_dirty(handle, old.inode); ext4_mark_inode_dirty(handle, new.inode); if (old.dir_bh) { retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); if (retval) goto end_rename; } if (new.dir_bh) { retval = ext4_rename_dir_finish(handle, &new, old.dir->i_ino); if (retval) goto end_rename; } ext4_update_dir_count(handle, &old); ext4_update_dir_count(handle, &new); retval = 0; end_rename: brelse(old.dir_bh); brelse(new.dir_bh); brelse(old.bh); brelse(new.bh); if (handle) ext4_journal_stop(handle); return retval; } |
0a7c3937a vfs: add RENAME_N... |
3752 3753 3754 3755 |
static int ext4_rename2(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) { |
cd808dece ext4: support REN... |
3756 |
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) |
0a7c3937a vfs: add RENAME_N... |
3757 |
return -EINVAL; |
bd42998a6 ext4: add cross r... |
3758 3759 3760 3761 |
if (flags & RENAME_EXCHANGE) { return ext4_cross_rename(old_dir, old_dentry, new_dir, new_dentry); } |
cd808dece ext4: support REN... |
3762 3763 |
return ext4_rename(old_dir, old_dentry, new_dir, new_dentry, flags); |
0a7c3937a vfs: add RENAME_N... |
3764 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
3765 3766 3767 |
/* * directories can handle most operations... */ |
754661f14 [PATCH] mark stru... |
3768 |
const struct inode_operations ext4_dir_inode_operations = { |
617ba13b3 [PATCH] ext4: ren... |
3769 3770 3771 3772 3773 3774 3775 3776 |
.create = ext4_create, .lookup = ext4_lookup, .link = ext4_link, .unlink = ext4_unlink, .symlink = ext4_symlink, .mkdir = ext4_mkdir, .rmdir = ext4_rmdir, .mknod = ext4_mknod, |
af51a2ac3 ext4: ->tmpfile()... |
3777 |
.tmpfile = ext4_tmpfile, |
2773bf00a fs: rename "renam... |
3778 |
.rename = ext4_rename2, |
617ba13b3 [PATCH] ext4: ren... |
3779 |
.setattr = ext4_setattr, |
617ba13b3 [PATCH] ext4: ren... |
3780 |
.listxattr = ext4_listxattr, |
4e34e719e fs: take the ACL ... |
3781 |
.get_acl = ext4_get_acl, |
64e178a71 ext2/3/4: use gen... |
3782 |
.set_acl = ext4_set_acl, |
abc8746eb ext4: hook fiemap... |
3783 |
.fiemap = ext4_fiemap, |
ac27a0ec1 [PATCH] ext4: ini... |
3784 |
}; |
754661f14 [PATCH] mark stru... |
3785 |
const struct inode_operations ext4_special_inode_operations = { |
617ba13b3 [PATCH] ext4: ren... |
3786 |
.setattr = ext4_setattr, |
617ba13b3 [PATCH] ext4: ren... |
3787 |
.listxattr = ext4_listxattr, |
4e34e719e fs: take the ACL ... |
3788 |
.get_acl = ext4_get_acl, |
64e178a71 ext2/3/4: use gen... |
3789 |
.set_acl = ext4_set_acl, |
ac27a0ec1 [PATCH] ext4: ini... |
3790 |
}; |