4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
19 /* percpu partition lock
21 * There are some use-cases like this in Lustre:
22 * . each CPU partition has it's own private data which is frequently changed,
23 * and mostly by the local CPU partition.
24 * . all CPU partitions share some global data, these data are rarely changed.
26 * LNet is typical example.
27 * CPU partition lock is designed for this kind of use-cases:
28 * . each CPU partition has it's own private lock
29 * . change on private data just needs to take the private lock
30 * . read on shared data just needs to take _any_ of private locks
31 * . change on shared data needs to take _all_ private locks,
32 * which is slow and should be really rare.
35 CFS_PERCPT_LOCK_EX = -1, /* negative */
38 struct cfs_percpt_lock {
39 /* cpu-partition-table for this lock */
40 struct cfs_cpt_table *pcl_cptab;
41 /* exclusively locked */
42 unsigned int pcl_locked;
43 /* private lock table */
44 spinlock_t **pcl_locks;
47 /* return number of private locks */
48 #define cfs_percpt_lock_num(pcl) cfs_cpt_number(pcl->pcl_cptab)
50 /* create a cpu-partition lock based on CPU partition table \a cptab,
51 * each private lock has extra \a psize bytes padding data
53 struct cfs_percpt_lock *cfs_percpt_lock_create(struct cfs_cpt_table *cptab,
54 struct lock_class_key *keys);
55 /* destroy a cpu-partition lock */
56 void cfs_percpt_lock_free(struct cfs_percpt_lock *pcl);
58 /* lock private lock \a index of \a pcl */
59 void cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index);
61 /* unlock private lock \a index of \a pcl */
62 void cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index);
64 #define CFS_PERCPT_LOCK_KEYS 256
66 /* NB: don't allocate keys dynamically, lockdep needs them to be in ".data" */
67 #define cfs_percpt_lock_alloc(cptab) \
69 static struct lock_class_key ___keys[CFS_PERCPT_LOCK_KEYS]; \
70 struct cfs_percpt_lock *___lk; \
72 if (cfs_cpt_number(cptab) > CFS_PERCPT_LOCK_KEYS) \
73 ___lk = cfs_percpt_lock_create(cptab, NULL); \
75 ___lk = cfs_percpt_lock_create(cptab, ___keys); \