#include <linux/mm.h>
#include <linux/utsname.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/sunrpc/clnt.h>
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
+static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
extern struct rpc_procinfo nfs4_procedures[];
extern nfs4_stateid zero_stateid;
/* Prevent leaks of NFSv4 errors into userland */
-static inline int nfs4_map_errors(int err)
+int nfs4_map_errors(int err)
{
if (err < -1000) {
- printk(KERN_WARNING "%s could not handle NFSv4 error %d\n",
+ dprintk("%s could not handle NFSv4 error %d\n",
__FUNCTION__, -err);
return -EIO;
}
nfsi->change_attr = cinfo->after;
}
+static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+{
+ struct inode *inode = state->inode;
+
+ open_flags &= (FMODE_READ|FMODE_WRITE);
+ /* Protect against nfs4_find_state() */
+ spin_lock(&inode->i_lock);
+ state->state |= open_flags;
+ /* NB! List reordering - see the reclaim code for why. */
+ if ((open_flags & FMODE_WRITE) && 0 == state->nwriters++)
+ list_move(&state->open_states, &state->owner->so_states);
+ if (open_flags & FMODE_READ)
+ state->nreaders++;
+ memcpy(&state->stateid, stateid, sizeof(state->stateid));
+ spin_unlock(&inode->i_lock);
+}
+
/*
* OPEN_RECLAIM:
* reclaim state on the server after a reboot.
return status;
}
-int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_exception exception = { };
return err;
}
-static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
+static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
{
struct nfs_open_confirmargs arg = {
.fh = fh,
return status;
}
-static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, struct nfs_openargs *o_arg, struct nfs_openres *o_res)
+{
+ struct nfs_server *server = NFS_SERVER(dir);
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
+ .rpc_argp = o_arg,
+ .rpc_resp = o_res,
+ .rpc_cred = sp->so_cred,
+ };
+ int status;
+
+ /* Update sequence id. The caller must serialize! */
+ o_arg->seqid = sp->so_seqid;
+ o_arg->id = sp->so_id;
+ o_arg->clientid = sp->so_client->cl_clientid;
+
+ status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+ nfs4_increment_seqid(status, sp);
+ if (status != 0)
+ goto out;
+ update_changeattr(dir, &o_res->cinfo);
+ if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
+ status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
+ sp, &o_res->stateid);
+ if (status != 0)
+ goto out;
+ }
+ if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
+ status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
+out:
+ return status;
+}
+
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags)
{
struct nfs_access_entry cache;
+ int mask = 0;
int status;
+ if (openflags & FMODE_READ)
+ mask |= MAY_READ;
+ if (openflags & FMODE_WRITE)
+ mask |= MAY_WRITE;
status = nfs_access_get_cached(inode, cred, &cache);
if (status == 0)
goto out;
return -EACCES;
}
+/*
+ * OPEN_EXPIRED:
+ * reclaim state on the server after a network partition.
+ * Assumes caller holds the appropriate lock
+ */
+static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+{
+ struct dentry *parent = dget_parent(dentry);
+ struct inode *dir = parent->d_inode;
+ struct inode *inode = state->inode;
+ struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs_delegation *delegation = NFS_I(inode)->delegation;
+ struct nfs_fattr f_attr = {
+ .valid = 0,
+ };
+ struct nfs_openargs o_arg = {
+ .fh = NFS_FH(dir),
+ .open_flags = state->state,
+ .name = &dentry->d_name,
+ .bitmask = server->attr_bitmask,
+ .claim = NFS4_OPEN_CLAIM_NULL,
+ };
+ struct nfs_openres o_res = {
+ .f_attr = &f_attr,
+ .server = server,
+ };
+ int status = 0;
+
+ if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
+ status = _nfs4_do_access(inode, sp->so_cred, state->state);
+ if (status < 0)
+ goto out;
+ memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
+ set_bit(NFS_DELEGATED_STATE, &state->flags);
+ goto out;
+ }
+ status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
+ if (status != 0)
+ goto out_nodeleg;
+ /* Check if files differ */
+ if ((f_attr.mode & S_IFMT) != (inode->i_mode & S_IFMT))
+ goto out_stale;
+ /* Has the file handle changed? */
+ if (nfs_compare_fh(&o_res.fh, NFS_FH(inode)) != 0) {
+ /* Verify if the change attributes are the same */
+ if (f_attr.change_attr != NFS_I(inode)->change_attr)
+ goto out_stale;
+ if (nfs_size_to_loff_t(f_attr.size) != inode->i_size)
+ goto out_stale;
+ /* Lets just pretend that this is the same file */
+ nfs_copy_fh(NFS_FH(inode), &o_res.fh);
+ NFS_I(inode)->fileid = f_attr.fileid;
+ }
+ memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
+ if (o_res.delegation_type != 0) {
+ if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM))
+ nfs_inode_set_delegation(inode, sp->so_cred, &o_res);
+ else
+ nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
+ }
+out_nodeleg:
+ clear_bit(NFS_DELEGATED_STATE, &state->flags);
+out:
+ dput(parent);
+ return status;
+out_stale:
+ status = -ESTALE;
+ /* Invalidate the state owner so we don't ever use it again */
+ nfs4_drop_state_owner(sp);
+ d_drop(dentry);
+ /* Should we be trying to close that stateid? */
+ goto out_nodeleg;
+}
+
+static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
+{
+ struct nfs_inode *nfsi = NFS_I(state->inode);
+ struct nfs_open_context *ctx;
+ int status;
+
+ spin_lock(&state->inode->i_lock);
+ list_for_each_entry(ctx, &nfsi->open_files, list) {
+ if (ctx->state != state)
+ continue;
+ get_nfs_open_context(ctx);
+ spin_unlock(&state->inode->i_lock);
+ status = _nfs4_open_expired(sp, state, ctx->dentry);
+ put_nfs_open_context(ctx);
+ return status;
+ }
+ spin_unlock(&state->inode->i_lock);
+ return -ENOENT;
+}
+
/*
* Returns an nfs4_state + an extra reference to the inode
*/
-int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
{
struct nfs_delegation *delegation;
struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_state_owner *sp = NULL;
struct nfs4_state *state = NULL;
int open_flags = flags & (FMODE_READ|FMODE_WRITE);
- int mask = 0;
int err;
/* Protect against reboot recovery - NOTE ORDER! */
goto out_err;
lock_kernel();
- err = _nfs4_do_access(inode, cred, mask);
+ err = _nfs4_do_access(inode, cred, open_flags);
unlock_kernel();
if (err != 0)
goto out_err;
- spin_lock(&inode->i_lock);
- memcpy(state->stateid.data, delegation->stateid.data,
- sizeof(state->stateid.data));
- state->state |= open_flags;
- if (open_flags & FMODE_READ)
- state->nreaders++;
- if (open_flags & FMODE_WRITE)
- state->nwriters++;
set_bit(NFS_DELEGATED_STATE, &state->flags);
- spin_unlock(&inode->i_lock);
+ update_open_stateid(state, &delegation->stateid, open_flags);
out_ok:
up(&sp->so_sema);
nfs4_put_state_owner(sp);
.f_attr = &f_attr,
.server = server,
};
- struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
- .rpc_argp = &o_arg,
- .rpc_resp = &o_res,
- .rpc_cred = cred,
- };
/* Protect against reboot recovery conflicts */
down_read(&clp->cl_sem);
o_arg.u.attrs = sattr;
/* Serialization for the sequence id */
down(&sp->so_sema);
- o_arg.seqid = sp->so_seqid;
- o_arg.id = sp->so_id;
- o_arg.clientid = clp->cl_clientid,
- status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
- nfs4_increment_seqid(status, sp);
- if (status)
+ status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
+ if (status != 0)
goto out_err;
- update_changeattr(dir, &o_res.cinfo);
- if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
- status = _nfs4_proc_open_confirm(server->client, &o_res.fh,
- sp, &o_res.stateid);
- if (status != 0)
- goto out_err;
- }
- if (!(f_attr.valid & NFS_ATTR_FATTR)) {
- status = server->rpc_ops->getattr(server, &o_res.fh, &f_attr);
- if (status < 0)
- goto out_err;
- }
status = -ENOMEM;
inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);
state = nfs4_get_open_state(inode, sp);
if (!state)
goto out_err;
- memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
- spin_lock(&inode->i_lock);
- if (flags & FMODE_READ)
- state->nreaders++;
- if (flags & FMODE_WRITE)
- state->nwriters++;
- state->state |= flags & (FMODE_READ|FMODE_WRITE);
- spin_unlock(&inode->i_lock);
+ update_open_stateid(state, &o_res.stateid, flags);
if (o_res.delegation_type != 0)
nfs_inode_set_delegation(inode, cred, &o_res);
up(&sp->so_sema);
}
-struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
{
struct nfs4_exception exception = { };
struct nfs4_state *res;
return rpc_call_sync(server->client, &msg, 0);
}
-int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
+static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
struct nfs_fh *fhandle, struct iattr *sattr,
struct nfs4_state *state)
{
nfs4_increment_seqid(task->tk_status, sp);
switch (task->tk_status) {
case 0:
- state->state = calldata->arg.open_flags;
memcpy(&state->stateid, &calldata->res.stateid,
sizeof(state->stateid));
break;
return;
}
}
+ state->state = calldata->arg.open_flags;
nfs4_put_open_state(state);
up(&sp->so_sema);
nfs4_put_state_owner(sp);
}
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return (struct inode *)cred;
state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
put_rpccred(cred);
if (IS_ERR(state))
struct inode *inode;
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
if (IS_ERR(state))
state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
if (size_change) {
struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
state = nfs4_find_state(inode, cred, FMODE_WRITE);
if (state == NULL) {
state = nfs4_open_delegated(dentry->d_inode,
* opens the file O_RDONLY. This will all be resolved with the VFS changes.
*/
-static struct inode *
+static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags)
{
- struct inode *inode;
- struct nfs4_state *state = NULL;
+ struct nfs4_state *state;
struct rpc_cred *cred;
+ int status = 0;
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+ if (IS_ERR(cred)) {
+ status = PTR_ERR(cred);
+ goto out;
+ }
state = nfs4_do_open(dir, dentry, flags, sattr, cred);
put_rpccred(cred);
- if (!IS_ERR(state)) {
- inode = state->inode;
- if (flags & O_EXCL) {
- struct nfs_fattr fattr;
- int status;
- status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
- NFS_FH(inode), sattr, state);
- if (status != 0) {
- nfs4_close_state(state, flags);
- iput(inode);
- inode = ERR_PTR(status);
- }
- }
- } else
- inode = (struct inode *)state;
- return inode;
+ if (IS_ERR(state)) {
+ status = PTR_ERR(state);
+ goto out;
+ }
+ d_instantiate(dentry, state->inode);
+ if (flags & O_EXCL) {
+ struct nfs_fattr fattr;
+ status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
+ NFS_FH(state->inode), sattr, state);
+ if (status == 0)
+ goto out;
+ } else if (flags != 0)
+ goto out;
+ nfs4_close_state(state, flags);
+out:
+ return status;
}
static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
return err;
}
-static int _nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
- struct iattr *sattr, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr)
+static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr)
{
struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr;
struct nfs4_create_arg arg = {
.dir_fh = NFS_FH(dir),
.server = server,
- .name = name,
+ .name = &dentry->d_name,
.attrs = sattr,
.ftype = NF4DIR,
.bitmask = server->attr_bitmask,
};
struct nfs4_create_res res = {
.server = server,
- .fh = fhandle,
- .fattr = fattr,
+ .fh = &fhandle,
+ .fattr = &fattr,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
};
int status;
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
- if (!status)
+ if (!status) {
update_changeattr(dir, &res.dir_cinfo);
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
+ }
return status;
}
-static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
- struct iattr *sattr, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr)
+static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr)
{
struct nfs4_exception exception = { };
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
- _nfs4_proc_mkdir(dir, name, sattr,
- fhandle, fattr),
+ _nfs4_proc_mkdir(dir, dentry, sattr),
&exception);
} while (exception.retry);
return err;
.pages = &page,
.pgbase = 0,
.count = count,
+ .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
};
struct nfs4_readdir_res res;
struct rpc_message msg = {
return err;
}
-static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
- struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
- struct nfs_fattr *fattr)
+static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr, dev_t rdev)
{
struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs_fh fh;
+ struct nfs_fattr fattr;
struct nfs4_create_arg arg = {
.dir_fh = NFS_FH(dir),
.server = server,
- .name = name,
+ .name = &dentry->d_name,
.attrs = sattr,
.bitmask = server->attr_bitmask,
};
struct nfs4_create_res res = {
.server = server,
- .fh = fh,
- .fattr = fattr,
+ .fh = &fh,
+ .fattr = &fattr,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
int status;
int mode = sattr->ia_mode;
- fattr->valid = 0;
+ fattr.valid = 0;
BUG_ON(!(sattr->ia_valid & ATTR_MODE));
BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
arg.ftype = NF4SOCK;
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
- if (!status)
+ if (status == 0) {
update_changeattr(dir, &res.dir_cinfo);
+ status = nfs_instantiate(dentry, &fh, &fattr);
+ }
return status;
}
-static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
- struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
- struct nfs_fattr *fattr)
+static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr, dev_t rdev)
{
struct nfs4_exception exception = { };
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
- _nfs4_proc_mknod(dir, name, sattr, rdev,
- fh, fattr),
+ _nfs4_proc_mknod(dir, dentry, sattr, rdev),
&exception);
} while (exception.retry);
return err;
/* Find our open stateid */
cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
- if (unlikely(cred == NULL))
- return -ENOMEM;
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
ctx = alloc_nfs_open_context(dentry, cred);
put_rpccred(cred);
if (unlikely(ctx == NULL))
return 0;
}
-int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
+static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
{
DEFINE_WAIT(wait);
sigset_t oldset;
int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port)
{
- static nfs4_verifier sc_verifier;
- static int initialized;
-
+ nfs4_verifier sc_verifier;
struct nfs4_setclientid setclientid = {
.sc_verifier = &sc_verifier,
.sc_prog = program,
.rpc_resp = clp,
.rpc_cred = clp->cl_cred,
};
+ u32 *p;
+ int loop = 0;
+ int status;
- if (!initialized) {
- struct timespec boot_time;
- u32 *p;
-
- initialized = 1;
- boot_time = CURRENT_TIME;
- p = (u32*)sc_verifier.data;
- *p++ = htonl((u32)boot_time.tv_sec);
- *p = htonl((u32)boot_time.tv_nsec);
+ p = (u32*)sc_verifier.data;
+ *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
+ *p = htonl((u32)clp->cl_boot_time.tv_nsec);
+
+ for(;;) {
+ setclientid.sc_name_len = scnprintf(setclientid.sc_name,
+ sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
+ clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr),
+ clp->cl_cred->cr_ops->cr_name,
+ clp->cl_id_uniquifier);
+ setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
+ sizeof(setclientid.sc_netid), "tcp");
+ setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
+ sizeof(setclientid.sc_uaddr), "%s.%d.%d",
+ clp->cl_ipaddr, port >> 8, port & 255);
+
+ status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+ if (status != -NFS4ERR_CLID_INUSE)
+ break;
+ if (signalled())
+ break;
+ if (loop++ & 1)
+ ssleep(clp->cl_lease_time + 1);
+ else
+ if (++clp->cl_id_uniquifier == 0)
+ break;
}
- setclientid.sc_name_len = scnprintf(setclientid.sc_name,
- sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u",
- clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr));
- setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
- sizeof(setclientid.sc_netid), "tcp");
- setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
- sizeof(setclientid.sc_uaddr), "%s.%d.%d",
- clp->cl_ipaddr, port >> 8, port & 255);
-
- return rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+ return status;
}
int
return err;
}
+static int do_vfs_lock(struct file *file, struct file_lock *fl)
+{
+ int res = 0;
+ switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+ case FL_POSIX:
+ res = posix_lock_file_wait(file, fl);
+ break;
+ case FL_FLOCK:
+ res = flock_lock_file_wait(file, fl);
+ break;
+ default:
+ BUG();
+ }
+ if (res < 0)
+ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+ __FUNCTION__);
+ return res;
+}
+
static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
{
struct inode *inode = state->inode;
out:
up(&state->lock_sema);
if (status == 0)
- posix_lock_file(request->fl_file, request);
+ do_vfs_lock(request->fl_file, request);
up_read(&clp->cl_sem);
return status;
}
return status;
}
-int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
+static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
return _nfs4_do_setlk(state, F_SETLK, request, 1);
}
+static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
+{
+ return _nfs4_do_setlk(state, F_SETLK, request, 0);
+}
+
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
struct nfs4_client *clp = state->owner->so_client;
if (status == 0) {
/* Note: we always want to sleep here! */
request->fl_flags |= FL_SLEEP;
- if (posix_lock_file_wait(request->fl_file, request) < 0)
+ if (do_vfs_lock(request->fl_file, request) < 0)
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
}
up_read(&clp->cl_sem);
return status;
}
+struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
+ .recover_open = nfs4_open_reclaim,
+ .recover_lock = nfs4_lock_reclaim,
+};
+
+struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
+ .recover_open = nfs4_open_expired,
+ .recover_lock = nfs4_lock_expired,
+};
+
struct nfs_rpc_ops nfs_v4_clientops = {
.version = 4, /* protocol version */
.dentry_ops = &nfs4_dentry_operations,