OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [lockd/] [clntlock.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/fs/lockd/clntlock.c
3
 *
4
 * Lock handling for the client side NLM implementation
5
 *
6
 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7
 */
8
 
9
#define __KERNEL_SYSCALLS__
10
 
11
#include <linux/module.h>
12
#include <linux/types.h>
13
#include <linux/sched.h>
14
#include <linux/nfs_fs.h>
15
#include <linux/unistd.h>
16
#include <linux/sunrpc/clnt.h>
17
#include <linux/sunrpc/svc.h>
18
#include <linux/lockd/lockd.h>
19
#include <linux/smp_lock.h>
20
 
21
#define NLMDBG_FACILITY         NLMDBG_CLIENT
22
 
23
/*
24
 * Local function prototypes
25
 */
26
static int                      reclaimer(void *ptr);
27
 
28
/*
29
 * The following functions handle blocking and granting from the
30
 * client perspective.
31
 */
32
 
33
/*
34
 * This is the representation of a blocked client lock.
35
 */
36
struct nlm_wait {
37
        struct nlm_wait *       b_next;         /* linked list */
38
        wait_queue_head_t       b_wait;         /* where to wait on */
39
        struct nlm_host *       b_host;
40
        struct file_lock *      b_lock;         /* local file lock */
41
        unsigned short          b_reclaim;      /* got to reclaim lock */
42
        u32                     b_status;       /* grant callback status */
43
};
44
 
45
static struct nlm_wait *        nlm_blocked;
46
 
47
/*
48
 * Block on a lock
49
 */
50
int
51
nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp)
52
{
53
        struct nlm_wait block, **head;
54
        int             err;
55
        u32             pstate;
56
 
57
        block.b_host   = host;
58
        block.b_lock   = fl;
59
        init_waitqueue_head(&block.b_wait);
60
        block.b_status = NLM_LCK_BLOCKED;
61
        block.b_next   = nlm_blocked;
62
        nlm_blocked    = &block;
63
 
64
        /* Remember pseudo nsm state */
65
        pstate = host->h_state;
66
 
67
        /* Go to sleep waiting for GRANT callback. Some servers seem
68
         * to lose callbacks, however, so we're going to poll from
69
         * time to time just to make sure.
70
         *
71
         * For now, the retry frequency is pretty high; normally
72
         * a 1 minute timeout would do. See the comment before
73
         * nlmclnt_lock for an explanation.
74
         */
75
        sleep_on_timeout(&block.b_wait, 30*HZ);
76
 
77
        for (head = &nlm_blocked; *head; head = &(*head)->b_next) {
78
                if (*head == &block) {
79
                        *head = block.b_next;
80
                        break;
81
                }
82
        }
83
 
84
        if (!signalled()) {
85
                *statp = block.b_status;
86
                return 0;
87
        }
88
 
89
        /* Okay, we were interrupted. Cancel the pending request
90
         * unless the server has rebooted.
91
         */
92
        if (pstate == host->h_state && (err = nlmclnt_cancel(host, fl)) < 0)
93
                printk(KERN_NOTICE
94
                        "lockd: CANCEL call failed (errno %d)\n", -err);
95
 
96
        return -ERESTARTSYS;
97
}
98
 
99
/*
100
 * The server lockd has called us back to tell us the lock was granted
101
 */
102
u32
103
nlmclnt_grant(struct nlm_lock *lock)
104
{
105
        struct nlm_wait *block;
106
 
107
        /*
108
         * Look up blocked request based on arguments.
109
         * Warning: must not use cookie to match it!
110
         */
111
        for (block = nlm_blocked; block; block = block->b_next) {
112
                if (nlm_compare_locks(block->b_lock, &lock->fl))
113
                        break;
114
        }
115
 
116
        /* Ooops, no blocked request found. */
117
        if (block == NULL)
118
                return nlm_lck_denied;
119
 
120
        /* Alright, we found the lock. Set the return status and
121
         * wake up the caller.
122
         */
123
        block->b_status = NLM_LCK_GRANTED;
124
        wake_up(&block->b_wait);
125
 
126
        return nlm_granted;
127
}
128
 
129
/*
130
 * The following procedures deal with the recovery of locks after a
131
 * server crash.
132
 */
