diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 299 |
1 files changed, 157 insertions, 142 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1141bd29e4e3..f21e917bb8ed 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -110,7 +110,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, | |||
110 | struct dentry *dentry = *dpp; | 110 | struct dentry *dentry = *dpp; |
111 | struct vfsmount *mnt = mntget(exp->ex_mnt); | 111 | struct vfsmount *mnt = mntget(exp->ex_mnt); |
112 | struct dentry *mounts = dget(dentry); | 112 | struct dentry *mounts = dget(dentry); |
113 | int err = nfs_ok; | 113 | int err = 0; |
114 | 114 | ||
115 | while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts)); | 115 | while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts)); |
116 | 116 | ||
@@ -148,14 +148,15 @@ out: | |||
148 | * clients and is explicitly disallowed for NFSv3 | 148 | * clients and is explicitly disallowed for NFSv3 |
149 | * NeilBrown <neilb@cse.unsw.edu.au> | 149 | * NeilBrown <neilb@cse.unsw.edu.au> |
150 | */ | 150 | */ |
151 | int | 151 | __be32 |
152 | nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, | 152 | nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, |
153 | int len, struct svc_fh *resfh) | 153 | int len, struct svc_fh *resfh) |
154 | { | 154 | { |
155 | struct svc_export *exp; | 155 | struct svc_export *exp; |
156 | struct dentry *dparent; | 156 | struct dentry *dparent; |
157 | struct dentry *dentry; | 157 | struct dentry *dentry; |
158 | int err; | 158 | __be32 err; |
159 | int host_err; | ||
159 | 160 | ||
160 | dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name); | 161 | dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name); |
161 | 162 | ||
@@ -193,7 +194,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, | |||
193 | exp2 = exp_parent(exp->ex_client, mnt, dentry, | 194 | exp2 = exp_parent(exp->ex_client, mnt, dentry, |
194 | &rqstp->rq_chandle); | 195 | &rqstp->rq_chandle); |
195 | if (IS_ERR(exp2)) { | 196 | if (IS_ERR(exp2)) { |
196 | err = PTR_ERR(exp2); | 197 | host_err = PTR_ERR(exp2); |
197 | dput(dentry); | 198 | dput(dentry); |
198 | mntput(mnt); | 199 | mntput(mnt); |
199 | goto out_nfserr; | 200 | goto out_nfserr; |
@@ -210,14 +211,14 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, | |||
210 | } else { | 211 | } else { |
211 | fh_lock(fhp); | 212 | fh_lock(fhp); |
212 | dentry = lookup_one_len(name, dparent, len); | 213 | dentry = lookup_one_len(name, dparent, len); |
213 | err = PTR_ERR(dentry); | 214 | host_err = PTR_ERR(dentry); |
214 | if (IS_ERR(dentry)) | 215 | if (IS_ERR(dentry)) |
215 | goto out_nfserr; | 216 | goto out_nfserr; |
216 | /* | 217 | /* |
217 | * check if we have crossed a mount point ... | 218 | * check if we have crossed a mount point ... |
218 | */ | 219 | */ |
219 | if (d_mountpoint(dentry)) { | 220 | if (d_mountpoint(dentry)) { |
220 | if ((err = nfsd_cross_mnt(rqstp, &dentry, &exp))) { | 221 | if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) { |
221 | dput(dentry); | 222 | dput(dentry); |
222 | goto out_nfserr; | 223 | goto out_nfserr; |
223 | } | 224 | } |
@@ -236,7 +237,7 @@ out: | |||
236 | return err; | 237 | return err; |
237 | 238 | ||
238 | out_nfserr: | 239 | out_nfserr: |
239 | err = nfserrno(err); | 240 | err = nfserrno(host_err); |
240 | goto out; | 241 | goto out; |
241 | } | 242 | } |
242 | 243 | ||
@@ -244,7 +245,7 @@ out_nfserr: | |||
244 | * Set various file attributes. | 245 | * Set various file attributes. |
245 | * N.B. After this call fhp needs an fh_put | 246 | * N.B. After this call fhp needs an fh_put |
246 | */ | 247 | */ |
247 | int | 248 | __be32 |
248 | nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | 249 | nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, |
249 | int check_guard, time_t guardtime) | 250 | int check_guard, time_t guardtime) |
250 | { | 251 | { |
@@ -253,7 +254,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
253 | int accmode = MAY_SATTR; | 254 | int accmode = MAY_SATTR; |
254 | int ftype = 0; | 255 | int ftype = 0; |
255 | int imode; | 256 | int imode; |
256 | int err; | 257 | __be32 err; |
258 | int host_err; | ||
257 | int size_change = 0; | 259 | int size_change = 0; |
258 | 260 | ||
259 | if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) | 261 | if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) |
@@ -319,19 +321,19 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
319 | * If we are changing the size of the file, then | 321 | * If we are changing the size of the file, then |
320 | * we need to break all leases. | 322 | * we need to break all leases. |
321 | */ | 323 | */ |
322 | err = break_lease(inode, FMODE_WRITE | O_NONBLOCK); | 324 | host_err = break_lease(inode, FMODE_WRITE | O_NONBLOCK); |
323 | if (err == -EWOULDBLOCK) | 325 | if (host_err == -EWOULDBLOCK) |
324 | err = -ETIMEDOUT; | 326 | host_err = -ETIMEDOUT; |
325 | if (err) /* ENOMEM or EWOULDBLOCK */ | 327 | if (host_err) /* ENOMEM or EWOULDBLOCK */ |
326 | goto out_nfserr; | 328 | goto out_nfserr; |
327 | 329 | ||
328 | err = get_write_access(inode); | 330 | host_err = get_write_access(inode); |
329 | if (err) | 331 | if (host_err) |
330 | goto out_nfserr; | 332 | goto out_nfserr; |
331 | 333 | ||
332 | size_change = 1; | 334 | size_change = 1; |
333 | err = locks_verify_truncate(inode, NULL, iap->ia_size); | 335 | host_err = locks_verify_truncate(inode, NULL, iap->ia_size); |
334 | if (err) { | 336 | if (host_err) { |
335 | put_write_access(inode); | 337 | put_write_access(inode); |
336 | goto out_nfserr; | 338 | goto out_nfserr; |
337 | } | 339 | } |
@@ -357,8 +359,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
357 | err = nfserr_notsync; | 359 | err = nfserr_notsync; |
358 | if (!check_guard || guardtime == inode->i_ctime.tv_sec) { | 360 | if (!check_guard || guardtime == inode->i_ctime.tv_sec) { |
359 | fh_lock(fhp); | 361 | fh_lock(fhp); |
360 | err = notify_change(dentry, iap); | 362 | host_err = notify_change(dentry, iap); |
361 | err = nfserrno(err); | 363 | err = nfserrno(host_err); |
362 | fh_unlock(fhp); | 364 | fh_unlock(fhp); |
363 | } | 365 | } |
364 | if (size_change) | 366 | if (size_change) |
@@ -370,7 +372,7 @@ out: | |||
370 | return err; | 372 | return err; |
371 | 373 | ||
372 | out_nfserr: | 374 | out_nfserr: |
373 | err = nfserrno(err); | 375 | err = nfserrno(host_err); |
374 | goto out; | 376 | goto out; |
375 | } | 377 | } |
376 | 378 | ||
@@ -420,11 +422,12 @@ out: | |||
420 | return error; | 422 | return error; |
421 | } | 423 | } |
422 | 424 | ||
423 | int | 425 | __be32 |
424 | nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, | 426 | nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, |
425 | struct nfs4_acl *acl) | 427 | struct nfs4_acl *acl) |
426 | { | 428 | { |
427 | int error; | 429 | __be32 error; |
430 | int host_error; | ||
428 | struct dentry *dentry; | 431 | struct dentry *dentry; |
429 | struct inode *inode; | 432 | struct inode *inode; |
430 | struct posix_acl *pacl = NULL, *dpacl = NULL; | 433 | struct posix_acl *pacl = NULL, *dpacl = NULL; |
@@ -440,20 +443,20 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
440 | if (S_ISDIR(inode->i_mode)) | 443 | if (S_ISDIR(inode->i_mode)) |
441 | flags = NFS4_ACL_DIR; | 444 | flags = NFS4_ACL_DIR; |
442 | 445 | ||
443 | error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags); | 446 | host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags); |
444 | if (error == -EINVAL) { | 447 | if (host_error == -EINVAL) { |
445 | error = nfserr_attrnotsupp; | 448 | error = nfserr_attrnotsupp; |
446 | goto out; | 449 | goto out; |
447 | } else if (error < 0) | 450 | } else if (host_error < 0) |
448 | goto out_nfserr; | 451 | goto out_nfserr; |
449 | 452 | ||
450 | error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS); | 453 | host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS); |
451 | if (error < 0) | 454 | if (host_error < 0) |
452 | goto out_nfserr; | 455 | goto out_nfserr; |
453 | 456 | ||
454 | if (S_ISDIR(inode->i_mode)) { | 457 | if (S_ISDIR(inode->i_mode)) { |
455 | error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT); | 458 | host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT); |
456 | if (error < 0) | 459 | if (host_error < 0) |
457 | goto out_nfserr; | 460 | goto out_nfserr; |
458 | } | 461 | } |
459 | 462 | ||
@@ -464,7 +467,7 @@ out: | |||
464 | posix_acl_release(dpacl); | 467 | posix_acl_release(dpacl); |
465 | return (error); | 468 | return (error); |
466 | out_nfserr: | 469 | out_nfserr: |
467 | error = nfserrno(error); | 470 | error = nfserrno(host_error); |
468 | goto out; | 471 | goto out; |
469 | } | 472 | } |
470 | 473 | ||
@@ -571,14 +574,14 @@ static struct accessmap nfs3_anyaccess[] = { | |||
571 | { 0, 0 } | 574 | { 0, 0 } |
572 | }; | 575 | }; |
573 | 576 | ||
574 | int | 577 | __be32 |
575 | nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *supported) | 578 | nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *supported) |
576 | { | 579 | { |
577 | struct accessmap *map; | 580 | struct accessmap *map; |
578 | struct svc_export *export; | 581 | struct svc_export *export; |
579 | struct dentry *dentry; | 582 | struct dentry *dentry; |
580 | u32 query, result = 0, sresult = 0; | 583 | u32 query, result = 0, sresult = 0; |
581 | unsigned int error; | 584 | __be32 error; |
582 | 585 | ||
583 | error = fh_verify(rqstp, fhp, 0, MAY_NOP); | 586 | error = fh_verify(rqstp, fhp, 0, MAY_NOP); |
584 | if (error) | 587 | if (error) |
@@ -598,7 +601,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor | |||
598 | query = *access; | 601 | query = *access; |
599 | for (; map->access; map++) { | 602 | for (; map->access; map++) { |
600 | if (map->access & query) { | 603 | if (map->access & query) { |
601 | unsigned int err2; | 604 | __be32 err2; |
602 | 605 | ||
603 | sresult |= map->access; | 606 | sresult |= map->access; |
604 | 607 | ||
@@ -637,13 +640,15 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor | |||
637 | * The access argument indicates the type of open (read/write/lock) | 640 | * The access argument indicates the type of open (read/write/lock) |
638 | * N.B. After this call fhp needs an fh_put | 641 | * N.B. After this call fhp needs an fh_put |
639 | */ | 642 | */ |
640 | int | 643 | __be32 |
641 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | 644 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, |
642 | int access, struct file **filp) | 645 | int access, struct file **filp) |
643 | { | 646 | { |
644 | struct dentry *dentry; | 647 | struct dentry *dentry; |
645 | struct inode *inode; | 648 | struct inode *inode; |
646 | int flags = O_RDONLY|O_LARGEFILE, err; | 649 | int flags = O_RDONLY|O_LARGEFILE; |
650 | __be32 err; | ||
651 | int host_err; | ||
647 | 652 | ||
648 | /* | 653 | /* |
649 | * If we get here, then the client has already done an "open", | 654 | * If we get here, then the client has already done an "open", |
@@ -673,10 +678,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
673 | * Check to see if there are any leases on this file. | 678 | * Check to see if there are any leases on this file. |
674 | * This may block while leases are broken. | 679 | * This may block while leases are broken. |
675 | */ | 680 | */ |
676 | err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0)); | 681 | host_err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0)); |
677 | if (err == -EWOULDBLOCK) | 682 | if (host_err == -EWOULDBLOCK) |
678 | err = -ETIMEDOUT; | 683 | host_err = -ETIMEDOUT; |
679 | if (err) /* NOMEM or WOULDBLOCK */ | 684 | if (host_err) /* NOMEM or WOULDBLOCK */ |
680 | goto out_nfserr; | 685 | goto out_nfserr; |
681 | 686 | ||
682 | if (access & MAY_WRITE) { | 687 | if (access & MAY_WRITE) { |
@@ -689,10 +694,9 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
689 | } | 694 | } |
690 | *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_mnt), flags); | 695 | *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_mnt), flags); |
691 | if (IS_ERR(*filp)) | 696 | if (IS_ERR(*filp)) |
692 | err = PTR_ERR(*filp); | 697 | host_err = PTR_ERR(*filp); |
693 | out_nfserr: | 698 | out_nfserr: |
694 | if (err) | 699 | err = nfserrno(host_err); |
695 | err = nfserrno(err); | ||
696 | out: | 700 | out: |
697 | return err; | 701 | return err; |
698 | } | 702 | } |
@@ -830,14 +834,15 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset | |||
830 | return size; | 834 | return size; |
831 | } | 835 | } |
832 | 836 | ||
833 | static int | 837 | static __be32 |
834 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 838 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
835 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | 839 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) |
836 | { | 840 | { |
837 | struct inode *inode; | 841 | struct inode *inode; |
838 | struct raparms *ra; | 842 | struct raparms *ra; |
839 | mm_segment_t oldfs; | 843 | mm_segment_t oldfs; |
840 | int err; | 844 | __be32 err; |
845 | int host_err; | ||
841 | 846 | ||
842 | err = nfserr_perm; | 847 | err = nfserr_perm; |
843 | inode = file->f_dentry->d_inode; | 848 | inode = file->f_dentry->d_inode; |
@@ -855,12 +860,12 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
855 | 860 | ||
856 | if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { | 861 | if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { |
857 | rqstp->rq_resused = 1; | 862 | rqstp->rq_resused = 1; |
858 | err = file->f_op->sendfile(file, &offset, *count, | 863 | host_err = file->f_op->sendfile(file, &offset, *count, |
859 | nfsd_read_actor, rqstp); | 864 | nfsd_read_actor, rqstp); |
860 | } else { | 865 | } else { |
861 | oldfs = get_fs(); | 866 | oldfs = get_fs(); |
862 | set_fs(KERNEL_DS); | 867 | set_fs(KERNEL_DS); |
863 | err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset); | 868 | host_err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset); |
864 | set_fs(oldfs); | 869 | set_fs(oldfs); |
865 | } | 870 | } |
866 | 871 | ||
@@ -874,13 +879,13 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
874 | spin_unlock(&rab->pb_lock); | 879 | spin_unlock(&rab->pb_lock); |
875 | } | 880 | } |
876 | 881 | ||
877 | if (err >= 0) { | 882 | if (host_err >= 0) { |
878 | nfsdstats.io_read += err; | 883 | nfsdstats.io_read += host_err; |
879 | *count = err; | 884 | *count = host_err; |
880 | err = 0; | 885 | err = 0; |
881 | fsnotify_access(file->f_dentry); | 886 | fsnotify_access(file->f_dentry); |
882 | } else | 887 | } else |
883 | err = nfserrno(err); | 888 | err = nfserrno(host_err); |
884 | out: | 889 | out: |
885 | return err; | 890 | return err; |
886 | } | 891 | } |
@@ -895,7 +900,7 @@ static void kill_suid(struct dentry *dentry) | |||
895 | mutex_unlock(&dentry->d_inode->i_mutex); | 900 | mutex_unlock(&dentry->d_inode->i_mutex); |
896 | } | 901 | } |
897 | 902 | ||
898 | static int | 903 | static __be32 |
899 | nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 904 | nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
900 | loff_t offset, struct kvec *vec, int vlen, | 905 | loff_t offset, struct kvec *vec, int vlen, |
901 | unsigned long cnt, int *stablep) | 906 | unsigned long cnt, int *stablep) |
@@ -904,7 +909,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
904 | struct dentry *dentry; | 909 | struct dentry *dentry; |
905 | struct inode *inode; | 910 | struct inode *inode; |
906 | mm_segment_t oldfs; | 911 | mm_segment_t oldfs; |
907 | int err = 0; | 912 | __be32 err = 0; |
913 | int host_err; | ||
908 | int stable = *stablep; | 914 | int stable = *stablep; |
909 | 915 | ||
910 | #ifdef MSNFS | 916 | #ifdef MSNFS |
@@ -940,18 +946,18 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
940 | 946 | ||
941 | /* Write the data. */ | 947 | /* Write the data. */ |
942 | oldfs = get_fs(); set_fs(KERNEL_DS); | 948 | oldfs = get_fs(); set_fs(KERNEL_DS); |
943 | err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset); | 949 | host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset); |
944 | set_fs(oldfs); | 950 | set_fs(oldfs); |
945 | if (err >= 0) { | 951 | if (host_err >= 0) { |
946 | nfsdstats.io_write += cnt; | 952 | nfsdstats.io_write += cnt; |
947 | fsnotify_modify(file->f_dentry); | 953 | fsnotify_modify(file->f_dentry); |
948 | } | 954 | } |
949 | 955 | ||
950 | /* clear setuid/setgid flag after write */ | 956 | /* clear setuid/setgid flag after write */ |
951 | if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) | 957 | if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) |
952 | kill_suid(dentry); | 958 | kill_suid(dentry); |
953 | 959 | ||
954 | if (err >= 0 && stable) { | 960 | if (host_err >= 0 && stable) { |
955 | static ino_t last_ino; | 961 | static ino_t last_ino; |
956 | static dev_t last_dev; | 962 | static dev_t last_dev; |
957 | 963 | ||
@@ -977,7 +983,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
977 | 983 | ||
978 | if (inode->i_state & I_DIRTY) { | 984 | if (inode->i_state & I_DIRTY) { |
979 | dprintk("nfsd: write sync %d\n", current->pid); | 985 | dprintk("nfsd: write sync %d\n", current->pid); |
980 | err=nfsd_sync(file); | 986 | host_err=nfsd_sync(file); |
981 | } | 987 | } |
982 | #if 0 | 988 | #if 0 |
983 | wake_up(&inode->i_wait); | 989 | wake_up(&inode->i_wait); |
@@ -987,11 +993,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
987 | last_dev = inode->i_sb->s_dev; | 993 | last_dev = inode->i_sb->s_dev; |
988 | } | 994 | } |
989 | 995 | ||
990 | dprintk("nfsd: write complete err=%d\n", err); | 996 | dprintk("nfsd: write complete host_err=%d\n", host_err); |
991 | if (err >= 0) | 997 | if (host_err >= 0) |
992 | err = 0; | 998 | err = 0; |
993 | else | 999 | else |
994 | err = nfserrno(err); | 1000 | err = nfserrno(host_err); |
995 | out: | 1001 | out: |
996 | return err; | 1002 | return err; |
997 | } | 1003 | } |
@@ -1001,12 +1007,12 @@ out: | |||
1001 | * on entry. On return, *count contains the number of bytes actually read. | 1007 | * on entry. On return, *count contains the number of bytes actually read. |
1002 | * N.B. After this call fhp needs an fh_put | 1008 | * N.B. After this call fhp needs an fh_put |
1003 | */ | 1009 | */ |
1004 | int | 1010 | __be32 |
1005 | nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 1011 | nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
1006 | loff_t offset, struct kvec *vec, int vlen, | 1012 | loff_t offset, struct kvec *vec, int vlen, |
1007 | unsigned long *count) | 1013 | unsigned long *count) |
1008 | { | 1014 | { |
1009 | int err; | 1015 | __be32 err; |
1010 | 1016 | ||
1011 | if (file) { | 1017 | if (file) { |
1012 | err = nfsd_permission(fhp->fh_export, fhp->fh_dentry, | 1018 | err = nfsd_permission(fhp->fh_export, fhp->fh_dentry, |
@@ -1030,12 +1036,12 @@ out: | |||
1030 | * The stable flag requests synchronous writes. | 1036 | * The stable flag requests synchronous writes. |
1031 | * N.B. After this call fhp needs an fh_put | 1037 | * N.B. After this call fhp needs an fh_put |
1032 | */ | 1038 | */ |
1033 | int | 1039 | __be32 |
1034 | nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 1040 | nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
1035 | loff_t offset, struct kvec *vec, int vlen, unsigned long cnt, | 1041 | loff_t offset, struct kvec *vec, int vlen, unsigned long cnt, |
1036 | int *stablep) | 1042 | int *stablep) |
1037 | { | 1043 | { |
1038 | int err = 0; | 1044 | __be32 err = 0; |
1039 | 1045 | ||
1040 | if (file) { | 1046 | if (file) { |
1041 | err = nfsd_permission(fhp->fh_export, fhp->fh_dentry, | 1047 | err = nfsd_permission(fhp->fh_export, fhp->fh_dentry, |
@@ -1067,12 +1073,12 @@ out: | |||
1067 | * Unfortunately we cannot lock the file to make sure we return full WCC | 1073 | * Unfortunately we cannot lock the file to make sure we return full WCC |
1068 | * data to the client, as locking happens lower down in the filesystem. | 1074 | * data to the client, as locking happens lower down in the filesystem. |
1069 | */ | 1075 | */ |
1070 | int | 1076 | __be32 |
1071 | nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1077 | nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, |
1072 | loff_t offset, unsigned long count) | 1078 | loff_t offset, unsigned long count) |
1073 | { | 1079 | { |
1074 | struct file *file; | 1080 | struct file *file; |
1075 | int err; | 1081 | __be32 err; |
1076 | 1082 | ||
1077 | if ((u64)count > ~(u64)offset) | 1083 | if ((u64)count > ~(u64)offset) |
1078 | return nfserr_inval; | 1084 | return nfserr_inval; |
@@ -1100,14 +1106,15 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1100 | * | 1106 | * |
1101 | * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp | 1107 | * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp |
1102 | */ | 1108 | */ |
1103 | int | 1109 | __be32 |
1104 | nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1110 | nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, |
1105 | char *fname, int flen, struct iattr *iap, | 1111 | char *fname, int flen, struct iattr *iap, |
1106 | int type, dev_t rdev, struct svc_fh *resfhp) | 1112 | int type, dev_t rdev, struct svc_fh *resfhp) |
1107 | { | 1113 | { |
1108 | struct dentry *dentry, *dchild = NULL; | 1114 | struct dentry *dentry, *dchild = NULL; |
1109 | struct inode *dirp; | 1115 | struct inode *dirp; |
1110 | int err; | 1116 | __be32 err; |
1117 | int host_err; | ||
1111 | 1118 | ||
1112 | err = nfserr_perm; | 1119 | err = nfserr_perm; |
1113 | if (!flen) | 1120 | if (!flen) |
@@ -1134,7 +1141,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1134 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ | 1141 | /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ |
1135 | fh_lock_nested(fhp, I_MUTEX_PARENT); | 1142 | fh_lock_nested(fhp, I_MUTEX_PARENT); |
1136 | dchild = lookup_one_len(fname, dentry, flen); | 1143 | dchild = lookup_one_len(fname, dentry, flen); |
1137 | err = PTR_ERR(dchild); | 1144 | host_err = PTR_ERR(dchild); |
1138 | if (IS_ERR(dchild)) | 1145 | if (IS_ERR(dchild)) |
1139 | goto out_nfserr; | 1146 | goto out_nfserr; |
1140 | err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); | 1147 | err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); |
@@ -1173,22 +1180,22 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1173 | err = nfserr_perm; | 1180 | err = nfserr_perm; |
1174 | switch (type) { | 1181 | switch (type) { |
1175 | case S_IFREG: | 1182 | case S_IFREG: |
1176 | err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1183 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); |
1177 | break; | 1184 | break; |
1178 | case S_IFDIR: | 1185 | case S_IFDIR: |
1179 | err = vfs_mkdir(dirp, dchild, iap->ia_mode); | 1186 | host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); |
1180 | break; | 1187 | break; |
1181 | case S_IFCHR: | 1188 | case S_IFCHR: |
1182 | case S_IFBLK: | 1189 | case S_IFBLK: |
1183 | case S_IFIFO: | 1190 | case S_IFIFO: |
1184 | case S_IFSOCK: | 1191 | case S_IFSOCK: |
1185 | err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); | 1192 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); |
1186 | break; | 1193 | break; |
1187 | default: | 1194 | default: |
1188 | printk("nfsd: bad file type %o in nfsd_create\n", type); | 1195 | printk("nfsd: bad file type %o in nfsd_create\n", type); |
1189 | err = -EINVAL; | 1196 | host_err = -EINVAL; |
1190 | } | 1197 | } |
1191 | if (err < 0) | 1198 | if (host_err < 0) |
1192 | goto out_nfserr; | 1199 | goto out_nfserr; |
1193 | 1200 | ||
1194 | if (EX_ISSYNC(fhp->fh_export)) { | 1201 | if (EX_ISSYNC(fhp->fh_export)) { |
@@ -1203,7 +1210,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1203 | * directories via NFS. | 1210 | * directories via NFS. |
1204 | */ | 1211 | */ |
1205 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) { | 1212 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) { |
1206 | int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); | 1213 | __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); |
1207 | if (err2) | 1214 | if (err2) |
1208 | err = err2; | 1215 | err = err2; |
1209 | } | 1216 | } |
@@ -1218,7 +1225,7 @@ out: | |||
1218 | return err; | 1225 | return err; |
1219 | 1226 | ||
1220 | out_nfserr: | 1227 | out_nfserr: |
1221 | err = nfserrno(err); | 1228 | err = nfserrno(host_err); |
1222 | goto out; | 1229 | goto out; |
1223 | } | 1230 | } |
1224 | 1231 | ||
@@ -1226,7 +1233,7 @@ out_nfserr: | |||
1226 | /* | 1233 | /* |
1227 | * NFSv3 version of nfsd_create | 1234 | * NFSv3 version of nfsd_create |
1228 | */ | 1235 | */ |
1229 | int | 1236 | __be32 |
1230 | nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1237 | nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, |
1231 | char *fname, int flen, struct iattr *iap, | 1238 | char *fname, int flen, struct iattr *iap, |
1232 | struct svc_fh *resfhp, int createmode, u32 *verifier, | 1239 | struct svc_fh *resfhp, int createmode, u32 *verifier, |
@@ -1234,7 +1241,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1234 | { | 1241 | { |
1235 | struct dentry *dentry, *dchild = NULL; | 1242 | struct dentry *dentry, *dchild = NULL; |
1236 | struct inode *dirp; | 1243 | struct inode *dirp; |
1237 | int err; | 1244 | __be32 err; |
1245 | int host_err; | ||
1238 | __u32 v_mtime=0, v_atime=0; | 1246 | __u32 v_mtime=0, v_atime=0; |
1239 | int v_mode=0; | 1247 | int v_mode=0; |
1240 | 1248 | ||
@@ -1264,7 +1272,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1264 | * Compose the response file handle. | 1272 | * Compose the response file handle. |
1265 | */ | 1273 | */ |
1266 | dchild = lookup_one_len(fname, dentry, flen); | 1274 | dchild = lookup_one_len(fname, dentry, flen); |
1267 | err = PTR_ERR(dchild); | 1275 | host_err = PTR_ERR(dchild); |
1268 | if (IS_ERR(dchild)) | 1276 | if (IS_ERR(dchild)) |
1269 | goto out_nfserr; | 1277 | goto out_nfserr; |
1270 | 1278 | ||
@@ -1320,8 +1328,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1320 | goto out; | 1328 | goto out; |
1321 | } | 1329 | } |
1322 | 1330 | ||
1323 | err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1331 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); |
1324 | if (err < 0) | 1332 | if (host_err < 0) |
1325 | goto out_nfserr; | 1333 | goto out_nfserr; |
1326 | 1334 | ||
1327 | if (EX_ISSYNC(fhp->fh_export)) { | 1335 | if (EX_ISSYNC(fhp->fh_export)) { |
@@ -1350,7 +1358,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1350 | */ | 1358 | */ |
1351 | set_attr: | 1359 | set_attr: |
1352 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) { | 1360 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) { |
1353 | int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); | 1361 | __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); |
1354 | if (err2) | 1362 | if (err2) |
1355 | err = err2; | 1363 | err = err2; |
1356 | } | 1364 | } |
@@ -1368,7 +1376,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1368 | return err; | 1376 | return err; |
1369 | 1377 | ||
1370 | out_nfserr: | 1378 | out_nfserr: |
1371 | err = nfserrno(err); | 1379 | err = nfserrno(host_err); |
1372 | goto out; | 1380 | goto out; |
1373 | } | 1381 | } |
1374 | #endif /* CONFIG_NFSD_V3 */ | 1382 | #endif /* CONFIG_NFSD_V3 */ |
@@ -1378,13 +1386,14 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1378 | * fits into the buffer. On return, it contains the true length. | 1386 | * fits into the buffer. On return, it contains the true length. |
1379 | * N.B. After this call fhp needs an fh_put | 1387 | * N.B. After this call fhp needs an fh_put |
1380 | */ | 1388 | */ |
1381 | int | 1389 | __be32 |
1382 | nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) | 1390 | nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) |
1383 | { | 1391 | { |
1384 | struct dentry *dentry; | 1392 | struct dentry *dentry; |
1385 | struct inode *inode; | 1393 | struct inode *inode; |
1386 | mm_segment_t oldfs; | 1394 | mm_segment_t oldfs; |
1387 | int err; | 1395 | __be32 err; |
1396 | int host_err; | ||
1388 | 1397 | ||
1389 | err = fh_verify(rqstp, fhp, S_IFLNK, MAY_NOP); | 1398 | err = fh_verify(rqstp, fhp, S_IFLNK, MAY_NOP); |
1390 | if (err) | 1399 | if (err) |
@@ -1403,18 +1412,18 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) | |||
1403 | */ | 1412 | */ |
1404 | 1413 | ||
1405 | oldfs = get_fs(); set_fs(KERNEL_DS); | 1414 | oldfs = get_fs(); set_fs(KERNEL_DS); |
1406 | err = inode->i_op->readlink(dentry, buf, *lenp); | 1415 | host_err = inode->i_op->readlink(dentry, buf, *lenp); |
1407 | set_fs(oldfs); | 1416 | set_fs(oldfs); |
1408 | 1417 | ||
1409 | if (err < 0) | 1418 | if (host_err < 0) |
1410 | goto out_nfserr; | 1419 | goto out_nfserr; |
1411 | *lenp = err; | 1420 | *lenp = host_err; |
1412 | err = 0; | 1421 | err = 0; |
1413 | out: | 1422 | out: |
1414 | return err; | 1423 | return err; |
1415 | 1424 | ||
1416 | out_nfserr: | 1425 | out_nfserr: |
1417 | err = nfserrno(err); | 1426 | err = nfserrno(host_err); |
1418 | goto out; | 1427 | goto out; |
1419 | } | 1428 | } |
1420 | 1429 | ||
@@ -1422,7 +1431,7 @@ out_nfserr: | |||
1422 | * Create a symlink and look up its inode | 1431 | * Create a symlink and look up its inode |
1423 | * N.B. After this call _both_ fhp and resfhp need an fh_put | 1432 | * N.B. After this call _both_ fhp and resfhp need an fh_put |
1424 | */ | 1433 | */ |
1425 | int | 1434 | __be32 |
1426 | nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1435 | nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, |
1427 | char *fname, int flen, | 1436 | char *fname, int flen, |
1428 | char *path, int plen, | 1437 | char *path, int plen, |
@@ -1430,7 +1439,8 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1430 | struct iattr *iap) | 1439 | struct iattr *iap) |
1431 | { | 1440 | { |
1432 | struct dentry *dentry, *dnew; | 1441 | struct dentry *dentry, *dnew; |
1433 | int err, cerr; | 1442 | __be32 err, cerr; |
1443 | int host_err; | ||
1434 | umode_t mode; | 1444 | umode_t mode; |
1435 | 1445 | ||
1436 | err = nfserr_noent; | 1446 | err = nfserr_noent; |
@@ -1446,7 +1456,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1446 | fh_lock(fhp); | 1456 | fh_lock(fhp); |
1447 | dentry = fhp->fh_dentry; | 1457 | dentry = fhp->fh_dentry; |
1448 | dnew = lookup_one_len(fname, dentry, flen); | 1458 | dnew = lookup_one_len(fname, dentry, flen); |
1449 | err = PTR_ERR(dnew); | 1459 | host_err = PTR_ERR(dnew); |
1450 | if (IS_ERR(dnew)) | 1460 | if (IS_ERR(dnew)) |
1451 | goto out_nfserr; | 1461 | goto out_nfserr; |
1452 | 1462 | ||
@@ -1458,21 +1468,21 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1458 | if (unlikely(path[plen] != 0)) { | 1468 | if (unlikely(path[plen] != 0)) { |
1459 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); | 1469 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); |
1460 | if (path_alloced == NULL) | 1470 | if (path_alloced == NULL) |
1461 | err = -ENOMEM; | 1471 | host_err = -ENOMEM; |
1462 | else { | 1472 | else { |
1463 | strncpy(path_alloced, path, plen); | 1473 | strncpy(path_alloced, path, plen); |
1464 | path_alloced[plen] = 0; | 1474 | path_alloced[plen] = 0; |
1465 | err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode); | 1475 | host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode); |
1466 | kfree(path_alloced); | 1476 | kfree(path_alloced); |
1467 | } | 1477 | } |
1468 | } else | 1478 | } else |
1469 | err = vfs_symlink(dentry->d_inode, dnew, path, mode); | 1479 | host_err = vfs_symlink(dentry->d_inode, dnew, path, mode); |
1470 | 1480 | ||
1471 | if (!err) | 1481 | if (!host_err) { |
1472 | if (EX_ISSYNC(fhp->fh_export)) | 1482 | if (EX_ISSYNC(fhp->fh_export)) |
1473 | err = nfsd_sync_dir(dentry); | 1483 | host_err = nfsd_sync_dir(dentry); |
1474 | if (err) | 1484 | } |
1475 | err = nfserrno(err); | 1485 | err = nfserrno(host_err); |
1476 | fh_unlock(fhp); | 1486 | fh_unlock(fhp); |
1477 | 1487 | ||
1478 | cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp); | 1488 | cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp); |
@@ -1482,7 +1492,7 @@ out: | |||
1482 | return err; | 1492 | return err; |
1483 | 1493 | ||
1484 | out_nfserr: | 1494 | out_nfserr: |
1485 | err = nfserrno(err); | 1495 | err = nfserrno(host_err); |
1486 | goto out; | 1496 | goto out; |
1487 | } | 1497 | } |
1488 | 1498 | ||
@@ -1490,13 +1500,14 @@ out_nfserr: | |||
1490 | * Create a hardlink | 1500 | * Create a hardlink |
1491 | * N.B. After this call _both_ ffhp and tfhp need an fh_put | 1501 | * N.B. After this call _both_ ffhp and tfhp need an fh_put |
1492 | */ | 1502 | */ |
1493 | int | 1503 | __be32 |
1494 | nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | 1504 | nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, |
1495 | char *name, int len, struct svc_fh *tfhp) | 1505 | char *name, int len, struct svc_fh *tfhp) |
1496 | { | 1506 | { |
1497 | struct dentry *ddir, *dnew, *dold; | 1507 | struct dentry *ddir, *dnew, *dold; |
1498 | struct inode *dirp, *dest; | 1508 | struct inode *dirp, *dest; |
1499 | int err; | 1509 | __be32 err; |
1510 | int host_err; | ||
1500 | 1511 | ||
1501 | err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE); | 1512 | err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE); |
1502 | if (err) | 1513 | if (err) |
@@ -1517,24 +1528,25 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1517 | dirp = ddir->d_inode; | 1528 | dirp = ddir->d_inode; |
1518 | 1529 | ||
1519 | dnew = lookup_one_len(name, ddir, len); | 1530 | dnew = lookup_one_len(name, ddir, len); |
1520 | err = PTR_ERR(dnew); | 1531 | host_err = PTR_ERR(dnew); |
1521 | if (IS_ERR(dnew)) | 1532 | if (IS_ERR(dnew)) |
1522 | goto out_nfserr; | 1533 | goto out_nfserr; |
1523 | 1534 | ||
1524 | dold = tfhp->fh_dentry; | 1535 | dold = tfhp->fh_dentry; |
1525 | dest = dold->d_inode; | 1536 | dest = dold->d_inode; |
1526 | 1537 | ||
1527 | err = vfs_link(dold, dirp, dnew); | 1538 | host_err = vfs_link(dold, dirp, dnew); |
1528 | if (!err) { | 1539 | if (!host_err) { |
1529 | if (EX_ISSYNC(ffhp->fh_export)) { | 1540 | if (EX_ISSYNC(ffhp->fh_export)) { |
1530 | err = nfserrno(nfsd_sync_dir(ddir)); | 1541 | err = nfserrno(nfsd_sync_dir(ddir)); |
1531 | write_inode_now(dest, 1); | 1542 | write_inode_now(dest, 1); |
1532 | } | 1543 | } |
1544 | err = 0; | ||
1533 | } else { | 1545 | } else { |
1534 | if (err == -EXDEV && rqstp->rq_vers == 2) | 1546 | if (host_err == -EXDEV && rqstp->rq_vers == 2) |
1535 | err = nfserr_acces; | 1547 | err = nfserr_acces; |
1536 | else | 1548 | else |
1537 | err = nfserrno(err); | 1549 | err = nfserrno(host_err); |
1538 | } | 1550 | } |
1539 | 1551 | ||
1540 | dput(dnew); | 1552 | dput(dnew); |
@@ -1544,7 +1556,7 @@ out: | |||
1544 | return err; | 1556 | return err; |
1545 | 1557 | ||
1546 | out_nfserr: | 1558 | out_nfserr: |
1547 | err = nfserrno(err); | 1559 | err = nfserrno(host_err); |
1548 | goto out_unlock; | 1560 | goto out_unlock; |
1549 | } | 1561 | } |
1550 | 1562 | ||
@@ -1552,13 +1564,14 @@ out_nfserr: | |||
1552 | * Rename a file | 1564 | * Rename a file |
1553 | * N.B. After this call _both_ ffhp and tfhp need an fh_put | 1565 | * N.B. After this call _both_ ffhp and tfhp need an fh_put |
1554 | */ | 1566 | */ |
1555 | int | 1567 | __be32 |
1556 | nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | 1568 | nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, |
1557 | struct svc_fh *tfhp, char *tname, int tlen) | 1569 | struct svc_fh *tfhp, char *tname, int tlen) |
1558 | { | 1570 | { |
1559 | struct dentry *fdentry, *tdentry, *odentry, *ndentry, *trap; | 1571 | struct dentry *fdentry, *tdentry, *odentry, *ndentry, *trap; |
1560 | struct inode *fdir, *tdir; | 1572 | struct inode *fdir, *tdir; |
1561 | int err; | 1573 | __be32 err; |
1574 | int host_err; | ||
1562 | 1575 | ||
1563 | err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE); | 1576 | err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE); |
1564 | if (err) | 1577 | if (err) |
@@ -1589,22 +1602,22 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1589 | fill_pre_wcc(tfhp); | 1602 | fill_pre_wcc(tfhp); |
1590 | 1603 | ||
1591 | odentry = lookup_one_len(fname, fdentry, flen); | 1604 | odentry = lookup_one_len(fname, fdentry, flen); |
1592 | err = PTR_ERR(odentry); | 1605 | host_err = PTR_ERR(odentry); |
1593 | if (IS_ERR(odentry)) | 1606 | if (IS_ERR(odentry)) |
1594 | goto out_nfserr; | 1607 | goto out_nfserr; |
1595 | 1608 | ||
1596 | err = -ENOENT; | 1609 | host_err = -ENOENT; |
1597 | if (!odentry->d_inode) | 1610 | if (!odentry->d_inode) |
1598 | goto out_dput_old; | 1611 | goto out_dput_old; |
1599 | err = -EINVAL; | 1612 | host_err = -EINVAL; |
1600 | if (odentry == trap) | 1613 | if (odentry == trap) |
1601 | goto out_dput_old; | 1614 | goto out_dput_old; |
1602 | 1615 | ||
1603 | ndentry = lookup_one_len(tname, tdentry, tlen); | 1616 | ndentry = lookup_one_len(tname, tdentry, tlen); |
1604 | err = PTR_ERR(ndentry); | 1617 | host_err = PTR_ERR(ndentry); |
1605 | if (IS_ERR(ndentry)) | 1618 | if (IS_ERR(ndentry)) |
1606 | goto out_dput_old; | 1619 | goto out_dput_old; |
1607 | err = -ENOTEMPTY; | 1620 | host_err = -ENOTEMPTY; |
1608 | if (ndentry == trap) | 1621 | if (ndentry == trap) |
1609 | goto out_dput_new; | 1622 | goto out_dput_new; |
1610 | 1623 | ||
@@ -1612,14 +1625,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1612 | if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) && | 1625 | if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) && |
1613 | ((atomic_read(&odentry->d_count) > 1) | 1626 | ((atomic_read(&odentry->d_count) > 1) |
1614 | || (atomic_read(&ndentry->d_count) > 1))) { | 1627 | || (atomic_read(&ndentry->d_count) > 1))) { |
1615 | err = -EPERM; | 1628 | host_err = -EPERM; |
1616 | } else | 1629 | } else |
1617 | #endif | 1630 | #endif |
1618 | err = vfs_rename(fdir, odentry, tdir, ndentry); | 1631 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); |
1619 | if (!err && EX_ISSYNC(tfhp->fh_export)) { | 1632 | if (!host_err && EX_ISSYNC(tfhp->fh_export)) { |
1620 | err = nfsd_sync_dir(tdentry); | 1633 | host_err = nfsd_sync_dir(tdentry); |
1621 | if (!err) | 1634 | if (!host_err) |
1622 | err = nfsd_sync_dir(fdentry); | 1635 | host_err = nfsd_sync_dir(fdentry); |
1623 | } | 1636 | } |
1624 | 1637 | ||
1625 | out_dput_new: | 1638 | out_dput_new: |
@@ -1627,8 +1640,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1627 | out_dput_old: | 1640 | out_dput_old: |
1628 | dput(odentry); | 1641 | dput(odentry); |
1629 | out_nfserr: | 1642 | out_nfserr: |
1630 | if (err) | 1643 | err = nfserrno(host_err); |
1631 | err = nfserrno(err); | ||
1632 | 1644 | ||
1633 | /* we cannot reply on fh_unlock on the two filehandles, | 1645 | /* we cannot reply on fh_unlock on the two filehandles, |
1634 | * as that would do the wrong thing if the two directories | 1646 | * as that would do the wrong thing if the two directories |
@@ -1647,13 +1659,14 @@ out: | |||
1647 | * Unlink a file or directory | 1659 | * Unlink a file or directory |
1648 | * N.B. After this call fhp needs an fh_put | 1660 | * N.B. After this call fhp needs an fh_put |
1649 | */ | 1661 | */ |
1650 | int | 1662 | __be32 |
1651 | nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | 1663 | nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, |
1652 | char *fname, int flen) | 1664 | char *fname, int flen) |
1653 | { | 1665 | { |
1654 | struct dentry *dentry, *rdentry; | 1666 | struct dentry *dentry, *rdentry; |
1655 | struct inode *dirp; | 1667 | struct inode *dirp; |
1656 | int err; | 1668 | __be32 err; |
1669 | int host_err; | ||
1657 | 1670 | ||
1658 | err = nfserr_acces; | 1671 | err = nfserr_acces; |
1659 | if (!flen || isdotent(fname, flen)) | 1672 | if (!flen || isdotent(fname, flen)) |
@@ -1667,7 +1680,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1667 | dirp = dentry->d_inode; | 1680 | dirp = dentry->d_inode; |
1668 | 1681 | ||
1669 | rdentry = lookup_one_len(fname, dentry, flen); | 1682 | rdentry = lookup_one_len(fname, dentry, flen); |
1670 | err = PTR_ERR(rdentry); | 1683 | host_err = PTR_ERR(rdentry); |
1671 | if (IS_ERR(rdentry)) | 1684 | if (IS_ERR(rdentry)) |
1672 | goto out_nfserr; | 1685 | goto out_nfserr; |
1673 | 1686 | ||
@@ -1684,22 +1697,23 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1684 | #ifdef MSNFS | 1697 | #ifdef MSNFS |
1685 | if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && | 1698 | if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && |
1686 | (atomic_read(&rdentry->d_count) > 1)) { | 1699 | (atomic_read(&rdentry->d_count) > 1)) { |
1687 | err = -EPERM; | 1700 | host_err = -EPERM; |
1688 | } else | 1701 | } else |
1689 | #endif | 1702 | #endif |
1690 | err = vfs_unlink(dirp, rdentry); | 1703 | host_err = vfs_unlink(dirp, rdentry); |
1691 | } else { /* It's RMDIR */ | 1704 | } else { /* It's RMDIR */ |
1692 | err = vfs_rmdir(dirp, rdentry); | 1705 | host_err = vfs_rmdir(dirp, rdentry); |
1693 | } | 1706 | } |
1694 | 1707 | ||
1695 | dput(rdentry); | 1708 | dput(rdentry); |
1696 | 1709 | ||
1697 | if (err == 0 && | 1710 | if (host_err) |
1698 | EX_ISSYNC(fhp->fh_export)) | 1711 | goto out_nfserr; |
1699 | err = nfsd_sync_dir(dentry); | 1712 | if (EX_ISSYNC(fhp->fh_export)) |
1713 | host_err = nfsd_sync_dir(dentry); | ||
1700 | 1714 | ||
1701 | out_nfserr: | 1715 | out_nfserr: |
1702 | err = nfserrno(err); | 1716 | err = nfserrno(host_err); |
1703 | out: | 1717 | out: |
1704 | return err; | 1718 | return err; |
1705 | } | 1719 | } |
@@ -1708,11 +1722,12 @@ out: | |||
1708 | * Read entries from a directory. | 1722 | * Read entries from a directory. |
1709 | * The NFSv3/4 verifier we ignore for now. | 1723 | * The NFSv3/4 verifier we ignore for now. |
1710 | */ | 1724 | */ |
1711 | int | 1725 | __be32 |
1712 | nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, | 1726 | nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, |
1713 | struct readdir_cd *cdp, encode_dent_fn func) | 1727 | struct readdir_cd *cdp, encode_dent_fn func) |
1714 | { | 1728 | { |
1715 | int err; | 1729 | __be32 err; |
1730 | int host_err; | ||
1716 | struct file *file; | 1731 | struct file *file; |
1717 | loff_t offset = *offsetp; | 1732 | loff_t offset = *offsetp; |
1718 | 1733 | ||
@@ -1734,10 +1749,10 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, | |||
1734 | 1749 | ||
1735 | do { | 1750 | do { |
1736 | cdp->err = nfserr_eof; /* will be cleared on successful read */ | 1751 | cdp->err = nfserr_eof; /* will be cleared on successful read */ |
1737 | err = vfs_readdir(file, (filldir_t) func, cdp); | 1752 | host_err = vfs_readdir(file, (filldir_t) func, cdp); |
1738 | } while (err >=0 && cdp->err == nfs_ok); | 1753 | } while (host_err >=0 && cdp->err == nfs_ok); |
1739 | if (err) | 1754 | if (host_err) |
1740 | err = nfserrno(err); | 1755 | err = nfserrno(host_err); |
1741 | else | 1756 | else |
1742 | err = cdp->err; | 1757 | err = cdp->err; |
1743 | *offsetp = vfs_llseek(file, 0, 1); | 1758 | *offsetp = vfs_llseek(file, 0, 1); |
@@ -1754,10 +1769,10 @@ out: | |||
1754 | * Get file system stats | 1769 | * Get file system stats |
1755 | * N.B. After this call fhp needs an fh_put | 1770 | * N.B. After this call fhp needs an fh_put |
1756 | */ | 1771 | */ |
1757 | int | 1772 | __be32 |
1758 | nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) | 1773 | nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) |
1759 | { | 1774 | { |
1760 | int err = fh_verify(rqstp, fhp, 0, MAY_NOP); | 1775 | __be32 err = fh_verify(rqstp, fhp, 0, MAY_NOP); |
1761 | if (!err && vfs_statfs(fhp->fh_dentry,stat)) | 1776 | if (!err && vfs_statfs(fhp->fh_dentry,stat)) |
1762 | err = nfserr_io; | 1777 | err = nfserr_io; |
1763 | return err; | 1778 | return err; |
@@ -1766,7 +1781,7 @@ nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) | |||
1766 | /* | 1781 | /* |
1767 | * Check for a user's access permissions to this inode. | 1782 | * Check for a user's access permissions to this inode. |
1768 | */ | 1783 | */ |
1769 | int | 1784 | __be32 |
1770 | nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) | 1785 | nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) |
1771 | { | 1786 | { |
1772 | struct inode *inode = dentry->d_inode; | 1787 | struct inode *inode = dentry->d_inode; |