]> granicus.if.org Git - zfs/blob - include/sys/zfs_rlock.h
Merge branch 'zfsonlinux/merge-spl'
[zfs] / include / sys / zfs_rlock.h
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25
26 #ifndef _SYS_FS_ZFS_RLOCK_H
27 #define _SYS_FS_ZFS_RLOCK_H
28
29 #ifdef  __cplusplus
30 extern "C" {
31 #endif
32
33 #include <sys/list.h>
34 #include <sys/avl.h>
35
36 #ifdef _KERNEL
37 #include <sys/condvar.h>
38 #else
39 #include <sys/zfs_context.h>
40 #endif
41
42 typedef enum {
43         RL_READER,
44         RL_WRITER,
45         RL_APPEND
46 } rl_type_t;
47
48 typedef struct zfs_rlock {
49         kmutex_t zr_mutex;      /* protects changes to zr_avl */
50         avl_tree_t zr_avl;      /* avl tree of range locks */
51         uint64_t *zr_size;      /* points to znode->z_size */
52         uint_t *zr_blksz;       /* points to znode->z_blksz */
53         uint64_t *zr_max_blksz; /* points to zfsvfs->z_max_blksz */
54 } zfs_rlock_t;
55
56 typedef struct rl {
57         zfs_rlock_t *r_zrl;
58         avl_node_t r_node;      /* avl node link */
59         uint64_t r_off;         /* file range offset */
60         uint64_t r_len;         /* file range length */
61         uint_t r_cnt;           /* range reference count in tree */
62         rl_type_t r_type;       /* range type */
63         kcondvar_t r_wr_cv;     /* cv for waiting writers */
64         kcondvar_t r_rd_cv;     /* cv for waiting readers */
65         uint8_t r_proxy;        /* acting for original range */
66         uint8_t r_write_wanted; /* writer wants to lock this range */
67         uint8_t r_read_wanted;  /* reader wants to lock this range */
68         list_node_t rl_node;    /* used for deferred release */
69 } rl_t;
70
71 /*
72  * Lock a range (offset, length) as either shared (RL_READER)
73  * or exclusive (RL_WRITER or RL_APPEND).  RL_APPEND is a special type that
74  * is converted to RL_WRITER that specified to lock from the start of the
75  * end of file.  Returns the range lock structure.
76  */
77 rl_t *zfs_range_lock(zfs_rlock_t *zrl, uint64_t off, uint64_t len,
78     rl_type_t type);
79
80 /* Unlock range and destroy range lock structure. */
81 void zfs_range_unlock(rl_t *rl);
82
83 /*
84  * Reduce range locked as RW_WRITER from whole file to specified range.
85  * Asserts the whole file was previously locked.
86  */
87 void zfs_range_reduce(rl_t *rl, uint64_t off, uint64_t len);
88
89 /*
90  * AVL comparison function used to order range locks
91  * Locks are ordered on the start offset of the range.
92  */
93 int zfs_range_compare(const void *arg1, const void *arg2);
94
95 static inline void
96 zfs_rlock_init(zfs_rlock_t *zrl)
97 {
98         mutex_init(&zrl->zr_mutex, NULL, MUTEX_DEFAULT, NULL);
99         avl_create(&zrl->zr_avl, zfs_range_compare,
100             sizeof (rl_t), offsetof(rl_t, r_node));
101         zrl->zr_size = NULL;
102         zrl->zr_blksz = NULL;
103         zrl->zr_max_blksz = NULL;
104 }
105
106 static inline void
107 zfs_rlock_destroy(zfs_rlock_t *zrl)
108 {
109         avl_destroy(&zrl->zr_avl);
110         mutex_destroy(&zrl->zr_mutex);
111 }
112
113 #ifdef  __cplusplus
114 }
115 #endif
116
117 #endif  /* _SYS_FS_ZFS_RLOCK_H */