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 | ||