diff options
Diffstat (limited to 'fs/ncpfs/dir.c')
| -rw-r--r-- | fs/ncpfs/dir.c | 221 |
1 files changed, 129 insertions, 92 deletions
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 9578cbe0cd58..aac8832e919e 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
| @@ -95,6 +95,34 @@ const struct dentry_operations ncp_root_dentry_operations = | |||
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | 97 | ||
| 98 | #define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber]) | ||
| 99 | |||
| 100 | static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator) | ||
| 101 | { | ||
| 102 | #ifdef CONFIG_NCPFS_SMALLDOS | ||
| 103 | int ns = ncp_namespace(i); | ||
| 104 | |||
| 105 | if ((ns == NW_NS_DOS) | ||
| 106 | #ifdef CONFIG_NCPFS_OS2_NS | ||
| 107 | || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS)) | ||
| 108 | #endif /* CONFIG_NCPFS_OS2_NS */ | ||
| 109 | ) | ||
| 110 | return 0; | ||
| 111 | #endif /* CONFIG_NCPFS_SMALLDOS */ | ||
| 112 | return 1; | ||
| 113 | } | ||
| 114 | |||
| 115 | #define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS) | ||
| 116 | |||
| 117 | static inline int ncp_case_sensitive(struct dentry *dentry) | ||
| 118 | { | ||
| 119 | #ifdef CONFIG_NCPFS_NFS_NS | ||
| 120 | return ncp_namespace(dentry->d_inode) == NW_NS_NFS; | ||
| 121 | #else | ||
| 122 | return 0; | ||
| 123 | #endif /* CONFIG_NCPFS_NFS_NS */ | ||
| 124 | } | ||
| 125 | |||
| 98 | /* | 126 | /* |
| 99 | * Note: leave the hash unchanged if the directory | 127 | * Note: leave the hash unchanged if the directory |
| 100 | * is case-sensitive. | 128 | * is case-sensitive. |
| @@ -102,13 +130,12 @@ const struct dentry_operations ncp_root_dentry_operations = | |||
| 102 | static int | 130 | static int |
| 103 | ncp_hash_dentry(struct dentry *dentry, struct qstr *this) | 131 | ncp_hash_dentry(struct dentry *dentry, struct qstr *this) |
| 104 | { | 132 | { |
| 105 | struct nls_table *t; | 133 | if (!ncp_case_sensitive(dentry)) { |
| 106 | unsigned long hash; | 134 | struct nls_table *t; |
| 107 | int i; | 135 | unsigned long hash; |
| 108 | 136 | int i; | |
| 109 | t = NCP_IO_TABLE(dentry); | ||
| 110 | 137 | ||
| 111 | if (!ncp_case_sensitive(dentry->d_inode)) { | 138 | t = NCP_IO_TABLE(dentry); |
| 112 | hash = init_name_hash(); | 139 | hash = init_name_hash(); |
| 113 | for (i=0; i<this->len ; i++) | 140 | for (i=0; i<this->len ; i++) |
| 114 | hash = partial_name_hash(ncp_tolower(t, this->name[i]), | 141 | hash = partial_name_hash(ncp_tolower(t, this->name[i]), |
| @@ -124,7 +151,7 @@ ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) | |||
| 124 | if (a->len != b->len) | 151 | if (a->len != b->len) |
| 125 | return 1; | 152 | return 1; |
| 126 | 153 | ||
| 127 | if (ncp_case_sensitive(dentry->d_inode)) | 154 | if (ncp_case_sensitive(dentry)) |
| 128 | return strncmp(a->name, b->name, a->len); | 155 | return strncmp(a->name, b->name, a->len); |
| 129 | 156 | ||
| 130 | return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len); | 157 | return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len); |
| @@ -266,7 +293,7 @@ leave_me:; | |||
| 266 | 293 | ||
| 267 | 294 | ||
| 268 | static int | 295 | static int |
| 269 | __ncp_lookup_validate(struct dentry *dentry) | 296 | ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd) |
| 270 | { | 297 | { |
| 271 | struct ncp_server *server; | 298 | struct ncp_server *server; |
| 272 | struct dentry *parent; | 299 | struct dentry *parent; |
| @@ -283,9 +310,6 @@ __ncp_lookup_validate(struct dentry *dentry) | |||
| 283 | 310 | ||
| 284 | server = NCP_SERVER(dir); | 311 | server = NCP_SERVER(dir); |
| 285 | 312 | ||
| 286 | if (!ncp_conn_valid(server)) | ||
| 287 | goto finished; | ||
| 288 | |||
| 289 | /* | 313 | /* |
| 290 | * Inspired by smbfs: | 314 | * Inspired by smbfs: |
| 291 | * The default validation is based on dentry age: | 315 | * The default validation is based on dentry age: |
| @@ -304,8 +328,11 @@ __ncp_lookup_validate(struct dentry *dentry) | |||
| 304 | if (ncp_is_server_root(dir)) { | 328 | if (ncp_is_server_root(dir)) { |
| 305 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 329 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
| 306 | dentry->d_name.len, 1); | 330 | dentry->d_name.len, 1); |
| 307 | if (!res) | 331 | if (!res) { |
| 308 | res = ncp_lookup_volume(server, __name, &(finfo.i)); | 332 | res = ncp_lookup_volume(server, __name, &(finfo.i)); |
| 333 | if (!res) | ||
| 334 | ncp_update_known_namespace(server, finfo.i.volNumber, NULL); | ||
| 335 | } | ||
| 309 | } else { | 336 | } else { |
| 310 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 337 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
| 311 | dentry->d_name.len, !ncp_preserve_case(dir)); | 338 | dentry->d_name.len, !ncp_preserve_case(dir)); |
| @@ -320,13 +347,17 @@ __ncp_lookup_validate(struct dentry *dentry) | |||
| 320 | * what we remember, it's not valid any more. | 347 | * what we remember, it's not valid any more. |
| 321 | */ | 348 | */ |
| 322 | if (!res) { | 349 | if (!res) { |
| 323 | if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) { | 350 | struct inode *inode = dentry->d_inode; |
| 351 | |||
| 352 | mutex_lock(&inode->i_mutex); | ||
| 353 | if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) { | ||
| 324 | ncp_new_dentry(dentry); | 354 | ncp_new_dentry(dentry); |
| 325 | val=1; | 355 | val=1; |
| 326 | } else | 356 | } else |
| 327 | DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n"); | 357 | DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n"); |
| 328 | 358 | ||
| 329 | ncp_update_inode2(dentry->d_inode, &finfo); | 359 | ncp_update_inode2(inode, &finfo); |
| 360 | mutex_unlock(&inode->i_mutex); | ||
| 330 | } | 361 | } |
| 331 | 362 | ||
| 332 | finished: | 363 | finished: |
| @@ -335,16 +366,6 @@ finished: | |||
| 335 | return val; | 366 | return val; |
| 336 | } | 367 | } |
| 337 | 368 | ||
| 338 | static int | ||
| 339 | ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd) | ||
| 340 | { | ||
| 341 | int res; | ||
| 342 | lock_kernel(); | ||
| 343 | res = __ncp_lookup_validate(dentry); | ||
| 344 | unlock_kernel(); | ||
| 345 | return res; | ||
| 346 | } | ||
| 347 | |||
| 348 | static struct dentry * | 369 | static struct dentry * |
| 349 | ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) | 370 | ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) |
| 350 | { | 371 | { |
| @@ -411,8 +432,6 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 411 | int result, mtime_valid = 0; | 432 | int result, mtime_valid = 0; |
| 412 | time_t mtime = 0; | 433 | time_t mtime = 0; |
| 413 | 434 | ||
| 414 | lock_kernel(); | ||
| 415 | |||
| 416 | ctl.page = NULL; | 435 | ctl.page = NULL; |
| 417 | ctl.cache = NULL; | 436 | ctl.cache = NULL; |
| 418 | 437 | ||
| @@ -421,6 +440,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 421 | (int) filp->f_pos); | 440 | (int) filp->f_pos); |
| 422 | 441 | ||
| 423 | result = -EIO; | 442 | result = -EIO; |
| 443 | /* Do not generate '.' and '..' when server is dead. */ | ||
| 424 | if (!ncp_conn_valid(server)) | 444 | if (!ncp_conn_valid(server)) |
| 425 | goto out; | 445 | goto out; |
| 426 | 446 | ||
| @@ -532,6 +552,12 @@ read_really: | |||
| 532 | ctl.head.end = ctl.fpos - 1; | 552 | ctl.head.end = ctl.fpos - 1; |
| 533 | ctl.head.eof = ctl.valid; | 553 | ctl.head.eof = ctl.valid; |
| 534 | finished: | 554 | finished: |
| 555 | if (ctl.page) { | ||
| 556 | kunmap(ctl.page); | ||
| 557 | SetPageUptodate(ctl.page); | ||
| 558 | unlock_page(ctl.page); | ||
| 559 | page_cache_release(ctl.page); | ||
| 560 | } | ||
| 535 | if (page) { | 561 | if (page) { |
| 536 | cache->head = ctl.head; | 562 | cache->head = ctl.head; |
| 537 | kunmap(page); | 563 | kunmap(page); |
| @@ -539,23 +565,17 @@ finished: | |||
| 539 | unlock_page(page); | 565 | unlock_page(page); |
| 540 | page_cache_release(page); | 566 | page_cache_release(page); |
| 541 | } | 567 | } |
| 542 | if (ctl.page) { | ||
| 543 | kunmap(ctl.page); | ||
| 544 | SetPageUptodate(ctl.page); | ||
| 545 | unlock_page(ctl.page); | ||
| 546 | page_cache_release(ctl.page); | ||
| 547 | } | ||
| 548 | out: | 568 | out: |
| 549 | unlock_kernel(); | ||
| 550 | return result; | 569 | return result; |
| 551 | } | 570 | } |
| 552 | 571 | ||
| 553 | static int | 572 | static int |
| 554 | ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 573 | ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
| 555 | struct ncp_cache_control *ctrl, struct ncp_entry_info *entry) | 574 | struct ncp_cache_control *ctrl, struct ncp_entry_info *entry, |
| 575 | int inval_childs) | ||
| 556 | { | 576 | { |
| 557 | struct dentry *newdent, *dentry = filp->f_path.dentry; | 577 | struct dentry *newdent, *dentry = filp->f_path.dentry; |
| 558 | struct inode *newino, *inode = dentry->d_inode; | 578 | struct inode *dir = dentry->d_inode; |
| 559 | struct ncp_cache_control ctl = *ctrl; | 579 | struct ncp_cache_control ctl = *ctrl; |
| 560 | struct qstr qname; | 580 | struct qstr qname; |
| 561 | int valid = 0; | 581 | int valid = 0; |
| @@ -564,9 +584,9 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | |||
| 564 | __u8 __name[NCP_MAXPATHLEN + 1]; | 584 | __u8 __name[NCP_MAXPATHLEN + 1]; |
| 565 | 585 | ||
| 566 | qname.len = sizeof(__name); | 586 | qname.len = sizeof(__name); |
| 567 | if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len, | 587 | if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len, |
| 568 | entry->i.entryName, entry->i.nameLen, | 588 | entry->i.entryName, entry->i.nameLen, |
| 569 | !ncp_preserve_entry_case(inode, entry->i.NSCreator))) | 589 | !ncp_preserve_entry_case(dir, entry->i.NSCreator))) |
| 570 | return 1; /* I'm not sure */ | 590 | return 1; /* I'm not sure */ |
| 571 | 591 | ||
| 572 | qname.name = __name; | 592 | qname.name = __name; |
| @@ -584,22 +604,64 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | |||
| 584 | goto end_advance; | 604 | goto end_advance; |
| 585 | } else { | 605 | } else { |
| 586 | hashed = 1; | 606 | hashed = 1; |
| 587 | memcpy((char *) newdent->d_name.name, qname.name, | 607 | |
| 588 | newdent->d_name.len); | 608 | /* If case sensitivity changed for this volume, all entries below this one |
| 609 | should be thrown away. This entry itself is not affected, as its case | ||
| 610 | sensitivity is controlled by its own parent. */ | ||
| 611 | if (inval_childs) | ||
| 612 | shrink_dcache_parent(newdent); | ||
| 613 | |||
| 614 | /* | ||
| 615 | * It is not as dangerous as it looks. NetWare's OS2 namespace is | ||
| 616 | * case preserving yet case insensitive. So we update dentry's name | ||
| 617 | * as received from server. We found dentry via d_lookup with our | ||
| 618 | * hash, so we know that hash does not change, and so replacing name | ||
| 619 | * should be reasonably safe. | ||
| 620 | */ | ||
| 621 | if (qname.len == newdent->d_name.len && | ||
| 622 | memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) { | ||
| 623 | struct inode *inode = newdent->d_inode; | ||
| 624 | |||
| 625 | /* | ||
| 626 | * Inside ncpfs all uses of d_name are either for debugging, | ||
| 627 | * or on functions which acquire inode mutex (mknod, creat, | ||
| 628 | * lookup). So grab i_mutex here, to be sure. d_path | ||
| 629 | * uses dcache_lock when generating path, so we should too. | ||
| 630 | * And finally d_compare is protected by dentry's d_lock, so | ||
| 631 | * here we go. | ||
| 632 | */ | ||
| 633 | if (inode) | ||
| 634 | mutex_lock(&inode->i_mutex); | ||
| 635 | spin_lock(&dcache_lock); | ||
| 636 | spin_lock(&newdent->d_lock); | ||
| 637 | memcpy((char *) newdent->d_name.name, qname.name, | ||
| 638 | newdent->d_name.len); | ||
| 639 | spin_unlock(&newdent->d_lock); | ||
| 640 | spin_unlock(&dcache_lock); | ||
| 641 | if (inode) | ||
| 642 | mutex_unlock(&inode->i_mutex); | ||
| 643 | } | ||
| 589 | } | 644 | } |
| 590 | 645 | ||
| 591 | if (!newdent->d_inode) { | 646 | if (!newdent->d_inode) { |
| 647 | struct inode *inode; | ||
| 648 | |||
| 592 | entry->opened = 0; | 649 | entry->opened = 0; |
| 593 | entry->ino = iunique(inode->i_sb, 2); | 650 | entry->ino = iunique(dir->i_sb, 2); |
| 594 | newino = ncp_iget(inode->i_sb, entry); | 651 | inode = ncp_iget(dir->i_sb, entry); |
| 595 | if (newino) { | 652 | if (inode) { |
| 596 | newdent->d_op = &ncp_dentry_operations; | 653 | newdent->d_op = &ncp_dentry_operations; |
| 597 | d_instantiate(newdent, newino); | 654 | d_instantiate(newdent, inode); |
| 598 | if (!hashed) | 655 | if (!hashed) |
| 599 | d_rehash(newdent); | 656 | d_rehash(newdent); |
| 600 | } | 657 | } |
| 601 | } else | 658 | } else { |
| 602 | ncp_update_inode2(newdent->d_inode, entry); | 659 | struct inode *inode = newdent->d_inode; |
| 660 | |||
| 661 | mutex_lock(&inode->i_mutex); | ||
| 662 | ncp_update_inode2(inode, entry); | ||
| 663 | mutex_unlock(&inode->i_mutex); | ||
| 664 | } | ||
| 603 | 665 | ||
| 604 | if (newdent->d_inode) { | 666 | if (newdent->d_inode) { |
| 605 | ino = newdent->d_inode->i_ino; | 667 | ino = newdent->d_inode->i_ino; |
| @@ -617,7 +679,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | |||
| 617 | ctl.cache = NULL; | 679 | ctl.cache = NULL; |
| 618 | ctl.idx -= NCP_DIRCACHE_SIZE; | 680 | ctl.idx -= NCP_DIRCACHE_SIZE; |
| 619 | ctl.ofs += 1; | 681 | ctl.ofs += 1; |
| 620 | ctl.page = grab_cache_page(&inode->i_data, ctl.ofs); | 682 | ctl.page = grab_cache_page(&dir->i_data, ctl.ofs); |
| 621 | if (ctl.page) | 683 | if (ctl.page) |
| 622 | ctl.cache = kmap(ctl.page); | 684 | ctl.cache = kmap(ctl.page); |
| 623 | } | 685 | } |
| @@ -633,7 +695,7 @@ end_advance: | |||
| 633 | if (!ino) | 695 | if (!ino) |
| 634 | ino = find_inode_number(dentry, &qname); | 696 | ino = find_inode_number(dentry, &qname); |
| 635 | if (!ino) | 697 | if (!ino) |
| 636 | ino = iunique(inode->i_sb, 2); | 698 | ino = iunique(dir->i_sb, 2); |
| 637 | ctl.filled = filldir(dirent, qname.name, qname.len, | 699 | ctl.filled = filldir(dirent, qname.name, qname.len, |
| 638 | filp->f_pos, ino, DT_UNKNOWN); | 700 | filp->f_pos, ino, DT_UNKNOWN); |
| 639 | if (!ctl.filled) | 701 | if (!ctl.filled) |
| @@ -660,6 +722,7 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, | |||
| 660 | (unsigned long) filp->f_pos); | 722 | (unsigned long) filp->f_pos); |
| 661 | 723 | ||
| 662 | for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { | 724 | for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { |
| 725 | int inval_dentry; | ||
| 663 | 726 | ||
| 664 | if (ncp_get_volume_info_with_number(server, i, &info) != 0) | 727 | if (ncp_get_volume_info_with_number(server, i, &info) != 0) |
| 665 | return; | 728 | return; |
| @@ -675,8 +738,9 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir, | |||
| 675 | info.volume_name); | 738 | info.volume_name); |
| 676 | continue; | 739 | continue; |
| 677 | } | 740 | } |
| 741 | inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL); | ||
| 678 | entry.volume = entry.i.volNumber; | 742 | entry.volume = entry.i.volNumber; |
| 679 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) | 743 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry)) |
| 680 | return; | 744 | return; |
| 681 | } | 745 | } |
| 682 | } | 746 | } |
| @@ -739,7 +803,7 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir, | |||
| 739 | rpl += onerpl; | 803 | rpl += onerpl; |
| 740 | rpls -= onerpl; | 804 | rpls -= onerpl; |
| 741 | entry.volume = entry.i.volNumber; | 805 | entry.volume = entry.i.volNumber; |
| 742 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) | 806 | if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0)) |
| 743 | break; | 807 | break; |
| 744 | } | 808 | } |
| 745 | } while (more); | 809 | } while (more); |
| @@ -775,17 +839,19 @@ int ncp_conn_logged_in(struct super_block *sb) | |||
| 775 | if (dent) { | 839 | if (dent) { |
| 776 | struct inode* ino = dent->d_inode; | 840 | struct inode* ino = dent->d_inode; |
| 777 | if (ino) { | 841 | if (ino) { |
| 842 | ncp_update_known_namespace(server, volNumber, NULL); | ||
| 778 | NCP_FINFO(ino)->volNumber = volNumber; | 843 | NCP_FINFO(ino)->volNumber = volNumber; |
| 779 | NCP_FINFO(ino)->dirEntNum = dirEntNum; | 844 | NCP_FINFO(ino)->dirEntNum = dirEntNum; |
| 780 | NCP_FINFO(ino)->DosDirNum = DosDirNum; | 845 | NCP_FINFO(ino)->DosDirNum = DosDirNum; |
| 846 | result = 0; | ||
| 781 | } else { | 847 | } else { |
| 782 | DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n"); | 848 | DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n"); |
| 783 | } | 849 | } |
| 784 | } else { | 850 | } else { |
| 785 | DPRINTK("ncpfs: sb->s_root == NULL!\n"); | 851 | DPRINTK("ncpfs: sb->s_root == NULL!\n"); |
| 786 | } | 852 | } |
| 787 | } | 853 | } else |
| 788 | result = 0; | 854 | result = 0; |
| 789 | 855 | ||
| 790 | out: | 856 | out: |
| 791 | return result; | 857 | return result; |
| @@ -799,7 +865,6 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struc | |||
| 799 | int error, res, len; | 865 | int error, res, len; |
| 800 | __u8 __name[NCP_MAXPATHLEN + 1]; | 866 | __u8 __name[NCP_MAXPATHLEN + 1]; |
| 801 | 867 | ||
| 802 | lock_kernel(); | ||
| 803 | error = -EIO; | 868 | error = -EIO; |
| 804 | if (!ncp_conn_valid(server)) | 869 | if (!ncp_conn_valid(server)) |
| 805 | goto finished; | 870 | goto finished; |
| @@ -813,6 +878,8 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struc | |||
| 813 | dentry->d_name.len, 1); | 878 | dentry->d_name.len, 1); |
| 814 | if (!res) | 879 | if (!res) |
| 815 | res = ncp_lookup_volume(server, __name, &(finfo.i)); | 880 | res = ncp_lookup_volume(server, __name, &(finfo.i)); |
| 881 | if (!res) | ||
| 882 | ncp_update_known_namespace(server, finfo.i.volNumber, NULL); | ||
| 816 | } else { | 883 | } else { |
| 817 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 884 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
| 818 | dentry->d_name.len, !ncp_preserve_case(dir)); | 885 | dentry->d_name.len, !ncp_preserve_case(dir)); |
| @@ -846,7 +913,6 @@ add_entry: | |||
| 846 | 913 | ||
| 847 | finished: | 914 | finished: |
| 848 | PPRINTK("ncp_lookup: result=%d\n", error); | 915 | PPRINTK("ncp_lookup: result=%d\n", error); |
| 849 | unlock_kernel(); | ||
| 850 | return ERR_PTR(error); | 916 | return ERR_PTR(error); |
| 851 | } | 917 | } |
| 852 | 918 | ||
| @@ -887,11 +953,6 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, | |||
| 887 | PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n", | 953 | PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n", |
| 888 | dentry->d_parent->d_name.name, dentry->d_name.name, mode); | 954 | dentry->d_parent->d_name.name, dentry->d_name.name, mode); |
| 889 | 955 | ||
| 890 | error = -EIO; | ||
| 891 | lock_kernel(); | ||
| 892 | if (!ncp_conn_valid(server)) | ||
| 893 | goto out; | ||
| 894 | |||
| 895 | ncp_age_dentry(server, dentry); | 956 | ncp_age_dentry(server, dentry); |
| 896 | len = sizeof(__name); | 957 | len = sizeof(__name); |
| 897 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 958 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
| @@ -917,6 +978,8 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, | |||
| 917 | if (result) { | 978 | if (result) { |
| 918 | if (result == 0x87) | 979 | if (result == 0x87) |
| 919 | error = -ENAMETOOLONG; | 980 | error = -ENAMETOOLONG; |
| 981 | else if (result < 0) | ||
| 982 | error = result; | ||
| 920 | DPRINTK("ncp_create: %s/%s failed\n", | 983 | DPRINTK("ncp_create: %s/%s failed\n", |
| 921 | dentry->d_parent->d_name.name, dentry->d_name.name); | 984 | dentry->d_parent->d_name.name, dentry->d_name.name); |
| 922 | goto out; | 985 | goto out; |
| @@ -935,7 +998,6 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, | |||
| 935 | 998 | ||
| 936 | error = ncp_instantiate(dir, dentry, &finfo); | 999 | error = ncp_instantiate(dir, dentry, &finfo); |
| 937 | out: | 1000 | out: |
| 938 | unlock_kernel(); | ||
| 939 | return error; | 1001 | return error; |
| 940 | } | 1002 | } |
| 941 | 1003 | ||
| @@ -955,11 +1017,6 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 955 | DPRINTK("ncp_mkdir: making %s/%s\n", | 1017 | DPRINTK("ncp_mkdir: making %s/%s\n", |
| 956 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1018 | dentry->d_parent->d_name.name, dentry->d_name.name); |
| 957 | 1019 | ||
| 958 | error = -EIO; | ||
| 959 | lock_kernel(); | ||
| 960 | if (!ncp_conn_valid(server)) | ||
| 961 | goto out; | ||
| 962 | |||
| 963 | ncp_age_dentry(server, dentry); | 1020 | ncp_age_dentry(server, dentry); |
| 964 | len = sizeof(__name); | 1021 | len = sizeof(__name); |
| 965 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 1022 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
| @@ -967,12 +1024,11 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 967 | if (error) | 1024 | if (error) |
| 968 | goto out; | 1025 | goto out; |
| 969 | 1026 | ||
| 970 | error = -EACCES; | 1027 | error = ncp_open_create_file_or_subdir(server, dir, __name, |
| 971 | if (ncp_open_create_file_or_subdir(server, dir, __name, | ||
| 972 | OC_MODE_CREATE, aDIR, | 1028 | OC_MODE_CREATE, aDIR, |
| 973 | cpu_to_le16(0xffff), | 1029 | cpu_to_le16(0xffff), |
| 974 | &finfo) == 0) | 1030 | &finfo); |
| 975 | { | 1031 | if (error == 0) { |
| 976 | if (ncp_is_nfs_extras(server, finfo.volume)) { | 1032 | if (ncp_is_nfs_extras(server, finfo.volume)) { |
| 977 | mode |= S_IFDIR; | 1033 | mode |= S_IFDIR; |
| 978 | finfo.i.nfs.mode = mode; | 1034 | finfo.i.nfs.mode = mode; |
| @@ -983,9 +1039,10 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 983 | goto out; | 1039 | goto out; |
| 984 | } | 1040 | } |
| 985 | error = ncp_instantiate(dir, dentry, &finfo); | 1041 | error = ncp_instantiate(dir, dentry, &finfo); |
| 1042 | } else if (error > 0) { | ||
| 1043 | error = -EACCES; | ||
| 986 | } | 1044 | } |
| 987 | out: | 1045 | out: |
| 988 | unlock_kernel(); | ||
| 989 | return error; | 1046 | return error; |
| 990 | } | 1047 | } |
| 991 | 1048 | ||
| @@ -998,11 +1055,6 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 998 | DPRINTK("ncp_rmdir: removing %s/%s\n", | 1055 | DPRINTK("ncp_rmdir: removing %s/%s\n", |
| 999 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1056 | dentry->d_parent->d_name.name, dentry->d_name.name); |
| 1000 | 1057 | ||
| 1001 | error = -EIO; | ||
| 1002 | lock_kernel(); | ||
| 1003 | if (!ncp_conn_valid(server)) | ||
| 1004 | goto out; | ||
| 1005 | |||
| 1006 | error = -EBUSY; | 1058 | error = -EBUSY; |
| 1007 | if (!d_unhashed(dentry)) | 1059 | if (!d_unhashed(dentry)) |
| 1008 | goto out; | 1060 | goto out; |
| @@ -1036,11 +1088,10 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 1036 | error = -ENOENT; | 1088 | error = -ENOENT; |
| 1037 | break; | 1089 | break; |
| 1038 | default: | 1090 | default: |
| 1039 | error = -EACCES; | 1091 | error = result < 0 ? result : -EACCES; |
| 1040 | break; | 1092 | break; |
| 1041 | } | 1093 | } |
| 1042 | out: | 1094 | out: |
| 1043 | unlock_kernel(); | ||
| 1044 | return error; | 1095 | return error; |
| 1045 | } | 1096 | } |
| 1046 | 1097 | ||
| @@ -1050,15 +1101,10 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1050 | struct ncp_server *server; | 1101 | struct ncp_server *server; |
| 1051 | int error; | 1102 | int error; |
| 1052 | 1103 | ||
| 1053 | lock_kernel(); | ||
| 1054 | server = NCP_SERVER(dir); | 1104 | server = NCP_SERVER(dir); |
| 1055 | DPRINTK("ncp_unlink: unlinking %s/%s\n", | 1105 | DPRINTK("ncp_unlink: unlinking %s/%s\n", |
| 1056 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1106 | dentry->d_parent->d_name.name, dentry->d_name.name); |
| 1057 | 1107 | ||
| 1058 | error = -EIO; | ||
| 1059 | if (!ncp_conn_valid(server)) | ||
| 1060 | goto out; | ||
| 1061 | |||
| 1062 | /* | 1108 | /* |
| 1063 | * Check whether to close the file ... | 1109 | * Check whether to close the file ... |
| 1064 | */ | 1110 | */ |
| @@ -1097,12 +1143,9 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1097 | error = -ENOENT; | 1143 | error = -ENOENT; |
| 1098 | break; | 1144 | break; |
| 1099 | default: | 1145 | default: |
| 1100 | error = -EACCES; | 1146 | error = error < 0 ? error : -EACCES; |
| 1101 | break; | 1147 | break; |
| 1102 | } | 1148 | } |
| 1103 | |||
| 1104 | out: | ||
| 1105 | unlock_kernel(); | ||
| 1106 | return error; | 1149 | return error; |
| 1107 | } | 1150 | } |
| 1108 | 1151 | ||
| @@ -1118,11 +1161,6 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 1118 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1161 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
| 1119 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name); | 1162 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name); |
| 1120 | 1163 | ||
| 1121 | error = -EIO; | ||
| 1122 | lock_kernel(); | ||
| 1123 | if (!ncp_conn_valid(server)) | ||
| 1124 | goto out; | ||
| 1125 | |||
| 1126 | ncp_age_dentry(server, old_dentry); | 1164 | ncp_age_dentry(server, old_dentry); |
| 1127 | ncp_age_dentry(server, new_dentry); | 1165 | ncp_age_dentry(server, new_dentry); |
| 1128 | 1166 | ||
| @@ -1161,11 +1199,10 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 1161 | error = -ENOENT; | 1199 | error = -ENOENT; |
| 1162 | break; | 1200 | break; |
| 1163 | default: | 1201 | default: |
| 1164 | error = -EACCES; | 1202 | error = error < 0 ? error : -EACCES; |
| 1165 | break; | 1203 | break; |
| 1166 | } | 1204 | } |
| 1167 | out: | 1205 | out: |
| 1168 | unlock_kernel(); | ||
| 1169 | return error; | 1206 | return error; |
| 1170 | } | 1207 | } |
| 1171 | 1208 | ||
