31 | 31 |
const (
|
32 | 32 |
readLock lockType = unix.F_RDLCK
|
33 | 33 |
writeLock lockType = unix.F_WRLCK
|
|
34 |
)
|
|
35 |
|
|
36 |
type cmdType int
|
|
37 |
|
|
38 |
const (
|
|
39 |
tryLock cmdType = unix.F_SETLK
|
|
40 |
waitLock cmdType = unix.F_SETLKW
|
34 | 41 |
)
|
35 | 42 |
|
36 | 43 |
type inode = uint64
|
|
89 | 96 |
defer f.ensureFhState()
|
90 | 97 |
}
|
91 | 98 |
|
92 | |
if _, err := f.doLock(flag, true); err != nil {
|
|
99 |
if _, err := f.doLock(waitLock, flag, true); err != nil {
|
93 | 100 |
return err
|
94 | 101 |
}
|
95 | 102 |
|
|
97 | 104 |
return nil
|
98 | 105 |
}
|
99 | 106 |
|
100 | |
func (f *Flock) doLock(lt lockType, blocking bool) (bool, error) {
|
|
107 |
func (f *Flock) doLock(cmd cmdType, lt lockType, blocking bool) (bool, error) {
|
101 | 108 |
// POSIX locks apply per inode and process, and the lock for an inode is
|
102 | 109 |
// released when *any* descriptor for that inode is closed. So we need to
|
103 | 110 |
// synchronize access to each inode internally, and must serialize lock and
|
|
142 | 149 |
wait <- f
|
143 | 150 |
}
|
144 | 151 |
|
145 | |
err = setlkw(f.fh.Fd(), lt)
|
|
152 |
err = setlkw(f.fh.Fd(), cmd, lt)
|
146 | 153 |
|
147 | 154 |
if err != nil {
|
148 | 155 |
f.doUnlock()
|
|
156 |
if cmd == tryLock && err == unix.EACCES {
|
|
157 |
return false, nil
|
|
158 |
}
|
149 | 159 |
return false, err
|
150 | 160 |
}
|
151 | 161 |
|
|
185 | 195 |
mu.Unlock()
|
186 | 196 |
|
187 | 197 |
if owner == f {
|
188 | |
err = setlkw(f.fh.Fd(), unix.F_UNLCK)
|
|
198 |
err = setlkw(f.fh.Fd(), waitLock, unix.F_UNLCK)
|
189 | 199 |
}
|
190 | 200 |
|
191 | 201 |
mu.Lock()
|
|
245 | 255 |
defer f.ensureFhState()
|
246 | 256 |
}
|
247 | 257 |
|
248 | |
haslock, err := f.doLock(flag, false)
|
|
258 |
haslock, err := f.doLock(tryLock, flag, false)
|
249 | 259 |
if err != nil {
|
250 | 260 |
return false, err
|
251 | 261 |
}
|
|
254 | 264 |
return haslock, nil
|
255 | 265 |
}
|
256 | 266 |
|
257 | |
// setlkw calls FcntlFlock with F_SETLKW for the entire file indicated by fd.
|
258 | |
func setlkw(fd uintptr, lt lockType) error {
|
|
267 |
// setlkw calls FcntlFlock with cmd for the entire file indicated by fd.
|
|
268 |
func setlkw(fd uintptr, cmd cmdType, lt lockType) error {
|
259 | 269 |
for {
|
260 | |
err := unix.FcntlFlock(fd, unix.F_SETLKW, &unix.Flock_t{
|
|
270 |
err := unix.FcntlFlock(fd, int(cmd), &unix.Flock_t{
|
261 | 271 |
Type: int16(lt),
|
262 | 272 |
Whence: io.SeekStart,
|
263 | 273 |
Start: 0,
|