at v4.12 660 lines 17 kB view raw
1/* 2 * Copyright (C) 2005, 2006 3 * Avishay Traeger (avishay@gmail.com) 4 * Copyright (C) 2008, 2009 5 * Boaz Harrosh <ooo@electrozaur.com> 6 * 7 * Copyrights for code taken from ext2: 8 * Copyright (C) 1992, 1993, 1994, 1995 9 * Remy Card (card@masi.ibp.fr) 10 * Laboratoire MASI - Institut Blaise Pascal 11 * Universite Pierre et Marie Curie (Paris VI) 12 * from 13 * linux/fs/minix/inode.c 14 * Copyright (C) 1991, 1992 Linus Torvalds 15 * 16 * This file is part of exofs. 17 * 18 * exofs is free software; you can redistribute it and/or modify 19 * it under the terms of the GNU General Public License as published by 20 * the Free Software Foundation. Since it is based on ext2, and the only 21 * valid version of GPL for the Linux kernel is version 2, the only valid 22 * version of GPL for exofs is version 2. 23 * 24 * exofs is distributed in the hope that it will be useful, 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * GNU General Public License for more details. 28 * 29 * You should have received a copy of the GNU General Public License 30 * along with exofs; if not, write to the Free Software 31 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 32 */ 33 34#include "exofs.h" 35 36static inline unsigned exofs_chunk_size(struct inode *inode) 37{ 38 return inode->i_sb->s_blocksize; 39} 40 41static inline void exofs_put_page(struct page *page) 42{ 43 kunmap(page); 44 put_page(page); 45} 46 47static unsigned exofs_last_byte(struct inode *inode, unsigned long page_nr) 48{ 49 loff_t last_byte = inode->i_size; 50 51 last_byte -= page_nr << PAGE_SHIFT; 52 if (last_byte > PAGE_SIZE) 53 last_byte = PAGE_SIZE; 54 return last_byte; 55} 56 57static int exofs_commit_chunk(struct page *page, loff_t pos, unsigned len) 58{ 59 struct address_space *mapping = page->mapping; 60 struct inode *dir = mapping->host; 61 int err = 0; 62 63 dir->i_version++; 64 65 if (!PageUptodate(page)) 66 SetPageUptodate(page); 67 68 if (pos+len > dir->i_size) { 69 i_size_write(dir, pos+len); 70 mark_inode_dirty(dir); 71 } 72 set_page_dirty(page); 73 74 if (IS_DIRSYNC(dir)) 75 err = write_one_page(page, 1); 76 else 77 unlock_page(page); 78 79 return err; 80} 81 82static bool exofs_check_page(struct page *page) 83{ 84 struct inode *dir = page->mapping->host; 85 unsigned chunk_size = exofs_chunk_size(dir); 86 char *kaddr = page_address(page); 87 unsigned offs, rec_len; 88 unsigned limit = PAGE_SIZE; 89 struct exofs_dir_entry *p; 90 char *error; 91 92 /* if the page is the last one in the directory */ 93 if ((dir->i_size >> PAGE_SHIFT) == page->index) { 94 limit = dir->i_size & ~PAGE_MASK; 95 if (limit & (chunk_size - 1)) 96 goto Ebadsize; 97 if (!limit) 98 goto out; 99 } 100 for (offs = 0; offs <= limit - EXOFS_DIR_REC_LEN(1); offs += rec_len) { 101 p = (struct exofs_dir_entry *)(kaddr + offs); 102 rec_len = le16_to_cpu(p->rec_len); 103 104 if (rec_len < EXOFS_DIR_REC_LEN(1)) 105 goto Eshort; 106 if (rec_len & 3) 107 goto Ealign; 108 if (rec_len < EXOFS_DIR_REC_LEN(p->name_len)) 109 goto Enamelen; 110 if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1)) 111 goto Espan; 112 } 113 if (offs != limit) 114 goto Eend; 115out: 116 SetPageChecked(page); 117 return true; 118 119Ebadsize: 120 EXOFS_ERR("ERROR [exofs_check_page]: " 121 "size of directory(0x%lx) is not a multiple of chunk size\n", 122 dir->i_ino 123 ); 124 goto fail; 125Eshort: 126 error = "rec_len is smaller than minimal"; 127 goto bad_entry; 128Ealign: 129 error = "unaligned directory entry"; 130 goto bad_entry; 131Enamelen: 132 error = "rec_len is too small for name_len"; 133 goto bad_entry; 134Espan: 135 error = "directory entry across blocks"; 136 goto bad_entry; 137bad_entry: 138 EXOFS_ERR( 139 "ERROR [exofs_check_page]: bad entry in directory(0x%lx): %s - " 140 "offset=%lu, inode=0x%llx, rec_len=%d, name_len=%d\n", 141 dir->i_ino, error, (page->index<<PAGE_SHIFT)+offs, 142 _LLU(le64_to_cpu(p->inode_no)), 143 rec_len, p->name_len); 144 goto fail; 145Eend: 146 p = (struct exofs_dir_entry *)(kaddr + offs); 147 EXOFS_ERR("ERROR [exofs_check_page]: " 148 "entry in directory(0x%lx) spans the page boundary" 149 "offset=%lu, inode=0x%llx\n", 150 dir->i_ino, (page->index<<PAGE_SHIFT)+offs, 151 _LLU(le64_to_cpu(p->inode_no))); 152fail: 153 SetPageError(page); 154 return false; 155} 156 157static struct page *exofs_get_page(struct inode *dir, unsigned long n) 158{ 159 struct address_space *mapping = dir->i_mapping; 160 struct page *page = read_mapping_page(mapping, n, NULL); 161 162 if (!IS_ERR(page)) { 163 kmap(page); 164 if (unlikely(!PageChecked(page))) { 165 if (PageError(page) || !exofs_check_page(page)) 166 goto fail; 167 } 168 } 169 return page; 170 171fail: 172 exofs_put_page(page); 173 return ERR_PTR(-EIO); 174} 175 176static inline int exofs_match(int len, const unsigned char *name, 177 struct exofs_dir_entry *de) 178{ 179 if (len != de->name_len) 180 return 0; 181 if (!de->inode_no) 182 return 0; 183 return !memcmp(name, de->name, len); 184} 185 186static inline 187struct exofs_dir_entry *exofs_next_entry(struct exofs_dir_entry *p) 188{ 189 return (struct exofs_dir_entry *)((char *)p + le16_to_cpu(p->rec_len)); 190} 191 192static inline unsigned 193exofs_validate_entry(char *base, unsigned offset, unsigned mask) 194{ 195 struct exofs_dir_entry *de = (struct exofs_dir_entry *)(base + offset); 196 struct exofs_dir_entry *p = 197 (struct exofs_dir_entry *)(base + (offset&mask)); 198 while ((char *)p < (char *)de) { 199 if (p->rec_len == 0) 200 break; 201 p = exofs_next_entry(p); 202 } 203 return (char *)p - base; 204} 205 206static unsigned char exofs_filetype_table[EXOFS_FT_MAX] = { 207 [EXOFS_FT_UNKNOWN] = DT_UNKNOWN, 208 [EXOFS_FT_REG_FILE] = DT_REG, 209 [EXOFS_FT_DIR] = DT_DIR, 210 [EXOFS_FT_CHRDEV] = DT_CHR, 211 [EXOFS_FT_BLKDEV] = DT_BLK, 212 [EXOFS_FT_FIFO] = DT_FIFO, 213 [EXOFS_FT_SOCK] = DT_SOCK, 214 [EXOFS_FT_SYMLINK] = DT_LNK, 215}; 216 217#define S_SHIFT 12 218static unsigned char exofs_type_by_mode[S_IFMT >> S_SHIFT] = { 219 [S_IFREG >> S_SHIFT] = EXOFS_FT_REG_FILE, 220 [S_IFDIR >> S_SHIFT] = EXOFS_FT_DIR, 221 [S_IFCHR >> S_SHIFT] = EXOFS_FT_CHRDEV, 222 [S_IFBLK >> S_SHIFT] = EXOFS_FT_BLKDEV, 223 [S_IFIFO >> S_SHIFT] = EXOFS_FT_FIFO, 224 [S_IFSOCK >> S_SHIFT] = EXOFS_FT_SOCK, 225 [S_IFLNK >> S_SHIFT] = EXOFS_FT_SYMLINK, 226}; 227 228static inline 229void exofs_set_de_type(struct exofs_dir_entry *de, struct inode *inode) 230{ 231 umode_t mode = inode->i_mode; 232 de->file_type = exofs_type_by_mode[(mode & S_IFMT) >> S_SHIFT]; 233} 234 235static int 236exofs_readdir(struct file *file, struct dir_context *ctx) 237{ 238 loff_t pos = ctx->pos; 239 struct inode *inode = file_inode(file); 240 unsigned int offset = pos & ~PAGE_MASK; 241 unsigned long n = pos >> PAGE_SHIFT; 242 unsigned long npages = dir_pages(inode); 243 unsigned chunk_mask = ~(exofs_chunk_size(inode)-1); 244 int need_revalidate = (file->f_version != inode->i_version); 245 246 if (pos > inode->i_size - EXOFS_DIR_REC_LEN(1)) 247 return 0; 248 249 for ( ; n < npages; n++, offset = 0) { 250 char *kaddr, *limit; 251 struct exofs_dir_entry *de; 252 struct page *page = exofs_get_page(inode, n); 253 254 if (IS_ERR(page)) { 255 EXOFS_ERR("ERROR: bad page in directory(0x%lx)\n", 256 inode->i_ino); 257 ctx->pos += PAGE_SIZE - offset; 258 return PTR_ERR(page); 259 } 260 kaddr = page_address(page); 261 if (unlikely(need_revalidate)) { 262 if (offset) { 263 offset = exofs_validate_entry(kaddr, offset, 264 chunk_mask); 265 ctx->pos = (n<<PAGE_SHIFT) + offset; 266 } 267 file->f_version = inode->i_version; 268 need_revalidate = 0; 269 } 270 de = (struct exofs_dir_entry *)(kaddr + offset); 271 limit = kaddr + exofs_last_byte(inode, n) - 272 EXOFS_DIR_REC_LEN(1); 273 for (; (char *)de <= limit; de = exofs_next_entry(de)) { 274 if (de->rec_len == 0) { 275 EXOFS_ERR("ERROR: " 276 "zero-length entry in directory(0x%lx)\n", 277 inode->i_ino); 278 exofs_put_page(page); 279 return -EIO; 280 } 281 if (de->inode_no) { 282 unsigned char t; 283 284 if (de->file_type < EXOFS_FT_MAX) 285 t = exofs_filetype_table[de->file_type]; 286 else 287 t = DT_UNKNOWN; 288 289 if (!dir_emit(ctx, de->name, de->name_len, 290 le64_to_cpu(de->inode_no), 291 t)) { 292 exofs_put_page(page); 293 return 0; 294 } 295 } 296 ctx->pos += le16_to_cpu(de->rec_len); 297 } 298 exofs_put_page(page); 299 } 300 return 0; 301} 302 303struct exofs_dir_entry *exofs_find_entry(struct inode *dir, 304 struct dentry *dentry, struct page **res_page) 305{ 306 const unsigned char *name = dentry->d_name.name; 307 int namelen = dentry->d_name.len; 308 unsigned reclen = EXOFS_DIR_REC_LEN(namelen); 309 unsigned long start, n; 310 unsigned long npages = dir_pages(dir); 311 struct page *page = NULL; 312 struct exofs_i_info *oi = exofs_i(dir); 313 struct exofs_dir_entry *de; 314 315 if (npages == 0) 316 goto out; 317 318 *res_page = NULL; 319 320 start = oi->i_dir_start_lookup; 321 if (start >= npages) 322 start = 0; 323 n = start; 324 do { 325 char *kaddr; 326 page = exofs_get_page(dir, n); 327 if (!IS_ERR(page)) { 328 kaddr = page_address(page); 329 de = (struct exofs_dir_entry *) kaddr; 330 kaddr += exofs_last_byte(dir, n) - reclen; 331 while ((char *) de <= kaddr) { 332 if (de->rec_len == 0) { 333 EXOFS_ERR("ERROR: zero-length entry in " 334 "directory(0x%lx)\n", 335 dir->i_ino); 336 exofs_put_page(page); 337 goto out; 338 } 339 if (exofs_match(namelen, name, de)) 340 goto found; 341 de = exofs_next_entry(de); 342 } 343 exofs_put_page(page); 344 } 345 if (++n >= npages) 346 n = 0; 347 } while (n != start); 348out: 349 return NULL; 350 351found: 352 *res_page = page; 353 oi->i_dir_start_lookup = n; 354 return de; 355} 356 357struct exofs_dir_entry *exofs_dotdot(struct inode *dir, struct page **p) 358{ 359 struct page *page = exofs_get_page(dir, 0); 360 struct exofs_dir_entry *de = NULL; 361 362 if (!IS_ERR(page)) { 363 de = exofs_next_entry( 364 (struct exofs_dir_entry *)page_address(page)); 365 *p = page; 366 } 367 return de; 368} 369 370ino_t exofs_parent_ino(struct dentry *child) 371{ 372 struct page *page; 373 struct exofs_dir_entry *de; 374 ino_t ino; 375 376 de = exofs_dotdot(d_inode(child), &page); 377 if (!de) 378 return 0; 379 380 ino = le64_to_cpu(de->inode_no); 381 exofs_put_page(page); 382 return ino; 383} 384 385ino_t exofs_inode_by_name(struct inode *dir, struct dentry *dentry) 386{ 387 ino_t res = 0; 388 struct exofs_dir_entry *de; 389 struct page *page; 390 391 de = exofs_find_entry(dir, dentry, &page); 392 if (de) { 393 res = le64_to_cpu(de->inode_no); 394 exofs_put_page(page); 395 } 396 return res; 397} 398 399int exofs_set_link(struct inode *dir, struct exofs_dir_entry *de, 400 struct page *page, struct inode *inode) 401{ 402 loff_t pos = page_offset(page) + 403 (char *) de - (char *) page_address(page); 404 unsigned len = le16_to_cpu(de->rec_len); 405 int err; 406 407 lock_page(page); 408 err = exofs_write_begin(NULL, page->mapping, pos, len, 0, &page, NULL); 409 if (err) 410 EXOFS_ERR("exofs_set_link: exofs_write_begin FAILED => %d\n", 411 err); 412 413 de->inode_no = cpu_to_le64(inode->i_ino); 414 exofs_set_de_type(de, inode); 415 if (likely(!err)) 416 err = exofs_commit_chunk(page, pos, len); 417 exofs_put_page(page); 418 dir->i_mtime = dir->i_ctime = current_time(dir); 419 mark_inode_dirty(dir); 420 return err; 421} 422 423int exofs_add_link(struct dentry *dentry, struct inode *inode) 424{ 425 struct inode *dir = d_inode(dentry->d_parent); 426 const unsigned char *name = dentry->d_name.name; 427 int namelen = dentry->d_name.len; 428 unsigned chunk_size = exofs_chunk_size(dir); 429 unsigned reclen = EXOFS_DIR_REC_LEN(namelen); 430 unsigned short rec_len, name_len; 431 struct page *page = NULL; 432 struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; 433 struct exofs_dir_entry *de; 434 unsigned long npages = dir_pages(dir); 435 unsigned long n; 436 char *kaddr; 437 loff_t pos; 438 int err; 439 440 for (n = 0; n <= npages; n++) { 441 char *dir_end; 442 443 page = exofs_get_page(dir, n); 444 err = PTR_ERR(page); 445 if (IS_ERR(page)) 446 goto out; 447 lock_page(page); 448 kaddr = page_address(page); 449 dir_end = kaddr + exofs_last_byte(dir, n); 450 de = (struct exofs_dir_entry *)kaddr; 451 kaddr += PAGE_SIZE - reclen; 452 while ((char *)de <= kaddr) { 453 if ((char *)de == dir_end) { 454 name_len = 0; 455 rec_len = chunk_size; 456 de->rec_len = cpu_to_le16(chunk_size); 457 de->inode_no = 0; 458 goto got_it; 459 } 460 if (de->rec_len == 0) { 461 EXOFS_ERR("ERROR: exofs_add_link: " 462 "zero-length entry in directory(0x%lx)\n", 463 inode->i_ino); 464 err = -EIO; 465 goto out_unlock; 466 } 467 err = -EEXIST; 468 if (exofs_match(namelen, name, de)) 469 goto out_unlock; 470 name_len = EXOFS_DIR_REC_LEN(de->name_len); 471 rec_len = le16_to_cpu(de->rec_len); 472 if (!de->inode_no && rec_len >= reclen) 473 goto got_it; 474 if (rec_len >= name_len + reclen) 475 goto got_it; 476 de = (struct exofs_dir_entry *) ((char *) de + rec_len); 477 } 478 unlock_page(page); 479 exofs_put_page(page); 480 } 481 482 EXOFS_ERR("exofs_add_link: BAD dentry=%p or inode=0x%lx\n", 483 dentry, inode->i_ino); 484 return -EINVAL; 485 486got_it: 487 pos = page_offset(page) + 488 (char *)de - (char *)page_address(page); 489 err = exofs_write_begin(NULL, page->mapping, pos, rec_len, 0, 490 &page, NULL); 491 if (err) 492 goto out_unlock; 493 if (de->inode_no) { 494 struct exofs_dir_entry *de1 = 495 (struct exofs_dir_entry *)((char *)de + name_len); 496 de1->rec_len = cpu_to_le16(rec_len - name_len); 497 de->rec_len = cpu_to_le16(name_len); 498 de = de1; 499 } 500 de->name_len = namelen; 501 memcpy(de->name, name, namelen); 502 de->inode_no = cpu_to_le64(inode->i_ino); 503 exofs_set_de_type(de, inode); 504 err = exofs_commit_chunk(page, pos, rec_len); 505 dir->i_mtime = dir->i_ctime = current_time(dir); 506 mark_inode_dirty(dir); 507 sbi->s_numfiles++; 508 509out_put: 510 exofs_put_page(page); 511out: 512 return err; 513out_unlock: 514 unlock_page(page); 515 goto out_put; 516} 517 518int exofs_delete_entry(struct exofs_dir_entry *dir, struct page *page) 519{ 520 struct address_space *mapping = page->mapping; 521 struct inode *inode = mapping->host; 522 struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; 523 char *kaddr = page_address(page); 524 unsigned from = ((char *)dir - kaddr) & ~(exofs_chunk_size(inode)-1); 525 unsigned to = ((char *)dir - kaddr) + le16_to_cpu(dir->rec_len); 526 loff_t pos; 527 struct exofs_dir_entry *pde = NULL; 528 struct exofs_dir_entry *de = (struct exofs_dir_entry *) (kaddr + from); 529 int err; 530 531 while (de < dir) { 532 if (de->rec_len == 0) { 533 EXOFS_ERR("ERROR: exofs_delete_entry:" 534 "zero-length entry in directory(0x%lx)\n", 535 inode->i_ino); 536 err = -EIO; 537 goto out; 538 } 539 pde = de; 540 de = exofs_next_entry(de); 541 } 542 if (pde) 543 from = (char *)pde - (char *)page_address(page); 544 pos = page_offset(page) + from; 545 lock_page(page); 546 err = exofs_write_begin(NULL, page->mapping, pos, to - from, 0, 547 &page, NULL); 548 if (err) 549 EXOFS_ERR("exofs_delete_entry: exofs_write_begin FAILED => %d\n", 550 err); 551 if (pde) 552 pde->rec_len = cpu_to_le16(to - from); 553 dir->inode_no = 0; 554 if (likely(!err)) 555 err = exofs_commit_chunk(page, pos, to - from); 556 inode->i_ctime = inode->i_mtime = current_time(inode); 557 mark_inode_dirty(inode); 558 sbi->s_numfiles--; 559out: 560 exofs_put_page(page); 561 return err; 562} 563 564/* kept aligned on 4 bytes */ 565#define THIS_DIR ".\0\0" 566#define PARENT_DIR "..\0" 567 568int exofs_make_empty(struct inode *inode, struct inode *parent) 569{ 570 struct address_space *mapping = inode->i_mapping; 571 struct page *page = grab_cache_page(mapping, 0); 572 unsigned chunk_size = exofs_chunk_size(inode); 573 struct exofs_dir_entry *de; 574 int err; 575 void *kaddr; 576 577 if (!page) 578 return -ENOMEM; 579 580 err = exofs_write_begin(NULL, page->mapping, 0, chunk_size, 0, 581 &page, NULL); 582 if (err) { 583 unlock_page(page); 584 goto fail; 585 } 586 587 kaddr = kmap_atomic(page); 588 de = (struct exofs_dir_entry *)kaddr; 589 de->name_len = 1; 590 de->rec_len = cpu_to_le16(EXOFS_DIR_REC_LEN(1)); 591 memcpy(de->name, THIS_DIR, sizeof(THIS_DIR)); 592 de->inode_no = cpu_to_le64(inode->i_ino); 593 exofs_set_de_type(de, inode); 594 595 de = (struct exofs_dir_entry *)(kaddr + EXOFS_DIR_REC_LEN(1)); 596 de->name_len = 2; 597 de->rec_len = cpu_to_le16(chunk_size - EXOFS_DIR_REC_LEN(1)); 598 de->inode_no = cpu_to_le64(parent->i_ino); 599 memcpy(de->name, PARENT_DIR, sizeof(PARENT_DIR)); 600 exofs_set_de_type(de, inode); 601 kunmap_atomic(kaddr); 602 err = exofs_commit_chunk(page, 0, chunk_size); 603fail: 604 put_page(page); 605 return err; 606} 607 608int exofs_empty_dir(struct inode *inode) 609{ 610 struct page *page = NULL; 611 unsigned long i, npages = dir_pages(inode); 612 613 for (i = 0; i < npages; i++) { 614 char *kaddr; 615 struct exofs_dir_entry *de; 616 page = exofs_get_page(inode, i); 617 618 if (IS_ERR(page)) 619 continue; 620 621 kaddr = page_address(page); 622 de = (struct exofs_dir_entry *)kaddr; 623 kaddr += exofs_last_byte(inode, i) - EXOFS_DIR_REC_LEN(1); 624 625 while ((char *)de <= kaddr) { 626 if (de->rec_len == 0) { 627 EXOFS_ERR("ERROR: exofs_empty_dir: " 628 "zero-length directory entry" 629 "kaddr=%p, de=%p\n", kaddr, de); 630 goto not_empty; 631 } 632 if (de->inode_no != 0) { 633 /* check for . and .. */ 634 if (de->name[0] != '.') 635 goto not_empty; 636 if (de->name_len > 2) 637 goto not_empty; 638 if (de->name_len < 2) { 639 if (le64_to_cpu(de->inode_no) != 640 inode->i_ino) 641 goto not_empty; 642 } else if (de->name[1] != '.') 643 goto not_empty; 644 } 645 de = exofs_next_entry(de); 646 } 647 exofs_put_page(page); 648 } 649 return 1; 650 651not_empty: 652 exofs_put_page(page); 653 return 0; 654} 655 656const struct file_operations exofs_dir_operations = { 657 .llseek = generic_file_llseek, 658 .read = generic_read_dir, 659 .iterate_shared = exofs_readdir, 660};