|
@@ -838,7 +838,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
|
|
|
p->o_arg.open_flags = flags;
|
|
|
p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
|
|
|
p->o_arg.clientid = server->nfs_client->cl_clientid;
|
|
|
- p->o_arg.id = sp->so_seqid.owner_id;
|
|
|
+ p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
|
|
|
+ p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
|
|
|
p->o_arg.name = &dentry->d_name;
|
|
|
p->o_arg.server = server;
|
|
|
p->o_arg.bitmask = server->attr_bitmask;
|
|
@@ -1466,8 +1467,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
|
|
|
goto unlock_no_action;
|
|
|
rcu_read_unlock();
|
|
|
}
|
|
|
- /* Update sequence id. */
|
|
|
- data->o_arg.id = sp->so_seqid.owner_id;
|
|
|
+ /* Update client id. */
|
|
|
data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
|
|
|
if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
|
|
|
task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
|
|
@@ -1954,10 +1954,19 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
|
|
|
};
|
|
|
int err;
|
|
|
do {
|
|
|
- err = nfs4_handle_exception(server,
|
|
|
- _nfs4_do_setattr(inode, cred, fattr, sattr, state),
|
|
|
- &exception);
|
|
|
+ err = _nfs4_do_setattr(inode, cred, fattr, sattr, state);
|
|
|
+ switch (err) {
|
|
|
+ case -NFS4ERR_OPENMODE:
|
|
|
+ if (state && !(state->state & FMODE_WRITE)) {
|
|
|
+ err = -EBADF;
|
|
|
+ if (sattr->ia_valid & ATTR_OPEN)
|
|
|
+ err = -EACCES;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ err = nfs4_handle_exception(server, err, &exception);
|
|
|
} while (exception.retry);
|
|
|
+out:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -4558,7 +4567,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
|
|
|
static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
|
|
|
{
|
|
|
struct nfs_server *server = NFS_SERVER(state->inode);
|
|
|
- struct nfs4_exception exception = { };
|
|
|
+ struct nfs4_exception exception = {
|
|
|
+ .inode = state->inode,
|
|
|
+ };
|
|
|
int err;
|
|
|
|
|
|
do {
|
|
@@ -4576,7 +4587,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
|
|
|
static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
|
|
|
{
|
|
|
struct nfs_server *server = NFS_SERVER(state->inode);
|
|
|
- struct nfs4_exception exception = { };
|
|
|
+ struct nfs4_exception exception = {
|
|
|
+ .inode = state->inode,
|
|
|
+ };
|
|
|
int err;
|
|
|
|
|
|
err = nfs4_set_lock_state(state, request);
|
|
@@ -4676,6 +4689,7 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *
|
|
|
{
|
|
|
struct nfs4_exception exception = {
|
|
|
.state = state,
|
|
|
+ .inode = state->inode,
|
|
|
};
|
|
|
int err;
|
|
|
|
|
@@ -4721,6 +4735,20 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
|
|
|
|
|
|
if (state == NULL)
|
|
|
return -ENOLCK;
|
|
|
+ /*
|
|
|
+ * Don't rely on the VFS having checked the file open mode,
|
|
|
+ * since it won't do this for flock() locks.
|
|
|
+ */
|
|
|
+ switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) {
|
|
|
+ case F_RDLCK:
|
|
|
+ if (!(filp->f_mode & FMODE_READ))
|
|
|
+ return -EBADF;
|
|
|
+ break;
|
|
|
+ case F_WRLCK:
|
|
|
+ if (!(filp->f_mode & FMODE_WRITE))
|
|
|
+ return -EBADF;
|
|
|
+ }
|
|
|
+
|
|
|
do {
|
|
|
status = nfs4_proc_setlk(state, cmd, request);
|
|
|
if ((status != -EAGAIN) || IS_SETLK(cmd))
|