1 /* 2 * Copyright (C) International Business Machines Corp., 2000-2004 3 * Portions Copyright (C) Christoph Hellwig, 2001-2002 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20 #include <linux/fs.h> 21 #include <linux/ctype.h> 22 #include <linux/quotaops.h> 23 #include "jfs_incore.h" 24 #include "jfs_superblock.h" 25 #include "jfs_inode.h" 26 #include "jfs_dinode.h" 27 #include "jfs_dmap.h" 28 #include "jfs_unicode.h" 29 #include "jfs_metapage.h" 30 #include "jfs_xattr.h" 31 #include "jfs_acl.h" 32 #include "jfs_debug.h" 33 34 /* 35 * forward references 36 */ 37 struct dentry_operations jfs_ci_dentry_operations; 38 39 static s64 commitZeroLink(tid_t, struct inode *); 40 41 /* 42 * NAME: jfs_create(dip, dentry, mode) 43 * 44 * FUNCTION: create a regular file in the parent directory <dip> 45 * with name = <from dentry> and mode = <mode> 46 * 47 * PARAMETER: dip - parent directory vnode 48 * dentry - dentry of new file 49 * mode - create mode (rwxrwxrwx). 50 * nd- nd struct 51 * 52 * RETURN: Errors from subroutines 53 * 54 */ 55 static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, 56 struct nameidata *nd) 57 { 58 int rc = 0; 59 tid_t tid; /* transaction id */ 60 struct inode *ip = NULL; /* child directory inode */ 61 ino_t ino; 62 struct component_name dname; /* child directory name */ 63 struct btstack btstack; 64 struct inode *iplist[2]; 65 struct tblock *tblk; 66 67 jfs_info("jfs_create: dip:0x%p name:%s", dip, dentry->d_name.name); 68 69 /* 70 * search parent directory for entry/freespace 71 * (dtSearch() returns parent directory page pinned) 72 */ 73 if ((rc = get_UCSname(&dname, dentry))) 74 goto out1; 75 76 /* 77 * Either iAlloc() or txBegin() may block. Deadlock can occur if we 78 * block there while holding dtree page, so we allocate the inode & 79 * begin the transaction before we search the directory. 80 */ 81 ip = ialloc(dip, mode); 82 if (ip == NULL) { 83 rc = -ENOSPC; 84 goto out2; 85 } 86 87 tid = txBegin(dip->i_sb, 0); 88 89 down(&JFS_IP(dip)->commit_sem); 90 down(&JFS_IP(ip)->commit_sem); 91 92 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { 93 jfs_err("jfs_create: dtSearch returned %d", rc); 94 goto out3; 95 } 96 97 tblk = tid_to_tblock(tid); 98 tblk->xflag |= COMMIT_CREATE; 99 tblk->ino = ip->i_ino; 100 tblk->u.ixpxd = JFS_IP(ip)->ixpxd; 101 102 iplist[0] = dip; 103 iplist[1] = ip; 104 105 /* 106 * initialize the child XAD tree root in-line in inode 107 */ 108 xtInitRoot(tid, ip); 109 110 /* 111 * create entry in parent directory for child directory 112 * (dtInsert() releases parent directory page) 113 */ 114 ino = ip->i_ino; 115 if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) { 116 if (rc == -EIO) { 117 jfs_err("jfs_create: dtInsert returned -EIO"); 118 txAbort(tid, 1); /* Marks Filesystem dirty */ 119 } else 120 txAbort(tid, 0); /* Filesystem full */ 121 goto out3; 122 } 123 124 ip->i_op = &jfs_file_inode_operations; 125 ip->i_fop = &jfs_file_operations; 126 ip->i_mapping->a_ops = &jfs_aops; 127 128 insert_inode_hash(ip); 129 mark_inode_dirty(ip); 130 131 dip->i_ctime = dip->i_mtime = CURRENT_TIME; 132 133 mark_inode_dirty(dip); 134 135 rc = txCommit(tid, 2, &iplist[0], 0); 136 137 out3: 138 txEnd(tid); 139 up(&JFS_IP(dip)->commit_sem); 140 up(&JFS_IP(ip)->commit_sem); 141 if (rc) { 142 ip->i_nlink = 0; 143 iput(ip); 144 } else 145 d_instantiate(dentry, ip); 146 147 out2: 148 free_UCSname(&dname); 149 150 #ifdef CONFIG_JFS_POSIX_ACL 151 if (rc == 0) 152 jfs_init_acl(ip, dip); 153 #endif 154 155 out1: 156 157 jfs_info("jfs_create: rc:%d", rc); 158 return rc; 159 } 160 161 162 /* 163 * NAME: jfs_mkdir(dip, dentry, mode) 164 * 165 * FUNCTION: create a child directory in the parent directory <dip> 166 * with name = <from dentry> and mode = <mode> 167 * 168 * PARAMETER: dip - parent directory vnode 169 * dentry - dentry of child directory 170 * mode - create mode (rwxrwxrwx). 171 * 172 * RETURN: Errors from subroutines 173 * 174 * note: 175 * EACCESS: user needs search+write permission on the parent directory 176 */ 177 static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) 178 { 179 int rc = 0; 180 tid_t tid; /* transaction id */ 181 struct inode *ip = NULL; /* child directory inode */ 182 ino_t ino; 183 struct component_name dname; /* child directory name */ 184 struct btstack btstack; 185 struct inode *iplist[2]; 186 struct tblock *tblk; 187 188 jfs_info("jfs_mkdir: dip:0x%p name:%s", dip, dentry->d_name.name); 189 190 /* link count overflow on parent directory ? */ 191 if (dip->i_nlink == JFS_LINK_MAX) { 192 rc = -EMLINK; 193 goto out1; 194 } 195 196 /* 197 * search parent directory for entry/freespace 198 * (dtSearch() returns parent directory page pinned) 199 */ 200 if ((rc = get_UCSname(&dname, dentry))) 201 goto out1; 202 203 /* 204 * Either iAlloc() or txBegin() may block. Deadlock can occur if we 205 * block there while holding dtree page, so we allocate the inode & 206 * begin the transaction before we search the directory. 207 */ 208 ip = ialloc(dip, S_IFDIR | mode); 209 if (ip == NULL) { 210 rc = -ENOSPC; 211 goto out2; 212 } 213 214 tid = txBegin(dip->i_sb, 0); 215 216 down(&JFS_IP(dip)->commit_sem); 217 down(&JFS_IP(ip)->commit_sem); 218 219 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { 220 jfs_err("jfs_mkdir: dtSearch returned %d", rc); 221 goto out3; 222 } 223 224 tblk = tid_to_tblock(tid); 225 tblk->xflag |= COMMIT_CREATE; 226 tblk->ino = ip->i_ino; 227 tblk->u.ixpxd = JFS_IP(ip)->ixpxd; 228 229 iplist[0] = dip; 230 iplist[1] = ip; 231 232 /* 233 * initialize the child directory in-line in inode 234 */ 235 dtInitRoot(tid, ip, dip->i_ino); 236 237 /* 238 * create entry in parent directory for child directory 239 * (dtInsert() releases parent directory page) 240 */ 241 ino = ip->i_ino; 242 if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) { 243 if (rc == -EIO) { 244 jfs_err("jfs_mkdir: dtInsert returned -EIO"); 245 txAbort(tid, 1); /* Marks Filesystem dirty */ 246 } else 247 txAbort(tid, 0); /* Filesystem full */ 248 goto out3; 249 } 250 251 ip->i_nlink = 2; /* for '.' */ 252 ip->i_op = &jfs_dir_inode_operations; 253 ip->i_fop = &jfs_dir_operations; 254 255 insert_inode_hash(ip); 256 mark_inode_dirty(ip); 257 258 /* update parent directory inode */ 259 dip->i_nlink++; /* for '..' from child directory */ 260 dip->i_ctime = dip->i_mtime = CURRENT_TIME; 261 mark_inode_dirty(dip); 262 263 rc = txCommit(tid, 2, &iplist[0], 0); 264 265 out3: 266 txEnd(tid); 267 up(&JFS_IP(dip)->commit_sem); 268 up(&JFS_IP(ip)->commit_sem); 269 if (rc) { 270 ip->i_nlink = 0; 271 iput(ip); 272 } else 273 d_instantiate(dentry, ip); 274 275 out2: 276 free_UCSname(&dname); 277 278 #ifdef CONFIG_JFS_POSIX_ACL 279 if (rc == 0) 280 jfs_init_acl(ip, dip); 281 #endif 282 283 out1: 284 285 jfs_info("jfs_mkdir: rc:%d", rc); 286 return rc; 287 } 288 289 /* 290 * NAME: jfs_rmdir(dip, dentry) 291 * 292 * FUNCTION: remove a link to child directory 293 * 294 * PARAMETER: dip - parent inode 295 * dentry - child directory dentry 296 * 297 * RETURN: -EINVAL - if name is . or .. 298 * -EINVAL - if . or .. exist but are invalid. 299 * errors from subroutines 300 * 301 * note: 302 * if other threads have the directory open when the last link 303 * is removed, the "." and ".." entries, if present, are removed before 304 * rmdir() returns and no new entries may be created in the directory, 305 * but the directory is not removed until the last reference to 306 * the directory is released (cf.unlink() of regular file). 307 */ 308 static int jfs_rmdir(struct inode *dip, struct dentry *dentry) 309 { 310 int rc; 311 tid_t tid; /* transaction id */ 312 struct inode *ip = dentry->d_inode; 313 ino_t ino; 314 struct component_name dname; 315 struct inode *iplist[2]; 316 struct tblock *tblk; 317 318 jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name); 319 320 /* Init inode for quota operations. */ 321 DQUOT_INIT(ip); 322 323 /* directory must be empty to be removed */ 324 if (!dtEmpty(ip)) { 325 rc = -ENOTEMPTY; 326 goto out; 327 } 328 329 if ((rc = get_UCSname(&dname, dentry))) { 330 goto out; 331 } 332 333 tid = txBegin(dip->i_sb, 0); 334 335 down(&JFS_IP(dip)->commit_sem); 336 down(&JFS_IP(ip)->commit_sem); 337 338 iplist[0] = dip; 339 iplist[1] = ip; 340 341 tblk = tid_to_tblock(tid); 342 tblk->xflag |= COMMIT_DELETE; 343 tblk->u.ip = ip; 344 345 /* 346 * delete the entry of target directory from parent directory 347 */ 348 ino = ip->i_ino; 349 if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) { 350 jfs_err("jfs_rmdir: dtDelete returned %d", rc); 351 if (rc == -EIO) 352 txAbort(tid, 1); 353 txEnd(tid); 354 up(&JFS_IP(dip)->commit_sem); 355 up(&JFS_IP(ip)->commit_sem); 356 357 goto out2; 358 } 359 360 /* update parent directory's link count corresponding 361 * to ".." entry of the target directory deleted 362 */ 363 dip->i_nlink--; 364 dip->i_ctime = dip->i_mtime = CURRENT_TIME; 365 mark_inode_dirty(dip); 366 367 /* 368 * OS/2 could have created EA and/or ACL 369 */ 370 /* free EA from both persistent and working map */ 371 if (JFS_IP(ip)->ea.flag & DXD_EXTENT) { 372 /* free EA pages */ 373 txEA(tid, ip, &JFS_IP(ip)->ea, NULL); 374 } 375 JFS_IP(ip)->ea.flag = 0; 376 377 /* free ACL from both persistent and working map */ 378 if (JFS_IP(ip)->acl.flag & DXD_EXTENT) { 379 /* free ACL pages */ 380 txEA(tid, ip, &JFS_IP(ip)->acl, NULL); 381 } 382 JFS_IP(ip)->acl.flag = 0; 383 384 /* mark the target directory as deleted */ 385 ip->i_nlink = 0; 386 mark_inode_dirty(ip); 387 388 rc = txCommit(tid, 2, &iplist[0], 0); 389 390 txEnd(tid); 391 392 up(&JFS_IP(dip)->commit_sem); 393 up(&JFS_IP(ip)->commit_sem); 394 395 /* 396 * Truncating the directory index table is not guaranteed. It 397 * may need to be done iteratively 398 */ 399 if (test_cflag(COMMIT_Stale, dip)) { 400 if (dip->i_size > 1) 401 jfs_truncate_nolock(dip, 0); 402 403 clear_cflag(COMMIT_Stale, dip); 404 } 405 406 out2: 407 free_UCSname(&dname); 408 409 out: 410 jfs_info("jfs_rmdir: rc:%d", rc); 411 return rc; 412 } 413 414 /* 415 * NAME: jfs_unlink(dip, dentry) 416 * 417 * FUNCTION: remove a link to object <vp> named by <name> 418 * from parent directory <dvp> 419 * 420 * PARAMETER: dip - inode of parent directory 421 * dentry - dentry of object to be removed 422 * 423 * RETURN: errors from subroutines 424 * 425 * note: 426 * temporary file: if one or more processes have the file open 427 * when the last link is removed, the link will be removed before 428 * unlink() returns, but the removal of the file contents will be 429 * postponed until all references to the files are closed. 430 * 431 * JFS does NOT support unlink() on directories. 432 * 433 */ 434 static int jfs_unlink(struct inode *dip, struct dentry *dentry) 435 { 436 int rc; 437 tid_t tid; /* transaction id */ 438 struct inode *ip = dentry->d_inode; 439 ino_t ino; 440 struct component_name dname; /* object name */ 441 struct inode *iplist[2]; 442 struct tblock *tblk; 443 s64 new_size = 0; 444 int commit_flag; 445 446 jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name); 447 448 /* Init inode for quota operations. */ 449 DQUOT_INIT(ip); 450 451 if ((rc = get_UCSname(&dname, dentry))) 452 goto out; 453 454 IWRITE_LOCK(ip); 455 456 tid = txBegin(dip->i_sb, 0); 457 458 down(&JFS_IP(dip)->commit_sem); 459 down(&JFS_IP(ip)->commit_sem); 460 461 iplist[0] = dip; 462 iplist[1] = ip; 463 464 /* 465 * delete the entry of target file from parent directory 466 */ 467 ino = ip->i_ino; 468 if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) { 469 jfs_err("jfs_unlink: dtDelete returned %d", rc); 470 if (rc == -EIO) 471 txAbort(tid, 1); /* Marks FS Dirty */ 472 txEnd(tid); 473 up(&JFS_IP(dip)->commit_sem); 474 up(&JFS_IP(ip)->commit_sem); 475 IWRITE_UNLOCK(ip); 476 goto out1; 477 } 478 479 ASSERT(ip->i_nlink); 480 481 ip->i_ctime = dip->i_ctime = dip->i_mtime = CURRENT_TIME; 482 mark_inode_dirty(dip); 483 484 /* update target's inode */ 485 ip->i_nlink--; 486 mark_inode_dirty(ip); 487 488 /* 489 * commit zero link count object 490 */ 491 if (ip->i_nlink == 0) { 492 assert(!test_cflag(COMMIT_Nolink, ip)); 493 /* free block resources */ 494 if ((new_size = commitZeroLink(tid, ip)) < 0) { 495 txAbort(tid, 1); /* Marks FS Dirty */ 496 txEnd(tid); 497 up(&JFS_IP(dip)->commit_sem); 498 up(&JFS_IP(ip)->commit_sem); 499 IWRITE_UNLOCK(ip); 500 rc = new_size; 501 goto out1; 502 } 503 tblk = tid_to_tblock(tid); 504 tblk->xflag |= COMMIT_DELETE; 505 tblk->u.ip = ip; 506 } 507 508 /* 509 * Incomplete truncate of file data can 510 * result in timing problems unless we synchronously commit the 511 * transaction. 512 */ 513 if (new_size) 514 commit_flag = COMMIT_SYNC; 515 else 516 commit_flag = 0; 517 518 /* 519 * If xtTruncate was incomplete, commit synchronously to avoid 520 * timing complications 521 */ 522 rc = txCommit(tid, 2, &iplist[0], commit_flag); 523 524 txEnd(tid); 525 526 up(&JFS_IP(dip)->commit_sem); 527 up(&JFS_IP(ip)->commit_sem); 528 529 530 while (new_size && (rc == 0)) { 531 tid = txBegin(dip->i_sb, 0); 532 down(&JFS_IP(ip)->commit_sem); 533 new_size = xtTruncate_pmap(tid, ip, new_size); 534 if (new_size < 0) { 535 txAbort(tid, 1); /* Marks FS Dirty */ 536 rc = new_size; 537 } else 538 rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC); 539 txEnd(tid); 540 up(&JFS_IP(ip)->commit_sem); 541 } 542 543 if (ip->i_nlink == 0) 544 set_cflag(COMMIT_Nolink, ip); 545 546 IWRITE_UNLOCK(ip); 547 548 /* 549 * Truncating the directory index table is not guaranteed. It 550 * may need to be done iteratively 551 */ 552 if (test_cflag(COMMIT_Stale, dip)) { 553 if (dip->i_size > 1) 554 jfs_truncate_nolock(dip, 0); 555 556 clear_cflag(COMMIT_Stale, dip); 557 } 558 559 out1: 560 free_UCSname(&dname); 561 out: 562 jfs_info("jfs_unlink: rc:%d", rc); 563 return rc; 564 } 565 566 /* 567 * NAME: commitZeroLink() 568 * 569 * FUNCTION: for non-directory, called by jfs_remove(), 570 * truncate a regular file, directory or symbolic 571 * link to zero length. return 0 if type is not 572 * one of these. 573 * 574 * if the file is currently associated with a VM segment 575 * only permanent disk and inode map resources are freed, 576 * and neither the inode nor indirect blocks are modified 577 * so that the resources can be later freed in the work 578 * map by ctrunc1. 579 * if there is no VM segment on entry, the resources are 580 * freed in both work and permanent map. 581 * (? for temporary file - memory object is cached even 582 * after no reference: 583 * reference count > 0 - ) 584 * 585 * PARAMETERS: cd - pointer to commit data structure. 586 * current inode is the one to truncate. 587 * 588 * RETURN: Errors from subroutines 589 */ 590 static s64 commitZeroLink(tid_t tid, struct inode *ip) 591 { 592 int filetype; 593 struct tblock *tblk; 594 595 jfs_info("commitZeroLink: tid = %d, ip = 0x%p", tid, ip); 596 597 filetype = ip->i_mode & S_IFMT; 598 switch (filetype) { 599 case S_IFREG: 600 break; 601 case S_IFLNK: 602 /* fast symbolic link */ 603 if (ip->i_size < IDATASIZE) { 604 ip->i_size = 0; 605 return 0; 606 } 607 break; 608 default: 609 assert(filetype != S_IFDIR); 610 return 0; 611 } 612 613 set_cflag(COMMIT_Freewmap, ip); 614 615 /* mark transaction of block map update type */ 616 tblk = tid_to_tblock(tid); 617 tblk->xflag |= COMMIT_PMAP; 618 619 /* 620 * free EA 621 */ 622 if (JFS_IP(ip)->ea.flag & DXD_EXTENT) 623 /* acquire maplock on EA to be freed from block map */ 624 txEA(tid, ip, &JFS_IP(ip)->ea, NULL); 625 626 /* 627 * free ACL 628 */ 629 if (JFS_IP(ip)->acl.flag & DXD_EXTENT) 630 /* acquire maplock on EA to be freed from block map */ 631 txEA(tid, ip, &JFS_IP(ip)->acl, NULL); 632 633 /* 634 * free xtree/data (truncate to zero length): 635 * free xtree/data pages from cache if COMMIT_PWMAP, 636 * free xtree/data blocks from persistent block map, and 637 * free xtree/data blocks from working block map if COMMIT_PWMAP; 638 */ 639 if (ip->i_size) 640 return xtTruncate_pmap(tid, ip, 0); 641 642 return 0; 643 } 644 645 646 /* 647 * NAME: jfs_free_zero_link() 648 * 649 * FUNCTION: for non-directory, called by iClose(), 650 * free resources of a file from cache and WORKING map 651 * for a file previously committed with zero link count 652 * while associated with a pager object, 653 * 654 * PARAMETER: ip - pointer to inode of file. 655 */ 656 void jfs_free_zero_link(struct inode *ip) 657 { 658 int type; 659 660 jfs_info("jfs_free_zero_link: ip = 0x%p", ip); 661 662 /* return if not reg or symbolic link or if size is 663 * already ok. 664 */ 665 type = ip->i_mode & S_IFMT; 666 667 switch (type) { 668 case S_IFREG: 669 break; 670 case S_IFLNK: 671 /* if its contained in inode nothing to do */ 672 if (ip->i_size < IDATASIZE) 673 return; 674 break; 675 default: 676 return; 677 } 678 679 /* 680 * free EA 681 */ 682 if (JFS_IP(ip)->ea.flag & DXD_EXTENT) { 683 s64 xaddr = addressDXD(&JFS_IP(ip)->ea); 684 int xlen = lengthDXD(&JFS_IP(ip)->ea); 685 struct maplock maplock; /* maplock for COMMIT_WMAP */ 686 struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */ 687 688 /* free EA pages from cache */ 689 invalidate_dxd_metapages(ip, JFS_IP(ip)->ea); 690 691 /* free EA extent from working block map */ 692 maplock.index = 1; 693 pxdlock = (struct pxd_lock *) & maplock; 694 pxdlock->flag = mlckFREEPXD; 695 PXDaddress(&pxdlock->pxd, xaddr); 696 PXDlength(&pxdlock->pxd, xlen); 697 txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); 698 } 699 700 /* 701 * free ACL 702 */ 703 if (JFS_IP(ip)->acl.flag & DXD_EXTENT) { 704 s64 xaddr = addressDXD(&JFS_IP(ip)->acl); 705 int xlen = lengthDXD(&JFS_IP(ip)->acl); 706 struct maplock maplock; /* maplock for COMMIT_WMAP */ 707 struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */ 708 709 invalidate_dxd_metapages(ip, JFS_IP(ip)->acl); 710 711 /* free ACL extent from working block map */ 712 maplock.index = 1; 713 pxdlock = (struct pxd_lock *) & maplock; 714 pxdlock->flag = mlckFREEPXD; 715 PXDaddress(&pxdlock->pxd, xaddr); 716 PXDlength(&pxdlock->pxd, xlen); 717 txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); 718 } 719 720 /* 721 * free xtree/data (truncate to zero length): 722 * free xtree/data pages from cache, and 723 * free xtree/data blocks from working block map; 724 */ 725 if (ip->i_size) 726 xtTruncate(0, ip, 0, COMMIT_WMAP); 727 } 728 729 /* 730 * NAME: jfs_link(vp, dvp, name, crp) 731 * 732 * FUNCTION: create a link to <vp> by the name = <name> 733 * in the parent directory <dvp> 734 * 735 * PARAMETER: vp - target object 736 * dvp - parent directory of new link 737 * name - name of new link to target object 738 * crp - credential 739 * 740 * RETURN: Errors from subroutines 741 * 742 * note: 743 * JFS does NOT support link() on directories (to prevent circular 744 * path in the directory hierarchy); 745 * EPERM: the target object is a directory, and either the caller 746 * does not have appropriate privileges or the implementation prohibits 747 * using link() on directories [XPG4.2]. 748 * 749 * JFS does NOT support links between file systems: 750 * EXDEV: target object and new link are on different file systems and 751 * implementation does not support links between file systems [XPG4.2]. 752 */ 753 static int jfs_link(struct dentry *old_dentry, 754 struct inode *dir, struct dentry *dentry) 755 { 756 int rc; 757 tid_t tid; 758 struct inode *ip = old_dentry->d_inode; 759 ino_t ino; 760 struct component_name dname; 761 struct btstack btstack; 762 struct inode *iplist[2]; 763 764 jfs_info("jfs_link: %s %s", old_dentry->d_name.name, 765 dentry->d_name.name); 766 767 if (ip->i_nlink == JFS_LINK_MAX) 768 return -EMLINK; 769 770 if (ip->i_nlink == 0) 771 return -ENOENT; 772 773 tid = txBegin(ip->i_sb, 0); 774 775 down(&JFS_IP(dir)->commit_sem); 776 down(&JFS_IP(ip)->commit_sem); 777 778 /* 779 * scan parent directory for entry/freespace 780 */ 781 if ((rc = get_UCSname(&dname, dentry))) 782 goto out; 783 784 if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) 785 goto free_dname; 786 787 /* 788 * create entry for new link in parent directory 789 */ 790 ino = ip->i_ino; 791 if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) 792 goto free_dname; 793 794 /* update object inode */ 795 ip->i_nlink++; /* for new link */ 796 ip->i_ctime = CURRENT_TIME; 797 mark_inode_dirty(dir); 798 atomic_inc(&ip->i_count); 799 800 iplist[0] = ip; 801 iplist[1] = dir; 802 rc = txCommit(tid, 2, &iplist[0], 0); 803 804 if (rc) { 805 ip->i_nlink--; 806 iput(ip); 807 } else 808 d_instantiate(dentry, ip); 809 810 free_dname: 811 free_UCSname(&dname); 812 813 out: 814 txEnd(tid); 815 816 up(&JFS_IP(dir)->commit_sem); 817 up(&JFS_IP(ip)->commit_sem); 818 819 jfs_info("jfs_link: rc:%d", rc); 820 return rc; 821 } 822 823 /* 824 * NAME: jfs_symlink(dip, dentry, name) 825 * 826 * FUNCTION: creates a symbolic link to <symlink> by name <name> 827 * in directory <dip> 828 * 829 * PARAMETER: dip - parent directory vnode 830 * dentry - dentry of symbolic link 831 * name - the path name of the existing object 832 * that will be the source of the link 833 * 834 * RETURN: errors from subroutines 835 * 836 * note: 837 * ENAMETOOLONG: pathname resolution of a symbolic link produced 838 * an intermediate result whose length exceeds PATH_MAX [XPG4.2] 839 */ 840 841 static int jfs_symlink(struct inode *dip, struct dentry *dentry, 842 const char *name) 843 { 844 int rc; 845 tid_t tid; 846 ino_t ino = 0; 847 struct component_name dname; 848 int ssize; /* source pathname size */ 849 struct btstack btstack; 850 struct inode *ip = dentry->d_inode; 851 unchar *i_fastsymlink; 852 s64 xlen = 0; 853 int bmask = 0, xsize; 854 s64 extent = 0, xaddr; 855 struct metapage *mp; 856 struct super_block *sb; 857 struct tblock *tblk; 858 859 struct inode *iplist[2]; 860 861 jfs_info("jfs_symlink: dip:0x%p name:%s", dip, name); 862 863 ssize = strlen(name) + 1; 864 865 /* 866 * search parent directory for entry/freespace 867 * (dtSearch() returns parent directory page pinned) 868 */ 869 870 if ((rc = get_UCSname(&dname, dentry))) 871 goto out1; 872 873 /* 874 * allocate on-disk/in-memory inode for symbolic link: 875 * (iAlloc() returns new, locked inode) 876 */ 877 ip = ialloc(dip, S_IFLNK | 0777); 878 if (ip == NULL) { 879 rc = -ENOSPC; 880 goto out2; 881 } 882 883 tid = txBegin(dip->i_sb, 0); 884 885 down(&JFS_IP(dip)->commit_sem); 886 down(&JFS_IP(ip)->commit_sem); 887 888 tblk = tid_to_tblock(tid); 889 tblk->xflag |= COMMIT_CREATE; 890 tblk->ino = ip->i_ino; 891 tblk->u.ixpxd = JFS_IP(ip)->ixpxd; 892 893 /* fix symlink access permission 894 * (dir_create() ANDs in the u.u_cmask, 895 * but symlinks really need to be 777 access) 896 */ 897 ip->i_mode |= 0777; 898 899 /* 900 * write symbolic link target path name 901 */ 902 xtInitRoot(tid, ip); 903 904 /* 905 * write source path name inline in on-disk inode (fast symbolic link) 906 */ 907 908 if (ssize <= IDATASIZE) { 909 ip->i_op = &jfs_symlink_inode_operations; 910 911 i_fastsymlink = JFS_IP(ip)->i_inline; 912 memcpy(i_fastsymlink, name, ssize); 913 ip->i_size = ssize - 1; 914 915 /* 916 * if symlink is > 128 bytes, we don't have the space to 917 * store inline extended attributes 918 */ 919 if (ssize > sizeof (JFS_IP(ip)->i_inline)) 920 JFS_IP(ip)->mode2 &= ~INLINEEA; 921 922 jfs_info("jfs_symlink: fast symlink added ssize:%d name:%s ", 923 ssize, name); 924 } 925 /* 926 * write source path name in a single extent 927 */ 928 else { 929 jfs_info("jfs_symlink: allocate extent ip:0x%p", ip); 930 931 ip->i_op = &page_symlink_inode_operations; 932 ip->i_mapping->a_ops = &jfs_aops; 933 934 /* 935 * even though the data of symlink object (source 936 * path name) is treated as non-journaled user data, 937 * it is read/written thru buffer cache for performance. 938 */ 939 sb = ip->i_sb; 940 bmask = JFS_SBI(sb)->bsize - 1; 941 xsize = (ssize + bmask) & ~bmask; 942 xaddr = 0; 943 xlen = xsize >> JFS_SBI(sb)->l2bsize; 944 if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) { 945 txAbort(tid, 0); 946 rc = -ENOSPC; 947 goto out3; 948 } 949 extent = xaddr; 950 ip->i_size = ssize - 1; 951 while (ssize) { 952 /* This is kind of silly since PATH_MAX == 4K */ 953 int copy_size = min(ssize, PSIZE); 954 955 mp = get_metapage(ip, xaddr, PSIZE, 1); 956 957 if (mp == NULL) { 958 xtTruncate(tid, ip, 0, COMMIT_PWMAP); 959 rc = -EIO; 960 txAbort(tid, 0); 961 goto out3; 962 } 963 memcpy(mp->data, name, copy_size); 964 flush_metapage(mp); 965 ssize -= copy_size; 966 name += copy_size; 967 xaddr += JFS_SBI(sb)->nbperpage; 968 } 969 } 970 971 /* 972 * create entry for symbolic link in parent directory 973 */ 974 rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE); 975 if (rc == 0) { 976 ino = ip->i_ino; 977 rc = dtInsert(tid, dip, &dname, &ino, &btstack); 978 } 979 if (rc) { 980 if (xlen) 981 xtTruncate(tid, ip, 0, COMMIT_PWMAP); 982 txAbort(tid, 0); 983 /* discard new inode */ 984 goto out3; 985 } 986 987 insert_inode_hash(ip); 988 mark_inode_dirty(ip); 989 990 /* 991 * commit update of parent directory and link object 992 */ 993 994 iplist[0] = dip; 995 iplist[1] = ip; 996 rc = txCommit(tid, 2, &iplist[0], 0); 997 998 out3: 999 txEnd(tid); 1000 up(&JFS_IP(dip)->commit_sem); 1001 up(&JFS_IP(ip)->commit_sem); 1002 if (rc) { 1003 ip->i_nlink = 0; 1004 iput(ip); 1005 } else 1006 d_instantiate(dentry, ip); 1007 1008 out2: 1009 free_UCSname(&dname); 1010 1011 #ifdef CONFIG_JFS_POSIX_ACL 1012 if (rc == 0) 1013 jfs_init_acl(ip, dip); 1014 #endif 1015 1016 out1: 1017 jfs_info("jfs_symlink: rc:%d", rc); 1018 return rc; 1019 } 1020 1021 1022 /* 1023 * NAME: jfs_rename 1024 * 1025 * FUNCTION: rename a file or directory 1026 */ 1027 static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, 1028 struct inode *new_dir, struct dentry *new_dentry) 1029 { 1030 struct btstack btstack; 1031 ino_t ino; 1032 struct component_name new_dname; 1033 struct inode *new_ip; 1034 struct component_name old_dname; 1035 struct inode *old_ip; 1036 int rc; 1037 tid_t tid; 1038 struct tlock *tlck; 1039 struct dt_lock *dtlck; 1040 struct lv *lv; 1041 int ipcount; 1042 struct inode *iplist[4]; 1043 struct tblock *tblk; 1044 s64 new_size = 0; 1045 int commit_flag; 1046 1047 1048 jfs_info("jfs_rename: %s %s", old_dentry->d_name.name, 1049 new_dentry->d_name.name); 1050 1051 old_ip = old_dentry->d_inode; 1052 new_ip = new_dentry->d_inode; 1053 1054 if ((rc = get_UCSname(&old_dname, old_dentry))) 1055 goto out1; 1056 1057 if ((rc = get_UCSname(&new_dname, new_dentry))) 1058 goto out2; 1059 1060 /* 1061 * Make sure source inode number is what we think it is 1062 */ 1063 rc = dtSearch(old_dir, &old_dname, &ino, &btstack, JFS_LOOKUP); 1064 if (rc || (ino != old_ip->i_ino)) { 1065 rc = -ENOENT; 1066 goto out3; 1067 } 1068 1069 /* 1070 * Make sure dest inode number (if any) is what we think it is 1071 */ 1072 rc = dtSearch(new_dir, &new_dname, &ino, &btstack, JFS_LOOKUP); 1073 if (rc == 0) { 1074 if ((new_ip == 0) || (ino != new_ip->i_ino)) { 1075 rc = -ESTALE; 1076 goto out3; 1077 } 1078 } else if (rc != -ENOENT) 1079 goto out3; 1080 else if (new_ip) { 1081 /* no entry exists, but one was expected */ 1082 rc = -ESTALE; 1083 goto out3; 1084 } 1085 1086 if (S_ISDIR(old_ip->i_mode)) { 1087 if (new_ip) { 1088 if (!dtEmpty(new_ip)) { 1089 rc = -ENOTEMPTY; 1090 goto out3; 1091 } 1092 } else if ((new_dir != old_dir) && 1093 (new_dir->i_nlink == JFS_LINK_MAX)) { 1094 rc = -EMLINK; 1095 goto out3; 1096 } 1097 } else if (new_ip) { 1098 IWRITE_LOCK(new_ip); 1099 /* Init inode for quota operations. */ 1100 DQUOT_INIT(new_ip); 1101 } 1102 1103 /* 1104 * The real work starts here 1105 */ 1106 tid = txBegin(new_dir->i_sb, 0); 1107 1108 down(&JFS_IP(new_dir)->commit_sem); 1109 down(&JFS_IP(old_ip)->commit_sem); 1110 if (old_dir != new_dir) 1111 down(&JFS_IP(old_dir)->commit_sem); 1112 1113 if (new_ip) { 1114 down(&JFS_IP(new_ip)->commit_sem); 1115 /* 1116 * Change existing directory entry to new inode number 1117 */ 1118 ino = new_ip->i_ino; 1119 rc = dtModify(tid, new_dir, &new_dname, &ino, 1120 old_ip->i_ino, JFS_RENAME); 1121 if (rc) 1122 goto out4; 1123 new_ip->i_nlink--; 1124 if (S_ISDIR(new_ip->i_mode)) { 1125 new_ip->i_nlink--; 1126 if (new_ip->i_nlink) { 1127 up(&JFS_IP(new_dir)->commit_sem); 1128 up(&JFS_IP(old_ip)->commit_sem); 1129 if (old_dir != new_dir) 1130 up(&JFS_IP(old_dir)->commit_sem); 1131 if (!S_ISDIR(old_ip->i_mode) && new_ip) 1132 IWRITE_UNLOCK(new_ip); 1133 jfs_error(new_ip->i_sb, 1134 "jfs_rename: new_ip->i_nlink != 0"); 1135 return -EIO; 1136 } 1137 tblk = tid_to_tblock(tid); 1138 tblk->xflag |= COMMIT_DELETE; 1139 tblk->u.ip = new_ip; 1140 } else if (new_ip->i_nlink == 0) { 1141 assert(!test_cflag(COMMIT_Nolink, new_ip)); 1142 /* free block resources */ 1143 if ((new_size = commitZeroLink(tid, new_ip)) < 0) { 1144 txAbort(tid, 1); /* Marks FS Dirty */ 1145 rc = new_size; 1146 goto out4; 1147 } 1148 tblk = tid_to_tblock(tid); 1149 tblk->xflag |= COMMIT_DELETE; 1150 tblk->u.ip = new_ip; 1151 } else { 1152 new_ip->i_ctime = CURRENT_TIME; 1153 mark_inode_dirty(new_ip); 1154 } 1155 } else { 1156 /* 1157 * Add new directory entry 1158 */ 1159 rc = dtSearch(new_dir, &new_dname, &ino, &btstack, 1160 JFS_CREATE); 1161 if (rc) { 1162 jfs_err("jfs_rename didn't expect dtSearch to fail " 1163 "w/rc = %d", rc); 1164 goto out4; 1165 } 1166 1167 ino = old_ip->i_ino; 1168 rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack); 1169 if (rc) { 1170 if (rc == -EIO) 1171 jfs_err("jfs_rename: dtInsert returned -EIO"); 1172 goto out4; 1173 } 1174 if (S_ISDIR(old_ip->i_mode)) 1175 new_dir->i_nlink++; 1176 } 1177 /* 1178 * Remove old directory entry 1179 */ 1180 1181 ino = old_ip->i_ino; 1182 rc = dtDelete(tid, old_dir, &old_dname, &ino, JFS_REMOVE); 1183 if (rc) { 1184 jfs_err("jfs_rename did not expect dtDelete to return rc = %d", 1185 rc); 1186 txAbort(tid, 1); /* Marks Filesystem dirty */ 1187 goto out4; 1188 } 1189 if (S_ISDIR(old_ip->i_mode)) { 1190 old_dir->i_nlink--; 1191 if (old_dir != new_dir) { 1192 /* 1193 * Change inode number of parent for moved directory 1194 */ 1195 1196 JFS_IP(old_ip)->i_dtroot.header.idotdot = 1197 cpu_to_le32(new_dir->i_ino); 1198 1199 /* Linelock header of dtree */ 1200 tlck = txLock(tid, old_ip, 1201 (struct metapage *) &JFS_IP(old_ip)->bxflag, 1202 tlckDTREE | tlckBTROOT | tlckRELINK); 1203 dtlck = (struct dt_lock *) & tlck->lock; 1204 ASSERT(dtlck->index == 0); 1205 lv = & dtlck->lv[0]; 1206 lv->offset = 0; 1207 lv->length = 1; 1208 dtlck->index++; 1209 } 1210 } 1211 1212 /* 1213 * Update ctime on changed/moved inodes & mark dirty 1214 */ 1215 old_ip->i_ctime = CURRENT_TIME; 1216 mark_inode_dirty(old_ip); 1217 1218 new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb); 1219 mark_inode_dirty(new_dir); 1220 1221 /* Build list of inodes modified by this transaction */ 1222 ipcount = 0; 1223 iplist[ipcount++] = old_ip; 1224 if (new_ip) 1225 iplist[ipcount++] = new_ip; 1226 iplist[ipcount++] = old_dir; 1227 1228 if (old_dir != new_dir) { 1229 iplist[ipcount++] = new_dir; 1230 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; 1231 mark_inode_dirty(old_dir); 1232 } 1233 1234 /* 1235 * Incomplete truncate of file data can 1236 * result in timing problems unless we synchronously commit the 1237 * transaction. 1238 */ 1239 if (new_size) 1240 commit_flag = COMMIT_SYNC; 1241 else 1242 commit_flag = 0; 1243 1244 rc = txCommit(tid, ipcount, iplist, commit_flag); 1245 1246 out4: 1247 txEnd(tid); 1248 1249 up(&JFS_IP(new_dir)->commit_sem); 1250 up(&JFS_IP(old_ip)->commit_sem); 1251 if (old_dir != new_dir) 1252 up(&JFS_IP(old_dir)->commit_sem); 1253 if (new_ip) 1254 up(&JFS_IP(new_ip)->commit_sem); 1255 1256 while (new_size && (rc == 0)) { 1257 tid = txBegin(new_ip->i_sb, 0); 1258 down(&JFS_IP(new_ip)->commit_sem); 1259 new_size = xtTruncate_pmap(tid, new_ip, new_size); 1260 if (new_size < 0) { 1261 txAbort(tid, 1); 1262 rc = new_size; 1263 } else 1264 rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC); 1265 txEnd(tid); 1266 up(&JFS_IP(new_ip)->commit_sem); 1267 } 1268 if (new_ip && (new_ip->i_nlink == 0)) 1269 set_cflag(COMMIT_Nolink, new_ip); 1270 out3: 1271 free_UCSname(&new_dname); 1272 out2: 1273 free_UCSname(&old_dname); 1274 out1: 1275 if (new_ip && !S_ISDIR(new_ip->i_mode)) 1276 IWRITE_UNLOCK(new_ip); 1277 /* 1278 * Truncating the directory index table is not guaranteed. It 1279 * may need to be done iteratively 1280 */ 1281 if (test_cflag(COMMIT_Stale, old_dir)) { 1282 if (old_dir->i_size > 1) 1283 jfs_truncate_nolock(old_dir, 0); 1284 1285 clear_cflag(COMMIT_Stale, old_dir); 1286 } 1287 1288 jfs_info("jfs_rename: returning %d", rc); 1289 return rc; 1290 } 1291 1292 1293 /* 1294 * NAME: jfs_mknod 1295 * 1296 * FUNCTION: Create a special file (device) 1297 */ 1298 static int jfs_mknod(struct inode *dir, struct dentry *dentry, 1299 int mode, dev_t rdev) 1300 { 1301 struct jfs_inode_info *jfs_ip; 1302 struct btstack btstack; 1303 struct component_name dname; 1304 ino_t ino; 1305 struct inode *ip; 1306 struct inode *iplist[2]; 1307 int rc; 1308 tid_t tid; 1309 struct tblock *tblk; 1310 1311 if (!new_valid_dev(rdev)) 1312 return -EINVAL; 1313 1314 jfs_info("jfs_mknod: %s", dentry->d_name.name); 1315 1316 if ((rc = get_UCSname(&dname, dentry))) 1317 goto out; 1318 1319 ip = ialloc(dir, mode); 1320 if (ip == NULL) { 1321 rc = -ENOSPC; 1322 goto out1; 1323 } 1324 jfs_ip = JFS_IP(ip); 1325 1326 tid = txBegin(dir->i_sb, 0); 1327 1328 down(&JFS_IP(dir)->commit_sem); 1329 down(&JFS_IP(ip)->commit_sem); 1330 1331 if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) 1332 goto out3; 1333 1334 tblk = tid_to_tblock(tid); 1335 tblk->xflag |= COMMIT_CREATE; 1336 tblk->ino = ip->i_ino; 1337 tblk->u.ixpxd = JFS_IP(ip)->ixpxd; 1338 1339 ino = ip->i_ino; 1340 if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) 1341 goto out3; 1342 1343 ip->i_op = &jfs_file_inode_operations; 1344 jfs_ip->dev = new_encode_dev(rdev); 1345 init_special_inode(ip, ip->i_mode, rdev); 1346 1347 insert_inode_hash(ip); 1348 mark_inode_dirty(ip); 1349 1350 dir->i_ctime = dir->i_mtime = CURRENT_TIME; 1351 1352 mark_inode_dirty(dir); 1353 1354 iplist[0] = dir; 1355 iplist[1] = ip; 1356 rc = txCommit(tid, 2, iplist, 0); 1357 1358 out3: 1359 txEnd(tid); 1360 up(&JFS_IP(ip)->commit_sem); 1361 up(&JFS_IP(dir)->commit_sem); 1362 if (rc) { 1363 ip->i_nlink = 0; 1364 iput(ip); 1365 } else 1366 d_instantiate(dentry, ip); 1367 1368 out1: 1369 free_UCSname(&dname); 1370 1371 #ifdef CONFIG_JFS_POSIX_ACL 1372 if (rc == 0) 1373 jfs_init_acl(ip, dir); 1374 #endif 1375 1376 out: 1377 jfs_info("jfs_mknod: returning %d", rc); 1378 return rc; 1379 } 1380 1381 static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd) 1382 { 1383 struct btstack btstack; 1384 ino_t inum; 1385 struct inode *ip; 1386 struct component_name key; 1387 const char *name = dentry->d_name.name; 1388 int len = dentry->d_name.len; 1389 int rc; 1390 1391 jfs_info("jfs_lookup: name = %s", name); 1392 1393 if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2) 1394 dentry->d_op = &jfs_ci_dentry_operations; 1395 1396 if ((name[0] == '.') && (len == 1)) 1397 inum = dip->i_ino; 1398 else if (strcmp(name, "..") == 0) 1399 inum = PARENT(dip); 1400 else { 1401 if ((rc = get_UCSname(&key, dentry))) 1402 return ERR_PTR(rc); 1403 rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP); 1404 free_UCSname(&key); 1405 if (rc == -ENOENT) { 1406 d_add(dentry, NULL); 1407 return ERR_PTR(0); 1408 } else if (rc) { 1409 jfs_err("jfs_lookup: dtSearch returned %d", rc); 1410 return ERR_PTR(rc); 1411 } 1412 } 1413 1414 ip = iget(dip->i_sb, inum); 1415 if (ip == NULL || is_bad_inode(ip)) { 1416 jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum); 1417 if (ip) 1418 iput(ip); 1419 return ERR_PTR(-EACCES); 1420 } 1421 1422 dentry = d_splice_alias(ip, dentry); 1423 1424 if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)) 1425 dentry->d_op = &jfs_ci_dentry_operations; 1426 1427 return dentry; 1428 } 1429 1430 struct dentry *jfs_get_parent(struct dentry *dentry) 1431 { 1432 struct super_block *sb = dentry->d_inode->i_sb; 1433 struct dentry *parent = ERR_PTR(-ENOENT); 1434 struct inode *inode; 1435 unsigned long parent_ino; 1436 1437 parent_ino = 1438 le32_to_cpu(JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot); 1439 inode = iget(sb, parent_ino); 1440 if (inode) { 1441 if (is_bad_inode(inode)) { 1442 iput(inode); 1443 parent = ERR_PTR(-EACCES); 1444 } else { 1445 parent = d_alloc_anon(inode); 1446 if (!parent) { 1447 parent = ERR_PTR(-ENOMEM); 1448 iput(inode); 1449 } 1450 } 1451 } 1452 1453 return parent; 1454 } 1455 1456 struct inode_operations jfs_dir_inode_operations = { 1457 .create = jfs_create, 1458 .lookup = jfs_lookup, 1459 .link = jfs_link, 1460 .unlink = jfs_unlink, 1461 .symlink = jfs_symlink, 1462 .mkdir = jfs_mkdir, 1463 .rmdir = jfs_rmdir, 1464 .mknod = jfs_mknod, 1465 .rename = jfs_rename, 1466 .setxattr = jfs_setxattr, 1467 .getxattr = jfs_getxattr, 1468 .listxattr = jfs_listxattr, 1469 .removexattr = jfs_removexattr, 1470 #ifdef CONFIG_JFS_POSIX_ACL 1471 .setattr = jfs_setattr, 1472 .permission = jfs_permission, 1473 #endif 1474 }; 1475 1476 struct file_operations jfs_dir_operations = { 1477 .read = generic_read_dir, 1478 .readdir = jfs_readdir, 1479 .fsync = jfs_fsync, 1480 }; 1481 1482 static int jfs_ci_hash(struct dentry *dir, struct qstr *this) 1483 { 1484 unsigned long hash; 1485 int i; 1486 1487 hash = init_name_hash(); 1488 for (i=0; i < this->len; i++) 1489 hash = partial_name_hash(tolower(this->name[i]), hash); 1490 this->hash = end_name_hash(hash); 1491 1492 return 0; 1493 } 1494 1495 static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b) 1496 { 1497 int i, result = 1; 1498 1499 if (a->len != b->len) 1500 goto out; 1501 for (i=0; i < a->len; i++) { 1502 if (tolower(a->name[i]) != tolower(b->name[i])) 1503 goto out; 1504 } 1505 result = 0; 1506 1507 /* 1508 * We want creates to preserve case. A negative dentry, a, that 1509 * has a different case than b may cause a new entry to be created 1510 * with the wrong case. Since we can't tell if a comes from a negative 1511 * dentry, we blindly replace it with b. This should be harmless if 1512 * a is not a negative dentry. 1513 */ 1514 memcpy((unsigned char *)a->name, b->name, a->len); 1515 out: 1516 return result; 1517 } 1518 1519 struct dentry_operations jfs_ci_dentry_operations = 1520 { 1521 .d_hash = jfs_ci_hash, 1522 .d_compare = jfs_ci_compare, 1523 }; 1524