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