Skip to content

Commit b1ece73

Browse files
bcodding-rhtrondmypd
authored andcommitted
lockd: Introduce nlmclnt_operations
NFS would enjoy the ability to modify the behavior of the NLM client's unlock RPC task in order to delay the transmission of the unlock until IO that was submitted under that lock has completed. This ability can ensure that the NLM client will always complete the transmission of an unlock even if the waiting caller has been interrupted with fatal signal. For this purpose, a pointer to a struct nlmclnt_operations can be assigned in a nfs_module's nfs_rpc_ops that will install those nlmclnt_operations on the nlm_host. The struct nlmclnt_operations defines three callback operations that will be used in a following patch: nlmclnt_alloc_call - used to call back after a successful allocation of a struct nlm_rqst in nlmclnt_proc(). nlmclnt_unlock_prepare - used to call back during NLM unlock's rpc_call_prepare. The NLM client defers calling rpc_call_start() until this callback returns false. nlmclnt_release_call - used to call back when the NLM client's struct nlm_rqst is freed. Signed-off-by: Benjamin Coddington <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Trond Myklebust <[email protected]>
1 parent 7d6ddf8 commit b1ece73

File tree

8 files changed

+54
-5
lines changed

8 files changed

+54
-5
lines changed

fs/lockd/clntlock.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
6969
if (host->h_rpcclnt == NULL && nlm_bind_host(host) == NULL)
7070
goto out_nobind;
7171

72+
host->h_nlmclnt_ops = nlm_init->nlmclnt_ops;
7273
return host;
7374
out_nobind:
7475
nlmclnt_release_host(host);

fs/lockd/clntproc.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,17 +150,22 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
150150
* @host: address of a valid nlm_host context representing the NLM server
151151
* @cmd: fcntl-style file lock operation to perform
152152
* @fl: address of arguments for the lock operation
153+
* @data: address of data to be sent to callback operations
153154
*
154155
*/
155-
int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
156+
int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl, void *data)
156157
{
157158
struct nlm_rqst *call;
158159
int status;
160+
const struct nlmclnt_operations *nlmclnt_ops = host->h_nlmclnt_ops;
159161

160162
call = nlm_alloc_call(host);
161163
if (call == NULL)
162164
return -ENOMEM;
163165

166+
if (nlmclnt_ops && nlmclnt_ops->nlmclnt_alloc_call)
167+
nlmclnt_ops->nlmclnt_alloc_call(data);
168+
164169
nlmclnt_locks_init_private(fl, host);
165170
if (!fl->fl_u.nfs_fl.owner) {
166171
/* lockowner allocation has failed */
@@ -169,6 +174,7 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
169174
}
170175
/* Set up the argument struct */
171176
nlmclnt_setlockargs(call, fl);
177+
call->a_callback_data = data;
172178

173179
if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
174180
if (fl->fl_type != F_UNLCK) {
@@ -214,8 +220,12 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
214220

215221
void nlmclnt_release_call(struct nlm_rqst *call)
216222
{
223+
const struct nlmclnt_operations *nlmclnt_ops = call->a_host->h_nlmclnt_ops;
224+
217225
if (!atomic_dec_and_test(&call->a_count))
218226
return;
227+
if (nlmclnt_ops && nlmclnt_ops->nlmclnt_release_call)
228+
nlmclnt_ops->nlmclnt_release_call(call->a_callback_data);
219229
nlmclnt_release_host(call->a_host);
220230
nlmclnt_release_lockargs(call);
221231
kfree(call);
@@ -687,6 +697,19 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
687697
return status;
688698
}
689699

700+
static void nlmclnt_unlock_prepare(struct rpc_task *task, void *data)
701+
{
702+
struct nlm_rqst *req = data;
703+
const struct nlmclnt_operations *nlmclnt_ops = req->a_host->h_nlmclnt_ops;
704+
bool defer_call = false;
705+
706+
if (nlmclnt_ops && nlmclnt_ops->nlmclnt_unlock_prepare)
707+
defer_call = nlmclnt_ops->nlmclnt_unlock_prepare(task, req->a_callback_data);
708+
709+
if (!defer_call)
710+
rpc_call_start(task);
711+
}
712+
690713
static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
691714
{
692715
struct nlm_rqst *req = data;
@@ -720,6 +743,7 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
720743
}
721744

722745
static const struct rpc_call_ops nlmclnt_unlock_ops = {
746+
.rpc_call_prepare = nlmclnt_unlock_prepare,
723747
.rpc_call_done = nlmclnt_unlock_callback,
724748
.rpc_release = nlmclnt_rpc_release,
725749
};

fs/nfs/client.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ static int nfs_start_lockd(struct nfs_server *server)
546546
.noresvport = server->flags & NFS_MOUNT_NORESVPORT ?
547547
1 : 0,
548548
.net = clp->cl_net,
549+
.nlmclnt_ops = clp->cl_nfs_mod->rpc_ops->nlmclnt_ops,
549550
};
550551

551552
if (nlm_init.nfs_version > 3)

fs/nfs/nfs3proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
870870
{
871871
struct inode *inode = file_inode(filp);
872872

873-
return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl);
873+
return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl, NULL);
874874
}
875875

