mirror of
https://github.com/ceph/ceph
synced 2025-01-03 17:42:36 +00:00
mds: fcntl. add skeleton [add, remove]_lock functions.
Implement helper functions to be used later.
This commit is contained in:
parent
aab26ff652
commit
f60e20e50a
@ -338,6 +338,107 @@ struct ceph_lock_state_t {
|
||||
multimap<__u64, ceph_filelock> held_locks; //current locks
|
||||
multimap<__u64, ceph_filelock> waiting_locks; //locks waiting for other locks
|
||||
//both of the above are keyed by starting offset
|
||||
|
||||
/*
|
||||
* Try to set a new lock. If it's blocked and wait_on_fail is true,
|
||||
* add the lock to waiting_locks.
|
||||
* The lock needs to be of type CEPH_LOCK_EXCL or CEPH_LOCK_SHARED.
|
||||
*
|
||||
* Returns true if set, false if not set.
|
||||
*/
|
||||
bool add_lock(ceph_filelock& new_lock, bool wait_on_fail) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove one lock described in old_lock. This may involve splitting a
|
||||
* previous lock or making a previous lock smaller.
|
||||
*/
|
||||
void remove_lock(ceph_filelock old_lock) {
|
||||
|
||||
}
|
||||
private:
|
||||
//get last lock prior to start position
|
||||
multimap<__u64, ceph_filelock>::iterator
|
||||
get_lower_bound(__u64 start, multimap<__u64, ceph_filelock>& lock_map) {
|
||||
multimap<__u64, ceph_filelock>::iterator lower_bound =
|
||||
lock_map.lower_bound(start);
|
||||
if ((lower_bound->first != start)
|
||||
&& (start != 0)
|
||||
&& (lower_bound != lock_map.begin())) --lower_bound;
|
||||
return lower_bound;
|
||||
}
|
||||
|
||||
//get latest-starting lock that goes over the byte "end"
|
||||
multimap<__u64, ceph_filelock>::iterator
|
||||
get_last_before(__u64 end, multimap<__u64, ceph_filelock>& lock_map) {
|
||||
multimap<__u64, ceph_filelock>::iterator last =
|
||||
lock_map.upper_bound(end);
|
||||
if (last != lock_map.begin()) --last;
|
||||
return last;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if an iterator's lock covers any of the same bounds as a given range
|
||||
* Rules: locks cover "length" bytes from "start", so the last covered
|
||||
* byte is at start + length - 1.
|
||||
* If the length is 0, the lock covers from "start" to the end of the file.
|
||||
*/
|
||||
bool share_space(multimap<__u64, ceph_filelock>::iterator& iter,
|
||||
__u64 start, __u64 end) {
|
||||
return ((iter->first > start && iter->first < end) ||
|
||||
((iter->first < start) &&
|
||||
(((iter->first + iter->second.length - 1) > start) ||
|
||||
(0 == iter->second.length))));
|
||||
}
|
||||
bool share_space(multimap<__u64, ceph_filelock>::iterator& iter,
|
||||
ceph_filelock& lock) {
|
||||
return share_space(iter, lock.start, lock.start+lock.length-1);
|
||||
}
|
||||
|
||||
/*
|
||||
*get a list of all locks overlapping with the given lock's range
|
||||
* lock: the lock to compare with.
|
||||
* overlaps: an empty list, to be filled.
|
||||
* Returns: true if at least one lock overlaps.
|
||||
*/
|
||||
bool get_overlapping_locks(ceph_filelock& lock,
|
||||
list<ceph_filelock*>& overlaps) {
|
||||
multimap<__u64, ceph_filelock>::iterator iter =
|
||||
get_last_before(lock.start + lock.length - 1, held_locks);
|
||||
bool cont = true;
|
||||
do {
|
||||
if (share_space(iter, lock)) {
|
||||
overlaps.push_front(&iter->second);
|
||||
}
|
||||
if ((iter->first < lock.start) && (CEPH_LOCK_EXCL == iter->second.type)) {
|
||||
//can't be any more overlapping locks or they'd interfere with this one
|
||||
cont = false;
|
||||
} else if (held_locks.begin() == iter) cont = false;
|
||||
else --iter;
|
||||
} while (cont);
|
||||
return !overlaps.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* split a list of locks up by whether they're owned by same
|
||||
* process as given lock
|
||||
* owner: the owning lock
|
||||
* locks: the list of locks (obtained from get_overlapping_locks, probably)
|
||||
* Will have all locks owned by owner removed
|
||||
* owned_locks: an empty list, to be filled with the locks owned by owner
|
||||
*/
|
||||
void split_by_owner(ceph_filelock& owner, list<ceph_filelock*>& locks,
|
||||
list<ceph_filelock*>& owned_locks) {
|
||||
list<ceph_filelock*>::iterator iter = locks.begin();
|
||||
while (iter != locks.end()) {
|
||||
if ((*iter)->client == owner.client &&
|
||||
(*iter)->pid_namespace == owner.pid_namespace &&
|
||||
(*iter)->pid == owner.pid) {
|
||||
owned_locks.push_back(*iter);
|
||||
iter = locks.erase(iter);
|
||||
} else ++iter;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct inode_t {
|
||||
|
Loading…
Reference in New Issue
Block a user