/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 only, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is included * in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU General Public License * version 2 along with this program; If not, see * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ /* * Range lock is used to allow multiple threads writing a single shared * file given each thread is writing to a non-overlapping portion of the * file. * * Refer to the possible upstream kernel version of range lock by * Jan Kara : https://lkml.org/lkml/2013/1/31/480 * * This file could later replaced by the upstream kernel version. */ /* * Author: Prakash Surya * Author: Bobi Jam */ #ifndef _RANGE_LOCK_H #define _RANGE_LOCK_H #include #include #define RL_FMT "[%llu, %llu]" #define RL_PARA(range) \ (range)->rl_node.in_extent.start, \ (range)->rl_node.in_extent.end struct range_lock { struct interval_node rl_node; /** * Process to enqueue this lock. */ struct task_struct *rl_task; /** * List of locks with the same range. */ struct list_head rl_next_lock; /** * Number of locks in the list rl_next_lock */ unsigned int rl_lock_count; /** * Number of ranges which are blocking acquisition of the lock */ unsigned int rl_blocking_ranges; /** * Sequence number of range lock. This number is used to get to know * the order the locks are queued; this is required for range_cancel(). */ __u64 rl_sequence; }; static inline struct range_lock *node2rangelock(const struct interval_node *n) { return container_of(n, struct range_lock, rl_node); } struct range_lock_tree { struct interval_node *rlt_root; spinlock_t rlt_lock; __u64 rlt_sequence; }; void range_lock_tree_init(struct range_lock_tree *tree); int range_lock_init(struct range_lock *lock, __u64 start, __u64 end); int range_lock(struct range_lock_tree *tree, struct range_lock *lock); void range_unlock(struct range_lock_tree *tree, struct range_lock *lock); #endif