aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2006-01-26 22:19:57 -0500
committerJeff Garzik <jgarzik@pobox.com>2006-01-26 22:19:57 -0500
commit97309d1a0bbdcb0813ea08574b4473d8e5416012 (patch)
tree0dcbcf5aa5146147e0ac1d0c4b73b868a67d333b /fs/nfsd
parentb4ea75b649417606fd6b38710a2962ec9770e772 (diff)
parentefd51b5c6798d103e3aa683464aebb2019b62119 (diff)
downloadkernel_samsung_tuna-97309d1a0bbdcb0813ea08574b4473d8e5416012.zip
kernel_samsung_tuna-97309d1a0bbdcb0813ea08574b4473d8e5416012.tar.gz
kernel_samsung_tuna-97309d1a0bbdcb0813ea08574b4473d8e5416012.tar.bz2
Merge branch 'upstream-fixes'
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4proc.c55
-rw-r--r--fs/nfsd/nfs4recover.c10
-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/vfs.c89
6 files changed, 193 insertions, 228 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 361b400..a00fe86 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
}
if (status)
goto out;
+
+ /* Openowner is now set, so sequence id will get bumped. Now we need
+ * these checks before we do any creates: */
+ if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+ return nfserr_grace;
+ if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+ return nfserr_no_grace;
+
switch (open->op_claim_type) {
case NFS4_OPEN_CLAIM_DELEGATE_CUR:
status = nfserr_inval;
@@ -210,6 +218,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
goto out;
break;
case NFS4_OPEN_CLAIM_PREVIOUS:
+ open->op_stateowner->so_confirmed = 1;
/*
* The CURRENT_FH is already set to the file being
* 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
goto out;
break;
case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+ open->op_stateowner->so_confirmed = 1;
printk("NFSD: unsupported OPEN claim type %d\n",
open->op_claim_type);
status = nfserr_notsupp;
@@ -584,31 +594,23 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
{
int status = nfs_ok;
- if (!current_fh->fh_dentry)
- return nfserr_nofilehandle;
-
- status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
nfs4_lock_state();
- if ((status = nfs4_preprocess_stateid_op(current_fh,
- &setattr->sa_stateid,
- CHECK_FH | WR_STATE, NULL))) {
- dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
- goto out_unlock;
- }
+ status = nfs4_preprocess_stateid_op(current_fh,
+ &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
nfs4_unlock_state();
+ if (status) {
+ dprintk("NFSD: nfsd4_setattr: couldn't process stateid!");
+ return status;
+ }
}
status = nfs_ok;
if (setattr->sa_acl != NULL)
status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
if (status)
- goto out;
+ return status;
status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
0, (time_t)0);
-out:
- return status;
-out_unlock:
- nfs4_unlock_state();
return status;
}
@@ -626,15 +628,17 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
return nfserr_inval;
nfs4_lock_state();
- if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
- CHECK_FH | WR_STATE, &filp))) {
- dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
- goto out;
- }
+ status = nfs4_preprocess_stateid_op(current_fh, stateid,
+ CHECK_FH | WR_STATE, &filp);
if (filp)
get_file(filp);
nfs4_unlock_state();
+ if (status) {
+ dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
+ return status;
+ }
+
write->wr_bytes_written = write->wr_buflen;
write->wr_how_written = write->wr_stable_how;
p = (u32 *)write->wr_verifier.data;
@@ -650,9 +654,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
if (status == nfserr_symlink)
status = nfserr_inval;
return status;
-out:
- nfs4_unlock_state();
- return status;
}
/* This routine never returns NFS_OK! If there are no other errors, it
@@ -768,6 +769,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
while (!status && resp->opcnt < args->opcnt) {
op = &args->ops[resp->opcnt++];
+ dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum);
+
/*
* The XDR decode routines may have pre-set op->status;
* for example, if there is a miscellaneous XDR error
@@ -792,17 +795,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
/* All operations except RENEW, SETCLIENTID, RESTOREFH
* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
* require a valid current filehandle
- *
- * SETATTR NOFILEHANDLE error handled in nfsd4_setattr
- * due to required returned bitmap argument
*/
if ((!current_fh->fh_dentry) &&
!((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
(op->opnum == OP_SETCLIENTID) ||
(op->opnum == OP_SETCLIENTID_CONFIRM) ||
(op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
- (op->opnum == OP_RELEASE_LOCKOWNER) ||
- (op->opnum == OP_SETATTR))) {
+ (op->opnum == OP_RELEASE_LOCKOWNER))) {
op->status = nfserr_nofilehandle;
goto encode_op;
}
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index be963a1..06da750 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -222,8 +222,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
nfs4_save_user(&uid, &gid);
- filp = dentry_open(dget(dir), mntget(rec_dir.mnt),
- O_RDWR);
+ filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
status = PTR_ERR(filp);
if (IS_ERR(filp))
goto out;
@@ -400,9 +399,10 @@ nfsd4_init_recdir(char *rec_dirname)
nfs4_save_user(&uid, &gid);
- status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir);
- if (status == -ENOENT)
- printk("NFSD: recovery directory %s doesn't exist\n",
+ status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
+ &rec_dir);
+ if (status)
+ printk("NFSD: unable to find recovery directory %s\n",
rec_dirname);
if (!status)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6bbefd0..1143cfb 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
sop->so_seqid = open->op_seqid;
sop->so_confirmed = 0;
rp = &sop->so_replay;
- rp->rp_status = NFSERR_SERVERFAULT;
+ rp->rp_status = nfserr_serverfault;
rp->rp_buflen = 0;
rp->rp_buf = rp->rp_ibuf;
return sop;
@@ -1178,7 +1178,6 @@ release_stateid(struct nfs4_stateid *stp, int flags)
locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
put_nfs4_file(stp->st_file);
kmem_cache_free(stateid_slab, stp);
- stp = NULL;
}
static void
@@ -1191,22 +1190,6 @@ move_to_close_lru(struct nfs4_stateowner *sop)
sop->so_time = get_seconds();
}
-static void
-release_state_owner(struct nfs4_stateid *stp, int flag)
-{
- struct nfs4_stateowner *sop = stp->st_stateowner;
-
- dprintk("NFSD: release_state_owner\n");
- release_stateid(stp, flag);
-
- /* place unused nfs4_stateowners on so_close_lru list to be
- * released by the laundromat service after the lease period
- * to enable us to handle CLOSE replay
- */
- if (sop->so_confirmed && list_empty(&sop->so_stateids))
- move_to_close_lru(sop);
-}
-
static int
cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
return ((sop->so_owner.len == owner->len) &&
@@ -1446,92 +1429,61 @@ static struct lock_manager_operations nfsd_lease_mng_ops = {
};
-/*
- * nfsd4_process_open1()
- * lookup stateowner.
- * found:
- * check confirmed
- * confirmed:
- * check seqid
- * not confirmed:
- * delete owner
- * create new owner
- * notfound:
- * verify clientid
- * create new owner
- *
- * called with nfs4_lock_state() held.
- */
int
nfsd4_process_open1(struct nfsd4_open *open)
{
- int status;
clientid_t *clientid = &open->op_clientid;
struct nfs4_client *clp = NULL;
unsigned int strhashval;
struct nfs4_stateowner *sop = NULL;
- status = nfserr_inval;
if (!check_name(open->op_owner))
- goto out;
+ return nfserr_inval;
if (STALE_CLIENTID(&open->op_clientid))
return nfserr_stale_clientid;
strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
sop = find_openstateowner_str(strhashval, open);
- if (sop) {
- open->op_stateowner = sop;
- /* check for replay */
- if (open->op_seqid == sop->so_seqid - 1){
- if (sop->so_replay.rp_buflen)
- return NFSERR_REPLAY_ME;
- else {
- /* The original OPEN failed so spectacularly
- * that we don't even have replay data saved!
- * Therefore, we have no choice but to continue
- * processing this OPEN; presumably, we'll
- * fail again for the same reason.
- */
- dprintk("nfsd4_process_open1:"
- " replay with no replay cache\n");
- goto renew;
- }
- } else if (sop->so_confirmed) {
- if (open->op_seqid == sop->so_seqid)
- goto renew;
- status = nfserr_bad_seqid;
- goto out;
- } else {
- /* If we get here, we received an OPEN for an
- * unconfirmed nfs4_stateowner. Since the seqid's are
- * different, purge the existing nfs4_stateowner, and
- * instantiate a new one.
- */
- clp = sop->so_client;
- release_stateowner(sop);
- }
- } else {
- /* nfs4_stateowner not found.
- * Verify clientid and instantiate new nfs4_stateowner.
- * If verify fails this is presumably the result of the
- * client's lease expiring.
- */
- status = nfserr_expired;
+ open->op_stateowner = sop;
+ if (!sop) {
+ /* Make sure the client's lease hasn't expired. */
clp = find_confirmed_client(clientid);
if (clp == NULL)
- goto out;
+ return nfserr_expired;
+ goto renew;
}
- status = nfserr_resource;
- sop = alloc_init_open_stateowner(strhashval, clp, open);
- if (sop == NULL)
- goto out;
- open->op_stateowner = sop;
+ if (!sop->so_confirmed) {
+ /* Replace unconfirmed owners without checking for replay. */
+ clp = sop->so_client;
+ release_stateowner(sop);
+ open->op_stateowner = NULL;
+ goto renew;
+ }
+ if (open->op_seqid == sop->so_seqid - 1) {
+ if (sop->so_replay.rp_buflen)
+ return NFSERR_REPLAY_ME;
+ /* The original OPEN failed so spectacularly
+ * that we don't even have replay data saved!
+ * Therefore, we have no choice but to continue
+ * processing this OPEN; presumably, we'll
+ * fail again for the same reason.
+ */
+ dprintk("nfsd4_process_open1: replay with no replay cache\n");
+ goto renew;
+ }
+ if (open->op_seqid != sop->so_seqid)
+ return nfserr_bad_seqid;
renew:
- status = nfs_ok;
+ if (open->op_stateowner == NULL) {
+ sop = alloc_init_open_stateowner(strhashval, clp, open);
+ if (sop == NULL)
+ return nfserr_resource;
+ open->op_stateowner = sop;
+ }
+ list_del_init(&sop->so_close_lru);
renew_client(sop->so_client);
-out:
- return status;
+ return nfs_ok;
}
static inline int
@@ -1648,7 +1600,7 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
if (!open->op_truncate)
return 0;
if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
- return -EINVAL;
+ return nfserr_inval;
return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
}
@@ -1657,26 +1609,26 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
{
struct file *filp = stp->st_vfs_file;
struct inode *inode = filp->f_dentry->d_inode;
- unsigned int share_access;
+ unsigned int share_access, new_writer;
int status;
set_access(&share_access, stp->st_access_bmap);
- share_access = ~share_access;
- share_access &= open->op_share_access;
-
- if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
- return nfsd4_truncate(rqstp, cur_fh, open);
+ new_writer = (~share_access) & open->op_share_access
+ & NFS4_SHARE_ACCESS_WRITE;
- status = get_write_access(inode);
- if (status)
- return nfserrno(status);
+ if (new_writer) {
+ status = get_write_access(inode);
+ if (status)
+ return nfserrno(status);
+ }
status = nfsd4_truncate(rqstp, cur_fh, open);
if (status) {
- put_write_access(inode);
+ if (new_writer)
+ put_write_access(inode);
return status;
}
/* remember the open */
- filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
+ filp->f_mode |= open->op_share_access;
set_bit(open->op_share_access, &stp->st_access_bmap);
set_bit(open->op_share_deny, &stp->st_deny_bmap);
@@ -1780,12 +1732,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
struct nfs4_delegation *dp = NULL;
int status;
- if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
- return nfserr_grace;
-
- if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
- return nfserr_no_grace;
-
status = nfserr_inval;
if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
goto out;
@@ -2423,15 +2369,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
CHECK_FH | OPEN_STATE | CLOSE_STATE,
&close->cl_stateowner, &stp, NULL)))
goto out;
- /*
- * Return success, but first update the stateid.
- */
status = nfs_ok;
update_stateid(&stp->st_stateid);
memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
- /* release_state_owner() calls nfsd_close() if needed */
- release_state_owner(stp, OPEN_STATE);
+ /* release_stateid() calls nfsd_close() if needed */
+ release_stateid(stp, OPEN_STATE);
+
+ /* place unused nfs4_stateowners on so_close_lru list to be
+ * released by the laundromat service after the lease period
+ * to enable us to handle CLOSE replay
+ */
+ if (list_empty(&close->cl_stateowner->so_stateids))
+ move_to_close_lru(close->cl_stateowner);
out:
if (close->cl_stateowner) {
nfs4_get_stateowner(close->cl_stateowner);
@@ -2633,7 +2583,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
sop->so_seqid = lock->lk_new_lock_seqid + 1;
sop->so_confirmed = 1;
rp = &sop->so_replay;
- rp->rp_status = NFSERR_SERVERFAULT;
+ rp->rp_status = nfserr_serverfault;
rp->rp_buflen = 0;
rp->rp_buf = rp->rp_ibuf;
return sop;
@@ -2700,6 +2650,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
if (check_lock_length(lock->lk_offset, lock->lk_length))
return nfserr_inval;
+ if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
+ dprintk("NFSD: nfsd4_lock: permission denied!\n");
+ return status;
+ }
+
nfs4_lock_state();
if (lock->lk_is_new) {
@@ -2720,11 +2675,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
lock->lk_new_open_seqid,
&lock->lk_new_open_stateid,
CHECK_FH | OPEN_STATE,
- &lock->lk_stateowner, &open_stp,
+ &lock->lk_replay_owner, &open_stp,
lock);
if (status)
goto out;
- open_sop = lock->lk_stateowner;
+ open_sop = lock->lk_replay_owner;
/* create lockowner and lock stateid */
fp = open_stp->st_file;
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
if (lock_sop == NULL)
goto out;
lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
- if (lock_stp == NULL) {
- release_stateowner(lock_sop);
+ if (lock_stp == NULL)
goto out;
- }
} else {
/* lock (lock owner + lock stateid) already exists */
status = nfs4_preprocess_seqid_op(current_fh,
lock->lk_old_lock_seqid,
&lock->lk_old_lock_stateid,
CHECK_FH | LOCK_STATE,
- &lock->lk_stateowner, &lock_stp, lock);
+ &lock->lk_replay_owner, &lock_stp, lock);
if (status)
goto out;
- lock_sop = lock->lk_stateowner;
+ lock_sop = lock->lk_replay_owner;
}
- /* lock->lk_stateowner and lock_stp have been created or found */
+ /* lock->lk_replay_owner and lock_stp have been created or found */
filp = lock_stp->st_vfs_file;
- if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
- dprintk("NFSD: nfsd4_lock: permission denied!\n");
- goto out;
- }
-
status = nfserr_grace;
if (nfs4_in_grace() && !lock->lk_reclaim)
goto out;
@@ -2802,8 +2750,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
*/
status = posix_lock_file(filp, &file_lock);
- if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
- file_lock.fl_ops->fl_release_private(&file_lock);
dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
switch (-status) {
case 0: /* success! */
@@ -2815,9 +2761,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
goto conflicting_lock;
case (EDEADLK):
status = nfserr_deadlock;
+ dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
+ goto out;
default:
+ status = nfserrno(status);
dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
- goto out_destroy_new_stateid;
+ goto out;
}
conflicting_lock:
@@ -2831,20 +2780,12 @@ conflicting_lock:
goto out;
}
nfs4_set_lock_denied(conflock, &lock->lk_denied);
-
-out_destroy_new_stateid:
- if (lock->lk_is_new) {
- dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
- /*
- * An error encountered after instantiation of the new
- * stateid has forced us to destroy it.
- */
- release_state_owner(lock_stp, LOCK_STATE);
- }
out:
- if (lock->lk_stateowner) {
- nfs4_get_stateowner(lock->lk_stateowner);
- *replay_owner = lock->lk_stateowner;
+ if (status && lock->lk_is_new && lock_sop)
+ release_stateowner(lock_sop);
+ if (lock->lk_replay_owner) {
+ nfs4_get_stateowner(lock->lk_replay_owner);
+ *replay_owner = lock->lk_replay_owner;
}
nfs4_unlock_state();
return status;
@@ -2977,8 +2918,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
* Try to unlock the file in the VFS.
*/
status = posix_lock_file(filp, &file_lock);
- if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
- file_lock.fl_ops->fl_release_private(&file_lock);
if (status) {
dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
goto out_nfserr;
@@ -3016,9 +2955,10 @@ check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
lock_kernel();
for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
- if ((*flpp)->fl_owner == (fl_owner_t)lowner)
+ if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
status = 1;
goto out;
+ }
}
out:
unlock_kernel();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index dcd6731..69d3501 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)
{
DECODE_HEAD;
- lock->lk_stateowner = NULL;
+ lock->lk_replay_owner = NULL;
/*
* type, reclaim(boolean), offset, length, new_lock_owner(boolean)
*/
@@ -1764,10 +1764,11 @@ nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
*/
if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
goto fail;
- nfserr = nfserr_toosmall;
p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
- if (p == NULL)
+ if (p == NULL) {
+ nfserr = nfserr_toosmall;
goto fail;
+ }
}
cd->buflen -= (p - cd->buffer);
cd->buffer = p;
@@ -1895,7 +1896,6 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie
static void
nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
{
-
ENCODE_SEQID_OP_HEAD;
if (!nfserr) {
@@ -1906,7 +1906,7 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock
} else if (nfserr == nfserr_denied)
nfsd4_encode_lock_denied(resp, &lock->lk_denied);
- ENCODE_SEQID_OP_TAIL(lock->lk_stateowner);
+ ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
}
static void
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 0aa1b96..3e6b75c 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)
return nfs_ok;
}
+static int
+nfsd_return_attrs(int err, struct nfsd_attrstat *resp)
+{
+ if (err) return err;
+ return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
+ resp->fh.fh_dentry,
+ &resp->stat));
+}
+static int
+nfsd_return_dirop(int err, struct nfsd_diropres *resp)
+{
+ if (err) return err;
+ return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
+ resp->fh.fh_dentry,
+ &resp->stat));
+}
/*
* Get a file's attributes
* N.B. After this call resp->fh needs an fh_put
@@ -44,10 +60,12 @@ static int
nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
struct nfsd_attrstat *resp)
{
+ int nfserr;
dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
- return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+ nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+ return nfsd_return_attrs(nfserr, resp);
}
/*
@@ -58,12 +76,14 @@ static int
nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
struct nfsd_attrstat *resp)
{
+ int nfserr;
dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
SVCFH_fmt(&argp->fh),
argp->attrs.ia_valid, (long) argp->attrs.ia_size);
fh_copy(&resp->fh, &argp->fh);
- return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
+ nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
+ return nfsd_return_attrs(nfserr, resp);
}
/*
@@ -86,7 +106,7 @@ nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
&resp->fh);
fh_put(&argp->fh);
- return nfserr;
+ return nfsd_return_dirop(nfserr, resp);
}
/*
@@ -142,7 +162,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
argp->vec, argp->vlen,
&resp->count);
- return nfserr;
+ if (nfserr) return nfserr;
+ return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
+ resp->fh.fh_dentry,
+ &resp->stat));
}
/*
@@ -165,7 +188,7 @@ nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
argp->vec, argp->vlen,
argp->len,
&stable);
- return nfserr;
+ return nfsd_return_attrs(nfserr, resp);
}
/*
@@ -322,7 +345,7 @@ out_unlock:
done:
fh_put(dirfhp);
- return nfserr;
+ return nfsd_return_dirop(nfserr, resp);
}
static int
@@ -425,7 +448,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
&argp->attrs, S_IFDIR, 0, &resp->fh);
fh_put(&argp->fh);
- return nfserr;
+ return nfsd_return_dirop(nfserr, resp);
}
/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index eef0576..5320e5a 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -710,14 +710,15 @@ static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
{
struct inode *inode = dp->d_inode;
int (*fsync) (struct file *, struct dentry *, int);
- int err = nfs_ok;
+ int err;
- filemap_fdatawrite(inode->i_mapping);
- if (fop && (fsync = fop->fsync))
- err=fsync(filp, dp, 0);
- filemap_fdatawait(inode->i_mapping);
+ err = filemap_fdatawrite(inode->i_mapping);
+ if (err == 0 && fop && (fsync = fop->fsync))
+ err = fsync(filp, dp, 0);
+ if (err == 0)
+ err = filemap_fdatawait(inode->i_mapping);
- return nfserrno(err);
+ return err;
}
@@ -734,10 +735,10 @@ nfsd_sync(struct file *filp)
return err;
}
-void
+int
nfsd_sync_dir(struct dentry *dp)
{
- nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
+ return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
}
/*
@@ -814,7 +815,7 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
return size;
}
-static inline int
+static int
nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
{
@@ -878,7 +879,7 @@ static void kill_suid(struct dentry *dentry)
mutex_unlock(&dentry->d_inode->i_mutex);
}
-static inline int
+static int
nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
loff_t offset, struct kvec *vec, int vlen,
unsigned long cnt, int *stablep)
@@ -890,9 +891,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
int err = 0;
int stable = *stablep;
+#ifdef MSNFS
err = nfserr_perm;
-#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
(!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
goto out;
@@ -1064,7 +1065,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
return err;
if (EX_ISSYNC(fhp->fh_export)) {
if (file->f_op && file->f_op->fsync) {
- err = nfsd_sync(file);
+ err = nfserrno(nfsd_sync(file));
} else {
err = nfserr_notsupp;
}
@@ -1132,7 +1133,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
"nfsd_create: parent %s/%s not locked!\n",
dentry->d_parent->d_name.name,
dentry->d_name.name);
- err = -EIO;
+ err = nfserr_io;
goto out;
}
}
@@ -1175,7 +1176,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out_nfserr;
if (EX_ISSYNC(fhp->fh_export)) {
- nfsd_sync_dir(dentry);
+ err = nfserrno(nfsd_sync_dir(dentry));
write_inode_now(dchild->d_inode, 1);
}
@@ -1185,9 +1186,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
* send along the gid when it tries to implement setgid
* directories via NFS.
*/
- err = 0;
- if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
- err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+ if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
+ int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+ if (err2)
+ err = err2;
+ }
/*
* Update the file handle to get the new inode info.
*/
@@ -1306,17 +1309,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out_nfserr;
if (EX_ISSYNC(fhp->fh_export)) {
- nfsd_sync_dir(dentry);
+ err = nfserrno(nfsd_sync_dir(dentry));
/* setattr will sync the child (or not) */
}
- /*
- * Update the filehandle to get the new inode info.
- */
- err = fh_update(resfhp);
- if (err)
- goto out;
-
if (createmode == NFS3_CREATE_EXCLUSIVE) {
/* Cram the verifier into atime/mtime/mode */
iap->ia_valid = ATTR_MTIME|ATTR_ATIME
@@ -1337,8 +1333,17 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
* implement setgid directories via NFS. Clear out all that cruft.
*/
set_attr:
- if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0)
- err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+ if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
+ int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+ if (err2)
+ err = err2;
+ }
+
+ /*
+ * Update the filehandle to get the new inode info.
+ */
+ if (!err)
+ err = fh_update(resfhp);
out:
fh_unlock(fhp);
@@ -1447,10 +1452,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
} else
err = vfs_symlink(dentry->d_inode, dnew, path, mode);
- if (!err) {
+ if (!err)
if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
- } else
+ err = nfsd_sync_dir(dentry);
+ if (err)
err = nfserrno(err);
fh_unlock(fhp);
@@ -1506,7 +1511,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
err = vfs_link(dold, dirp, dnew);
if (!err) {
if (EX_ISSYNC(ffhp->fh_export)) {
- nfsd_sync_dir(ddir);
+ err = nfserrno(nfsd_sync_dir(ddir));
write_inode_now(dest, 1);
}
} else {
@@ -1590,13 +1595,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
((atomic_read(&odentry->d_count) > 1)
|| (atomic_read(&ndentry->d_count) > 1))) {
- err = nfserr_perm;
+ err = -EPERM;
} else
#endif
err = vfs_rename(fdir, odentry, tdir, ndentry);
if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
+ err = nfsd_sync_dir(tdentry);
+ if (!err)
+ err = nfsd_sync_dir(fdentry);
}
out_dput_new:
@@ -1661,7 +1667,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
(atomic_read(&rdentry->d_count) > 1)) {
- err = nfserr_perm;
+ err = -EPERM;
} else
#endif
err = vfs_unlink(dirp, rdentry);
@@ -1671,17 +1677,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
dput(rdentry);
- if (err)
- goto out_nfserr;
- if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
-
-out:
- return err;
+ if (err == 0 &&
+ EX_ISSYNC(fhp->fh_export))
+ err = nfsd_sync_dir(dentry);
out_nfserr:
err = nfserrno(err);
- goto out;
+out:
+ return err;
}
/*