Skip to content

Commit 586759f

Browse files
Marc EshelJ. Bruce Fields
Marc Eshel
authored and
J. Bruce Fields
committed
gfs2: nfs lock support for gfs2
Add NFS lock support to GFS2. Signed-off-by: Marc Eshel <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]> Acked-by: Steven Whitehouse <[email protected]>
1 parent 1a8322b commit 586759f

File tree

2 files changed

+104
-10
lines changed

2 files changed

+104
-10
lines changed

fs/gfs2/locking/dlm/plock.c

Lines changed: 99 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ struct plock_op {
2525
struct gdlm_plock_info info;
2626
};
2727

28+
struct plock_xop {
29+
struct plock_op xop;
30+
void *callback;
31+
void *fl;
32+
void *file;
33+
struct file_lock flc;
34+
};
35+
36+
2837
static inline void set_version(struct gdlm_plock_info *info)
2938
{
3039
info->version[0] = GDLM_PLOCK_VERSION_MAJOR;
@@ -64,12 +73,14 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
6473
{
6574
struct gdlm_ls *ls = lockspace;
6675
struct plock_op *op;
76+
struct plock_xop *xop;
6777
int rv;
6878

69-
op = kzalloc(sizeof(*op), GFP_KERNEL);
70-
if (!op)
79+
xop = kzalloc(sizeof(*xop), GFP_KERNEL);
80+
if (!xop)
7181
return -ENOMEM;
7282

83+
op = &xop->xop;
7384
op->info.optype = GDLM_PLOCK_OP_LOCK;
7485
op->info.pid = fl->fl_pid;
7586
op->info.ex = (fl->fl_type == F_WRLCK);
@@ -79,9 +90,21 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
7990
op->info.start = fl->fl_start;
8091
op->info.end = fl->fl_end;
8192
op->info.owner = (__u64)(long) fl->fl_owner;
93+
if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
94+
xop->callback = fl->fl_lmops->fl_grant;
95+
locks_init_lock(&xop->flc);
96+
locks_copy_lock(&xop->flc, fl);
97+
xop->fl = fl;
98+
xop->file = file;
99+
} else
100+
xop->callback = NULL;
82101

83102
send_op(op);
84-
wait_event(recv_wq, (op->done != 0));
103+
104+
if (xop->callback == NULL)
105+
wait_event(recv_wq, (op->done != 0));
106+
else
107+
return -EINPROGRESS;
85108

86109
spin_lock(&ops_lock);
87110
if (!list_empty(&op->list)) {
@@ -99,7 +122,63 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
99122
(unsigned long long)name->ln_number);
100123
}
101124

102-
kfree(op);
125+
kfree(xop);
126+
return rv;
127+
}
128+
129+
/* Returns failure iff a succesful lock operation should be canceled */
130+
static int gdlm_plock_callback(struct plock_op *op)
131+
{
132+
struct file *file;
133+
struct file_lock *fl;
134+
struct file_lock *flc;
135+
int (*notify)(void *, void *, int) = NULL;
136+
struct plock_xop *xop = (struct plock_xop *)op;
137+
int rv = 0;
138+
139+
spin_lock(&ops_lock);
140+
if (!list_empty(&op->list)) {
141+
printk(KERN_INFO "plock op on list\n");
142+
list_del(&op->list);
143+
}
144+
spin_unlock(&ops_lock);
145+
146+
/* check if the following 2 are still valid or make a copy */
147+
file = xop->file;
148+
flc = &xop->flc;
149+
fl = xop->fl;
150+
notify = xop->callback;
151+
152+
if (op->info.rv) {
153+
notify(flc, NULL, op->info.rv);
154+
goto out;
155+
}
156+
157+
/* got fs lock; bookkeep locally as well: */
158+
flc->fl_flags &= ~FL_SLEEP;
159+
if (posix_lock_file(file, flc, NULL)) {
160+
/*
161+
* This can only happen in the case of kmalloc() failure.
162+
* The filesystem's own lock is the authoritative lock,
163+
* so a failure to get the lock locally is not a disaster.
164+
* As long as GFS cannot reliably cancel locks (especially
165+
* in a low-memory situation), we're better off ignoring
166+
* this failure than trying to recover.
167+
*/
168+
log_error("gdlm_plock: vfs lock error file %p fl %p",
169+
file, fl);
170+
}
171+
172+
rv = notify(flc, NULL, 0);
173+
if (rv) {
174+
/* XXX: We need to cancel the fs lock here: */
175+
printk("gfs2 lock granted after lock request failed;"
176+
" dangling lock!\n");
177+
goto out;
178+
}
179+
180+
out:
181+
kfree(xop);
103182
return rv;
104183
}
105184

@@ -138,6 +217,9 @@ int gdlm_punlock(void *lockspace, struct lm_lockname *name,
138217

139218
rv = op->info.rv;
140219

220+
if (rv == -ENOENT)
221+
rv = 0;
222+
141223
kfree(op);
142224
return rv;
143225
}
@@ -161,6 +243,7 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
161243
op->info.start = fl->fl_start;
162244
op->info.end = fl->fl_end;
163245

246+
164247
send_op(op);
165248
wait_event(recv_wq, (op->done != 0));
166249

@@ -173,9 +256,10 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
173256

174257
rv = op->info.rv;
175258

176-
if (rv == 0)
177-
fl->fl_type = F_UNLCK;
178-
else if (rv > 0) {
259+
fl->fl_type = F_UNLCK;
260+
if (rv == -ENOENT)
261+
rv = 0;
262+
else if (rv == 0 && op->info.pid != fl->fl_pid) {
179263
fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
180264
fl->fl_pid = op->info.pid;
181265
fl->fl_start = op->info.start;
@@ -243,9 +327,14 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
243327
}
244328
spin_unlock(&ops_lock);
245329

246-
if (found)
247-
wake_up(&recv_wq);
248-
else
330+
if (found) {
331+
struct plock_xop *xop;
332+
xop = (struct plock_xop *)op;
333+
if (xop->callback)
334+
count = gdlm_plock_callback(op);
335+
else
336+
wake_up(&recv_wq);
337+
} else
249338
printk(KERN_INFO "gdlm dev_write no op %x %llx\n", info.fsid,
250339
(unsigned long long)info.number);
251340
return count;

fs/gfs2/ops_file.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,11 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
520520
}
521521
}
522522

523+
if (cmd == F_CANCELLK) {
524+
/* Hack: */
525+
cmd = F_SETLK;
526+
fl->fl_type = F_UNLCK;
527+
}
523528
if (IS_GETLK(cmd))
524529
return gfs2_lm_plock_get(sdp, &name, file, fl);
525530
else if (fl->fl_type == F_UNLCK)

0 commit comments

Comments
 (0)