1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* AFS filesystem directory editing 3 * 4 * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/fs.h> 10 #include <linux/namei.h> 11 #include <linux/pagemap.h> 12 #include <linux/iversion.h> 13 #include <linux/folio_queue.h> 14 #include "internal.h" 15 #include "xdr_fs.h" 16 17 /* 18 * Find a number of contiguous clear bits in a directory block bitmask. 19 * 20 * There are 64 slots, which means we can load the entire bitmap into a 21 * variable. The first bit doesn't count as it corresponds to the block header 22 * slot. nr_slots is between 1 and 9. 23 */ 24 static int afs_find_contig_bits(union afs_xdr_dir_block *block, unsigned int nr_slots) 25 { 26 u64 bitmap; 27 u32 mask; 28 int bit, n; 29 30 bitmap = (u64)block->hdr.bitmap[0] << 0 * 8; 31 bitmap |= (u64)block->hdr.bitmap[1] << 1 * 8; 32 bitmap |= (u64)block->hdr.bitmap[2] << 2 * 8; 33 bitmap |= (u64)block->hdr.bitmap[3] << 3 * 8; 34 bitmap |= (u64)block->hdr.bitmap[4] << 4 * 8; 35 bitmap |= (u64)block->hdr.bitmap[5] << 5 * 8; 36 bitmap |= (u64)block->hdr.bitmap[6] << 6 * 8; 37 bitmap |= (u64)block->hdr.bitmap[7] << 7 * 8; 38 bitmap >>= 1; /* The first entry is metadata */ 39 bit = 1; 40 mask = (1 << nr_slots) - 1; 41 42 do { 43 if (sizeof(unsigned long) == 8) 44 n = ffz(bitmap); 45 else 46 n = ((u32)bitmap) != 0 ? 47 ffz((u32)bitmap) : 48 ffz((u32)(bitmap >> 32)) + 32; 49 bitmap >>= n; 50 bit += n; 51 52 if ((bitmap & mask) == 0) { 53 if (bit > 64 - nr_slots) 54 return -1; 55 return bit; 56 } 57 58 n = __ffs(bitmap); 59 bitmap >>= n; 60 bit += n; 61 } while (bitmap); 62 63 return -1; 64 } 65 66 /* 67 * Set a number of contiguous bits in the directory block bitmap. 68 */ 69 static void afs_set_contig_bits(union afs_xdr_dir_block *block, 70 int bit, unsigned int nr_slots) 71 { 72 u64 mask; 73 74 mask = (1 << nr_slots) - 1; 75 mask <<= bit; 76 77 block->hdr.bitmap[0] |= (u8)(mask >> 0 * 8); 78 block->hdr.bitmap[1] |= (u8)(mask >> 1 * 8); 79 block->hdr.bitmap[2] |= (u8)(mask >> 2 * 8); 80 block->hdr.bitmap[3] |= (u8)(mask >> 3 * 8); 81 block->hdr.bitmap[4] |= (u8)(mask >> 4 * 8); 82 block->hdr.bitmap[5] |= (u8)(mask >> 5 * 8); 83 block->hdr.bitmap[6] |= (u8)(mask >> 6 * 8); 84 block->hdr.bitmap[7] |= (u8)(mask >> 7 * 8); 85 } 86 87 /* 88 * Clear a number of contiguous bits in the directory block bitmap. 89 */ 90 static void afs_clear_contig_bits(union afs_xdr_dir_block *block, 91 int bit, unsigned int nr_slots) 92 { 93 u64 mask; 94 95 mask = (1 << nr_slots) - 1; 96 mask <<= bit; 97 98 block->hdr.bitmap[0] &= ~(u8)(mask >> 0 * 8); 99 block->hdr.bitmap[1] &= ~(u8)(mask >> 1 * 8); 100 block->hdr.bitmap[2] &= ~(u8)(mask >> 2 * 8); 101 block->hdr.bitmap[3] &= ~(u8)(mask >> 3 * 8); 102 block->hdr.bitmap[4] &= ~(u8)(mask >> 4 * 8); 103 block->hdr.bitmap[5] &= ~(u8)(mask >> 5 * 8); 104 block->hdr.bitmap[6] &= ~(u8)(mask >> 6 * 8); 105 block->hdr.bitmap[7] &= ~(u8)(mask >> 7 * 8); 106 } 107 108 /* 109 * Get a specific block, extending the directory storage to cover it as needed. 110 */ 111 static union afs_xdr_dir_block *afs_dir_get_block(struct afs_dir_iter *iter, size_t block) 112 { 113 struct folio_queue *fq; 114 struct afs_vnode *dvnode = iter->dvnode; 115 struct folio *folio; 116 size_t blpos = block * AFS_DIR_BLOCK_SIZE; 117 size_t blend = (block + 1) * AFS_DIR_BLOCK_SIZE, fpos = iter->fpos; 118 int ret; 119 120 if (dvnode->directory_size < blend) { 121 size_t cur_size = dvnode->directory_size; 122 123 ret = netfs_alloc_folioq_buffer( 124 NULL, &dvnode->directory, &cur_size, blend, 125 mapping_gfp_mask(dvnode->netfs.inode.i_mapping)); 126 dvnode->directory_size = cur_size; 127 if (ret < 0) 128 goto fail; 129 } 130 131 fq = iter->fq; 132 if (!fq) 133 fq = dvnode->directory; 134 135 /* Search the folio queue for the folio containing the block... */ 136 for (; fq; fq = fq->next) { 137 for (int s = iter->fq_slot; s < folioq_count(fq); s++) { 138 size_t fsize = folioq_folio_size(fq, s); 139 140 if (blend <= fpos + fsize) { 141 /* ... and then return the mapped block. */ 142 folio = folioq_folio(fq, s); 143 if (WARN_ON_ONCE(folio_pos(folio) != fpos)) 144 goto fail; 145 iter->fq = fq; 146 iter->fq_slot = s; 147 iter->fpos = fpos; 148 return kmap_local_folio(folio, blpos - fpos); 149 } 150 fpos += fsize; 151 } 152 iter->fq_slot = 0; 153 } 154 155 fail: 156 iter->fq = NULL; 157 iter->fq_slot = 0; 158 afs_invalidate_dir(dvnode, afs_dir_invalid_edit_get_block); 159 return NULL; 160 } 161 162 /* 163 * Scan a directory block looking for a dirent of the right name. 164 */ 165 static int afs_dir_scan_block(const union afs_xdr_dir_block *block, const struct qstr *name, 166 unsigned int blocknum) 167 { 168 const union afs_xdr_dirent *de; 169 u64 bitmap; 170 int d, len, n; 171 172 _enter(""); 173 174 bitmap = (u64)block->hdr.bitmap[0] << 0 * 8; 175 bitmap |= (u64)block->hdr.bitmap[1] << 1 * 8; 176 bitmap |= (u64)block->hdr.bitmap[2] << 2 * 8; 177 bitmap |= (u64)block->hdr.bitmap[3] << 3 * 8; 178 bitmap |= (u64)block->hdr.bitmap[4] << 4 * 8; 179 bitmap |= (u64)block->hdr.bitmap[5] << 5 * 8; 180 bitmap |= (u64)block->hdr.bitmap[6] << 6 * 8; 181 bitmap |= (u64)block->hdr.bitmap[7] << 7 * 8; 182 183 for (d = (blocknum == 0 ? AFS_DIR_RESV_BLOCKS0 : AFS_DIR_RESV_BLOCKS); 184 d < AFS_DIR_SLOTS_PER_BLOCK; 185 d++) { 186 if (!((bitmap >> d) & 1)) 187 continue; 188 de = &block->dirents[d]; 189 if (de->u.valid != 1) 190 continue; 191 192 /* The block was NUL-terminated by afs_dir_check_page(). */ 193 len = strlen(de->u.name); 194 if (len == name->len && 195 memcmp(de->u.name, name->name, name->len) == 0) 196 return d; 197 198 n = round_up(12 + len + 1 + 4, AFS_DIR_DIRENT_SIZE); 199 n /= AFS_DIR_DIRENT_SIZE; 200 d += n - 1; 201 } 202 203 return -1; 204 } 205 206 /* 207 * Initialise a new directory block. Note that block 0 is special and contains 208 * some extra metadata. 209 */ 210 static void afs_edit_init_block(union afs_xdr_dir_block *meta, 211 union afs_xdr_dir_block *block, int block_num) 212 { 213 memset(block, 0, sizeof(*block)); 214 block->hdr.npages = htons(1); 215 block->hdr.magic = AFS_DIR_MAGIC; 216 block->hdr.bitmap[0] = 1; 217 218 if (block_num == 0) { 219 block->hdr.bitmap[0] = 0xff; 220 block->hdr.bitmap[1] = 0x1f; 221 memset(block->meta.alloc_ctrs, 222 AFS_DIR_SLOTS_PER_BLOCK, 223 sizeof(block->meta.alloc_ctrs)); 224 meta->meta.alloc_ctrs[0] = 225 AFS_DIR_SLOTS_PER_BLOCK - AFS_DIR_RESV_BLOCKS0; 226 } 227 228 if (block_num < AFS_DIR_BLOCKS_WITH_CTR) 229 meta->meta.alloc_ctrs[block_num] = 230 AFS_DIR_SLOTS_PER_BLOCK - AFS_DIR_RESV_BLOCKS; 231 } 232 233 /* 234 * Edit a directory's file data to add a new directory entry. Doing this after 235 * create, mkdir, symlink, link or rename if the data version number is 236 * incremented by exactly one avoids the need to re-download the entire 237 * directory contents. 238 * 239 * The caller must hold the inode locked. 240 */ 241 void afs_edit_dir_add(struct afs_vnode *vnode, 242 struct qstr *name, struct afs_fid *new_fid, 243 enum afs_edit_dir_reason why) 244 { 245 union afs_xdr_dir_block *meta, *block; 246 union afs_xdr_dirent *de; 247 struct afs_dir_iter iter = { .dvnode = vnode }; 248 unsigned int nr_blocks, b, entry; 249 loff_t i_size; 250 int slot; 251 252 _enter(",,{%d,%s},", name->len, name->name); 253 254 i_size = i_size_read(&vnode->netfs.inode); 255 if (i_size > AFS_DIR_BLOCK_SIZE * AFS_DIR_MAX_BLOCKS || 256 (i_size & (AFS_DIR_BLOCK_SIZE - 1))) { 257 afs_invalidate_dir(vnode, afs_dir_invalid_edit_add_bad_size); 258 return; 259 } 260 261 meta = afs_dir_get_block(&iter, 0); 262 if (!meta) 263 return; 264 265 /* Work out how many slots we're going to need. */ 266 iter.nr_slots = afs_dir_calc_slots(name->len); 267 268 if (i_size == 0) 269 goto new_directory; 270 nr_blocks = i_size / AFS_DIR_BLOCK_SIZE; 271 272 /* Find a block that has sufficient slots available. Each folio 273 * contains two or more directory blocks. 274 */ 275 for (b = 0; b < nr_blocks + 1; b++) { 276 /* If the directory extended into a new folio, then we need to 277 * tack a new folio on the end. 278 */ 279 if (nr_blocks >= AFS_DIR_MAX_BLOCKS) 280 goto error_too_many_blocks; 281 282 /* Lower dir blocks have a counter in the header we can check. */ 283 if (b < AFS_DIR_BLOCKS_WITH_CTR && 284 meta->meta.alloc_ctrs[b] < iter.nr_slots) 285 continue; 286 287 block = afs_dir_get_block(&iter, b); 288 if (!block) 289 goto error; 290 291 /* Abandon the edit if we got a callback break. */ 292 if (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags)) 293 goto already_invalidated; 294 295 _debug("block %u: %2u %3u %u", 296 b, 297 (b < AFS_DIR_BLOCKS_WITH_CTR) ? meta->meta.alloc_ctrs[b] : 99, 298 ntohs(block->hdr.npages), 299 ntohs(block->hdr.magic)); 300 301 /* Initialise the block if necessary. */ 302 if (b == nr_blocks) { 303 _debug("init %u", b); 304 afs_edit_init_block(meta, block, b); 305 afs_set_i_size(vnode, (b + 1) * AFS_DIR_BLOCK_SIZE); 306 } 307 308 /* We need to try and find one or more consecutive slots to 309 * hold the entry. 310 */ 311 slot = afs_find_contig_bits(block, iter.nr_slots); 312 if (slot >= 0) { 313 _debug("slot %u", slot); 314 goto found_space; 315 } 316 317 kunmap_local(block); 318 } 319 320 /* There are no spare slots of sufficient size, yet the operation 321 * succeeded. Download the directory again. 322 */ 323 trace_afs_edit_dir(vnode, why, afs_edit_dir_create_nospc, 0, 0, 0, 0, name->name); 324 afs_invalidate_dir(vnode, afs_dir_invalid_edit_add_no_slots); 325 goto out_unmap; 326 327 new_directory: 328 afs_edit_init_block(meta, meta, 0); 329 i_size = AFS_DIR_BLOCK_SIZE; 330 afs_set_i_size(vnode, i_size); 331 slot = AFS_DIR_RESV_BLOCKS0; 332 block = afs_dir_get_block(&iter, 0); 333 nr_blocks = 1; 334 b = 0; 335 336 found_space: 337 /* Set the dirent slot. */ 338 trace_afs_edit_dir(vnode, why, afs_edit_dir_create, b, slot, 339 new_fid->vnode, new_fid->unique, name->name); 340 de = &block->dirents[slot]; 341 de->u.valid = 1; 342 de->u.unused[0] = 0; 343 de->u.hash_next = 0; // TODO: Really need to maintain this 344 de->u.vnode = htonl(new_fid->vnode); 345 de->u.unique = htonl(new_fid->unique); 346 memcpy(de->u.name, name->name, name->len + 1); 347 de->u.name[name->len] = 0; 348 349 /* Adjust the bitmap. */ 350 afs_set_contig_bits(block, slot, iter.nr_slots); 351 352 /* Adjust the allocation counter. */ 353 if (b < AFS_DIR_BLOCKS_WITH_CTR) 354 meta->meta.alloc_ctrs[b] -= iter.nr_slots; 355 356 /* Adjust the hash chain. */ 357 entry = b * AFS_DIR_SLOTS_PER_BLOCK + slot; 358 iter.bucket = afs_dir_hash_name(name); 359 de->u.hash_next = meta->meta.hashtable[iter.bucket]; 360 meta->meta.hashtable[iter.bucket] = htons(entry); 361 kunmap_local(block); 362 363 inode_inc_iversion_raw(&vnode->netfs.inode); 364 afs_stat_v(vnode, n_dir_cr); 365 _debug("Insert %s in %u[%u]", name->name, b, slot); 366 367 netfs_single_mark_inode_dirty(&vnode->netfs.inode); 368 369 out_unmap: 370 kunmap_local(meta); 371 _leave(""); 372 return; 373 374 already_invalidated: 375 trace_afs_edit_dir(vnode, why, afs_edit_dir_create_inval, 0, 0, 0, 0, name->name); 376 kunmap_local(block); 377 goto out_unmap; 378 379 error_too_many_blocks: 380 afs_invalidate_dir(vnode, afs_dir_invalid_edit_add_too_many_blocks); 381 error: 382 trace_afs_edit_dir(vnode, why, afs_edit_dir_create_error, 0, 0, 0, 0, name->name); 383 goto out_unmap; 384 } 385 386 /* 387 * Edit a directory's file data to remove a new directory entry. Doing this 388 * after unlink, rmdir or rename if the data version number is incremented by 389 * exactly one avoids the need to re-download the entire directory contents. 390 * 391 * The caller must hold the inode locked. 392 */ 393 void afs_edit_dir_remove(struct afs_vnode *vnode, 394 struct qstr *name, enum afs_edit_dir_reason why) 395 { 396 union afs_xdr_dir_block *meta, *block, *pblock; 397 union afs_xdr_dirent *de, *pde; 398 struct afs_dir_iter iter = { .dvnode = vnode }; 399 struct afs_fid fid; 400 unsigned int b, slot, entry; 401 loff_t i_size; 402 __be16 next; 403 int found; 404 405 _enter(",,{%d,%s},", name->len, name->name); 406 407 i_size = i_size_read(&vnode->netfs.inode); 408 if (i_size < AFS_DIR_BLOCK_SIZE || 409 i_size > AFS_DIR_BLOCK_SIZE * AFS_DIR_MAX_BLOCKS || 410 (i_size & (AFS_DIR_BLOCK_SIZE - 1))) { 411 afs_invalidate_dir(vnode, afs_dir_invalid_edit_rem_bad_size); 412 return; 413 } 414 415 if (!afs_dir_init_iter(&iter, name)) 416 return; 417 418 meta = afs_dir_find_block(&iter, 0); 419 if (!meta) 420 return; 421 422 /* Find the entry in the blob. */ 423 found = afs_dir_search_bucket(&iter, name, &fid); 424 if (found < 0) { 425 /* Didn't find the dirent to clobber. Re-download. */ 426 trace_afs_edit_dir(vnode, why, afs_edit_dir_delete_noent, 427 0, 0, 0, 0, name->name); 428 afs_invalidate_dir(vnode, afs_dir_invalid_edit_rem_wrong_name); 429 goto out_unmap; 430 } 431 432 entry = found; 433 b = entry / AFS_DIR_SLOTS_PER_BLOCK; 434 slot = entry % AFS_DIR_SLOTS_PER_BLOCK; 435 436 block = afs_dir_find_block(&iter, b); 437 if (!block) 438 goto error; 439 if (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags)) 440 goto already_invalidated; 441 442 /* Check and clear the entry. */ 443 de = &block->dirents[slot]; 444 if (de->u.valid != 1) 445 goto error_unmap; 446 447 trace_afs_edit_dir(vnode, why, afs_edit_dir_delete, b, slot, 448 ntohl(de->u.vnode), ntohl(de->u.unique), 449 name->name); 450 451 /* Adjust the bitmap. */ 452 afs_clear_contig_bits(block, slot, iter.nr_slots); 453 454 /* Adjust the allocation counter. */ 455 if (b < AFS_DIR_BLOCKS_WITH_CTR) 456 meta->meta.alloc_ctrs[b] += iter.nr_slots; 457 458 /* Clear the constituent entries. */ 459 next = de->u.hash_next; 460 memset(de, 0, sizeof(*de) * iter.nr_slots); 461 kunmap_local(block); 462 463 /* Adjust the hash chain: if iter->prev_entry is 0, the hashtable head 464 * index is previous; otherwise it's slot number of the previous entry. 465 */ 466 if (!iter.prev_entry) { 467 __be16 prev_next = meta->meta.hashtable[iter.bucket]; 468 469 if (unlikely(prev_next != htons(entry))) { 470 pr_warn("%llx:%llx:%x: not head of chain b=%x p=%x,%x e=%x %*s", 471 vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique, 472 iter.bucket, iter.prev_entry, prev_next, entry, 473 name->len, name->name); 474 goto error; 475 } 476 meta->meta.hashtable[iter.bucket] = next; 477 } else { 478 unsigned int pb = iter.prev_entry / AFS_DIR_SLOTS_PER_BLOCK; 479 unsigned int ps = iter.prev_entry % AFS_DIR_SLOTS_PER_BLOCK; 480 __be16 prev_next; 481 482 pblock = afs_dir_find_block(&iter, pb); 483 if (!pblock) 484 goto error; 485 pde = &pblock->dirents[ps]; 486 prev_next = pde->u.hash_next; 487 if (prev_next != htons(entry)) { 488 kunmap_local(pblock); 489 pr_warn("%llx:%llx:%x: not prev in chain b=%x p=%x,%x e=%x %*s", 490 vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique, 491 iter.bucket, iter.prev_entry, prev_next, entry, 492 name->len, name->name); 493 goto error; 494 } 495 pde->u.hash_next = next; 496 kunmap_local(pblock); 497 } 498 499 netfs_single_mark_inode_dirty(&vnode->netfs.inode); 500 501 inode_set_iversion_raw(&vnode->netfs.inode, vnode->status.data_version); 502 afs_stat_v(vnode, n_dir_rm); 503 _debug("Remove %s from %u[%u]", name->name, b, slot); 504 505 out_unmap: 506 kunmap_local(meta); 507 _leave(""); 508 return; 509 510 already_invalidated: 511 kunmap_local(block); 512 trace_afs_edit_dir(vnode, why, afs_edit_dir_delete_inval, 513 0, 0, 0, 0, name->name); 514 goto out_unmap; 515 516 error_unmap: 517 kunmap_local(block); 518 error: 519 trace_afs_edit_dir(vnode, why, afs_edit_dir_delete_error, 520 0, 0, 0, 0, name->name); 521 goto out_unmap; 522 } 523 524 /* 525 * Edit a subdirectory that has been moved between directories to update the 526 * ".." entry. 527 */ 528 void afs_edit_dir_update_dotdot(struct afs_vnode *vnode, struct afs_vnode *new_dvnode, 529 enum afs_edit_dir_reason why) 530 { 531 union afs_xdr_dir_block *block; 532 union afs_xdr_dirent *de; 533 struct afs_dir_iter iter = { .dvnode = vnode }; 534 unsigned int nr_blocks, b; 535 loff_t i_size; 536 int slot; 537 538 _enter(""); 539 540 i_size = i_size_read(&vnode->netfs.inode); 541 if (i_size < AFS_DIR_BLOCK_SIZE) { 542 afs_invalidate_dir(vnode, afs_dir_invalid_edit_upd_bad_size); 543 return; 544 } 545 546 nr_blocks = i_size / AFS_DIR_BLOCK_SIZE; 547 548 /* Find a block that has sufficient slots available. Each folio 549 * contains two or more directory blocks. 550 */ 551 for (b = 0; b < nr_blocks; b++) { 552 block = afs_dir_get_block(&iter, b); 553 if (!block) 554 goto error; 555 556 /* Abandon the edit if we got a callback break. */ 557 if (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags)) 558 goto already_invalidated; 559 560 slot = afs_dir_scan_block(block, &dotdot_name, b); 561 if (slot >= 0) 562 goto found_dirent; 563 564 kunmap_local(block); 565 } 566 567 /* Didn't find the dirent to clobber. Download the directory again. */ 568 trace_afs_edit_dir(vnode, why, afs_edit_dir_update_nodd, 569 0, 0, 0, 0, ".."); 570 afs_invalidate_dir(vnode, afs_dir_invalid_edit_upd_no_dd); 571 goto out; 572 573 found_dirent: 574 de = &block->dirents[slot]; 575 de->u.vnode = htonl(new_dvnode->fid.vnode); 576 de->u.unique = htonl(new_dvnode->fid.unique); 577 578 trace_afs_edit_dir(vnode, why, afs_edit_dir_update_dd, b, slot, 579 ntohl(de->u.vnode), ntohl(de->u.unique), ".."); 580 581 kunmap_local(block); 582 netfs_single_mark_inode_dirty(&vnode->netfs.inode); 583 inode_set_iversion_raw(&vnode->netfs.inode, vnode->status.data_version); 584 585 out: 586 _leave(""); 587 return; 588 589 already_invalidated: 590 kunmap_local(block); 591 trace_afs_edit_dir(vnode, why, afs_edit_dir_update_inval, 592 0, 0, 0, 0, ".."); 593 goto out; 594 595 error: 596 trace_afs_edit_dir(vnode, why, afs_edit_dir_update_error, 597 0, 0, 0, 0, ".."); 598 goto out; 599 } 600 601 /* 602 * Initialise a new directory. We need to fill in the "." and ".." entries. 603 */ 604 void afs_mkdir_init_dir(struct afs_vnode *dvnode, struct afs_vnode *parent_dvnode) 605 { 606 union afs_xdr_dir_block *meta; 607 struct afs_dir_iter iter = { .dvnode = dvnode }; 608 union afs_xdr_dirent *de; 609 unsigned int slot = AFS_DIR_RESV_BLOCKS0; 610 loff_t i_size; 611 612 i_size = i_size_read(&dvnode->netfs.inode); 613 if (i_size != AFS_DIR_BLOCK_SIZE) { 614 afs_invalidate_dir(dvnode, afs_dir_invalid_edit_add_bad_size); 615 return; 616 } 617 618 meta = afs_dir_get_block(&iter, 0); 619 if (!meta) 620 return; 621 622 afs_edit_init_block(meta, meta, 0); 623 624 de = &meta->dirents[slot]; 625 de->u.valid = 1; 626 de->u.vnode = htonl(dvnode->fid.vnode); 627 de->u.unique = htonl(dvnode->fid.unique); 628 memcpy(de->u.name, ".", 2); 629 trace_afs_edit_dir(dvnode, afs_edit_dir_for_mkdir, afs_edit_dir_mkdir, 0, slot, 630 dvnode->fid.vnode, dvnode->fid.unique, "."); 631 slot++; 632 633 de = &meta->dirents[slot]; 634 de->u.valid = 1; 635 de->u.vnode = htonl(parent_dvnode->fid.vnode); 636 de->u.unique = htonl(parent_dvnode->fid.unique); 637 memcpy(de->u.name, "..", 3); 638 trace_afs_edit_dir(dvnode, afs_edit_dir_for_mkdir, afs_edit_dir_mkdir, 0, slot, 639 parent_dvnode->fid.vnode, parent_dvnode->fid.unique, ".."); 640 641 afs_set_contig_bits(meta, AFS_DIR_RESV_BLOCKS0, 2); 642 meta->meta.alloc_ctrs[0] -= 2; 643 kunmap_local(meta); 644 645 netfs_single_mark_inode_dirty(&dvnode->netfs.inode); 646 set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags); 647 set_bit(AFS_VNODE_DIR_READ, &dvnode->flags); 648 } 649