aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@austin.ibm.com>2006-01-24 15:34:47 -0500
committerDave Kleikamp <shaggy@austin.ibm.com>2006-01-24 15:34:47 -0500
commit0a0fc0ddbe732779366ab6b1b879f62195e65967 (patch)
tree7b42490a676cf39ae0691b6859ecf7fd410f229b /fs/nfsd
parent4d5dbd0945d9e0833dd7964a3d6ee33157f7cc7a (diff)
parent3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff)
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs2acl.c2
-rw-r--r--fs/nfsd/nfs3acl.c2
-rw-r--r--fs/nfsd/nfs3proc.c11
-rw-r--r--fs/nfsd/nfs3xdr.c47
-rw-r--r--fs/nfsd/nfs4callback.c11
-rw-r--r--fs/nfsd/nfs4proc.c55
-rw-r--r--fs/nfsd/nfs4recover.c30
-rw-r--r--fs/nfsd/nfs4state.c220
-rw-r--r--fs/nfsd/nfs4xdr.c10
-rw-r--r--fs/nfsd/nfsproc.c37
-rw-r--r--fs/nfsd/nfsxdr.c52
-rw-r--r--fs/nfsd/vfs.c250
12 files changed, 343 insertions, 384 deletions
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 7cbf0682b2f0..fc95c4df6693 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -107,7 +107,7 @@ static int nfsacld_proc_setacl(struct svc_rqst * rqstp,
107 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); 107 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
108 108
109 fh = fh_copy(&resp->fh, &argp->fh); 109 fh = fh_copy(&resp->fh, &argp->fh);
110 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); 110 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_SATTR);
111 111
112 if (!nfserr) { 112 if (!nfserr) {
113 nfserr = nfserrno( nfsd_set_posix_acl( 113 nfserr = nfserrno( nfsd_set_posix_acl(
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 64ba40572fea..16e10c170aed 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -101,7 +101,7 @@ static int nfsd3_proc_setacl(struct svc_rqst * rqstp,
101 int nfserr = 0; 101 int nfserr = 0;
102 102
103 fh = fh_copy(&resp->fh, &argp->fh); 103 fh = fh_copy(&resp->fh, &argp->fh);
104 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); 104 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_SATTR);
105 105
106 if (!nfserr) { 106 if (!nfserr) {
107 nfserr = nfserrno( nfsd_set_posix_acl( 107 nfserr = nfserrno( nfsd_set_posix_acl(
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/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 583c0710e45e..d828662d737d 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -53,7 +53,7 @@
53#define NFSPROC4_CB_COMPOUND 1 53#define NFSPROC4_CB_COMPOUND 1
54 54
55/* declarations */ 55/* declarations */
56static void nfs4_cb_null(struct rpc_task *task); 56static const struct rpc_call_ops nfs4_cb_null_ops;
57 57
58/* Index of predefined Linux callback client operations */ 58/* Index of predefined Linux callback client operations */
59 59
@@ -431,7 +431,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
431 } 431 }
432 clnt->cl_intr = 0; 432 clnt->cl_intr = 0;
433 clnt->cl_softrtry = 1; 433 clnt->cl_softrtry = 1;
434 clnt->cl_chatty = 1;
435 434
436 /* Kick rpciod, put the call on the wire. */ 435 /* Kick rpciod, put the call on the wire. */
437 436
@@ -447,7 +446,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
447 msg.rpc_cred = nfsd4_lookupcred(clp,0); 446 msg.rpc_cred = nfsd4_lookupcred(clp,0);
448 if (IS_ERR(msg.rpc_cred)) 447 if (IS_ERR(msg.rpc_cred))
449 goto out_rpciod; 448 goto out_rpciod;
450 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, nfs4_cb_null, NULL); 449 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
451 put_rpccred(msg.rpc_cred); 450 put_rpccred(msg.rpc_cred);
452 451
453 if (status != 0) { 452 if (status != 0) {
@@ -469,7 +468,7 @@ out_err:
469} 468}
470 469
471static void 470static void
472nfs4_cb_null(struct rpc_task *task) 471nfs4_cb_null(struct rpc_task *task, void *dummy)
473{ 472{
474 struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; 473 struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
475 struct nfs4_callback *cb = &clp->cl_callback; 474 struct nfs4_callback *cb = &clp->cl_callback;
@@ -488,6 +487,10 @@ out:
488 put_nfs4_client(clp); 487 put_nfs4_client(clp);
489} 488}
490 489
490static const struct rpc_call_ops nfs4_cb_null_ops = {
491 .rpc_call_done = nfs4_cb_null,
492};
493
491/* 494/*
492 * called with dp->dl_count inc'ed. 495 * called with dp->dl_count inc'ed.
493 * nfs4_lock_state() may or may not have been called. 496 * nfs4_lock_state() may or may not have been called.
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 361b4007d4a0..a00fe8686293 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -192,6 +192,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
192 } 192 }
193 if (status) 193 if (status)
194 goto out; 194 goto out;
195
196 /* Openowner is now set, so sequence id will get bumped. Now we need
197 * these checks before we do any creates: */
198 if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
199 return nfserr_grace;
200 if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
201 return nfserr_no_grace;
202
195 switch (open->op_claim_type) { 203 switch (open->op_claim_type) {
196 case NFS4_OPEN_CLAIM_DELEGATE_CUR: 204 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
197 status = nfserr_inval; 205 status = nfserr_inval;
@@ -210,6 +218,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
210 goto out; 218 goto out;
211 break; 219 break;
212 case NFS4_OPEN_CLAIM_PREVIOUS: 220 case NFS4_OPEN_CLAIM_PREVIOUS:
221 open->op_stateowner->so_confirmed = 1;
213 /* 222 /*
214 * The CURRENT_FH is already set to the file being 223 * The CURRENT_FH is already set to the file being
215 * opened. (1) set open->op_cinfo, (2) set 224 * opened. (1) set open->op_cinfo, (2) set
@@ -221,6 +230,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
221 goto out; 230 goto out;
222 break; 231 break;
223 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 232 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
233 open->op_stateowner->so_confirmed = 1;
224 printk("NFSD: unsupported OPEN claim type %d\n", 234 printk("NFSD: unsupported OPEN claim type %d\n",
225 open->op_claim_type); 235 open->op_claim_type);
226 status = nfserr_notsupp; 236 status = nfserr_notsupp;
@@ -584,31 +594,23 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
584{ 594{
585 int status = nfs_ok; 595 int status = nfs_ok;
586 596
587 if (!current_fh->fh_dentry)
588 return nfserr_nofilehandle;
589
590 status = nfs_ok;
591 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 597 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
592 nfs4_lock_state(); 598 nfs4_lock_state();
593 if ((status = nfs4_preprocess_stateid_op(current_fh, 599 status = nfs4_preprocess_stateid_op(current_fh,
594 &setattr->sa_stateid, 600 &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
595 CHECK_FH | WR_STATE, NULL))) {
596 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
597 goto out_unlock;
598 }
599 nfs4_unlock_state(); 601 nfs4_unlock_state();
602 if (status) {
603 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!");
604 return status;
605 }
600 } 606 }
601 status = nfs_ok; 607 status = nfs_ok;
602 if (setattr->sa_acl != NULL) 608 if (setattr->sa_acl != NULL)
603 status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl); 609 status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
604 if (status) 610 if (status)
605 goto out; 611 return status;
606 status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 612 status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
607 0, (time_t)0); 613 0, (time_t)0);
608out:
609 return status;
610out_unlock:
611 nfs4_unlock_state();
612 return status; 614 return status;
613} 615}
614 616
@@ -626,15 +628,17 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
626 return nfserr_inval; 628 return nfserr_inval;
627 629
628 nfs4_lock_state(); 630 nfs4_lock_state();
629 if ((status = nfs4_preprocess_stateid_op(current_fh, stateid, 631 status = nfs4_preprocess_stateid_op(current_fh, stateid,
630 CHECK_FH | WR_STATE, &filp))) { 632 CHECK_FH | WR_STATE, &filp);
631 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
632 goto out;
633 }
634 if (filp) 633 if (filp)
635 get_file(filp); 634 get_file(filp);
636 nfs4_unlock_state(); 635 nfs4_unlock_state();
637 636
637 if (status) {
638 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
639 return status;
640 }
641
638 write->wr_bytes_written = write->wr_buflen; 642 write->wr_bytes_written = write->wr_buflen;
639 write->wr_how_written = write->wr_stable_how; 643 write->wr_how_written = write->wr_stable_how;
640 p = (u32 *)write->wr_verifier.data; 644 p = (u32 *)write->wr_verifier.data;
@@ -650,9 +654,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
650 if (status == nfserr_symlink) 654 if (status == nfserr_symlink)
651 status = nfserr_inval; 655 status = nfserr_inval;
652 return status; 656 return status;
653out:
654 nfs4_unlock_state();
655 return status;
656} 657}
657 658
658/* This routine never returns NFS_OK! If there are no other errors, it 659/* This routine never returns NFS_OK! If there are no other errors, it
@@ -768,6 +769,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
768 while (!status && resp->opcnt < args->opcnt) { 769 while (!status && resp->opcnt < args->opcnt) {
769 op = &args->ops[resp->opcnt++]; 770 op = &args->ops[resp->opcnt++];
770 771
772 dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum);
773
771 /* 774 /*
772 * The XDR decode routines may have pre-set op->status; 775 * The XDR decode routines may have pre-set op->status;
773 * for example, if there is a miscellaneous XDR error 776 * for example, if there is a miscellaneous XDR error
@@ -792,17 +795,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
792 /* All operations except RENEW, SETCLIENTID, RESTOREFH 795 /* All operations except RENEW, SETCLIENTID, RESTOREFH
793 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH 796 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
794 * require a valid current filehandle 797 * require a valid current filehandle
795 *
796 * SETATTR NOFILEHANDLE error handled in nfsd4_setattr
797 * due to required returned bitmap argument
798 */ 798 */
799 if ((!current_fh->fh_dentry) && 799 if ((!current_fh->fh_dentry) &&
800 !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) || 800 !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
801 (op->opnum == OP_SETCLIENTID) || 801 (op->opnum == OP_SETCLIENTID) ||
802 (op->opnum == OP_SETCLIENTID_CONFIRM) || 802 (op->opnum == OP_SETCLIENTID_CONFIRM) ||
803 (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) || 803 (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
804 (op->opnum == OP_RELEASE_LOCKOWNER) || 804 (op->opnum == OP_RELEASE_LOCKOWNER))) {
805 (op->opnum == OP_SETATTR))) {
806 op->status = nfserr_nofilehandle; 805 op->status = nfserr_nofilehandle;
807 goto encode_op; 806 goto encode_op;
808 } 807 }
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 954cf893d50c..06da7506363c 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -121,9 +121,9 @@ out:
121static void 121static void
122nfsd4_sync_rec_dir(void) 122nfsd4_sync_rec_dir(void)
123{ 123{
124 down(&rec_dir.dentry->d_inode->i_sem); 124 mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
125 nfsd_sync_dir(rec_dir.dentry); 125 nfsd_sync_dir(rec_dir.dentry);
126 up(&rec_dir.dentry->d_inode->i_sem); 126 mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
127} 127}
128 128
129int 129int
@@ -143,7 +143,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
143 nfs4_save_user(&uid, &gid); 143 nfs4_save_user(&uid, &gid);
144 144
145 /* lock the parent */ 145 /* lock the parent */
146 down(&rec_dir.dentry->d_inode->i_sem); 146 mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
147 147
148 dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1); 148 dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1);
149 if (IS_ERR(dentry)) { 149 if (IS_ERR(dentry)) {
@@ -159,7 +159,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
159out_put: 159out_put:
160 dput(dentry); 160 dput(dentry);
161out_unlock: 161out_unlock:
162 up(&rec_dir.dentry->d_inode->i_sem); 162 mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
163 if (status == 0) { 163 if (status == 0) {
164 clp->cl_firststate = 1; 164 clp->cl_firststate = 1;
165 nfsd4_sync_rec_dir(); 165 nfsd4_sync_rec_dir();
@@ -222,8 +222,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
222 222
223 nfs4_save_user(&uid, &gid); 223 nfs4_save_user(&uid, &gid);
224 224
225 filp = dentry_open(dget(dir), mntget(rec_dir.mnt), 225 filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
226 O_RDWR);
227 status = PTR_ERR(filp); 226 status = PTR_ERR(filp);
228 if (IS_ERR(filp)) 227 if (IS_ERR(filp))
229 goto out; 228 goto out;
@@ -259,9 +258,9 @@ nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
259 printk("nfsd4: non-file found in client recovery directory\n"); 258 printk("nfsd4: non-file found in client recovery directory\n");
260 return -EINVAL; 259 return -EINVAL;
261 } 260 }
262 down(&dir->d_inode->i_sem); 261 mutex_lock(&dir->d_inode->i_mutex);
263 status = vfs_unlink(dir->d_inode, dentry); 262 status = vfs_unlink(dir->d_inode, dentry);
264 up(&dir->d_inode->i_sem); 263 mutex_unlock(&dir->d_inode->i_mutex);
265 return status; 264 return status;
266} 265}
267 266
@@ -274,9 +273,9 @@ nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
274 * any regular files anyway, just in case the directory was created by 273 * any regular files anyway, just in case the directory was created by
275 * a kernel from the future.... */ 274 * a kernel from the future.... */
276 nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); 275 nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
277 down(&dir->d_inode->i_sem); 276 mutex_lock(&dir->d_inode->i_mutex);
278 status = vfs_rmdir(dir->d_inode, dentry); 277 status = vfs_rmdir(dir->d_inode, dentry);
279 up(&dir->d_inode->i_sem); 278 mutex_unlock(&dir->d_inode->i_mutex);
280 return status; 279 return status;
281} 280}
282 281
@@ -288,9 +287,9 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
288 287
289 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); 288 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
290 289
291 down(&rec_dir.dentry->d_inode->i_sem); 290 mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
292 dentry = lookup_one_len(name, rec_dir.dentry, namlen); 291 dentry = lookup_one_len(name, rec_dir.dentry, namlen);
293 up(&rec_dir.dentry->d_inode->i_sem); 292 mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
294 if (IS_ERR(dentry)) { 293 if (IS_ERR(dentry)) {
295 status = PTR_ERR(dentry); 294 status = PTR_ERR(dentry);
296 return status; 295 return status;
@@ -400,9 +399,10 @@ nfsd4_init_recdir(char *rec_dirname)
400 399
401 nfs4_save_user(&uid, &gid); 400 nfs4_save_user(&uid, &gid);
402 401
403 status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir); 402 status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
404 if (status == -ENOENT) 403 &rec_dir);
405 printk("NFSD: recovery directory %s doesn't exist\n", 404 if (status)
405 printk("NFSD: unable to find recovery directory %s\n",
406 rec_dirname); 406 rec_dirname);
407 407
408 if (!status) 408 if (!status)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6bbefd06f10d..1143cfb64549 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1088,7 +1088,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
1088 sop->so_seqid = open->op_seqid; 1088 sop->so_seqid = open->op_seqid;
1089 sop->so_confirmed = 0; 1089 sop->so_confirmed = 0;
1090 rp = &sop->so_replay; 1090 rp = &sop->so_replay;
1091 rp->rp_status = NFSERR_SERVERFAULT; 1091 rp->rp_status = nfserr_serverfault;
1092 rp->rp_buflen = 0; 1092 rp->rp_buflen = 0;
1093 rp->rp_buf = rp->rp_ibuf; 1093 rp->rp_buf = rp->rp_ibuf;
1094 return sop; 1094 return sop;
@@ -1178,7 +1178,6 @@ release_stateid(struct nfs4_stateid *stp, int flags)
1178 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner); 1178 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
1179 put_nfs4_file(stp->st_file); 1179 put_nfs4_file(stp->st_file);
1180 kmem_cache_free(stateid_slab, stp); 1180 kmem_cache_free(stateid_slab, stp);
1181 stp = NULL;
1182} 1181}
1183 1182
1184static void 1183static void
@@ -1191,22 +1190,6 @@ move_to_close_lru(struct nfs4_stateowner *sop)
1191 sop->so_time = get_seconds(); 1190 sop->so_time = get_seconds();
1192} 1191}
1193 1192
1194static void
1195release_state_owner(struct nfs4_stateid *stp, int flag)
1196{
1197 struct nfs4_stateowner *sop = stp->st_stateowner;
1198
1199 dprintk("NFSD: release_state_owner\n");
1200 release_stateid(stp, flag);
1201
1202 /* place unused nfs4_stateowners on so_close_lru list to be
1203 * released by the laundromat service after the lease period
1204 * to enable us to handle CLOSE replay
1205 */
1206 if (sop->so_confirmed && list_empty(&sop->so_stateids))
1207 move_to_close_lru(sop);
1208}
1209
1210static int 1193static int
1211cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) { 1194cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
1212 return ((sop->so_owner.len == owner->len) && 1195 return ((sop->so_owner.len == owner->len) &&
@@ -1446,92 +1429,61 @@ static struct lock_manager_operations nfsd_lease_mng_ops = {
1446}; 1429};
1447 1430
1448 1431
1449/*
1450 * nfsd4_process_open1()
1451 * lookup stateowner.
1452 * found:
1453 * check confirmed
1454 * confirmed:
1455 * check seqid
1456 * not confirmed:
1457 * delete owner
1458 * create new owner
1459 * notfound:
1460 * verify clientid
1461 * create new owner
1462 *
1463 * called with nfs4_lock_state() held.
1464 */
1465int 1432int
1466nfsd4_process_open1(struct nfsd4_open *open) 1433nfsd4_process_open1(struct nfsd4_open *open)
1467{ 1434{
1468 int status;
1469 clientid_t *clientid = &open->op_clientid; 1435 clientid_t *clientid = &open->op_clientid;
1470 struct nfs4_client *clp = NULL; 1436 struct nfs4_client *clp = NULL;
1471 unsigned int strhashval; 1437 unsigned int strhashval;
1472 struct nfs4_stateowner *sop = NULL; 1438 struct nfs4_stateowner *sop = NULL;
1473 1439
1474 status = nfserr_inval;
1475 if (!check_name(open->op_owner)) 1440 if (!check_name(open->op_owner))
1476 goto out; 1441 return nfserr_inval;
1477 1442
1478 if (STALE_CLIENTID(&open->op_clientid)) 1443 if (STALE_CLIENTID(&open->op_clientid))
1479 return nfserr_stale_clientid; 1444 return nfserr_stale_clientid;
1480 1445
1481 strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner); 1446 strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
1482 sop = find_openstateowner_str(strhashval, open); 1447 sop = find_openstateowner_str(strhashval, open);
1483 if (sop) { 1448 open->op_stateowner = sop;
1484 open->op_stateowner = sop; 1449 if (!sop) {
1485 /* check for replay */ 1450 /* Make sure the client's lease hasn't expired. */
1486 if (open->op_seqid == sop->so_seqid - 1){
1487 if (sop->so_replay.rp_buflen)
1488 return NFSERR_REPLAY_ME;
1489 else {
1490 /* The original OPEN failed so spectacularly
1491 * that we don't even have replay data saved!
1492 * Therefore, we have no choice but to continue
1493 * processing this OPEN; presumably, we'll
1494 * fail again for the same reason.
1495 */
1496 dprintk("nfsd4_process_open1:"
1497 " replay with no replay cache\n");
1498 goto renew;
1499 }
1500 } else if (sop->so_confirmed) {
1501 if (open->op_seqid == sop->so_seqid)
1502 goto renew;
1503 status = nfserr_bad_seqid;
1504 goto out;
1505 } else {
1506 /* If we get here, we received an OPEN for an
1507 * unconfirmed nfs4_stateowner. Since the seqid's are
1508 * different, purge the existing nfs4_stateowner, and
1509 * instantiate a new one.
1510 */
1511 clp = sop->so_client;
1512 release_stateowner(sop);
1513 }
1514 } else {
1515 /* nfs4_stateowner not found.
1516 * Verify clientid and instantiate new nfs4_stateowner.
1517 * If verify fails this is presumably the result of the
1518 * client's lease expiring.
1519 */
1520 status = nfserr_expired;
1521 clp = find_confirmed_client(clientid); 1451 clp = find_confirmed_client(clientid);
1522 if (clp == NULL) 1452 if (clp == NULL)
1523 goto out; 1453 return nfserr_expired;
1454 goto renew;
1524 } 1455 }
1525 status = nfserr_resource; 1456 if (!sop->so_confirmed) {
1526 sop = alloc_init_open_stateowner(strhashval, clp, open); 1457 /* Replace unconfirmed owners without checking for replay. */
1527 if (sop == NULL) 1458 clp = sop->so_client;
1528 goto out; 1459 release_stateowner(sop);
1529 open->op_stateowner = sop; 1460 open->op_stateowner = NULL;
1461 goto renew;
1462 }
1463 if (open->op_seqid == sop->so_seqid - 1) {
1464 if (sop->so_replay.rp_buflen)
1465 return NFSERR_REPLAY_ME;
1466 /* The original OPEN failed so spectacularly
1467 * that we don't even have replay data saved!
1468 * Therefore, we have no choice but to continue
1469 * processing this OPEN; presumably, we'll
1470 * fail again for the same reason.
1471 */
1472 dprintk("nfsd4_process_open1: replay with no replay cache\n");
1473 goto renew;
1474 }
1475 if (open->op_seqid != sop->so_seqid)
1476 return nfserr_bad_seqid;
1530renew: 1477renew:
1531 status = nfs_ok; 1478 if (open->op_stateowner == NULL) {
1479 sop = alloc_init_open_stateowner(strhashval, clp, open);
1480 if (sop == NULL)
1481 return nfserr_resource;
1482 open->op_stateowner = sop;
1483 }
1484 list_del_init(&sop->so_close_lru);
1532 renew_client(sop->so_client); 1485 renew_client(sop->so_client);
1533out: 1486 return nfs_ok;
1534 return status;
1535} 1487}
1536 1488
1537static inline int 1489static inline int
@@ -1648,7 +1600,7 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
1648 if (!open->op_truncate) 1600 if (!open->op_truncate)
1649 return 0; 1601 return 0;
1650 if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) 1602 if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
1651 return -EINVAL; 1603 return nfserr_inval;
1652 return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0); 1604 return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
1653} 1605}
1654 1606
@@ -1657,26 +1609,26 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
1657{ 1609{
1658 struct file *filp = stp->st_vfs_file; 1610 struct file *filp = stp->st_vfs_file;
1659 struct inode *inode = filp->f_dentry->d_inode; 1611 struct inode *inode = filp->f_dentry->d_inode;
1660 unsigned int share_access; 1612 unsigned int share_access, new_writer;
1661 int status; 1613 int status;
1662 1614
1663 set_access(&share_access, stp->st_access_bmap); 1615 set_access(&share_access, stp->st_access_bmap);
1664 share_access = ~share_access; 1616 new_writer = (~share_access) & open->op_share_access
1665 share_access &= open->op_share_access; 1617 & NFS4_SHARE_ACCESS_WRITE;
1666
1667 if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
1668 return nfsd4_truncate(rqstp, cur_fh, open);
1669 1618
1670 status = get_write_access(inode); 1619 if (new_writer) {
1671 if (status) 1620 status = get_write_access(inode);
1672 return nfserrno(status); 1621 if (status)
1622 return nfserrno(status);
1623 }
1673 status = nfsd4_truncate(rqstp, cur_fh, open); 1624 status = nfsd4_truncate(rqstp, cur_fh, open);
1674 if (status) { 1625 if (status) {
1675 put_write_access(inode); 1626 if (new_writer)
1627 put_write_access(inode);
1676 return status; 1628 return status;
1677 } 1629 }
1678 /* remember the open */ 1630 /* remember the open */
1679 filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ; 1631 filp->f_mode |= open->op_share_access;
1680 set_bit(open->op_share_access, &stp->st_access_bmap); 1632 set_bit(open->op_share_access, &stp->st_access_bmap);
1681 set_bit(open->op_share_deny, &stp->st_deny_bmap); 1633 set_bit(open->op_share_deny, &stp->st_deny_bmap);
1682 1634
@@ -1780,12 +1732,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1780 struct nfs4_delegation *dp = NULL; 1732 struct nfs4_delegation *dp = NULL;
1781 int status; 1733 int status;
1782 1734
1783 if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
1784 return nfserr_grace;
1785
1786 if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
1787 return nfserr_no_grace;
1788
1789 status = nfserr_inval; 1735 status = nfserr_inval;
1790 if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) 1736 if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
1791 goto out; 1737 goto out;
@@ -2423,15 +2369,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
2423 CHECK_FH | OPEN_STATE | CLOSE_STATE, 2369 CHECK_FH | OPEN_STATE | CLOSE_STATE,
2424 &close->cl_stateowner, &stp, NULL))) 2370 &close->cl_stateowner, &stp, NULL)))
2425 goto out; 2371 goto out;
2426 /*
2427 * Return success, but first update the stateid.
2428 */
2429 status = nfs_ok; 2372 status = nfs_ok;
2430 update_stateid(&stp->st_stateid); 2373 update_stateid(&stp->st_stateid);
2431 memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t)); 2374 memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
2432 2375
2433 /* release_state_owner() calls nfsd_close() if needed */ 2376 /* release_stateid() calls nfsd_close() if needed */
2434 release_state_owner(stp, OPEN_STATE); 2377 release_stateid(stp, OPEN_STATE);
2378
2379 /* place unused nfs4_stateowners on so_close_lru list to be
2380 * released by the laundromat service after the lease period
2381 * to enable us to handle CLOSE replay
2382 */
2383 if (list_empty(&close->cl_stateowner->so_stateids))
2384 move_to_close_lru(close->cl_stateowner);
2435out: 2385out:
2436 if (close->cl_stateowner) { 2386 if (close->cl_stateowner) {
2437 nfs4_get_stateowner(close->cl_stateowner); 2387 nfs4_get_stateowner(close->cl_stateowner);
@@ -2633,7 +2583,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2633 sop->so_seqid = lock->lk_new_lock_seqid + 1; 2583 sop->so_seqid = lock->lk_new_lock_seqid + 1;
2634 sop->so_confirmed = 1; 2584 sop->so_confirmed = 1;
2635 rp = &sop->so_replay; 2585 rp = &sop->so_replay;
2636 rp->rp_status = NFSERR_SERVERFAULT; 2586 rp->rp_status = nfserr_serverfault;
2637 rp->rp_buflen = 0; 2587 rp->rp_buflen = 0;
2638 rp->rp_buf = rp->rp_ibuf; 2588 rp->rp_buf = rp->rp_ibuf;
2639 return sop; 2589 return sop;
@@ -2700,6 +2650,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2700 if (check_lock_length(lock->lk_offset, lock->lk_length)) 2650 if (check_lock_length(lock->lk_offset, lock->lk_length))
2701 return nfserr_inval; 2651 return nfserr_inval;
2702 2652
2653 if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
2654 dprintk("NFSD: nfsd4_lock: permission denied!\n");
2655 return status;
2656 }
2657
2703 nfs4_lock_state(); 2658 nfs4_lock_state();
2704 2659
2705 if (lock->lk_is_new) { 2660 if (lock->lk_is_new) {
@@ -2720,11 +2675,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2720 lock->lk_new_open_seqid, 2675 lock->lk_new_open_seqid,
2721 &lock->lk_new_open_stateid, 2676 &lock->lk_new_open_stateid,
2722 CHECK_FH | OPEN_STATE, 2677 CHECK_FH | OPEN_STATE,
2723 &lock->lk_stateowner, &open_stp, 2678 &lock->lk_replay_owner, &open_stp,
2724 lock); 2679 lock);
2725 if (status) 2680 if (status)
2726 goto out; 2681 goto out;
2727 open_sop = lock->lk_stateowner; 2682 open_sop = lock->lk_replay_owner;
2728 /* create lockowner and lock stateid */ 2683 /* create lockowner and lock stateid */
2729 fp = open_stp->st_file; 2684 fp = open_stp->st_file;
2730 strhashval = lock_ownerstr_hashval(fp->fi_inode, 2685 strhashval = lock_ownerstr_hashval(fp->fi_inode,
@@ -2739,29 +2694,22 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2739 if (lock_sop == NULL) 2694 if (lock_sop == NULL)
2740 goto out; 2695 goto out;
2741 lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp); 2696 lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
2742 if (lock_stp == NULL) { 2697 if (lock_stp == NULL)
2743 release_stateowner(lock_sop);
2744 goto out; 2698 goto out;
2745 }
2746 } else { 2699 } else {
2747 /* lock (lock owner + lock stateid) already exists */ 2700 /* lock (lock owner + lock stateid) already exists */
2748 status = nfs4_preprocess_seqid_op(current_fh, 2701 status = nfs4_preprocess_seqid_op(current_fh,
2749 lock->lk_old_lock_seqid, 2702 lock->lk_old_lock_seqid,
2750 &lock->lk_old_lock_stateid, 2703 &lock->lk_old_lock_stateid,
2751 CHECK_FH | LOCK_STATE, 2704 CHECK_FH | LOCK_STATE,
2752 &lock->lk_stateowner, &lock_stp, lock); 2705 &lock->lk_replay_owner, &lock_stp, lock);
2753 if (status) 2706 if (status)
2754 goto out; 2707 goto out;
2755 lock_sop = lock->lk_stateowner; 2708 lock_sop = lock->lk_replay_owner;
2756 } 2709 }
2757 /* lock->lk_stateowner and lock_stp have been created or found */ 2710 /* lock->lk_replay_owner and lock_stp have been created or found */
2758 filp = lock_stp->st_vfs_file; 2711 filp = lock_stp->st_vfs_file;
2759 2712
2760 if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
2761 dprintk("NFSD: nfsd4_lock: permission denied!\n");
2762 goto out;
2763 }
2764
2765 status = nfserr_grace; 2713 status = nfserr_grace;
2766 if (nfs4_in_grace() && !lock->lk_reclaim) 2714 if (nfs4_in_grace() && !lock->lk_reclaim)
2767 goto out; 2715 goto out;
@@ -2802,8 +2750,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2802 */ 2750 */
2803 2751
2804 status = posix_lock_file(filp, &file_lock); 2752 status = posix_lock_file(filp, &file_lock);
2805 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2806 file_lock.fl_ops->fl_release_private(&file_lock);
2807 dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status); 2753 dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
2808 switch (-status) { 2754 switch (-status) {
2809 case 0: /* success! */ 2755 case 0: /* success! */
@@ -2815,9 +2761,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2815 goto conflicting_lock; 2761 goto conflicting_lock;
2816 case (EDEADLK): 2762 case (EDEADLK):
2817 status = nfserr_deadlock; 2763 status = nfserr_deadlock;
2764 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
2765 goto out;
2818 default: 2766 default:
2767 status = nfserrno(status);
2819 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); 2768 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
2820 goto out_destroy_new_stateid; 2769 goto out;
2821 } 2770 }
2822 2771
2823conflicting_lock: 2772conflicting_lock:
@@ -2831,20 +2780,12 @@ conflicting_lock:
2831 goto out; 2780 goto out;
2832 } 2781 }
2833 nfs4_set_lock_denied(conflock, &lock->lk_denied); 2782 nfs4_set_lock_denied(conflock, &lock->lk_denied);
2834
2835out_destroy_new_stateid:
2836 if (lock->lk_is_new) {
2837 dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
2838 /*
2839 * An error encountered after instantiation of the new
2840 * stateid has forced us to destroy it.
2841 */
2842 release_state_owner(lock_stp, LOCK_STATE);
2843 }
2844out: 2783out:
2845 if (lock->lk_stateowner) { 2784 if (status && lock->lk_is_new && lock_sop)
2846 nfs4_get_stateowner(lock->lk_stateowner); 2785 release_stateowner(lock_sop);
2847 *replay_owner = lock->lk_stateowner; 2786 if (lock->lk_replay_owner) {
2787 nfs4_get_stateowner(lock->lk_replay_owner);
2788 *replay_owner = lock->lk_replay_owner;
2848 } 2789 }
2849 nfs4_unlock_state(); 2790 nfs4_unlock_state();
2850 return status; 2791 return status;
@@ -2977,8 +2918,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2977 * Try to unlock the file in the VFS. 2918 * Try to unlock the file in the VFS.
2978 */ 2919 */
2979 status = posix_lock_file(filp, &file_lock); 2920 status = posix_lock_file(filp, &file_lock);
2980 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2981 file_lock.fl_ops->fl_release_private(&file_lock);
2982 if (status) { 2921 if (status) {
2983 dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n"); 2922 dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
2984 goto out_nfserr; 2923 goto out_nfserr;
@@ -3016,9 +2955,10 @@ check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
3016 2955
3017 lock_kernel(); 2956 lock_kernel();
3018 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { 2957 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
3019 if ((*flpp)->fl_owner == (fl_owner_t)lowner) 2958 if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
3020 status = 1; 2959 status = 1;
3021 goto out; 2960 goto out;
2961 }
3022 } 2962 }
3023out: 2963out:
3024 unlock_kernel(); 2964 unlock_kernel();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index dcd673186944..69d3501173a8 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -528,7 +528,7 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
528{ 528{
529 DECODE_HEAD; 529 DECODE_HEAD;
530 530
531 lock->lk_stateowner = NULL; 531 lock->lk_replay_owner = NULL;
532 /* 532 /*
533 * type, reclaim(boolean), offset, length, new_lock_owner(boolean) 533 * type, reclaim(boolean), offset, length, new_lock_owner(boolean)
534 */ 534 */
@@ -1764,10 +1764,11 @@ nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
1764 */ 1764 */
1765 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)) 1765 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
1766 goto fail; 1766 goto fail;
1767 nfserr = nfserr_toosmall;
1768 p = nfsd4_encode_rdattr_error(p, buflen, nfserr); 1767 p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
1769 if (p == NULL) 1768 if (p == NULL) {
1769 nfserr = nfserr_toosmall;
1770 goto fail; 1770 goto fail;
1771 }
1771 } 1772 }
1772 cd->buflen -= (p - cd->buffer); 1773 cd->buflen -= (p - cd->buffer);
1773 cd->buffer = p; 1774 cd->buffer = p;
@@ -1895,7 +1896,6 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie
1895static void 1896static void
1896nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock) 1897nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
1897{ 1898{
1898
1899 ENCODE_SEQID_OP_HEAD; 1899 ENCODE_SEQID_OP_HEAD;
1900 1900
1901 if (!nfserr) { 1901 if (!nfserr) {
@@ -1906,7 +1906,7 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock
1906 } else if (nfserr == nfserr_denied) 1906 } else if (nfserr == nfserr_denied)
1907 nfsd4_encode_lock_denied(resp, &lock->lk_denied); 1907 nfsd4_encode_lock_denied(resp, &lock->lk_denied);
1908 1908
1909 ENCODE_SEQID_OP_TAIL(lock->lk_stateowner); 1909 ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
1910} 1910}
1911 1911
1912static void 1912static void
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 0aa1b9603d7f..3e6b75cd90fd 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -36,6 +36,22 @@ nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
36 return nfs_ok; 36 return nfs_ok;
37} 37}
38 38
39static int
40nfsd_return_attrs(int err, struct nfsd_attrstat *resp)
41{
42 if (err) return err;
43 return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
44 resp->fh.fh_dentry,
45 &resp->stat));
46}
47static int
48nfsd_return_dirop(int err, struct nfsd_diropres *resp)
49{
50 if (err) return err;
51 return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
52 resp->fh.fh_dentry,
53 &resp->stat));
54}
39/* 55/*
40 * Get a file's attributes 56 * Get a file's attributes
41 * N.B. After this call resp->fh needs an fh_put 57 * N.B. After this call resp->fh needs an fh_put
@@ -44,10 +60,12 @@ static int
44nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, 60nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
45 struct nfsd_attrstat *resp) 61 struct nfsd_attrstat *resp)
46{ 62{
63 int nfserr;
47 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); 64 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
48 65
49 fh_copy(&resp->fh, &argp->fh); 66 fh_copy(&resp->fh, &argp->fh);
50 return fh_verify(rqstp, &resp->fh, 0, MAY_NOP); 67 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
68 return nfsd_return_attrs(nfserr, resp);
51} 69}
52 70
53/* 71/*
@@ -58,12 +76,14 @@ static int
58nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp, 76nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
59 struct nfsd_attrstat *resp) 77 struct nfsd_attrstat *resp)
60{ 78{
79 int nfserr;
61 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n", 80 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
62 SVCFH_fmt(&argp->fh), 81 SVCFH_fmt(&argp->fh),
63 argp->attrs.ia_valid, (long) argp->attrs.ia_size); 82 argp->attrs.ia_valid, (long) argp->attrs.ia_size);
64 83
65 fh_copy(&resp->fh, &argp->fh); 84 fh_copy(&resp->fh, &argp->fh);
66 return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0); 85 nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
86 return nfsd_return_attrs(nfserr, resp);
67} 87}
68 88
69/* 89/*
@@ -86,7 +106,7 @@ nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
86 &resp->fh); 106 &resp->fh);
87 107
88 fh_put(&argp->fh); 108 fh_put(&argp->fh);
89 return nfserr; 109 return nfsd_return_dirop(nfserr, resp);
90} 110}
91 111
92/* 112/*
@@ -142,7 +162,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
142 argp->vec, argp->vlen, 162 argp->vec, argp->vlen,
143 &resp->count); 163 &resp->count);
144 164
145 return nfserr; 165 if (nfserr) return nfserr;
166 return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
167 resp->fh.fh_dentry,
168 &resp->stat));
146} 169}
147 170
148/* 171/*
@@ -165,7 +188,7 @@ nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
165 argp->vec, argp->vlen, 188 argp->vec, argp->vlen,
166 argp->len, 189 argp->len,
167 &stable); 190 &stable);
168 return nfserr; 191 return nfsd_return_attrs(nfserr, resp);
169} 192}
170 193
171/* 194/*
@@ -322,7 +345,7 @@ out_unlock:
322 345
323done: 346done:
324 fh_put(dirfhp); 347 fh_put(dirfhp);
325 return nfserr; 348 return nfsd_return_dirop(nfserr, resp);
326} 349}
327 350
328static int 351static int
@@ -425,7 +448,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
425 nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, 448 nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
426 &argp->attrs, S_IFDIR, 0, &resp->fh); 449 &argp->attrs, S_IFDIR, 0, &resp->fh);
427 fh_put(&argp->fh); 450 fh_put(&argp->fh);
428 return nfserr; 451 return nfsd_return_dirop(nfserr, resp);
429} 452}
430 453
431/* 454/*
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index b45999ff33e6..e3a0797dd56b 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -37,7 +37,7 @@ static u32 nfs_ftypes[] = {
37/* 37/*
38 * XDR functions for basic NFS types 38 * XDR functions for basic NFS types
39 */ 39 */
40static inline u32 * 40static u32 *
41decode_fh(u32 *p, struct svc_fh *fhp) 41decode_fh(u32 *p, struct svc_fh *fhp)
42{ 42{
43 fh_init(fhp, NFS_FHSIZE); 43 fh_init(fhp, NFS_FHSIZE);
@@ -151,47 +151,45 @@ decode_sattr(u32 *p, struct iattr *iap)
151 return p; 151 return p;
152} 152}
153 153
154static inline u32 * 154static 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..5320e5afaddb 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -48,8 +48,8 @@
48#include <linux/fsnotify.h> 48#include <linux/fsnotify.h>
49#include <linux/posix_acl.h> 49#include <linux/posix_acl.h>
50#include <linux/posix_acl_xattr.h> 50#include <linux/posix_acl_xattr.h>
51#ifdef CONFIG_NFSD_V4
52#include <linux/xattr.h> 51#include <linux/xattr.h>
52#ifdef CONFIG_NFSD_V4
53#include <linux/nfs4.h> 53#include <linux/nfs4.h>
54#include <linux/nfs4_acl.h> 54#include <linux/nfs4_acl.h>
55#include <linux/nfsd_idmap.h> 55#include <linux/nfsd_idmap.h>
@@ -365,8 +365,30 @@ out_nfserr:
365 goto out; 365 goto out;
366} 366}
367 367
368#if defined(CONFIG_NFSD_V4) 368#if defined(CONFIG_NFSD_V2_ACL) || \
369 defined(CONFIG_NFSD_V3_ACL) || \
370 defined(CONFIG_NFSD_V4)
371static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
372{
373 ssize_t buflen;
374 int error;
375
376 buflen = vfs_getxattr(dentry, key, NULL, 0);
377 if (buflen <= 0)
378 return buflen;
379
380 *buf = kmalloc(buflen, GFP_KERNEL);
381 if (!*buf)
382 return -ENOMEM;
383
384 error = vfs_getxattr(dentry, key, *buf, buflen);
385 if (error < 0)
386 return error;
387 return buflen;
388}
389#endif
369 390
391#if defined(CONFIG_NFSD_V4)
370static int 392static int
371set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key) 393set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
372{ 394{
@@ -374,7 +396,6 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
374 size_t buflen; 396 size_t buflen;
375 char *buf = NULL; 397 char *buf = NULL;
376 int error = 0; 398 int error = 0;
377 struct inode *inode = dentry->d_inode;
378 399
379 buflen = posix_acl_xattr_size(pacl->a_count); 400 buflen = posix_acl_xattr_size(pacl->a_count);
380 buf = kmalloc(buflen, GFP_KERNEL); 401 buf = kmalloc(buflen, GFP_KERNEL);
@@ -388,15 +409,7 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
388 goto out; 409 goto out;
389 } 410 }
390 411
391 error = -EOPNOTSUPP; 412 error = vfs_setxattr(dentry, key, buf, len, 0);
392 if (inode->i_op && inode->i_op->setxattr) {
393 down(&inode->i_sem);
394 security_inode_setxattr(dentry, key, buf, len, 0);
395 error = inode->i_op->setxattr(dentry, key, buf, len, 0);
396 if (!error)
397 security_inode_post_setxattr(dentry, key, buf, len, 0);
398 up(&inode->i_sem);
399 }
400out: 413out:
401 kfree(buf); 414 kfree(buf);
402 return error; 415 return error;
@@ -455,44 +468,19 @@ out_nfserr:
455static struct posix_acl * 468static struct posix_acl *
456_get_posix_acl(struct dentry *dentry, char *key) 469_get_posix_acl(struct dentry *dentry, char *key)
457{ 470{
458 struct inode *inode = dentry->d_inode; 471 void *buf = NULL;
459 char *buf = NULL;
460 int buflen, error = 0;
461 struct posix_acl *pacl = NULL; 472 struct posix_acl *pacl = NULL;
473 int buflen;
462 474
463 error = -EOPNOTSUPP; 475 buflen = nfsd_getxattr(dentry, key, &buf);
464 if (inode->i_op == NULL) 476 if (!buflen)
465 goto out_err; 477 buflen = -ENODATA;
466 if (inode->i_op->getxattr == NULL) 478 if (buflen <= 0)
467 goto out_err; 479 return ERR_PTR(buflen);
468
469 error = security_inode_getxattr(dentry, key);
470 if (error)
471 goto out_err;
472
473 buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
474 if (buflen <= 0) {
475 error = buflen < 0 ? buflen : -ENODATA;
476 goto out_err;
477 }
478
479 buf = kmalloc(buflen, GFP_KERNEL);
480 if (buf == NULL) {
481 error = -ENOMEM;
482 goto out_err;
483 }
484
485 error = inode->i_op->getxattr(dentry, key, buf, buflen);
486 if (error < 0)
487 goto out_err;
488 480
489 pacl = posix_acl_from_xattr(buf, buflen); 481 pacl = posix_acl_from_xattr(buf, buflen);
490 out:
491 kfree(buf); 482 kfree(buf);
492 return pacl; 483 return pacl;
493 out_err:
494 pacl = ERR_PTR(error);
495 goto out;
496} 484}
497 485
498int 486int
@@ -717,33 +705,40 @@ nfsd_close(struct file *filp)
717 * As this calls fsync (not fdatasync) there is no need for a write_inode 705 * As this calls fsync (not fdatasync) there is no need for a write_inode
718 * after it. 706 * after it.
719 */ 707 */
720static inline void nfsd_dosync(struct file *filp, struct dentry *dp, 708static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
721 struct file_operations *fop) 709 struct file_operations *fop)
722{ 710{
723 struct inode *inode = dp->d_inode; 711 struct inode *inode = dp->d_inode;
724 int (*fsync) (struct file *, struct dentry *, int); 712 int (*fsync) (struct file *, struct dentry *, int);
713 int err;
714
715 err = filemap_fdatawrite(inode->i_mapping);
716 if (err == 0 && fop && (fsync = fop->fsync))
717 err = fsync(filp, dp, 0);
718 if (err == 0)
719 err = filemap_fdatawait(inode->i_mapping);
725 720
726 filemap_fdatawrite(inode->i_mapping); 721 return err;
727 if (fop && (fsync = fop->fsync))
728 fsync(filp, dp, 0);
729 filemap_fdatawait(inode->i_mapping);
730} 722}
731 723
732 724
733static void 725static int
734nfsd_sync(struct file *filp) 726nfsd_sync(struct file *filp)
735{ 727{
728 int err;
736 struct inode *inode = filp->f_dentry->d_inode; 729 struct inode *inode = filp->f_dentry->d_inode;
737 dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name); 730 dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
738 down(&inode->i_sem); 731 mutex_lock(&inode->i_mutex);
739 nfsd_dosync(filp, filp->f_dentry, filp->f_op); 732 err=nfsd_dosync(filp, filp->f_dentry, filp->f_op);
740 up(&inode->i_sem); 733 mutex_unlock(&inode->i_mutex);
734
735 return err;
741} 736}
742 737
743void 738int
744nfsd_sync_dir(struct dentry *dp) 739nfsd_sync_dir(struct dentry *dp)
745{ 740{
746 nfsd_dosync(NULL, dp, dp->d_inode->i_fop); 741 return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
747} 742}
748 743
749/* 744/*
@@ -820,7 +815,7 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
820 return size; 815 return size;
821} 816}
822 817
823static inline int 818static int
824nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 819nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
825 loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 820 loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
826{ 821{
@@ -874,7 +869,17 @@ out:
874 return err; 869 return err;
875} 870}
876 871
877static inline int 872static void kill_suid(struct dentry *dentry)
873{
874 struct iattr ia;
875 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
876
877 mutex_lock(&dentry->d_inode->i_mutex);
878 notify_change(dentry, &ia);
879 mutex_unlock(&dentry->d_inode->i_mutex);
880}
881
882static int
878nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 883nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
879 loff_t offset, struct kvec *vec, int vlen, 884 loff_t offset, struct kvec *vec, int vlen,
880 unsigned long cnt, int *stablep) 885 unsigned long cnt, int *stablep)
@@ -886,9 +891,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
886 int err = 0; 891 int err = 0;
887 int stable = *stablep; 892 int stable = *stablep;
888 893
894#ifdef MSNFS
889 err = nfserr_perm; 895 err = nfserr_perm;
890 896
891#ifdef MSNFS
892 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 897 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
893 (!lock_may_write(file->f_dentry->d_inode, offset, cnt))) 898 (!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
894 goto out; 899 goto out;
@@ -927,14 +932,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
927 } 932 }
928 933
929 /* clear setuid/setgid flag after write */ 934 /* clear setuid/setgid flag after write */
930 if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) { 935 if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
931 struct iattr ia; 936 kill_suid(dentry);
932 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
933
934 down(&inode->i_sem);
935 notify_change(dentry, &ia);
936 up(&inode->i_sem);
937 }
938 937
939 if (err >= 0 && stable) { 938 if (err >= 0 && stable) {
940 static ino_t last_ino; 939 static ino_t last_ino;
@@ -962,7 +961,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
962 961
963 if (inode->i_state & I_DIRTY) { 962 if (inode->i_state & I_DIRTY) {
964 dprintk("nfsd: write sync %d\n", current->pid); 963 dprintk("nfsd: write sync %d\n", current->pid);
965 nfsd_sync(file); 964 err=nfsd_sync(file);
966 } 965 }
967#if 0 966#if 0
968 wake_up(&inode->i_wait); 967 wake_up(&inode->i_wait);
@@ -1066,7 +1065,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1066 return err; 1065 return err;
1067 if (EX_ISSYNC(fhp->fh_export)) { 1066 if (EX_ISSYNC(fhp->fh_export)) {
1068 if (file->f_op && file->f_op->fsync) { 1067 if (file->f_op && file->f_op->fsync) {
1069 nfsd_sync(file); 1068 err = nfserrno(nfsd_sync(file));
1070 } else { 1069 } else {
1071 err = nfserr_notsupp; 1070 err = nfserr_notsupp;
1072 } 1071 }
@@ -1134,7 +1133,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1134 "nfsd_create: parent %s/%s not locked!\n", 1133 "nfsd_create: parent %s/%s not locked!\n",
1135 dentry->d_parent->d_name.name, 1134 dentry->d_parent->d_name.name,
1136 dentry->d_name.name); 1135 dentry->d_name.name);
1137 err = -EIO; 1136 err = nfserr_io;
1138 goto out; 1137 goto out;
1139 } 1138 }
1140 } 1139 }
@@ -1177,7 +1176,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1177 goto out_nfserr; 1176 goto out_nfserr;
1178 1177
1179 if (EX_ISSYNC(fhp->fh_export)) { 1178 if (EX_ISSYNC(fhp->fh_export)) {
1180 nfsd_sync_dir(dentry); 1179 err = nfserrno(nfsd_sync_dir(dentry));
1181 write_inode_now(dchild->d_inode, 1); 1180 write_inode_now(dchild->d_inode, 1);
1182 } 1181 }
1183 1182
@@ -1187,9 +1186,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1187 * send along the gid when it tries to implement setgid 1186 * send along the gid when it tries to implement setgid
1188 * directories via NFS. 1187 * directories via NFS.
1189 */ 1188 */
1190 err = 0; 1189 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
1191 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) 1190 int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1192 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); 1191 if (err2)
1192 err = err2;
1193 }
1193 /* 1194 /*
1194 * Update the file handle to get the new inode info. 1195 * Update the file handle to get the new inode info.
1195 */ 1196 */
@@ -1308,17 +1309,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1308 goto out_nfserr; 1309 goto out_nfserr;
1309 1310
1310 if (EX_ISSYNC(fhp->fh_export)) { 1311 if (EX_ISSYNC(fhp->fh_export)) {
1311 nfsd_sync_dir(dentry); 1312 err = nfserrno(nfsd_sync_dir(dentry));
1312 /* setattr will sync the child (or not) */ 1313 /* setattr will sync the child (or not) */
1313 } 1314 }
1314 1315
1315 /*
1316 * Update the filehandle to get the new inode info.
1317 */
1318 err = fh_update(resfhp);
1319 if (err)
1320 goto out;
1321
1322 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1316 if (createmode == NFS3_CREATE_EXCLUSIVE) {
1323 /* Cram the verifier into atime/mtime/mode */ 1317 /* Cram the verifier into atime/mtime/mode */
1324 iap->ia_valid = ATTR_MTIME|ATTR_ATIME 1318 iap->ia_valid = ATTR_MTIME|ATTR_ATIME
@@ -1339,8 +1333,17 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1339 * implement setgid directories via NFS. Clear out all that cruft. 1333 * implement setgid directories via NFS. Clear out all that cruft.
1340 */ 1334 */
1341 set_attr: 1335 set_attr:
1342 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) 1336 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
1343 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); 1337 int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1338 if (err2)
1339 err = err2;
1340 }
1341
1342 /*
1343 * Update the filehandle to get the new inode info.
1344 */
1345 if (!err)
1346 err = fh_update(resfhp);
1344 1347
1345 out: 1348 out:
1346 fh_unlock(fhp); 1349 fh_unlock(fhp);
@@ -1449,10 +1452,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1449 } else 1452 } else
1450 err = vfs_symlink(dentry->d_inode, dnew, path, mode); 1453 err = vfs_symlink(dentry->d_inode, dnew, path, mode);
1451 1454
1452 if (!err) { 1455 if (!err)
1453 if (EX_ISSYNC(fhp->fh_export)) 1456 if (EX_ISSYNC(fhp->fh_export))
1454 nfsd_sync_dir(dentry); 1457 err = nfsd_sync_dir(dentry);
1455 } else 1458 if (err)
1456 err = nfserrno(err); 1459 err = nfserrno(err);
1457 fh_unlock(fhp); 1460 fh_unlock(fhp);
1458 1461
@@ -1508,7 +1511,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1508 err = vfs_link(dold, dirp, dnew); 1511 err = vfs_link(dold, dirp, dnew);
1509 if (!err) { 1512 if (!err) {
1510 if (EX_ISSYNC(ffhp->fh_export)) { 1513 if (EX_ISSYNC(ffhp->fh_export)) {
1511 nfsd_sync_dir(ddir); 1514 err = nfserrno(nfsd_sync_dir(ddir));
1512 write_inode_now(dest, 1); 1515 write_inode_now(dest, 1);
1513 } 1516 }
1514 } else { 1517 } else {
@@ -1592,13 +1595,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1592 if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) && 1595 if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1593 ((atomic_read(&odentry->d_count) > 1) 1596 ((atomic_read(&odentry->d_count) > 1)
1594 || (atomic_read(&ndentry->d_count) > 1))) { 1597 || (atomic_read(&ndentry->d_count) > 1))) {
1595 err = nfserr_perm; 1598 err = -EPERM;
1596 } else 1599 } else
1597#endif 1600#endif
1598 err = vfs_rename(fdir, odentry, tdir, ndentry); 1601 err = vfs_rename(fdir, odentry, tdir, ndentry);
1599 if (!err && EX_ISSYNC(tfhp->fh_export)) { 1602 if (!err && EX_ISSYNC(tfhp->fh_export)) {
1600 nfsd_sync_dir(tdentry); 1603 err = nfsd_sync_dir(tdentry);
1601 nfsd_sync_dir(fdentry); 1604 if (!err)
1605 err = nfsd_sync_dir(fdentry);
1602 } 1606 }
1603 1607
1604 out_dput_new: 1608 out_dput_new:
@@ -1663,7 +1667,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1663#ifdef MSNFS 1667#ifdef MSNFS
1664 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 1668 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1665 (atomic_read(&rdentry->d_count) > 1)) { 1669 (atomic_read(&rdentry->d_count) > 1)) {
1666 err = nfserr_perm; 1670 err = -EPERM;
1667 } else 1671 } else
1668#endif 1672#endif
1669 err = vfs_unlink(dirp, rdentry); 1673 err = vfs_unlink(dirp, rdentry);
@@ -1673,17 +1677,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1673 1677
1674 dput(rdentry); 1678 dput(rdentry);
1675 1679
1676 if (err) 1680 if (err == 0 &&
1677 goto out_nfserr; 1681 EX_ISSYNC(fhp->fh_export))
1678 if (EX_ISSYNC(fhp->fh_export)) 1682 err = nfsd_sync_dir(dentry);
1679 nfsd_sync_dir(dentry);
1680
1681out:
1682 return err;
1683 1683
1684out_nfserr: 1684out_nfserr:
1685 err = nfserrno(err); 1685 err = nfserrno(err);
1686 goto out; 1686out:
1687 return err;
1687} 1688}
1688 1689
1689/* 1690/*
@@ -1874,39 +1875,25 @@ nfsd_get_posix_acl(struct svc_fh *fhp, int type)
1874 ssize_t size; 1875 ssize_t size;
1875 struct posix_acl *acl; 1876 struct posix_acl *acl;
1876 1877
1877 if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr) 1878 if (!IS_POSIXACL(inode))
1879 return ERR_PTR(-EOPNOTSUPP);
1880
1881 switch (type) {
1882 case ACL_TYPE_ACCESS:
1883 name = POSIX_ACL_XATTR_ACCESS;
1884 break;
1885 case ACL_TYPE_DEFAULT:
1886 name = POSIX_ACL_XATTR_DEFAULT;
1887 break;
1888 default:
1878 return ERR_PTR(-EOPNOTSUPP); 1889 return ERR_PTR(-EOPNOTSUPP);
1879 switch(type) {
1880 case ACL_TYPE_ACCESS:
1881 name = POSIX_ACL_XATTR_ACCESS;
1882 break;
1883 case ACL_TYPE_DEFAULT:
1884 name = POSIX_ACL_XATTR_DEFAULT;
1885 break;
1886 default:
1887 return ERR_PTR(-EOPNOTSUPP);
1888 } 1890 }
1889 1891
1890 size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0); 1892 size = nfsd_getxattr(fhp->fh_dentry, name, &value);
1893 if (size < 0)
1894 return ERR_PTR(size);
1891 1895
1892 if (size < 0) {
1893 acl = ERR_PTR(size);
1894 goto getout;
1895 } else if (size > 0) {
1896 value = kmalloc(size, GFP_KERNEL);
1897 if (!value) {
1898 acl = ERR_PTR(-ENOMEM);
1899 goto getout;
1900 }
1901 size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
1902 if (size < 0) {
1903 acl = ERR_PTR(size);
1904 goto getout;
1905 }
1906 }
1907 acl = posix_acl_from_xattr(value, size); 1896 acl = posix_acl_from_xattr(value, size);
1908
1909getout:
1910 kfree(value); 1897 kfree(value);
1911 return acl; 1898 return acl;
1912} 1899}
@@ -1947,16 +1934,13 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1947 } else 1934 } else
1948 size = 0; 1935 size = 0;
1949 1936
1950 if (!fhp->fh_locked)
1951 fh_lock(fhp); /* unlocking is done automatically */
1952 if (size) 1937 if (size)
1953 error = inode->i_op->setxattr(fhp->fh_dentry, name, 1938 error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
1954 value, size, 0);
1955 else { 1939 else {
1956 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT) 1940 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1957 error = 0; 1941 error = 0;
1958 else { 1942 else {
1959 error = inode->i_op->removexattr(fhp->fh_dentry, name); 1943 error = vfs_removexattr(fhp->fh_dentry, name);
1960 if (error == -ENODATA) 1944 if (error == -ENODATA)
1961 error = 0; 1945 error = 0;
1962 } 1946 }