diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp
index 35b7d908c0..5572964562 100644
a
|
b
|
struct advisory_lock : public DoublyLinkedListLinkImpl<advisory_lock> {
|
173 | 173 | list_link link; |
174 | 174 | team_id team; |
175 | 175 | pid_t session; |
| 176 | int fd; |
176 | 177 | off_t start; |
177 | 178 | off_t end; |
178 | 179 | bool shared; |
… |
… |
test_advisory_lock(struct vnode* vnode, struct flock* flock)
|
1626 | 1627 | if \a flock is NULL. |
1627 | 1628 | */ |
1628 | 1629 | static status_t |
1629 | | release_advisory_lock(struct vnode* vnode, struct flock* flock) |
| 1630 | release_advisory_lock(struct vnode* vnode, int fd, struct flock* flock) |
1630 | 1631 | { |
1631 | 1632 | FUNCTION(("release_advisory_lock(vnode = %p, flock = %p)\n", vnode, flock)); |
1632 | 1633 | |
… |
… |
release_advisory_lock(struct vnode* vnode, struct flock* flock)
|
1645 | 1646 | struct advisory_lock* lock = iterator.Next(); |
1646 | 1647 | bool removeLock = false; |
1647 | 1648 | |
1648 | | if (lock->session == session) |
| 1649 | if (lock->session == session && lock->fd == fd) |
1649 | 1650 | removeLock = true; |
1650 | | else if (lock->team == team && advisory_lock_intersects(lock, flock)) { |
| 1651 | else if (lock->team == team && lock->fd == fd |
| 1652 | && advisory_lock_intersects(lock, flock)) { |
1651 | 1653 | bool endsBeyond = false; |
1652 | 1654 | bool startsBefore = false; |
1653 | 1655 | if (flock != NULL) { |
… |
… |
release_advisory_lock(struct vnode* vnode, struct flock* flock)
|
1678 | 1680 | |
1679 | 1681 | secondLock->team = lock->team; |
1680 | 1682 | secondLock->session = lock->session; |
| 1683 | secondLock->fd = lock->fd; |
1681 | 1684 | // values must already be normalized when getting here |
1682 | 1685 | secondLock->start = flock->l_start + flock->l_len; |
1683 | 1686 | secondLock->end = lock->end; |
… |
… |
release_advisory_lock(struct vnode* vnode, struct flock* flock)
|
1733 | 1736 | will wait for the lock to become available, if there are any collisions |
1734 | 1737 | (it will return B_PERMISSION_DENIED in this case if \a wait is \c false). |
1735 | 1738 | |
1736 | | If \a session is -1, POSIX semantics are used for this lock. Otherwise, |
| 1739 | If \a fd is -1, POSIX semantics are used for this lock. Otherwise, |
1737 | 1740 | BSD flock() semantics are used, that is, all children can unlock the file |
1738 | 1741 | in question (we even allow parents to remove the lock, though, but that |
1739 | 1742 | seems to be in line to what the BSD's are doing). |
1740 | 1743 | */ |
1741 | 1744 | static status_t |
1742 | | acquire_advisory_lock(struct vnode* vnode, pid_t session, struct flock* flock, |
| 1745 | acquire_advisory_lock(struct vnode* vnode, int fd, struct flock* flock, |
1743 | 1746 | bool wait) |
1744 | 1747 | { |
1745 | 1748 | FUNCTION(("acquire_advisory_lock(vnode = %p, flock = %p, wait = %s)\n", |
… |
… |
acquire_advisory_lock(struct vnode* vnode, pid_t session, struct flock* flock,
|
1768 | 1771 | while (iterator.HasNext()) { |
1769 | 1772 | struct advisory_lock* lock = iterator.Next(); |
1770 | 1773 | |
1771 | | // TODO: locks from the same team might be joinable! |
1772 | | if (lock->team != team && advisory_lock_intersects(lock, flock)) { |
| 1774 | if ((lock->team != team || lock->fd != fd) |
| 1775 | && advisory_lock_intersects(lock, flock)) { |
1773 | 1776 | // locks do overlap |
1774 | 1777 | if (!shared || !lock->shared) { |
1775 | 1778 | // we need to wait |
… |
… |
acquire_advisory_lock(struct vnode* vnode, pid_t session, struct flock* flock,
|
1786 | 1789 | |
1787 | 1790 | if (!wait) { |
1788 | 1791 | put_advisory_locking(locking); |
1789 | | return session != -1 ? B_WOULD_BLOCK : B_PERMISSION_DENIED; |
| 1792 | return fd != -1 ? B_WOULD_BLOCK : B_PERMISSION_DENIED; |
1790 | 1793 | } |
1791 | 1794 | |
1792 | 1795 | status = switch_sem_etc(locking->lock, waitForLock, 1, |
… |
… |
acquire_advisory_lock(struct vnode* vnode, pid_t session, struct flock* flock,
|
1808 | 1811 | } |
1809 | 1812 | |
1810 | 1813 | lock->team = team_get_current_team_id(); |
1811 | | lock->session = session; |
| 1814 | lock->session = thread_get_current_thread()->team->session_id; |
| 1815 | lock->fd = fd; |
1812 | 1816 | // values must already be normalized when getting here |
1813 | 1817 | lock->start = flock->l_start; |
1814 | 1818 | lock->end = flock->l_start - 1 + flock->l_len; |
… |
… |
file_close(struct file_descriptor* descriptor)
|
5626 | 5630 | // remove all outstanding locks for this team |
5627 | 5631 | if (HAS_FS_CALL(vnode, release_lock)) |
5628 | 5632 | status = FS_CALL(vnode, release_lock, descriptor->cookie, NULL); |
5629 | | else |
5630 | | status = release_advisory_lock(vnode, NULL); |
| 5633 | else { |
| 5634 | // FIXME should also release fd-pinned locks (how do we get the fd?) |
| 5635 | // status = release_advisory_lock(vnode, fd, NULL); |
| 5636 | status = release_advisory_lock(vnode, -1, NULL); |
| 5637 | } |
5631 | 5638 | } |
5632 | 5639 | return status; |
5633 | 5640 | } |
… |
… |
common_fcntl(int fd, int op, size_t argument, bool kernel)
|
6210 | 6217 | status = FS_CALL(vnode, release_lock, descriptor->cookie, |
6211 | 6218 | &flock); |
6212 | 6219 | } else |
6213 | | status = release_advisory_lock(vnode, &flock); |
| 6220 | status = release_advisory_lock(vnode, -1, &flock); |
6214 | 6221 | } else { |
6215 | 6222 | // the open mode must match the lock type |
6216 | 6223 | if (((descriptor->open_mode & O_RWMASK) == O_RDONLY |
… |
… |
_user_flock(int fd, int operation)
|
9110 | 9117 | |
9111 | 9118 | status_t status; |
9112 | 9119 | if ((operation & LOCK_UN) != 0) |
9113 | | status = release_advisory_lock(vnode, &flock); |
| 9120 | status = release_advisory_lock(vnode, fd, &flock); |
9114 | 9121 | else { |
9115 | | status = acquire_advisory_lock(vnode, |
9116 | | thread_get_current_thread()->team->session_id, &flock, |
| 9122 | status = acquire_advisory_lock(vnode, fd, &flock, |
9117 | 9123 | (operation & LOCK_NB) == 0); |
9118 | 9124 | } |
9119 | 9125 | |