876876
static int nfs3_have_delegation(struct inode *inode, fmode_t flags)

fs/nfs/proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
638638
{
639639
struct inode *inode = file_inode(filp);
640640

641-
return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl);
641+
return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl, NULL);
642642
}
643643

644644
/* Helper functions for NFS lock bounds checking */

include/linux/lockd/bind.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
/* Dummy declarations */
2020
struct svc_rqst;
21+
struct rpc_task;
2122

2223
/*
2324
* This is the set of functions for lockd->nfsd communication
@@ -43,6 +44,7 @@ struct nlmclnt_initdata {
4344
u32 nfs_version;
4445
int noresvport;
4546
struct net *net;
47+
const struct nlmclnt_operations *nlmclnt_ops;
4648
};
4749

4850
/*
@@ -52,8 +54,26 @@ struct nlmclnt_initdata {
5254
extern struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init);
5355
extern void nlmclnt_done(struct nlm_host *host);
5456

55-
extern int nlmclnt_proc(struct nlm_host *host, int cmd,
56-
struct file_lock *fl);
57+
/*
58+
* NLM client operations provide a means to modify RPC processing of NLM
59+
* requests. Callbacks receive a pointer to data passed into the call to
60+
* nlmclnt_proc().
61+
*/
62+
struct nlmclnt_operations {
63+
/* Called on successful allocation of nlm_rqst, use for allocation or
64+
* reference counting. */
65+
void (*nlmclnt_alloc_call)(void *);
66+
67+
/* Called in rpc_task_prepare for unlock. A return value of true
68+
* indicates the callback has put the task to sleep on a waitqueue
69+
* and NLM should not call rpc_call_start(). */
70+
bool (*nlmclnt_unlock_prepare)(struct rpc_task*, void *);
71+
72+
/* Called when the nlm_rqst is freed, callbacks should clean up here */
73+
void (*nlmclnt_release_call)(void *);
74+
};
75+
76+
extern int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl, void *data);
5777
extern int lockd_up(struct net *net);
5878
extern void lockd_down(struct net *net);
5979

include/linux/lockd/lockd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct nlm_host {
6969
char *h_addrbuf; /* address eyecatcher */
7070
struct net *net; /* host net */
7171
char nodename[UNX_MAXNODENAME + 1];
72+
const struct nlmclnt_operations *h_nlmclnt_ops; /* Callback ops for NLM users */
7273
};
7374

7475
/*
@@ -142,6 +143,7 @@ struct nlm_rqst {
142143
struct nlm_block * a_block;
143144
unsigned int a_retries; /* Retry count */
144145
u8 a_owner[NLMCLNT_OHSIZE];
146+
void * a_callback_data; /* sent to nlmclnt_operations callbacks */
145147
};
146148

147149
/*

include/linux/nfs_xdr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,7 @@ struct nfs_rpc_ops {
15511551
const struct inode_operations *dir_inode_ops;
15521552
const struct inode_operations *file_inode_ops;
15531553
const struct file_operations *file_ops;
1554+
const struct nlmclnt_operations *nlmclnt_ops;
15541555

15551556
int (*getroot) (struct nfs_server *, struct nfs_fh *,
15561557
struct nfs_fsinfo *);

0 commit comments

Comments
 (0)