.. | .. |
---|
32 | 32 | |
---|
33 | 33 | static void ceph_fl_copy_lock(struct file_lock *dst, struct file_lock *src) |
---|
34 | 34 | { |
---|
35 | | - struct inode *inode = file_inode(src->fl_file); |
---|
| 35 | + struct inode *inode = file_inode(dst->fl_file); |
---|
36 | 36 | atomic_inc(&ceph_inode(inode)->i_filelock_ref); |
---|
37 | 37 | } |
---|
38 | 38 | |
---|
.. | .. |
---|
59 | 59 | static int ceph_lock_message(u8 lock_type, u16 operation, struct inode *inode, |
---|
60 | 60 | int cmd, u8 wait, struct file_lock *fl) |
---|
61 | 61 | { |
---|
62 | | - struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; |
---|
| 62 | + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); |
---|
63 | 63 | struct ceph_mds_request *req; |
---|
64 | 64 | int err; |
---|
65 | 65 | u64 length = 0; |
---|
.. | .. |
---|
73 | 73 | * window. Caller function will decrease the counter. |
---|
74 | 74 | */ |
---|
75 | 75 | fl->fl_ops = &ceph_fl_lock_ops; |
---|
76 | | - atomic_inc(&ceph_inode(inode)->i_filelock_ref); |
---|
| 76 | + fl->fl_ops->fl_copy_lock(fl, NULL); |
---|
77 | 77 | } |
---|
78 | 78 | |
---|
79 | 79 | if (operation != CEPH_MDS_OP_SETFILELOCK || cmd == CEPH_LOCK_UNLOCK) |
---|
.. | .. |
---|
206 | 206 | return 0; |
---|
207 | 207 | } |
---|
208 | 208 | |
---|
| 209 | +static int try_unlock_file(struct file *file, struct file_lock *fl) |
---|
| 210 | +{ |
---|
| 211 | + int err; |
---|
| 212 | + unsigned int orig_flags = fl->fl_flags; |
---|
| 213 | + fl->fl_flags |= FL_EXISTS; |
---|
| 214 | + err = locks_lock_file_wait(file, fl); |
---|
| 215 | + fl->fl_flags = orig_flags; |
---|
| 216 | + if (err == -ENOENT) { |
---|
| 217 | + if (!(orig_flags & FL_EXISTS)) |
---|
| 218 | + err = 0; |
---|
| 219 | + return err; |
---|
| 220 | + } |
---|
| 221 | + return 1; |
---|
| 222 | +} |
---|
| 223 | + |
---|
209 | 224 | /** |
---|
210 | 225 | * Attempt to set an fcntl lock. |
---|
211 | 226 | * For now, this just goes away to the server. Later it may be more awesome. |
---|
.. | .. |
---|
236 | 251 | spin_lock(&ci->i_ceph_lock); |
---|
237 | 252 | if (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) { |
---|
238 | 253 | err = -EIO; |
---|
239 | | - } else if (op == CEPH_MDS_OP_SETFILELOCK) { |
---|
240 | | - /* |
---|
241 | | - * increasing i_filelock_ref closes race window between |
---|
242 | | - * handling request reply and adding file_lock struct to |
---|
243 | | - * inode. Otherwise, i_auth_cap may get trimmed in the |
---|
244 | | - * window. Caller function will decrease the counter. |
---|
245 | | - */ |
---|
246 | | - fl->fl_ops = &ceph_fl_lock_ops; |
---|
247 | | - atomic_inc(&ci->i_filelock_ref); |
---|
248 | 254 | } |
---|
249 | 255 | spin_unlock(&ci->i_ceph_lock); |
---|
250 | 256 | if (err < 0) { |
---|
.. | .. |
---|
260 | 266 | else |
---|
261 | 267 | lock_cmd = CEPH_LOCK_UNLOCK; |
---|
262 | 268 | |
---|
| 269 | + if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK == fl->fl_type) { |
---|
| 270 | + err = try_unlock_file(file, fl); |
---|
| 271 | + if (err <= 0) |
---|
| 272 | + return err; |
---|
| 273 | + } |
---|
| 274 | + |
---|
263 | 275 | err = ceph_lock_message(CEPH_LOCK_FCNTL, op, inode, lock_cmd, wait, fl); |
---|
264 | 276 | if (!err) { |
---|
265 | | - if (op == CEPH_MDS_OP_SETFILELOCK) { |
---|
| 277 | + if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK != fl->fl_type) { |
---|
266 | 278 | dout("mds locked, locking locally\n"); |
---|
267 | 279 | err = posix_lock_file(file, fl, NULL); |
---|
268 | 280 | if (err) { |
---|
.. | .. |
---|
298 | 310 | spin_lock(&ci->i_ceph_lock); |
---|
299 | 311 | if (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) { |
---|
300 | 312 | err = -EIO; |
---|
301 | | - } else { |
---|
302 | | - /* see comment in ceph_lock */ |
---|
303 | | - fl->fl_ops = &ceph_fl_lock_ops; |
---|
304 | | - atomic_inc(&ci->i_filelock_ref); |
---|
305 | 313 | } |
---|
306 | 314 | spin_unlock(&ci->i_ceph_lock); |
---|
307 | 315 | if (err < 0) { |
---|
.. | .. |
---|
320 | 328 | else |
---|
321 | 329 | lock_cmd = CEPH_LOCK_UNLOCK; |
---|
322 | 330 | |
---|
| 331 | + if (F_UNLCK == fl->fl_type) { |
---|
| 332 | + err = try_unlock_file(file, fl); |
---|
| 333 | + if (err <= 0) |
---|
| 334 | + return err; |
---|
| 335 | + } |
---|
| 336 | + |
---|
323 | 337 | err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK, |
---|
324 | 338 | inode, lock_cmd, wait, fl); |
---|
325 | | - if (!err) { |
---|
| 339 | + if (!err && F_UNLCK != fl->fl_type) { |
---|
326 | 340 | err = locks_lock_file_wait(file, fl); |
---|
327 | 341 | if (err) { |
---|
328 | 342 | ceph_lock_message(CEPH_LOCK_FLOCK, |
---|