133
 
134
/*
135
 * Mark the locks for reclaiming.
136
 * FIXME: In 2.5 we don't want to iterate through any global file_lock_list.
137
 *        Maintain NLM lock reclaiming lists in the nlm_host instead.
138
 */
139
static
140
void nlmclnt_mark_reclaim(struct nlm_host *host)
141
{
142
        struct file_lock *fl;
143
        struct inode *inode;
144
        struct list_head *tmp;
145
 
146
        list_for_each(tmp, &file_lock_list) {
147
                fl = list_entry(tmp, struct file_lock, fl_link);
148
 
149
                inode = fl->fl_file->f_dentry->d_inode;
150
                if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
151
                        continue;
152
                if (fl->fl_u.nfs_fl.host != host)
153
                        continue;
154
                if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED))
155
                        continue;
156
                fl->fl_u.nfs_fl.flags |= NFS_LCK_RECLAIM;
157
        }
158
}
159
 
160
/*
161
 * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number,
162
 * that we mark locks for reclaiming, and that we bump the pseudo NSM state.
163
 */
164
static inline
165
void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate)
166
{
167
        host->h_monitored = 0;
168
        host->h_nsmstate = newstate;
169
        host->h_state++;
170
        host->h_nextrebind = 0;
171
        nlm_rebind_host(host);
172
        nlmclnt_mark_reclaim(host);
173
        dprintk("NLM: reclaiming locks for host %s", host->h_name);
174
}
175
 
176
/*
177
 * Reclaim all locks on server host. We do this by spawning a separate
178
 * reclaimer thread.
179
 */
180
void
181
nlmclnt_recovery(struct nlm_host *host, u32 newstate)
182
{
183
        if (host->h_reclaiming++) {
184
                if (host->h_nsmstate == newstate)
185
                        return;
186
                nlmclnt_prepare_reclaim(host, newstate);
187
        } else {
188
                nlmclnt_prepare_reclaim(host, newstate);
189
                nlm_get_host(host);
190
                MOD_INC_USE_COUNT;
191
                if (kernel_thread(reclaimer, host, CLONE_SIGNAL) < 0)
192
                        MOD_DEC_USE_COUNT;
193
        }
194
}
195
 
196
static int
197
reclaimer(void *ptr)
198
{
199
        struct nlm_host   *host = (struct nlm_host *) ptr;
200
        struct nlm_wait   *block;
201
        struct list_head *tmp;
202
        struct file_lock *fl;
203
        struct inode *inode;
204
 
205
        daemonize();
206
        reparent_to_init();
207
        snprintf(current->comm, sizeof(current->comm),
208
                 "%s-reclaim",
209
                 host->h_name);
210
 
211
        /* This one ensures that our parent doesn't terminate while the
212
         * reclaim is in progress */
213
        lock_kernel();
214
        lockd_up();
215
 
216
        /* First, reclaim all locks that have been marked. */
217
restart:
218
        list_for_each(tmp, &file_lock_list) {
219
                fl = list_entry(tmp, struct file_lock, fl_link);
220
 
221
                inode = fl->fl_file->f_dentry->d_inode;
222
                if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
223
                        continue;
224
                if (fl->fl_u.nfs_fl.host != host)
225
                        continue;
226
                if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM))
227
                        continue;
228
 
229
                fl->fl_u.nfs_fl.flags &= ~NFS_LCK_RECLAIM;
230
                nlmclnt_reclaim(host, fl);
231
                if (signalled())
232
                        break;
233
                goto restart;
234
        }
235
 
236
        host->h_reclaiming = 0;
237
        wake_up(&host->h_gracewait);
238
 
239
        /* Now, wake up all processes that sleep on a blocked lock */
240
        for (block = nlm_blocked; block; block = block->b_next) {
241
                if (block->b_host == host) {
242
                        block->b_status = NLM_LCK_DENIED_GRACE_PERIOD;
243
                        wake_up(&block->b_wait);
244
                }
245
        }
246
 
247
        /* Release host handle after use */
248
        nlm_release_host(host);
249
        lockd_down();
250
        unlock_kernel();
251
        MOD_DEC_USE_COUNT;
252
 
253
        return 0;
254
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.