aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ncpfs/dir.c
diff options
context:
space:
mode:
authorPetr Vandrovec <petr@vandrovec.name>2010-09-26 19:47:33 -0400
committerArnd Bergmann <arnd@arndb.de>2010-10-04 15:10:52 -0400
commit2e54eb96e2c801f33d95b5dade15212ac4d6c4a5 (patch)
treec2996f29aa49881e93c7a37fad41e4961f6b8578 /fs/ncpfs/dir.c
parent60056794127a25d641465b706e8828186f7a2e1f (diff)
BKL: Remove BKL from ncpfs
Dozen of changes in ncpfs to provide some locking other than BKL. In readdir cache unlock and mark complete first page as last operation, so it can be used for synchronization, as code intended. When updating dentry name on case insensitive filesystems do at least some basic locking... Hold i_mutex when updating inode fields. Push some ncp_conn_is_valid down to ncp_request. Connection can become invalid at any moment, and fewer error code paths to test the better. Use i_size_{read,write} to modify file size. Set inode's backing_dev_info as ncpfs has its own special bdi. In ioctl unbreak ioctls invoked on filesystem mounted 'ro' - tests are for inode writeable or owner match, but were turned to filesystem writeable and inode writeable or owner match. Also collect all permission checks in single place. Add some locking, and remove comments saying that it would be cool to add some locks to the code. Constify some pointers. Signed-off-by: Petr Vandrovec <petr@vandrovec.name> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'fs/ncpfs/dir.c')
-rw-r--r--fs/ncpfs/dir.c221
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
100static 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
117static 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 =
102static int 130static int
103ncp_hash_dentry(struct dentry *dentry, struct qstr *this) 131ncp_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
268static int 295static int
269__ncp_lookup_validate(struct dentry *dentry) 296ncp_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
332finished: 363finished:
@@ -335,16 +366,6 @@ finished:
335 return val; 366 return val;
336} 367}
337 368
338static int
339ncp_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
348static struct dentry * 369static struct dentry *
349ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) 370ncp_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;
534finished: 554finished:
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 }
548out: 568out:
549 unlock_kernel();
550 return result; 569 return result;
551} 570}
552 571
553static int 572static int
554ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, 573ncp_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
790out: 856out:
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
847finished: 914finished:
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);
937out: 1000out:
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 }
987out: 1045out:
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 }
1042out: 1094out:
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
1104out:
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 }
1167out: 1205out:
1168 unlock_kernel();
1169 return error; 1206 return error;
1170} 1207}
1171 1208