#define LDLM_FL_BL_AST 0x10000000
#define LDLM_FL_BL_DONE 0x20000000
+/* measure lock contention and return -EUSERS if locking contention is high */
+#define LDLM_FL_DENY_ON_CONTENTION 0x40000000
+
/* The blocking callback is overloaded to perform two functions. These flags
* indicate which operation should be performed. */
#define LDLM_CB_BLOCKING 1
/* default values for the "max_nolock_size", "contention_time"
* and "contended_locks" namespace tunables */
-#define NS_DEFAULT_MAX_NOLOCK_BYTES 131072
+#define NS_DEFAULT_MAX_NOLOCK_BYTES 0
#define NS_DEFAULT_CONTENTION_SECONDS 2
-#define NS_DEFAULT_CONTENDED_LOCKS 0
+#define NS_DEFAULT_CONTENDED_LOCKS 32
struct ldlm_namespace {
char *ns_name;
void ldlm_resource_iterate(struct ldlm_namespace *, struct ldlm_res_id *,
ldlm_iterator_t iter, void *data);
-/* measure lock contention and return -EBUSY if locking contention is high */
-#define LDLM_FL_DENY_ON_CONTENTION 0x10000000
-
/* ldlm_flock.c */
int ldlm_flock_completion_ast(struct ldlm_lock *lock, int flags, void *data);
__u64 req_end = req->l_req_extent.end;
int compat = 1;
int scan = 0;
+ int check_contention;
ENTRY;
lockmode_verify(req_mode);
list_for_each(tmp, queue) {
+ check_contention = 1;
+
lock = list_entry(tmp, struct ldlm_lock, l_res_link);
if (req == lock)
lock->l_policy_data.l_extent.start > req_end) {
/* if a non group lock doesn't overlap skip it */
continue;
- }
+ } else if (lock->l_req_extent.end < req_start ||
+ lock->l_req_extent.start > req_end)
+ /* false contention, the requests doesn't really overlap */
+ check_contention = 0;
if (!work_list)
RETURN(0);
/* don't count conflicting glimpse locks */
- *contended_locks +=
- !(lock->l_req_mode == LCK_PR &&
- lock->l_policy_data.l_extent.start == 0 &&
- lock->l_policy_data.l_extent.end == OBD_OBJECT_EOF);
+ if (lock->l_req_mode == LCK_PR &&
+ lock->l_policy_data.l_extent.start == 0 &&
+ lock->l_policy_data.l_extent.end == OBD_OBJECT_EOF)
+ check_contention = 0;
+
+ *contended_locks += check_contention;
compat = 0;
if (lock->l_blocking_ast)
req->l_req_mode != LCK_GROUP &&
req_end - req_start <=
req->l_resource->lr_namespace->ns_max_nolock_size)
- GOTO(destroylock, compat = -EBUSY);
+ GOTO(destroylock, compat = -EUSERS);
RETURN(compat);
destroylock:
csum = crc32_le(csum, kmap(page), CFS_PAGE_SIZE);
kunmap(page);
if (origin == LLAP_ORIGIN_READAHEAD ||
- origin == LLAP_ORIGIN_READPAGE) {
+ origin == LLAP_ORIGIN_READPAGE ||
+ origin == LLAP_ORIGIN_LOCKLESS_IO) {
llap->llap_checksum = 0;
} else if (origin == LLAP_ORIGIN_COMMIT_WRITE ||
llap->llap_checksum == 0) {
RETURN(ret);
}
-/* the kernel calls us here when a page is unhashed from the page cache.
- * the page will be locked and the kernel is holding a spinlock, so
- * we need to be careful. we're just tearing down our book-keeping
- * here. */
-void ll_removepage(struct page *page)
+static void __ll_put_llap(struct page *page)
{
struct inode *inode = page->mapping->host;
struct obd_export *exp;
int rc;
ENTRY;
- LASSERT(!in_interrupt());
-
- /* sync pages or failed read pages can leave pages in the page
- * cache that don't have our data associated with them anymore */
- if (page_private(page) == 0) {
- EXIT;
- return;
- }
-
- LL_CDEBUG_PAGE(D_PAGE, page, "being evicted\n");
-
exp = ll_i2obdexp(inode);
if (exp == NULL) {
CERROR("page %p ind %lu gave null export\n", page, page->index);
sbi->ll_async_page_count--;
spin_unlock(&sbi->ll_lock);
OBD_SLAB_FREE(llap, ll_async_page_slab, ll_async_page_slab_size);
+
+ EXIT;
+}
+
+/* the kernel calls us here when a page is unhashed from the page cache.
+ * the page will be locked and the kernel is holding a spinlock, so
+ * we need to be careful. we're just tearing down our book-keeping
+ * here. */
+void ll_removepage(struct page *page)
+{
+ ENTRY;
+
+ LASSERT(!in_interrupt());
+
+ /* sync pages or failed read pages can leave pages in the page
+ * cache that don't have our data associated with them anymore */
+ if (page_private(page) == 0) {
+ EXIT;
+ return;
+ }
+
+ LASSERT(!llap_cast_private(page)->llap_lockless_io_page);
+ LL_CDEBUG_PAGE(D_PAGE, page, "being evicted\n");
+ __ll_put_llap(page);
+
EXIT;
}
for (i = 0, pp = pages; i < numpages; i++, pp++) {
if (*pp) {
LL_CDEBUG_PAGE(D_PAGE, (*pp), "free\n");
- ll_removepage(*pp);
+ __ll_put_llap(*pp);
if (page_private(*pp))
CERROR("the llap wasn't freed\n");
(*pp)->mapping = NULL;
if (page_count(*pp) != 1)
CERROR("page %p, flags %#lx, count %i, private %p\n",
- (*pp), (*pp)->flags, page_count(*pp),
+ (*pp), (unsigned long)(*pp)->flags, page_count(*pp),
(void*)page_private(*pp));
__free_pages(*pp, 0);
}
llap = llap_from_page(page, LLAP_ORIGIN_LOCKLESS_IO);
if (IS_ERR(llap))
GOTO(err, rc = PTR_ERR(llap));
+ llap->llap_lockless_io_page = 1;
}
RETURN(pages);
err:
}
static ssize_t ll_file_copy_pages(struct page **pages, int numpages,
- char *buf, loff_t pos, size_t count, int rw)
+ char *buf, loff_t pos, size_t count,
+ int rw)
{
ssize_t amount = 0;
int i;
+ int updatechecksum = ll_i2sbi(pages[0]->mapping->host)->ll_flags &
+ LL_SBI_CHECKSUM;
ENTRY;
for (i = 0; i < numpages; i++) {
"buf = %p, bytes = %u\n",
(rw == WRITE) ? "CFU" : "CTU",
vaddr + offset, buf, bytes);
- if (rw == WRITE)
+ if (rw == WRITE) {
left = copy_from_user(vaddr + offset, buf, bytes);
- else
+ if (updatechecksum) {
+ struct ll_async_page *llap;
+
+ llap = llap_cast_private(pages[i]);
+ llap->llap_checksum = crc32_le(0, vaddr,
+ CFS_PAGE_SIZE);
+ }
+ } else {
left = copy_to_user(buf, vaddr + offset, bytes);
+ }
kunmap(pages[i]);
amount += bytes;
if (left) {