aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs3proc.c11
-rw-r--r--fs/nfsd/nfs3xdr.c47
-rw-r--r--fs/nfsd/nfsxdr.c48
-rw-r--r--fs/nfsd/vfs.c20
-rw-r--r--include/linux/nfsd/xdr.h3
-rw-r--r--include/linux/nfsd/xdr3.h1
6 files changed, 75 insertions, 55 deletions
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 041380fe667b..6d2dfed1de08 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -56,13 +56,20 @@ static int
56nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, 56nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
57 struct nfsd3_attrstat *resp) 57 struct nfsd3_attrstat *resp)
58{ 58{
59 int nfserr; 59 int err, nfserr;
60 60
61 dprintk("nfsd: GETATTR(3) %s\n", 61 dprintk("nfsd: GETATTR(3) %s\n",
62 SVCFH_fmt(&argp->fh)); 62 SVCFH_fmt(&argp->fh));
63 63
64 fh_copy(&resp->fh, &argp->fh); 64 fh_copy(&resp->fh, &argp->fh);
65 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); 65 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
66 if (nfserr)
67 RETURN_STATUS(nfserr);
68
69 err = vfs_getattr(resp->fh.fh_export->ex_mnt,
70 resp->fh.fh_dentry, &resp->stat);
71 nfserr = nfserrno(err);
72
66 RETURN_STATUS(nfserr); 73 RETURN_STATUS(nfserr);
67} 74}
68 75
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 9147b8524d05..243d94b9653a 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -154,37 +154,34 @@ decode_sattr3(u32 *p, struct iattr *iap)
154} 154}
155 155
156static inline u32 * 156static inline u32 *
157encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) 157encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp,
158 struct kstat *stat)
158{ 159{
159 struct vfsmount *mnt = fhp->fh_export->ex_mnt;
160 struct dentry *dentry = fhp->fh_dentry; 160 struct dentry *dentry = fhp->fh_dentry;
161 struct kstat stat;
162 struct timespec time; 161 struct timespec time;
163 162
164 vfs_getattr(mnt, dentry, &stat); 163 *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
165 164 *p++ = htonl((u32) stat->mode);
166 *p++ = htonl(nfs3_ftypes[(stat.mode & S_IFMT) >> 12]); 165 *p++ = htonl((u32) stat->nlink);
167 *p++ = htonl((u32) stat.mode); 166 *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
168 *p++ = htonl((u32) stat.nlink); 167 *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
169 *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid)); 168 if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
170 *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid));
171 if (S_ISLNK(stat.mode) && stat.size > NFS3_MAXPATHLEN) {
172 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); 169 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
173 } else { 170 } else {
174 p = xdr_encode_hyper(p, (u64) stat.size); 171 p = xdr_encode_hyper(p, (u64) stat->size);
175 } 172 }
176 p = xdr_encode_hyper(p, ((u64)stat.blocks) << 9); 173 p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
177 *p++ = htonl((u32) MAJOR(stat.rdev)); 174 *p++ = htonl((u32) MAJOR(stat->rdev));
178 *p++ = htonl((u32) MINOR(stat.rdev)); 175 *p++ = htonl((u32) MINOR(stat->rdev));
179 if (is_fsid(fhp, rqstp->rq_reffh)) 176 if (is_fsid(fhp, rqstp->rq_reffh))
180 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid); 177 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
181 else 178 else
182 p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat.dev)); 179 p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat->dev));
183 p = xdr_encode_hyper(p, (u64) stat.ino); 180 p = xdr_encode_hyper(p, (u64) stat->ino);
184 p = encode_time3(p, &stat.atime); 181 p = encode_time3(p, &stat->atime);
185 lease_get_mtime(dentry->d_inode, &time); 182 lease_get_mtime(dentry->d_inode, &time);
186 p = encode_time3(p, &time); 183 p = encode_time3(p, &time);
187 p = encode_time3(p, &stat.ctime); 184 p = encode_time3(p, &stat->ctime);
188 185
189 return p; 186 return p;
190} 187}
@@ -232,8 +229,14 @@ encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
232{ 229{
233 struct dentry *dentry = fhp->fh_dentry; 230 struct dentry *dentry = fhp->fh_dentry;
234 if (dentry && dentry->d_inode != NULL) { 231 if (dentry && dentry->d_inode != NULL) {
235 *p++ = xdr_one; /* attributes follow */ 232 int err;
236 return encode_fattr3(rqstp, p, fhp); 233 struct kstat stat;
234
235 err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat);
236 if (!err) {
237 *p++ = xdr_one; /* attributes follow */
238 return encode_fattr3(rqstp, p, fhp, &stat);
239 }
237 } 240 }
238 *p++ = xdr_zero; 241 *p++ = xdr_zero;
239 return p; 242 return p;
@@ -616,7 +619,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
616 struct nfsd3_attrstat *resp) 619 struct nfsd3_attrstat *resp)
617{ 620{
618 if (resp->status == 0) 621 if (resp->status == 0)
619 p = encode_fattr3(rqstp, p, &resp->fh); 622 p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat);
620 return xdr_ressize_check(rqstp, p); 623 return xdr_ressize_check(rqstp, p);
621} 624}
622 625
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index b45999ff33e6..aa7bb41b293d 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -152,46 +152,44 @@ decode_sattr(u32 *p, struct iattr *iap)
152} 152}
153 153
154static inline u32 * 154static inline u32 *
155encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) 155encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp,
156 struct kstat *stat)
156{ 157{
157 struct vfsmount *mnt = fhp->fh_export->ex_mnt;
158 struct dentry *dentry = fhp->fh_dentry; 158 struct dentry *dentry = fhp->fh_dentry;
159 struct kstat stat;
160 int type; 159 int type;
161 struct timespec time; 160 struct timespec time;
162 161
163 vfs_getattr(mnt, dentry, &stat); 162 type = (stat->mode & S_IFMT);
164 type = (stat.mode & S_IFMT);
165 163
166 *p++ = htonl(nfs_ftypes[type >> 12]); 164 *p++ = htonl(nfs_ftypes[type >> 12]);
167 *p++ = htonl((u32) stat.mode); 165 *p++ = htonl((u32) stat->mode);
168 *p++ = htonl((u32) stat.nlink); 166 *p++ = htonl((u32) stat->nlink);
169 *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid)); 167 *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
170 *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid)); 168 *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
171 169
172 if (S_ISLNK(type) && stat.size > NFS_MAXPATHLEN) { 170 if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
173 *p++ = htonl(NFS_MAXPATHLEN); 171 *p++ = htonl(NFS_MAXPATHLEN);
174 } else { 172 } else {
175 *p++ = htonl((u32) stat.size); 173 *p++ = htonl((u32) stat->size);
176 } 174 }
177 *p++ = htonl((u32) stat.blksize); 175 *p++ = htonl((u32) stat->blksize);
178 if (S_ISCHR(type) || S_ISBLK(type)) 176 if (S_ISCHR(type) || S_ISBLK(type))
179 *p++ = htonl(new_encode_dev(stat.rdev)); 177 *p++ = htonl(new_encode_dev(stat->rdev));
180 else 178 else
181 *p++ = htonl(0xffffffff); 179 *p++ = htonl(0xffffffff);
182 *p++ = htonl((u32) stat.blocks); 180 *p++ = htonl((u32) stat->blocks);
183 if (is_fsid(fhp, rqstp->rq_reffh)) 181 if (is_fsid(fhp, rqstp->rq_reffh))
184 *p++ = htonl((u32) fhp->fh_export->ex_fsid); 182 *p++ = htonl((u32) fhp->fh_export->ex_fsid);
185 else 183 else
186 *p++ = htonl(new_encode_dev(stat.dev)); 184 *p++ = htonl(new_encode_dev(stat->dev));
187 *p++ = htonl((u32) stat.ino); 185 *p++ = htonl((u32) stat->ino);
188 *p++ = htonl((u32) stat.atime.tv_sec); 186 *p++ = htonl((u32) stat->atime.tv_sec);
189 *p++ = htonl(stat.atime.tv_nsec ? stat.atime.tv_nsec / 1000 : 0); 187 *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);
190 lease_get_mtime(dentry->d_inode, &time); 188 lease_get_mtime(dentry->d_inode, &time);
191 *p++ = htonl((u32) time.tv_sec); 189 *p++ = htonl((u32) time.tv_sec);
192 *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0); 190 *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0);
193 *p++ = htonl((u32) stat.ctime.tv_sec); 191 *p++ = htonl((u32) stat->ctime.tv_sec);
194 *p++ = htonl(stat.ctime.tv_nsec ? stat.ctime.tv_nsec / 1000 : 0); 192 *p++ = htonl(stat->ctime.tv_nsec ? stat->ctime.tv_nsec / 1000 : 0);
195 193
196 return p; 194 return p;
197} 195}
@@ -199,7 +197,9 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
199/* Helper function for NFSv2 ACL code */ 197/* Helper function for NFSv2 ACL code */
200u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) 198u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
201{ 199{
202 return encode_fattr(rqstp, p, fhp); 200 struct kstat stat;
201 vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, &stat);
202 return encode_fattr(rqstp, p, fhp, &stat);
203} 203}
204 204
205/* 205/*
@@ -394,7 +394,7 @@ int
394nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p, 394nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
395 struct nfsd_attrstat *resp) 395 struct nfsd_attrstat *resp)
396{ 396{
397 p = encode_fattr(rqstp, p, &resp->fh); 397 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
398 return xdr_ressize_check(rqstp, p); 398 return xdr_ressize_check(rqstp, p);
399} 399}
400 400
@@ -403,7 +403,7 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
403 struct nfsd_diropres *resp) 403 struct nfsd_diropres *resp)
404{ 404{
405 p = encode_fh(p, &resp->fh); 405 p = encode_fh(p, &resp->fh);
406 p = encode_fattr(rqstp, p, &resp->fh); 406 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
407 return xdr_ressize_check(rqstp, p); 407 return xdr_ressize_check(rqstp, p);
408} 408}
409 409
@@ -428,7 +428,7 @@ int
428nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p, 428nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
429 struct nfsd_readres *resp) 429 struct nfsd_readres *resp)
430{ 430{
431 p = encode_fattr(rqstp, p, &resp->fh); 431 p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
432 *p++ = htonl(resp->count); 432 *p++ = htonl(resp->count);
433 xdr_ressize_check(rqstp, p); 433 xdr_ressize_check(rqstp, p);
434 434
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index af7c3c3074b0..f83ab4cf4265 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -717,27 +717,33 @@ nfsd_close(struct file *filp)
717 * As this calls fsync (not fdatasync) there is no need for a write_inode 717 * As this calls fsync (not fdatasync) there is no need for a write_inode
718 * after it. 718 * after it.
719 */ 719 */
720static inline void nfsd_dosync(struct file *filp, struct dentry *dp, 720static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
721 struct file_operations *fop) 721 struct file_operations *fop)
722{ 722{
723 struct inode *inode = dp->d_inode; 723 struct inode *inode = dp->d_inode;
724 int (*fsync) (struct file *, struct dentry *, int); 724 int (*fsync) (struct file *, struct dentry *, int);
725 int err = nfs_ok;
725 726
726 filemap_fdatawrite(inode->i_mapping); 727 filemap_fdatawrite(inode->i_mapping);
727 if (fop && (fsync = fop->fsync)) 728 if (fop && (fsync = fop->fsync))
728 fsync(filp, dp, 0); 729 err=fsync(filp, dp, 0);
729 filemap_fdatawait(inode->i_mapping); 730 filemap_fdatawait(inode->i_mapping);
731
732 return nfserrno(err);
730} 733}
731 734
732 735
733static void 736static int
734nfsd_sync(struct file *filp) 737nfsd_sync(struct file *filp)
735{ 738{
739 int err;
736 struct inode *inode = filp->f_dentry->d_inode; 740 struct inode *inode = filp->f_dentry->d_inode;
737 dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name); 741 dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
738 down(&inode->i_sem); 742 down(&inode->i_sem);
739 nfsd_dosync(filp, filp->f_dentry, filp->f_op); 743 err=nfsd_dosync(filp, filp->f_dentry, filp->f_op);
740 up(&inode->i_sem); 744 up(&inode->i_sem);
745
746 return err;
741} 747}
742 748
743void 749void
@@ -962,7 +968,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
962 968
963 if (inode->i_state & I_DIRTY) { 969 if (inode->i_state & I_DIRTY) {
964 dprintk("nfsd: write sync %d\n", current->pid); 970 dprintk("nfsd: write sync %d\n", current->pid);
965 nfsd_sync(file); 971 err=nfsd_sync(file);
966 } 972 }
967#if 0 973#if 0
968 wake_up(&inode->i_wait); 974 wake_up(&inode->i_wait);
@@ -1066,7 +1072,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1066 return err; 1072 return err;
1067 if (EX_ISSYNC(fhp->fh_export)) { 1073 if (EX_ISSYNC(fhp->fh_export)) {
1068 if (file->f_op && file->f_op->fsync) { 1074 if (file->f_op && file->f_op->fsync) {
1069 nfsd_sync(file); 1075 err = nfsd_sync(file);
1070 } else { 1076 } else {
1071 err = nfserr_notsupp; 1077 err = nfserr_notsupp;
1072 } 1078 }
diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h
index 130d4f588a37..3f4f7142bbe3 100644
--- a/include/linux/nfsd/xdr.h
+++ b/include/linux/nfsd/xdr.h
@@ -88,10 +88,12 @@ struct nfsd_readdirargs {
88 88
89struct nfsd_attrstat { 89struct nfsd_attrstat {
90 struct svc_fh fh; 90 struct svc_fh fh;
91 struct kstat stat;
91}; 92};
92 93
93struct nfsd_diropres { 94struct nfsd_diropres {
94 struct svc_fh fh; 95 struct svc_fh fh;
96 struct kstat stat;
95}; 97};
96 98
97struct nfsd_readlinkres { 99struct nfsd_readlinkres {
@@ -101,6 +103,7 @@ struct nfsd_readlinkres {
101struct nfsd_readres { 103struct nfsd_readres {
102 struct svc_fh fh; 104 struct svc_fh fh;
103 unsigned long count; 105 unsigned long count;
106 struct kstat stat;
104}; 107};
105 108
106struct nfsd_readdirres { 109struct nfsd_readdirres {
diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
index 3c2a71b43bac..a4322741f8b9 100644
--- a/include/linux/nfsd/xdr3.h
+++ b/include/linux/nfsd/xdr3.h
@@ -126,6 +126,7 @@ struct nfsd3_setaclargs {
126struct nfsd3_attrstat { 126struct nfsd3_attrstat {
127 __u32 status; 127 __u32 status;
128 struct svc_fh fh; 128 struct svc_fh fh;
129 struct kstat stat;
129}; 130};
130 131
131/* LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD */ 132/* LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD */