Loading fs/nfsd/vfs.c +16 −23 Original line number Original line Diff line number Diff line Loading @@ -1464,41 +1464,34 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, __be32 __be32 nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) { { mm_segment_t oldfs; __be32 err; __be32 err; int host_err; const char *link; struct path path; struct path path; DEFINE_DELAYED_CALL(done); int len; err = fh_verify(rqstp, fhp, S_IFLNK, NFSD_MAY_NOP); err = fh_verify(rqstp, fhp, S_IFLNK, NFSD_MAY_NOP); if (err) if (unlikely(err)) goto out; return err; path.mnt = fhp->fh_export->ex_path.mnt; path.mnt = fhp->fh_export->ex_path.mnt; path.dentry = fhp->fh_dentry; path.dentry = fhp->fh_dentry; err = nfserr_inval; if (unlikely(!d_is_symlink(path.dentry))) if (!d_is_symlink(path.dentry)) return nfserr_inval; goto out; touch_atime(&path); touch_atime(&path); /* N.B. Why does this call need a get_fs()?? * Remove the set_fs and watch the fireworks:-) --okir */ oldfs = get_fs(); set_fs(KERNEL_DS); host_err = vfs_readlink(path.dentry, (char __user *)buf, *lenp); set_fs(oldfs); if (host_err < 0) link = vfs_get_link(path.dentry, &done); goto out_nfserr; if (IS_ERR(link)) *lenp = host_err; return nfserrno(PTR_ERR(link)); err = 0; out: return err; out_nfserr: len = strlen(link); err = nfserrno(host_err); if (len < *lenp) goto out; *lenp = len; memcpy(buf, link, *lenp); do_delayed_call(&done); return 0; } } /* /* Loading Loading
fs/nfsd/vfs.c +16 −23 Original line number Original line Diff line number Diff line Loading @@ -1464,41 +1464,34 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, __be32 __be32 nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) { { mm_segment_t oldfs; __be32 err; __be32 err; int host_err; const char *link; struct path path; struct path path; DEFINE_DELAYED_CALL(done); int len; err = fh_verify(rqstp, fhp, S_IFLNK, NFSD_MAY_NOP); err = fh_verify(rqstp, fhp, S_IFLNK, NFSD_MAY_NOP); if (err) if (unlikely(err)) goto out; return err; path.mnt = fhp->fh_export->ex_path.mnt; path.mnt = fhp->fh_export->ex_path.mnt; path.dentry = fhp->fh_dentry; path.dentry = fhp->fh_dentry; err = nfserr_inval; if (unlikely(!d_is_symlink(path.dentry))) if (!d_is_symlink(path.dentry)) return nfserr_inval; goto out; touch_atime(&path); touch_atime(&path); /* N.B. Why does this call need a get_fs()?? * Remove the set_fs and watch the fireworks:-) --okir */ oldfs = get_fs(); set_fs(KERNEL_DS); host_err = vfs_readlink(path.dentry, (char __user *)buf, *lenp); set_fs(oldfs); if (host_err < 0) link = vfs_get_link(path.dentry, &done); goto out_nfserr; if (IS_ERR(link)) *lenp = host_err; return nfserrno(PTR_ERR(link)); err = 0; out: return err; out_nfserr: len = strlen(link); err = nfserrno(host_err); if (len < *lenp) goto out; *lenp = len; memcpy(buf, link, *lenp); do_delayed_call(&done); return 0; } } /* /* Loading