Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 | /*
* 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.sun.com/software/products/lustre/docs/GPLv2.pdf
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
* GPL HEADER END
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 2010, 2012, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
* Lustre is a trademark of Sun Microsystems, Inc.
*/
/** \defgroup LDLM Lustre Distributed Lock Manager
*
* Lustre DLM is based on VAX DLM.
* Its two main roles are:
* - To provide locking assuring consistency of data on all Lustre nodes.
* - To allow clients to cache state protected by a lock by holding the
* lock until a conflicting lock is requested or it is expired by the LRU.
*
* @{
*/
#ifndef _LUSTRE_DLM_H__
#define _LUSTRE_DLM_H__
#include <linux/lustre_dlm.h>
#include <lustre_lib.h>
#include <lustre_net.h>
#include <lustre_import.h>
#include <lustre_handles.h>
#include <interval_tree.h> /* for interval_node{}, ldlm_extent */
#include <lu_ref.h>
#include "lustre_dlm_flags.h"
struct obd_ops;
struct obd_device;
#define OBD_LDLM_DEVICENAME "ldlm"
#define LDLM_DEFAULT_LRU_SIZE (100 * num_online_cpus())
#define LDLM_DEFAULT_MAX_ALIVE (cfs_time_seconds(36000))
#define LDLM_CTIME_AGE_LIMIT (10)
#define LDLM_DEFAULT_PARALLEL_AST_LIMIT 1024
/**
* LDLM non-error return states
*/
typedef enum {
ELDLM_OK = 0,
ELDLM_LOCK_CHANGED = 300,
ELDLM_LOCK_ABORTED = 301,
ELDLM_LOCK_REPLACED = 302,
ELDLM_NO_LOCK_DATA = 303,
ELDLM_LOCK_WOULDBLOCK = 304,
ELDLM_NAMESPACE_EXISTS = 400,
ELDLM_BAD_NAMESPACE = 401
} ldlm_error_t;
/**
* LDLM namespace type.
* The "client" type is actually an indication that this is a narrow local view
* into complete namespace on the server. Such namespaces cannot make any
* decisions about lack of conflicts or do any autonomous lock granting without
* first speaking to a server.
*/
typedef enum {
LDLM_NAMESPACE_SERVER = 1 << 0,
LDLM_NAMESPACE_CLIENT = 1 << 1
} ldlm_side_t;
/**
* The blocking callback is overloaded to perform two functions. These flags
* indicate which operation should be performed.
*/
#define LDLM_CB_BLOCKING 1
#define LDLM_CB_CANCELING 2
/**
* \name Lock Compatibility Matrix.
*
* A lock has both a type (extent, flock, inode bits, or plain) and a mode.
* Lock types are described in their respective implementation files:
* ldlm_{extent,flock,inodebits,plain}.c.
*
* There are six lock modes along with a compatibility matrix to indicate if
* two locks are compatible.
*
* - EX: Exclusive mode. Before a new file is created, MDS requests EX lock
* on the parent.
* - PW: Protective Write (normal write) mode. When a client requests a write
* lock from an OST, a lock with PW mode will be issued.
* - PR: Protective Read (normal read) mode. When a client requests a read from
* an OST, a lock with PR mode will be issued. Also, if the client opens a
* file for execution, it is granted a lock with PR mode.
* - CW: Concurrent Write mode. The type of lock that the MDS grants if a client
* requests a write lock during a file open operation.
* - CR Concurrent Read mode. When a client performs a path lookup, MDS grants
* an inodebit lock with the CR mode on the intermediate path component.
* - NL Null mode.
*
* <PRE>
* NL CR CW PR PW EX
* NL 1 1 1 1 1 1
* CR 1 1 1 1 1 0
* CW 1 1 1 0 0 0
* PR 1 1 0 1 0 0
* PW 1 1 0 0 0 0
* EX 1 0 0 0 0 0
* </PRE>
*/
/** @{ */
#define LCK_COMPAT_EX LCK_NL
#define LCK_COMPAT_PW (LCK_COMPAT_EX | LCK_CR)
#define LCK_COMPAT_PR (LCK_COMPAT_PW | LCK_PR)
#define LCK_COMPAT_CW (LCK_COMPAT_PW | LCK_CW)
#define LCK_COMPAT_CR (LCK_COMPAT_CW | LCK_PR | LCK_PW)
#define LCK_COMPAT_NL (LCK_COMPAT_CR | LCK_EX | LCK_GROUP)
#define LCK_COMPAT_GROUP (LCK_GROUP | LCK_NL)
#define LCK_COMPAT_COS (LCK_COS)
/** @} Lock Compatibility Matrix */
extern ldlm_mode_t lck_compat_array[];
static inline void lockmode_verify(ldlm_mode_t mode)
{
LASSERT(mode > LCK_MINMODE && mode < LCK_MAXMODE);
}
static inline int lockmode_compat(ldlm_mode_t exist_mode, ldlm_mode_t new_mode)
{
return (lck_compat_array[exist_mode] & new_mode);
}
/*
*
* cluster name spaces
*
*/
#define DLM_OST_NAMESPACE 1
#define DLM_MDS_NAMESPACE 2
/* XXX
- do we just separate this by security domains and use a prefix for
multiple namespaces in the same domain?
-
*/
/**
* Locking rules for LDLM:
*
* lr_lock
*
* lr_lock
* waiting_locks_spinlock
*
* lr_lock
* led_lock
*
* lr_lock
* ns_lock
*
* lr_lvb_mutex
* lr_lock
*
*/
struct ldlm_pool;
struct ldlm_lock;
struct ldlm_resource;
struct ldlm_namespace;
/**
* Operations on LDLM pools.
* LDLM pool is a pool of locks in the namespace without any implicitly
* specified limits.
* Locks in the pool are organized in LRU.
* Local memory pressure or server instructions (e.g. mempressure on server)
* can trigger freeing of locks from the pool
*/
struct ldlm_pool_ops {
/** Recalculate pool \a pl usage */
int (*po_recalc)(struct ldlm_pool *pl);
/** Cancel at least \a nr locks from pool \a pl */
int (*po_shrink)(struct ldlm_pool *pl, int nr,
unsigned int gfp_mask);
int (*po_setup)(struct ldlm_pool *pl, int limit);
};
/** One second for pools thread check interval. Each pool has own period. */
#define LDLM_POOLS_THREAD_PERIOD (1)
/** ~6% margin for modest pools. See ldlm_pool.c for details. */
#define LDLM_POOLS_MODEST_MARGIN_SHIFT (4)
/** Default recalc period for server side pools in sec. */
#define LDLM_POOL_SRV_DEF_RECALC_PERIOD (1)
/** Default recalc period for client side pools in sec. */
#define LDLM_POOL_CLI_DEF_RECALC_PERIOD (10)
/**
* LDLM pool structure to track granted locks.
* For purposes of determining when to release locks on e.g. memory pressure.
* This feature is commonly referred to as lru_resize.
*/
struct ldlm_pool {
/** Pool proc directory. */
struct proc_dir_entry *pl_proc_dir;
/** Pool name, must be long enough to hold compound proc entry name. */
char pl_name[100];
/** Lock for protecting SLV/CLV updates. */
spinlock_t pl_lock;
/** Number of allowed locks in in pool, both, client and server side. */
atomic_t pl_limit;
/** Number of granted locks in */
atomic_t pl_granted;
/** Grant rate per T. */
atomic_t pl_grant_rate;
/** Cancel rate per T. */
atomic_t pl_cancel_rate;
/** Server lock volume (SLV). Protected by pl_lock. */
__u64 pl_server_lock_volume;
/** Current biggest client lock volume. Protected by pl_lock. */
__u64 pl_client_lock_volume;
/** Lock volume factor. SLV on client is calculated as following:
* server_slv * lock_volume_factor. */
atomic_t pl_lock_volume_factor;
/** Time when last SLV from server was obtained. */
time_t pl_recalc_time;
/** Recalculation period for pool. */
time_t pl_recalc_period;
/** Recalculation and shrink operations. */
struct ldlm_pool_ops *pl_ops;
/** Number of planned locks for next period. */
int pl_grant_plan;
/** Pool statistics. */
struct lprocfs_stats *pl_stats;
};
typedef int (*ldlm_res_policy)(struct ldlm_namespace *, struct ldlm_lock **,
void *req_cookie, ldlm_mode_t mode, __u64 flags,
void *data);
typedef int (*ldlm_cancel_for_recovery)(struct ldlm_lock *lock);
/**
* LVB operations.
* LVB is Lock Value Block. This is a special opaque (to LDLM) value that could
* be associated with an LDLM lock and transferred from client to server and
* back.
*
* Currently LVBs are used by:
* - OSC-OST code to maintain current object size/times
* - layout lock code to return the layout when the layout lock is granted
*/
struct ldlm_valblock_ops {
int (*lvbo_init)(struct ldlm_resource *res);
int (*lvbo_update)(struct ldlm_resource *res,
struct ptlrpc_request *r,
int increase);
int (*lvbo_free)(struct ldlm_resource *res);
/* Return size of lvb data appropriate RPC size can be reserved */
int (*lvbo_size)(struct ldlm_lock *lock);
/* Called to fill in lvb data to RPC buffer @buf */
int (*lvbo_fill)(struct ldlm_lock *lock, void *buf, int buflen);
};
/**
* LDLM pools related, type of lock pool in the namespace.
* Greedy means release cached locks aggressively
*/
typedef enum {
LDLM_NAMESPACE_GREEDY = 1 << 0,
LDLM_NAMESPACE_MODEST = 1 << 1
} ldlm_appetite_t;
/**
* Default values for the "max_nolock_size", "contention_time" and
* "contended_locks" namespace tunables.
*/
#define NS_DEFAULT_MAX_NOLOCK_BYTES 0
#define NS_DEFAULT_CONTENTION_SECONDS 2
#define NS_DEFAULT_CONTENDED_LOCKS 32
struct ldlm_ns_bucket {
/** back pointer to namespace */
struct ldlm_namespace *nsb_namespace;
/**
* Estimated lock callback time. Used by adaptive timeout code to
* avoid spurious client evictions due to unresponsiveness when in
* fact the network or overall system load is at fault
*/
struct adaptive_timeout nsb_at_estimate;
};
enum {
/** LDLM namespace lock stats */
LDLM_NSS_LOCKS = 0,
LDLM_NSS_LAST
};
typedef enum {
/** invalide type */
LDLM_NS_TYPE_UNKNOWN = 0,
/** mdc namespace */
LDLM_NS_TYPE_MDC,
/** mds namespace */
LDLM_NS_TYPE_MDT,
/** osc namespace */
LDLM_NS_TYPE_OSC,
/** ost namespace */
LDLM_NS_TYPE_OST,
/** mgc namespace */
LDLM_NS_TYPE_MGC,
/** mgs namespace */
LDLM_NS_TYPE_MGT,
} ldlm_ns_type_t;
/**
* LDLM Namespace.
*
* Namespace serves to contain locks related to a particular service.
* There are two kinds of namespaces:
* - Server namespace has knowledge of all locks and is therefore authoritative
* to make decisions like what locks could be granted and what conflicts
* exist during new lock enqueue.
* - Client namespace only has limited knowledge about locks in the namespace,
* only seeing locks held by the client.
*
* Every Lustre service has one server namespace present on the server serving
* that service. Every client connected to the service has a client namespace
* for it.
* Every lock obtained by client in that namespace is actually represented by
* two in-memory locks. One on the server and one on the client. The locks are
* linked by a special cookie by which one node can tell to the other which lock
* it actually means during communications. Such locks are called remote locks.
* The locks held by server only without any reference to a client are called
* local locks.
*/
struct ldlm_namespace {
/** Backward link to OBD, required for LDLM pool to store new SLV. */
struct obd_device *ns_obd;
/** Flag indicating if namespace is on client instead of server */
ldlm_side_t ns_client;
/** Resource hash table for namespace. */
struct cfs_hash *ns_rs_hash;
/** serialize */
spinlock_t ns_lock;
/** big refcount (by bucket) */
atomic_t ns_bref;
/**
* Namespace connect flags supported by server (may be changed via
* /proc, LRU resize may be disabled/enabled).
*/
__u64 ns_connect_flags;
/** Client side original connect flags supported by server. */
__u64 ns_orig_connect_flags;
/* namespace proc dir entry */
struct proc_dir_entry *ns_proc_dir_entry;
/**
* Position in global namespace list linking all namespaces on
* the node.
*/
struct list_head ns_list_chain;
/**
* List of unused locks for this namespace. This list is also called
* LRU lock list.
* Unused locks are locks with zero reader/writer reference counts.
* This list is only used on clients for lock caching purposes.
* When we want to release some locks voluntarily or if server wants
* us to release some locks due to e.g. memory pressure, we take locks
* to release from the head of this list.
* Locks are linked via l_lru field in \see struct ldlm_lock.
*/
struct list_head ns_unused_list;
/** Number of locks in the LRU list above */
int ns_nr_unused;
/**
* Maximum number of locks permitted in the LRU. If 0, means locks
* are managed by pools and there is no preset limit, rather it is all
* controlled by available memory on this client and on server.
*/
unsigned int ns_max_unused;
/** Maximum allowed age (last used time) for locks in the LRU */
unsigned int ns_max_age;
/**
* Server only: number of times we evicted clients due to lack of reply
* to ASTs.
*/
unsigned int ns_timeouts;
/**
* Number of seconds since the file change time after which the
* MDT will return an UPDATE lock along with a LOOKUP lock.
* This allows the client to start caching negative dentries
* for a directory and may save an RPC for a later stat.
*/
unsigned int ns_ctime_age_limit;
/**
* Used to rate-limit ldlm_namespace_dump calls.
* \see ldlm_namespace_dump. Increased by 10 seconds every time
* it is called.
*/
cfs_time_t ns_next_dump;
/** "policy" function that does actual lock conflict determination */
ldlm_res_policy ns_policy;
/**
* LVB operations for this namespace.
* \see struct ldlm_valblock_ops
*/
struct ldlm_valblock_ops *ns_lvbo;
/**
* Used by filter code to store pointer to OBD of the service.
* Should be dropped in favor of \a ns_obd
*/
void *ns_lvbp;
/**
* Wait queue used by __ldlm_namespace_free. Gets woken up every time
* a resource is removed.
*/
wait_queue_head_t ns_waitq;
/** LDLM pool structure for this namespace */
struct ldlm_pool ns_pool;
/** Definition of how eagerly unused locks will be released from LRU */
ldlm_appetite_t ns_appetite;
/**
* If more than \a ns_contended_locks are found, the resource is
* considered to be contended. Lock enqueues might specify that no
* contended locks should be granted
*/
unsigned ns_contended_locks;
/**
* The resources in this namespace remember contended state during
* \a ns_contention_time, in seconds.
*/
unsigned ns_contention_time;
/**
* Limit size of contended extent locks, in bytes.
* If extended lock is requested for more then this many bytes and
* caller instructs us not to grant contended locks, we would disregard
* such a request.
*/
unsigned ns_max_nolock_size;
/** Limit of parallel AST RPC count. */
unsigned ns_max_parallel_ast;
/** Callback to cancel locks before replaying it during recovery. */
ldlm_cancel_for_recovery ns_cancel_for_recovery;
/** LDLM lock stats */
struct lprocfs_stats *ns_stats;
/**
* Flag to indicate namespace is being freed. Used to determine if
* recalculation of LDLM pool statistics should be skipped.
*/
unsigned ns_stopping:1;
};
/**
* Returns 1 if namespace \a ns is a client namespace.
*/
static inline int ns_is_client(struct ldlm_namespace *ns)
{
LASSERT(ns != NULL);
LASSERT(!(ns->ns_client & ~(LDLM_NAMESPACE_CLIENT |
LDLM_NAMESPACE_SERVER)));
LASSERT(ns->ns_client == LDLM_NAMESPACE_CLIENT ||
ns->ns_client == LDLM_NAMESPACE_SERVER);
return ns->ns_client == LDLM_NAMESPACE_CLIENT;
}
/**
* Returns 1 if namespace \a ns is a server namespace.
*/
static inline int ns_is_server(struct ldlm_namespace *ns)
{
LASSERT(ns != NULL);
LASSERT(!(ns->ns_client & ~(LDLM_NAMESPACE_CLIENT |
LDLM_NAMESPACE_SERVER)));
LASSERT(ns->ns_client == LDLM_NAMESPACE_CLIENT ||
ns->ns_client == LDLM_NAMESPACE_SERVER);
return ns->ns_client == LDLM_NAMESPACE_SERVER;
}
/**
* Returns 1 if namespace \a ns supports early lock cancel (ELC).
*/
static inline int ns_connect_cancelset(struct ldlm_namespace *ns)
{
LASSERT(ns != NULL);
return !!(ns->ns_connect_flags & OBD_CONNECT_CANCELSET);
}
/**
* Returns 1 if this namespace supports lru_resize.
*/
static inline int ns_connect_lru_resize(struct ldlm_namespace *ns)
{
LASSERT(ns != NULL);
return !!(ns->ns_connect_flags & OBD_CONNECT_LRU_RESIZE);
}
static inline void ns_register_cancel(struct ldlm_namespace *ns,
ldlm_cancel_for_recovery arg)
{
LASSERT(ns != NULL);
ns->ns_cancel_for_recovery = arg;
}
struct ldlm_lock;
/** Type for blocking callback function of a lock. */
typedef int (*ldlm_blocking_callback)(struct ldlm_lock *lock,
struct ldlm_lock_desc *new, void *data,
int flag);
/** Type for completion callback function of a lock. */
typedef int (*ldlm_completion_callback)(struct ldlm_lock *lock, __u64 flags,
void *data);
/** Type for glimpse callback function of a lock. */
typedef int (*ldlm_glimpse_callback)(struct ldlm_lock *lock, void *data);
/** Work list for sending GL ASTs to multiple locks. */
struct ldlm_glimpse_work {
struct ldlm_lock *gl_lock; /* lock to glimpse */
struct list_head gl_list; /* linkage to other gl work structs */
__u32 gl_flags;/* see LDLM_GL_WORK_* below */
union ldlm_gl_desc *gl_desc; /* glimpse descriptor to be packed in
* glimpse callback request */
};
/** The ldlm_glimpse_work is allocated on the stack and should not be freed. */
#define LDLM_GL_WORK_NOFREE 0x1
/** Interval node data for each LDLM_EXTENT lock. */
struct ldlm_interval {
struct interval_node li_node; /* node for tree management */
struct list_head li_group; /* the locks which have the same
* policy - group of the policy */
};
#define to_ldlm_interval(n) container_of(n, struct ldlm_interval, li_node)
/**
* Interval tree for extent locks.
* The interval tree must be accessed under the resource lock.
* Interval trees are used for granted extent locks to speed up conflicts
* lookup. See ldlm/interval_tree.c for more details.
*/
struct ldlm_interval_tree {
/** Tree size. */
int lit_size;
ldlm_mode_t lit_mode; /* lock mode */
struct interval_node *lit_root; /* actual ldlm_interval */
};
/** Whether to track references to exports by LDLM locks. */
#define LUSTRE_TRACKS_LOCK_EXP_REFS (0)
/** Cancel flags. */
typedef enum {
LCF_ASYNC = 0x1, /* Cancel locks asynchronously. */
LCF_LOCAL = 0x2, /* Cancel locks locally, not notifing server */
LCF_BL_AST = 0x4, /* Cancel locks marked as LDLM_FL_BL_AST
* in the same RPC */
} ldlm_cancel_flags_t;
struct ldlm_flock {
__u64 start;
__u64 end;
__u64 owner;
__u64 blocking_owner;
struct obd_export *blocking_export;
/* Protected by the hash lock */
__u32 blocking_refs;
__u32 pid;
};
typedef union {
struct ldlm_extent l_extent;
struct ldlm_flock l_flock;
struct ldlm_inodebits l_inodebits;
} ldlm_policy_data_t;
void ldlm_convert_policy_to_wire(ldlm_type_t type,
const ldlm_policy_data_t *lpolicy,
ldlm_wire_policy_data_t *wpolicy);
void ldlm_convert_policy_to_local(struct obd_export *exp, ldlm_type_t type,
const ldlm_wire_policy_data_t *wpolicy,
ldlm_policy_data_t *lpolicy);
enum lvb_type {
LVB_T_NONE = 0,
LVB_T_OST = 1,
LVB_T_LQUOTA = 2,
LVB_T_LAYOUT = 3,
};
/**
* LDLM lock structure
*
* Represents a single LDLM lock and its state in memory. Each lock is
* associated with a single ldlm_resource, the object which is being
* locked. There may be multiple ldlm_locks on a single resource,
* depending on the lock type and whether the locks are conflicting or
* not.
*/
struct ldlm_lock {
/**
* Local lock handle.
* When remote side wants to tell us about a lock, they address
* it by this opaque handle. The handle does not hold a
* reference on the ldlm_lock, so it can be safely passed to
* other threads or nodes. When the lock needs to be accessed
* from the handle, it is looked up again in the lock table, and
* may no longer exist.
*
* Must be first in the structure.
*/
struct portals_handle l_handle;
/**
* Lock reference count.
* This is how many users have pointers to actual structure, so that
* we do not accidentally free lock structure that is in use.
*/
atomic_t l_refc;
/**
* Internal spinlock protects l_resource. We should hold this lock
* first before taking res_lock.
*/
spinlock_t l_lock;
/**
* Pointer to actual resource this lock is in.
* ldlm_lock_change_resource() can change this.
*/
struct ldlm_resource *l_resource;
/**
* List item for client side LRU list.
* Protected by ns_lock in struct ldlm_namespace.
*/
struct list_head l_lru;
/**
* Linkage to resource's lock queues according to current lock state.
* (could be granted, waiting or converting)
* Protected by lr_lock in struct ldlm_resource.
*/
struct list_head l_res_link;
/**
* Tree node for ldlm_extent.
*/
struct ldlm_interval *l_tree_node;
/**
* Per export hash of locks.
* Protected by per-bucket exp->exp_lock_hash locks.
*/
struct hlist_node l_exp_hash;
/**
* Per export hash of flock locks.
* Protected by per-bucket exp->exp_flock_hash locks.
*/
struct hlist_node l_exp_flock_hash;
/**
* Requested mode.
* Protected by lr_lock.
*/
ldlm_mode_t l_req_mode;
/**
* Granted mode, also protected by lr_lock.
*/
ldlm_mode_t l_granted_mode;
/** Lock completion handler pointer. Called when lock is granted. */
ldlm_completion_callback l_completion_ast;
/**
* Lock blocking AST handler pointer.
* It plays two roles:
* - as a notification of an attempt to queue a conflicting lock (once)
* - as a notification when the lock is being cancelled.
*
* As such it's typically called twice: once for the initial conflict
* and then once more when the last user went away and the lock is
* cancelled (could happen recursively).
*/
ldlm_blocking_callback l_blocking_ast;
/**
* Lock glimpse handler.
* Glimpse handler is used to obtain LVB updates from a client by
* server
*/
ldlm_glimpse_callback l_glimpse_ast;
/**
* Lock export.
* This is a pointer to actual client export for locks that were granted
* to clients. Used server-side.
*/
struct obd_export *l_export;
/**
* Lock connection export.
* Pointer to server export on a client.
*/
struct obd_export *l_conn_export;
/**
* Remote lock handle.
* If the lock is remote, this is the handle of the other side lock
* (l_handle)
*/
struct lustre_handle l_remote_handle;
/**
* Representation of private data specific for a lock type.
* Examples are: extent range for extent lock or bitmask for ibits locks
*/
ldlm_policy_data_t l_policy_data;
/**
* Lock state flags. Protected by lr_lock.
* \see lustre_dlm_flags.h where the bits are defined.
*/
__u64 l_flags;
/**
* Lock r/w usage counters.
* Protected by lr_lock.
*/
__u32 l_readers;
__u32 l_writers;
/**
* If the lock is granted, a process sleeps on this waitq to learn when
* it's no longer in use. If the lock is not granted, a process sleeps
* on this waitq to learn when it becomes granted.
*/
wait_queue_head_t l_waitq;
/**
* Seconds. It will be updated if there is any activity related to
* the lock, e.g. enqueue the lock or send blocking AST.
*/
cfs_time_t l_last_activity;
/**
* Time last used by e.g. being matched by lock match.
* Jiffies. Should be converted to time if needed.
*/
cfs_time_t l_last_used;
/** Originally requested extent for the extent lock. */
struct ldlm_extent l_req_extent;
/*
* Client-side-only members.
*/
enum lvb_type l_lvb_type;
/**
* Temporary storage for a LVB received during an enqueue operation.
*/
__u32 l_lvb_len;
void *l_lvb_data;
/** Private storage for lock user. Opaque to LDLM. */
void *l_ast_data;
/*
* Server-side-only members.
*/
/**
* Connection cookie for the client originating the operation.
* Used by Commit on Share (COS) code. Currently only used for
* inodebits locks on MDS.
*/
__u64 l_client_cookie;
/**
* List item for locks waiting for cancellation from clients.
* The lists this could be linked into are:
* waiting_locks_list (protected by waiting_locks_spinlock),
* then if the lock timed out, it is moved to
* expired_lock_thread.elt_expired_locks for further processing.
* Protected by elt_lock.
*/
struct list_head l_pending_chain;
/**
* Set when lock is sent a blocking AST. Time in seconds when timeout
* is reached and client holding this lock could be evicted.
* This timeout could be further extended by e.g. certain IO activity
* under this lock.
* \see ost_rw_prolong_locks
*/
cfs_time_t l_callback_timeout;
/** Local PID of process which created this lock. */
__u32 l_pid;
/**
* Number of times blocking AST was sent for this lock.
* This is for debugging. Valid values are 0 and 1, if there is an
* attempt to send blocking AST more than once, an assertion would be
* hit. \see ldlm_work_bl_ast_lock
*/
int l_bl_ast_run;
/** List item ldlm_add_ast_work_item() for case of blocking ASTs. */
struct list_head l_bl_ast;
/** List item ldlm_add_ast_work_item() for case of completion ASTs. */
struct list_head l_cp_ast;
/** For ldlm_add_ast_work_item() for "revoke" AST used in COS. */
struct list_head l_rk_ast;
/**
* Pointer to a conflicting lock that caused blocking AST to be sent
* for this lock
*/
struct ldlm_lock *l_blocking_lock;
/**
* Protected by lr_lock, linkages to "skip lists".
* For more explanations of skip lists see ldlm/ldlm_inodebits.c
*/
struct list_head l_sl_mode;
struct list_head l_sl_policy;
/** Reference tracking structure to debug leaked locks. */
struct lu_ref l_reference;
#if LUSTRE_TRACKS_LOCK_EXP_REFS
/* Debugging stuff for bug 20498, for tracking export references. */
/** number of export references taken */
int l_exp_refs_nr;
/** link all locks referencing one export */
struct list_head l_exp_refs_link;
/** referenced export object */
struct obd_export *l_exp_refs_target;
#endif
/**
* export blocking dlm lock list, protected by
* l_export->exp_bl_list_lock.
* Lock order of waiting_lists_spinlock, exp_bl_list_lock and res lock
* is: res lock -> exp_bl_list_lock -> wanting_lists_spinlock.
*/
struct list_head l_exp_list;
};
/**
* LDLM resource description.
* Basically, resource is a representation for a single object.
* Object has a name which is currently 4 64-bit integers. LDLM user is
* responsible for creation of a mapping between objects it wants to be
* protected and resource names.
*
* A resource can only hold locks of a single lock type, though there may be
* multiple ldlm_locks on a single resource, depending on the lock type and
* whether the locks are conflicting or not.
*/
struct ldlm_resource {
struct ldlm_ns_bucket *lr_ns_bucket;
/**
* List item for list in namespace hash.
* protected by ns_lock
*/
struct hlist_node lr_hash;
/** Spinlock to protect locks under this resource. */
spinlock_t lr_lock;
/**
* protected by lr_lock
* @{ */
/** List of locks in granted state */
struct list_head lr_granted;
/** List of locks waiting to change their granted mode (converted) */
struct list_head lr_converting;
/**
* List of locks that could not be granted due to conflicts and
* that are waiting for conflicts to go away */
struct list_head lr_waiting;
/** @} */
/* XXX No longer needed? Remove ASAP */
ldlm_mode_t lr_most_restr;
/** Type of locks this resource can hold. Only one type per resource. */
ldlm_type_t lr_type; /* LDLM_{PLAIN,EXTENT,FLOCK,IBITS} */
/** Resource name */
struct ldlm_res_id lr_name;
/** Reference count for this resource */
atomic_t lr_refcount;
/**
* Interval trees (only for extent locks) for all modes of this resource
*/
struct ldlm_interval_tree lr_itree[LCK_MODE_NUM];
/**
* Server-side-only lock value block elements.
* To serialize lvbo_init.
*/
struct mutex lr_lvb_mutex;
int lr_lvb_len;
/** protected by lr_lock */
void *lr_lvb_data;
/** When the resource was considered as contended. */
cfs_time_t lr_contention_time;
/** List of references to this resource. For debugging. */
struct lu_ref lr_reference;
struct inode *lr_lvb_inode;
};
static inline bool ldlm_has_layout(struct ldlm_lock *lock)
{
return lock->l_resource->lr_type == LDLM_IBITS &&
lock->l_policy_data.l_inodebits.bits & MDS_INODELOCK_LAYOUT;
}
static inline char *
ldlm_ns_name(struct ldlm_namespace *ns)
{
return ns->ns_rs_hash->hs_name;
}
static inline struct ldlm_namespace *
ldlm_res_to_ns(struct ldlm_resource *res)
{
return res->lr_ns_bucket->nsb_namespace;
}
static inline struct ldlm_namespace *
ldlm_lock_to_ns(struct ldlm_lock *lock)
{
return ldlm_res_to_ns(lock->l_resource);
}
static inline char *
ldlm_lock_to_ns_name(struct ldlm_lock *lock)
{
return ldlm_ns_name(ldlm_lock_to_ns(lock));
}
static inline struct adaptive_timeout *
ldlm_lock_to_ns_at(struct ldlm_lock *lock)
{
return &lock->l_resource->lr_ns_bucket->nsb_at_estimate;
}
static inline int ldlm_lvbo_init(struct ldlm_resource *res)
{
struct ldlm_namespace *ns = ldlm_res_to_ns(res);
if (ns->ns_lvbo != NULL && ns->ns_lvbo->lvbo_init != NULL)
return ns->ns_lvbo->lvbo_init(res);
return 0;
}
static inline int ldlm_lvbo_size(struct ldlm_lock *lock)
{
struct ldlm_namespace *ns = ldlm_lock_to_ns(lock);
if (ns->ns_lvbo != NULL && ns->ns_lvbo->lvbo_size != NULL)
return ns->ns_lvbo->lvbo_size(lock);
return 0;
}
static inline int ldlm_lvbo_fill(struct ldlm_lock *lock, void *buf, int len)
{
struct ldlm_namespace *ns = ldlm_lock_to_ns(lock);
if (ns->ns_lvbo != NULL) {
LASSERT(ns->ns_lvbo->lvbo_fill != NULL);
return ns->ns_lvbo->lvbo_fill(lock, buf, len);
}
return 0;
}
struct ldlm_ast_work {
struct ldlm_lock *w_lock;
int w_blocking;
struct ldlm_lock_desc w_desc;
struct list_head w_list;
int w_flags;
void *w_data;
int w_datalen;
};
/**
* Common ldlm_enqueue parameters
*/
struct ldlm_enqueue_info {
__u32 ei_type; /** Type of the lock being enqueued. */
__u32 ei_mode; /** Mode of the lock being enqueued. */
void *ei_cb_bl; /** blocking lock callback */
void *ei_cb_cp; /** lock completion callback */
void *ei_cb_gl; /** lock glimpse callback */
void *ei_cbdata; /** Data to be passed into callbacks. */
};
extern struct obd_ops ldlm_obd_ops;
extern char *ldlm_lockname[];
extern char *ldlm_typename[];
extern char *ldlm_it2str(int it);
/**
* Just a fancy CDEBUG call with log level preset to LDLM_DEBUG.
* For the cases where we do not have actual lock to print along
* with a debugging message that is ldlm-related
*/
#define LDLM_DEBUG_NOLOCK(format, a...) \
CDEBUG(D_DLMTRACE, "### " format "\n" , ##a)
/**
* Support function for lock information printing into debug logs.
* \see LDLM_DEBUG
*/
#define ldlm_lock_debug(msgdata, mask, cdls, lock, fmt, a...) do { \
CFS_CHECK_STACK(msgdata, mask, cdls); \
\
if (((mask) & D_CANTMASK) != 0 || \
((libcfs_debug & (mask)) != 0 && \
(libcfs_subsystem_debug & DEBUG_SUBSYSTEM) != 0)) \
_ldlm_lock_debug(lock, msgdata, fmt, ##a); \
} while(0)
void _ldlm_lock_debug(struct ldlm_lock *lock,
struct libcfs_debug_msg_data *data,
const char *fmt, ...)
__attribute__ ((format (printf, 3, 4)));
/**
* Rate-limited version of lock printing function.
*/
#define LDLM_DEBUG_LIMIT(mask, lock, fmt, a...) do { \
static struct cfs_debug_limit_state _ldlm_cdls; \
LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, mask, &_ldlm_cdls); \
ldlm_lock_debug(&msgdata, mask, &_ldlm_cdls, lock, "### " fmt , ##a);\
} while (0)
#define LDLM_ERROR(lock, fmt, a...) LDLM_DEBUG_LIMIT(D_ERROR, lock, fmt, ## a)
#define LDLM_WARN(lock, fmt, a...) LDLM_DEBUG_LIMIT(D_WARNING, lock, fmt, ## a)
/** Non-rate-limited lock printing function for debugging purposes. */
#define LDLM_DEBUG(lock, fmt, a...) do { \
if (likely(lock != NULL)) { \
LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_DLMTRACE, NULL); \
ldlm_lock_debug(&msgdata, D_DLMTRACE, NULL, lock, \
"### " fmt , ##a); \
} else { \
LDLM_DEBUG_NOLOCK("no dlm lock: " fmt, ##a); \
} \
} while (0)
typedef int (*ldlm_processing_policy)(struct ldlm_lock *lock, __u64 *flags,
int first_enq, ldlm_error_t *err,
struct list_head *work_list);
/**
* Return values for lock iterators.
* Also used during deciding of lock grants and cancellations.
*/
#define LDLM_ITER_CONTINUE 1 /* keep iterating */
#define LDLM_ITER_STOP 2 /* stop iterating */
typedef int (*ldlm_iterator_t)(struct ldlm_lock *, void *);
typedef int (*ldlm_res_iterator_t)(struct ldlm_resource *, void *);
/** \defgroup ldlm_iterator Lock iterators
*
* LDLM provides for a way to iterate through every lock on a resource or
* namespace or every resource in a namespace.
* @{ */
int ldlm_resource_foreach(struct ldlm_resource *res, ldlm_iterator_t iter,
void *closure);
void ldlm_namespace_foreach(struct ldlm_namespace *ns, ldlm_iterator_t iter,
void *closure);
int ldlm_resource_iterate(struct ldlm_namespace *, const struct ldlm_res_id *,
ldlm_iterator_t iter, void *data);
/** @} ldlm_iterator */
int ldlm_replay_locks(struct obd_import *imp);
/* ldlm_flock.c */
int ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data);
/* ldlm_extent.c */
__u64 ldlm_extent_shift_kms(struct ldlm_lock *lock, __u64 old_kms);
struct ldlm_callback_suite {
ldlm_completion_callback lcs_completion;
ldlm_blocking_callback lcs_blocking;
ldlm_glimpse_callback lcs_glimpse;
};
/* ldlm_lockd.c */
int ldlm_del_waiting_lock(struct ldlm_lock *lock);
int ldlm_refresh_waiting_lock(struct ldlm_lock *lock, int timeout);
int ldlm_get_ref(void);
void ldlm_put_ref(void);
int ldlm_init_export(struct obd_export *exp);
void ldlm_destroy_export(struct obd_export *exp);
struct ldlm_lock *ldlm_request_lock(struct ptlrpc_request *req);
/* ldlm_lock.c */
void ldlm_register_intent(struct ldlm_namespace *ns, ldlm_res_policy arg);
void ldlm_lock2handle(const struct ldlm_lock *lock,
struct lustre_handle *lockh);
struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *, __u64 flags);
void ldlm_cancel_callback(struct ldlm_lock *);
int ldlm_lock_remove_from_lru(struct ldlm_lock *);
int ldlm_lock_set_data(struct lustre_handle *, void *);
/**
* Obtain a lock reference by its handle.
*/
static inline struct ldlm_lock *ldlm_handle2lock(const struct lustre_handle *h)
{
return __ldlm_handle2lock(h, 0);
}
#define LDLM_LOCK_REF_DEL(lock) \
lu_ref_del(&lock->l_reference, "handle", current)
static inline struct ldlm_lock *
ldlm_handle2lock_long(const struct lustre_handle *h, __u64 flags)
{
struct ldlm_lock *lock;
lock = __ldlm_handle2lock(h, flags);
if (lock != NULL)
LDLM_LOCK_REF_DEL(lock);
return lock;
}
/**
* Update Lock Value Block Operations (LVBO) on a resource taking into account
* data from reqest \a r
*/
static inline int ldlm_res_lvbo_update(struct ldlm_resource *res,
struct ptlrpc_request *r, int increase)
{
if (ldlm_res_to_ns(res)->ns_lvbo &&
ldlm_res_to_ns(res)->ns_lvbo->lvbo_update) {
return ldlm_res_to_ns(res)->ns_lvbo->lvbo_update(res, r,
increase);
}
return 0;
}
int ldlm_error2errno(ldlm_error_t error);
ldlm_error_t ldlm_errno2error(int err_no); /* don't call it `errno': this
* confuses user-space. */
#if LUSTRE_TRACKS_LOCK_EXP_REFS
void ldlm_dump_export_locks(struct obd_export *exp);
#endif
/**
* Release a temporary lock reference obtained by ldlm_handle2lock() or
* __ldlm_handle2lock().
*/
#define LDLM_LOCK_PUT(lock) \
do { \
LDLM_LOCK_REF_DEL(lock); \
/*LDLM_DEBUG((lock), "put");*/ \
ldlm_lock_put(lock); \
} while (0)
/**
* Release a lock reference obtained by some other means (see
* LDLM_LOCK_PUT()).
*/
#define LDLM_LOCK_RELEASE(lock) \
do { \
/*LDLM_DEBUG((lock), "put");*/ \
ldlm_lock_put(lock); \
} while (0)
#define LDLM_LOCK_GET(lock) \
({ \
ldlm_lock_get(lock); \
/*LDLM_DEBUG((lock), "get");*/ \
lock; \
})
#define ldlm_lock_list_put(head, member, count) \
({ \
struct ldlm_lock *_lock, *_next; \
int c = count; \
list_for_each_entry_safe(_lock, _next, head, member) { \
if (c-- == 0) \
break; \
list_del_init(&_lock->member); \
LDLM_LOCK_RELEASE(_lock); \
} \
LASSERT(c <= 0); \
})
struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock);
void ldlm_lock_put(struct ldlm_lock *lock);
void ldlm_lock_destroy(struct ldlm_lock *lock);
void ldlm_lock2desc(struct ldlm_lock *lock, struct ldlm_lock_desc *desc);
void ldlm_lock_addref(struct lustre_handle *lockh, __u32 mode);
int ldlm_lock_addref_try(struct lustre_handle *lockh, __u32 mode);
void ldlm_lock_decref(struct lustre_handle *lockh, __u32 mode);
void ldlm_lock_decref_and_cancel(struct lustre_handle *lockh, __u32 mode);
void ldlm_lock_fail_match_locked(struct ldlm_lock *lock);
void ldlm_lock_fail_match(struct ldlm_lock *lock);
void ldlm_lock_allow_match(struct ldlm_lock *lock);
void ldlm_lock_allow_match_locked(struct ldlm_lock *lock);
ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags,
const struct ldlm_res_id *, ldlm_type_t type,
ldlm_policy_data_t *, ldlm_mode_t mode,
struct lustre_handle *, int unref);
ldlm_mode_t ldlm_revalidate_lock_handle(struct lustre_handle *lockh,
__u64 *bits);
struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
__u32 *flags);
void ldlm_lock_downgrade(struct ldlm_lock *lock, int new_mode);
void ldlm_lock_cancel(struct ldlm_lock *lock);
void ldlm_reprocess_all(struct ldlm_resource *res);
void ldlm_reprocess_all_ns(struct ldlm_namespace *ns);
void ldlm_lock_dump_handle(int level, struct lustre_handle *);
void ldlm_unlink_lock_skiplist(struct ldlm_lock *req);
/* resource.c */
struct ldlm_namespace *
ldlm_namespace_new(struct obd_device *obd, char *name,
ldlm_side_t client, ldlm_appetite_t apt,
ldlm_ns_type_t ns_type);
int ldlm_namespace_cleanup(struct ldlm_namespace *ns, __u64 flags);
void ldlm_namespace_free(struct ldlm_namespace *ns,
struct obd_import *imp, int force);
void ldlm_namespace_register(struct ldlm_namespace *ns, ldlm_side_t client);
void ldlm_namespace_unregister(struct ldlm_namespace *ns, ldlm_side_t client);
void ldlm_namespace_get(struct ldlm_namespace *ns);
void ldlm_namespace_put(struct ldlm_namespace *ns);
int ldlm_proc_setup(void);
#ifdef LPROCFS
void ldlm_proc_cleanup(void);
#else
static inline void ldlm_proc_cleanup(void) {}
#endif
/* resource.c - internal */
struct ldlm_resource *ldlm_resource_get(struct ldlm_namespace *ns,
struct ldlm_resource *parent,
const struct ldlm_res_id *,
ldlm_type_t type, int create);
struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res);
int ldlm_resource_putref(struct ldlm_resource *res);
void ldlm_resource_add_lock(struct ldlm_resource *res,
struct list_head *head,
struct ldlm_lock *lock);
void ldlm_resource_unlink_lock(struct ldlm_lock *lock);
void ldlm_res2desc(struct ldlm_resource *res, struct ldlm_resource_desc *desc);
void ldlm_dump_all_namespaces(ldlm_side_t client, int level);
void ldlm_namespace_dump(int level, struct ldlm_namespace *);
void ldlm_resource_dump(int level, struct ldlm_resource *);
int ldlm_lock_change_resource(struct ldlm_namespace *, struct ldlm_lock *,
const struct ldlm_res_id *);
#define LDLM_RESOURCE_ADDREF(res) do { \
lu_ref_add_atomic(&(res)->lr_reference, __FUNCTION__, current); \
} while (0)
#define LDLM_RESOURCE_DELREF(res) do { \
lu_ref_del(&(res)->lr_reference, __FUNCTION__, current); \
} while (0)
/* ldlm_request.c */
int ldlm_expired_completion_wait(void *data);
/** \defgroup ldlm_local_ast Default AST handlers for local locks
* These AST handlers are typically used for server-side local locks and are
* also used by client-side lock handlers to perform minimum level base
* processing.
* @{ */
int ldlm_blocking_ast_nocheck(struct ldlm_lock *lock);
int ldlm_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
void *data, int flag);
int ldlm_glimpse_ast(struct ldlm_lock *lock, void *reqp);
int ldlm_completion_ast_async(struct ldlm_lock *lock, __u64 flags, void *data);
int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data);
/** @} ldlm_local_ast */
/** \defgroup ldlm_cli_api API to operate on locks from actual LDLM users.
* These are typically used by client and server (*_local versions)
* to obtain and release locks.
* @{ */
int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp,
struct ldlm_enqueue_info *einfo,
const struct ldlm_res_id *res_id,
ldlm_policy_data_t const *policy, __u64 *flags,
void *lvb, __u32 lvb_len, enum lvb_type lvb_type,
struct lustre_handle *lockh, int async);
int ldlm_prep_enqueue_req(struct obd_export *exp,
struct ptlrpc_request *req,
struct list_head *cancels,
int count);
int ldlm_prep_elc_req(struct obd_export *exp,
struct ptlrpc_request *req,
int version, int opc, int canceloff,
struct list_head *cancels, int count);
struct ptlrpc_request *ldlm_enqueue_pack(struct obd_export *exp, int lvb_len);
int ldlm_handle_enqueue0(struct ldlm_namespace *ns, struct ptlrpc_request *req,
const struct ldlm_request *dlm_req,
const struct ldlm_callback_suite *cbs);
int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req,
ldlm_type_t type, __u8 with_policy, ldlm_mode_t mode,
__u64 *flags, void *lvb, __u32 lvb_len,
struct lustre_handle *lockh, int rc);
int ldlm_cli_enqueue_local(struct ldlm_namespace *ns,
const struct ldlm_res_id *res_id,
ldlm_type_t type, ldlm_policy_data_t *policy,
ldlm_mode_t mode, __u64 *flags,
ldlm_blocking_callback blocking,
ldlm_completion_callback completion,
ldlm_glimpse_callback glimpse,
void *data, __u32 lvb_len, enum lvb_type lvb_type,
const __u64 *client_cookie,
struct lustre_handle *lockh);
int ldlm_server_ast(struct lustre_handle *lockh, struct ldlm_lock_desc *new,
void *data, __u32 data_len);
int ldlm_cli_convert(struct lustre_handle *, int new_mode, __u32 *flags);
int ldlm_cli_update_pool(struct ptlrpc_request *req);
int ldlm_cli_cancel(struct lustre_handle *lockh,
ldlm_cancel_flags_t cancel_flags);
int ldlm_cli_cancel_unused(struct ldlm_namespace *, const struct ldlm_res_id *,
ldlm_cancel_flags_t flags, void *opaque);
int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
const struct ldlm_res_id *res_id,
ldlm_policy_data_t *policy,
ldlm_mode_t mode,
ldlm_cancel_flags_t flags,
void *opaque);
int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *head,
int count, ldlm_cancel_flags_t flags);
int ldlm_cancel_resource_local(struct ldlm_resource *res,
struct list_head *cancels,
ldlm_policy_data_t *policy,
ldlm_mode_t mode, int lock_flags,
ldlm_cancel_flags_t cancel_flags, void *opaque);
int ldlm_cli_cancel_list_local(struct list_head *cancels, int count,
ldlm_cancel_flags_t flags);
int ldlm_cli_cancel_list(struct list_head *head, int count,
struct ptlrpc_request *req, ldlm_cancel_flags_t flags);
/** @} ldlm_cli_api */
/* mds/handler.c */
/* This has to be here because recursive inclusion sucks. */
int intent_disposition(struct ldlm_reply *rep, int flag);
void intent_set_disposition(struct ldlm_reply *rep, int flag);
/* ioctls for trying requests */
#define IOC_LDLM_TYPE 'f'
#define IOC_LDLM_MIN_NR 40
#define IOC_LDLM_TEST _IOWR('f', 40, long)
#define IOC_LDLM_DUMP _IOWR('f', 41, long)
#define IOC_LDLM_REGRESS_START _IOWR('f', 42, long)
#define IOC_LDLM_REGRESS_STOP _IOWR('f', 43, long)
#define IOC_LDLM_MAX_NR 43
/**
* "Modes" of acquiring lock_res, necessary to tell lockdep that taking more
* than one lock_res is dead-lock safe.
*/
enum lock_res_type {
LRT_NORMAL,
LRT_NEW
};
/** Lock resource. */
static inline void lock_res(struct ldlm_resource *res)
{
spin_lock(&res->lr_lock);
}
/** Lock resource with a way to instruct lockdep code about nestedness-safe. */
static inline void lock_res_nested(struct ldlm_resource *res,
enum lock_res_type mode)
{
spin_lock_nested(&res->lr_lock, mode);
}
/** Unlock resource. */
static inline void unlock_res(struct ldlm_resource *res)
{
spin_unlock(&res->lr_lock);
}
/** Check if resource is already locked, assert if not. */
static inline void check_res_locked(struct ldlm_resource *res)
{
LASSERT(spin_is_locked(&res->lr_lock));
}
struct ldlm_resource * lock_res_and_lock(struct ldlm_lock *lock);
void unlock_res_and_lock(struct ldlm_lock *lock);
/* ldlm_pool.c */
/** \defgroup ldlm_pools Various LDLM pool related functions
* There are not used outside of ldlm.
* @{
*/
int ldlm_pools_recalc(ldlm_side_t client);
int ldlm_pools_init(void);
void ldlm_pools_fini(void);
int ldlm_pool_init(struct ldlm_pool *pl, struct ldlm_namespace *ns,
int idx, ldlm_side_t client);
int ldlm_pool_shrink(struct ldlm_pool *pl, int nr,
unsigned int gfp_mask);
void ldlm_pool_fini(struct ldlm_pool *pl);
int ldlm_pool_setup(struct ldlm_pool *pl, int limit);
int ldlm_pool_recalc(struct ldlm_pool *pl);
__u32 ldlm_pool_get_lvf(struct ldlm_pool *pl);
__u64 ldlm_pool_get_slv(struct ldlm_pool *pl);
__u64 ldlm_pool_get_clv(struct ldlm_pool *pl);
__u32 ldlm_pool_get_limit(struct ldlm_pool *pl);
void ldlm_pool_set_slv(struct ldlm_pool *pl, __u64 slv);
void ldlm_pool_set_clv(struct ldlm_pool *pl, __u64 clv);
void ldlm_pool_set_limit(struct ldlm_pool *pl, __u32 limit);
void ldlm_pool_add(struct ldlm_pool *pl, struct ldlm_lock *lock);
void ldlm_pool_del(struct ldlm_pool *pl, struct ldlm_lock *lock);
/** @} */
#endif
/** @} LDLM */
|