aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/lustre/lustre/obdclass
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/lustre/lustre/obdclass')
-rw-r--r--drivers/staging/lustre/lustre/obdclass/Makefile12
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_internal.h95
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_io.c1152
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_lock.c275
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_object.c1061
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_page.c1046
-rw-r--r--drivers/staging/lustre/lustre/obdclass/class_obd.c535
-rw-r--r--drivers/staging/lustre/lustre/obdclass/debug.c96
-rw-r--r--drivers/staging/lustre/lustre/obdclass/genops.c1514
-rw-r--r--drivers/staging/lustre/lustre/obdclass/kernelcomm.c238
-rw-r--r--drivers/staging/lustre/lustre/obdclass/linkea.c249
-rw-r--r--drivers/staging/lustre/lustre/obdclass/linux/linux-module.c531
-rw-r--r--drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c162
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog.c523
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_cat.c236
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_internal.h79
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_obd.c225
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_swab.c412
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lprocfs_counters.c133
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lprocfs_status.c1810
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lu_object.c2058
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lu_ref.c47
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lustre_handles.c240
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lustre_peer.c214
-rw-r--r--drivers/staging/lustre/lustre/obdclass/obd_config.c1559
-rw-r--r--drivers/staging/lustre/lustre/obdclass/obd_mount.c1244
-rw-r--r--drivers/staging/lustre/lustre/obdclass/obdo.c181
-rw-r--r--drivers/staging/lustre/lustre/obdclass/statfs_pack.c58
-rw-r--r--drivers/staging/lustre/lustre/obdclass/uuid.c47
29 files changed, 0 insertions, 16032 deletions
diff --git a/drivers/staging/lustre/lustre/obdclass/Makefile b/drivers/staging/lustre/lustre/obdclass/Makefile
deleted file mode 100644
index e3fa9acff4c4..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-subdir-ccflags-y += -I$(srctree)/drivers/staging/lustre/include
-subdir-ccflags-y += -I$(srctree)/drivers/staging/lustre/lustre/include
-
-obj-$(CONFIG_LUSTRE_FS) += obdclass.o
-
-obdclass-y := linux/linux-module.o linux/linux-sysctl.o \
- llog.o llog_cat.o llog_obd.o llog_swab.o class_obd.o debug.o \
- genops.o uuid.o lprocfs_status.o lprocfs_counters.o \
- lustre_handles.o lustre_peer.o statfs_pack.o linkea.o \
- obdo.o obd_config.o obd_mount.o lu_object.o lu_ref.o \
- cl_object.o cl_page.o cl_lock.o cl_io.o kernelcomm.o
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_internal.h b/drivers/staging/lustre/lustre/obdclass/cl_internal.h
deleted file mode 100644
index a0db830ca841..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/cl_internal.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * Internal cl interfaces.
- *
- * Author: Nikita Danilov <nikita.danilov@sun.com>
- */
-#ifndef _CL_INTERNAL_H
-#define _CL_INTERNAL_H
-
-#define CLT_PVEC_SIZE (14)
-
-/**
- * Possible levels of the nesting. Currently this is 2: there are "top"
- * entities (files, extent locks), and "sub" entities (stripes and stripe
- * locks). This is used only for debugging counters right now.
- */
-enum clt_nesting_level {
- CNL_TOP,
- CNL_SUB,
- CNL_NR
-};
-
-/**
- * Thread local state internal for generic cl-code.
- */
-struct cl_thread_info {
- /*
- * Common fields.
- */
- struct cl_io clt_io;
- struct cl_2queue clt_queue;
-
- /*
- * Fields used by cl_lock.c
- */
- struct cl_lock_descr clt_descr;
- struct cl_page_list clt_list;
- /** @} debugging */
-
- /*
- * Fields used by cl_page.c
- */
- struct cl_page *clt_pvec[CLT_PVEC_SIZE];
-
- /*
- * Fields used by cl_io.c
- */
- /**
- * Pointer to the topmost ongoing IO in this thread.
- */
- struct cl_io *clt_current_io;
- /**
- * Used for submitting a sync io.
- */
- struct cl_sync_io clt_anchor;
- /**
- * Fields used by cl_lock_discard_pages().
- */
- pgoff_t clt_next_index;
- pgoff_t clt_fn_index; /* first non-overlapped index */
-};
-
-struct cl_thread_info *cl_env_info(const struct lu_env *env);
-
-#endif /* _CL_INTERNAL_H */
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c
deleted file mode 100644
index ab84e011b560..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/cl_io.c
+++ /dev/null
@@ -1,1152 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * Client IO.
- *
- * Author: Nikita Danilov <nikita.danilov@sun.com>
- * Author: Jinshan Xiong <jinshan.xiong@intel.com>
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_fid.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <cl_object.h>
-#include "cl_internal.h"
-
-/*****************************************************************************
- *
- * cl_io interface.
- *
- */
-
-#define cl_io_for_each(slice, io) \
- list_for_each_entry((slice), &io->ci_layers, cis_linkage)
-#define cl_io_for_each_reverse(slice, io) \
- list_for_each_entry_reverse((slice), &io->ci_layers, cis_linkage)
-
-static inline int cl_io_type_is_valid(enum cl_io_type type)
-{
- return CIT_READ <= type && type < CIT_OP_NR;
-}
-
-static inline int cl_io_is_loopable(const struct cl_io *io)
-{
- return cl_io_type_is_valid(io->ci_type) && io->ci_type != CIT_MISC;
-}
-
-/**
- * Returns true iff there is an IO ongoing in the given environment.
- */
-int cl_io_is_going(const struct lu_env *env)
-{
- return cl_env_info(env)->clt_current_io != NULL;
-}
-
-/**
- * cl_io invariant that holds at all times when exported cl_io_*() functions
- * are entered and left.
- */
-static int cl_io_invariant(const struct cl_io *io)
-{
- struct cl_io *up;
-
- up = io->ci_parent;
- return
- /*
- * io can own pages only when it is ongoing. Sub-io might
- * still be in CIS_LOCKED state when top-io is in
- * CIS_IO_GOING.
- */
- ergo(io->ci_owned_nr > 0, io->ci_state == CIS_IO_GOING ||
- (io->ci_state == CIS_LOCKED && up));
-}
-
-/**
- * Finalize \a io, by calling cl_io_operations::cio_fini() bottom-to-top.
- */
-void cl_io_fini(const struct lu_env *env, struct cl_io *io)
-{
- struct cl_io_slice *slice;
- struct cl_thread_info *info;
-
- LINVRNT(cl_io_type_is_valid(io->ci_type));
- LINVRNT(cl_io_invariant(io));
-
- while (!list_empty(&io->ci_layers)) {
- slice = container_of(io->ci_layers.prev, struct cl_io_slice,
- cis_linkage);
- list_del_init(&slice->cis_linkage);
- if (slice->cis_iop->op[io->ci_type].cio_fini)
- slice->cis_iop->op[io->ci_type].cio_fini(env, slice);
- /*
- * Invalidate slice to catch use after free. This assumes that
- * slices are allocated within session and can be touched
- * after ->cio_fini() returns.
- */
- slice->cis_io = NULL;
- }
- io->ci_state = CIS_FINI;
- info = cl_env_info(env);
- if (info->clt_current_io == io)
- info->clt_current_io = NULL;
-
- /* sanity check for layout change */
- switch (io->ci_type) {
- case CIT_READ:
- case CIT_WRITE:
- case CIT_DATA_VERSION:
- break;
- case CIT_FAULT:
- break;
- case CIT_FSYNC:
- LASSERT(!io->ci_need_restart);
- break;
- case CIT_SETATTR:
- case CIT_MISC:
- /* Check ignore layout change conf */
- LASSERT(ergo(io->ci_ignore_layout || !io->ci_verify_layout,
- !io->ci_need_restart));
- break;
- default:
- LBUG();
- }
-}
-EXPORT_SYMBOL(cl_io_fini);
-
-static int cl_io_init0(const struct lu_env *env, struct cl_io *io,
- enum cl_io_type iot, struct cl_object *obj)
-{
- struct cl_object *scan;
- int result;
-
- LINVRNT(io->ci_state == CIS_ZERO || io->ci_state == CIS_FINI);
- LINVRNT(cl_io_type_is_valid(iot));
- LINVRNT(cl_io_invariant(io));
-
- io->ci_type = iot;
- INIT_LIST_HEAD(&io->ci_lockset.cls_todo);
- INIT_LIST_HEAD(&io->ci_lockset.cls_done);
- INIT_LIST_HEAD(&io->ci_layers);
-
- result = 0;
- cl_object_for_each(scan, obj) {
- if (scan->co_ops->coo_io_init) {
- result = scan->co_ops->coo_io_init(env, scan, io);
- if (result != 0)
- break;
- }
- }
- if (result == 0)
- io->ci_state = CIS_INIT;
- return result;
-}
-
-/**
- * Initialize sub-io, by calling cl_io_operations::cio_init() top-to-bottom.
- *
- * \pre obj != cl_object_top(obj)
- */
-int cl_io_sub_init(const struct lu_env *env, struct cl_io *io,
- enum cl_io_type iot, struct cl_object *obj)
-{
- struct cl_thread_info *info = cl_env_info(env);
-
- LASSERT(obj != cl_object_top(obj));
- if (!info->clt_current_io)
- info->clt_current_io = io;
- return cl_io_init0(env, io, iot, obj);
-}
-EXPORT_SYMBOL(cl_io_sub_init);
-
-/**
- * Initialize \a io, by calling cl_io_operations::cio_init() top-to-bottom.
- *
- * Caller has to call cl_io_fini() after a call to cl_io_init(), no matter
- * what the latter returned.
- *
- * \pre obj == cl_object_top(obj)
- * \pre cl_io_type_is_valid(iot)
- * \post cl_io_type_is_valid(io->ci_type) && io->ci_type == iot
- */
-int cl_io_init(const struct lu_env *env, struct cl_io *io,
- enum cl_io_type iot, struct cl_object *obj)
-{
- struct cl_thread_info *info = cl_env_info(env);
-
- LASSERT(obj == cl_object_top(obj));
- LASSERT(!info->clt_current_io);
-
- info->clt_current_io = io;
- return cl_io_init0(env, io, iot, obj);
-}
-EXPORT_SYMBOL(cl_io_init);
-
-/**
- * Initialize read or write io.
- *
- * \pre iot == CIT_READ || iot == CIT_WRITE
- */
-int cl_io_rw_init(const struct lu_env *env, struct cl_io *io,
- enum cl_io_type iot, loff_t pos, size_t count)
-{
- LINVRNT(iot == CIT_READ || iot == CIT_WRITE);
- LINVRNT(io->ci_obj);
-
- LU_OBJECT_HEADER(D_VFSTRACE, env, &io->ci_obj->co_lu,
- "io range: %u [%llu, %llu) %u %u\n",
- iot, (__u64)pos, (__u64)pos + count,
- io->u.ci_rw.crw_nonblock, io->u.ci_wr.wr_append);
- io->u.ci_rw.crw_pos = pos;
- io->u.ci_rw.crw_count = count;
- return cl_io_init(env, io, iot, io->ci_obj);
-}
-EXPORT_SYMBOL(cl_io_rw_init);
-
-static int cl_lock_descr_sort(const struct cl_lock_descr *d0,
- const struct cl_lock_descr *d1)
-{
- return lu_fid_cmp(lu_object_fid(&d0->cld_obj->co_lu),
- lu_object_fid(&d1->cld_obj->co_lu));
-}
-
-/*
- * Sort locks in lexicographical order of their (fid, start-offset) pairs.
- */
-static void cl_io_locks_sort(struct cl_io *io)
-{
- int done = 0;
-
- /* hidden treasure: bubble sort for now. */
- do {
- struct cl_io_lock_link *curr;
- struct cl_io_lock_link *prev;
- struct cl_io_lock_link *temp;
-
- done = 1;
- prev = NULL;
-
- list_for_each_entry_safe(curr, temp,
- &io->ci_lockset.cls_todo,
- cill_linkage) {
- if (prev) {
- switch (cl_lock_descr_sort(&prev->cill_descr,
- &curr->cill_descr)) {
- case 0:
- /*
- * IMPOSSIBLE: Identical locks are
- * already removed at
- * this point.
- */
- default:
- LBUG();
- case 1:
- list_move_tail(&curr->cill_linkage,
- &prev->cill_linkage);
- done = 0;
- continue; /* don't change prev: it's
- * still "previous"
- */
- case -1: /* already in order */
- break;
- }
- }
- prev = curr;
- }
- } while (!done);
-}
-
-static void cl_lock_descr_merge(struct cl_lock_descr *d0,
- const struct cl_lock_descr *d1)
-{
- d0->cld_start = min(d0->cld_start, d1->cld_start);
- d0->cld_end = max(d0->cld_end, d1->cld_end);
-
- if (d1->cld_mode == CLM_WRITE && d0->cld_mode != CLM_WRITE)
- d0->cld_mode = CLM_WRITE;
-
- if (d1->cld_mode == CLM_GROUP && d0->cld_mode != CLM_GROUP)
- d0->cld_mode = CLM_GROUP;
-}
-
-static int cl_lockset_merge(const struct cl_lockset *set,
- const struct cl_lock_descr *need)
-{
- struct cl_io_lock_link *scan;
-
- list_for_each_entry(scan, &set->cls_todo, cill_linkage) {
- if (!cl_object_same(scan->cill_descr.cld_obj, need->cld_obj))
- continue;
-
- /* Merge locks for the same object because ldlm lock server
- * may expand the lock extent, otherwise there is a deadlock
- * case if two conflicted locks are queueud for the same object
- * and lock server expands one lock to overlap the another.
- * The side effect is that it can generate a multi-stripe lock
- * that may cause casacading problem
- */
- cl_lock_descr_merge(&scan->cill_descr, need);
- CDEBUG(D_VFSTRACE, "lock: %d: [%lu, %lu]\n",
- scan->cill_descr.cld_mode, scan->cill_descr.cld_start,
- scan->cill_descr.cld_end);
- return 1;
- }
- return 0;
-}
-
-static int cl_lockset_lock(const struct lu_env *env, struct cl_io *io,
- struct cl_lockset *set)
-{
- struct cl_io_lock_link *link;
- struct cl_io_lock_link *temp;
- int result;
-
- result = 0;
- list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage) {
- result = cl_lock_request(env, io, &link->cill_lock);
- if (result < 0)
- break;
-
- list_move(&link->cill_linkage, &set->cls_done);
- }
- return result;
-}
-
-/**
- * Takes locks necessary for the current iteration of io.
- *
- * Calls cl_io_operations::cio_lock() top-to-bottom to collect locks required
- * by layers for the current iteration. Then sort locks (to avoid dead-locks),
- * and acquire them.
- */
-int cl_io_lock(const struct lu_env *env, struct cl_io *io)
-{
- const struct cl_io_slice *scan;
- int result = 0;
-
- LINVRNT(cl_io_is_loopable(io));
- LINVRNT(io->ci_state == CIS_IT_STARTED);
- LINVRNT(cl_io_invariant(io));
-
- cl_io_for_each(scan, io) {
- if (!scan->cis_iop->op[io->ci_type].cio_lock)
- continue;
- result = scan->cis_iop->op[io->ci_type].cio_lock(env, scan);
- if (result != 0)
- break;
- }
- if (result == 0) {
- cl_io_locks_sort(io);
- result = cl_lockset_lock(env, io, &io->ci_lockset);
- }
- if (result != 0)
- cl_io_unlock(env, io);
- else
- io->ci_state = CIS_LOCKED;
- return result;
-}
-EXPORT_SYMBOL(cl_io_lock);
-
-/**
- * Release locks takes by io.
- */
-void cl_io_unlock(const struct lu_env *env, struct cl_io *io)
-{
- struct cl_lockset *set;
- struct cl_io_lock_link *link;
- struct cl_io_lock_link *temp;
- const struct cl_io_slice *scan;
-
- LASSERT(cl_io_is_loopable(io));
- LASSERT(CIS_IT_STARTED <= io->ci_state && io->ci_state < CIS_UNLOCKED);
- LINVRNT(cl_io_invariant(io));
-
- set = &io->ci_lockset;
-
- list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage) {
- list_del_init(&link->cill_linkage);
- if (link->cill_fini)
- link->cill_fini(env, link);
- }
-
- list_for_each_entry_safe(link, temp, &set->cls_done, cill_linkage) {
- list_del_init(&link->cill_linkage);
- cl_lock_release(env, &link->cill_lock);
- if (link->cill_fini)
- link->cill_fini(env, link);
- }
-
- cl_io_for_each_reverse(scan, io) {
- if (scan->cis_iop->op[io->ci_type].cio_unlock)
- scan->cis_iop->op[io->ci_type].cio_unlock(env, scan);
- }
- io->ci_state = CIS_UNLOCKED;
-}
-EXPORT_SYMBOL(cl_io_unlock);
-
-/**
- * Prepares next iteration of io.
- *
- * Calls cl_io_operations::cio_iter_init() top-to-bottom. This exists to give
- * layers a chance to modify io parameters, e.g., so that lov can restrict io
- * to a single stripe.
- */
-int cl_io_iter_init(const struct lu_env *env, struct cl_io *io)
-{
- const struct cl_io_slice *scan;
- int result;
-
- LINVRNT(cl_io_is_loopable(io));
- LINVRNT(io->ci_state == CIS_INIT || io->ci_state == CIS_IT_ENDED);
- LINVRNT(cl_io_invariant(io));
-
- result = 0;
- cl_io_for_each(scan, io) {
- if (!scan->cis_iop->op[io->ci_type].cio_iter_init)
- continue;
- result = scan->cis_iop->op[io->ci_type].cio_iter_init(env,
- scan);
- if (result != 0)
- break;
- }
- if (result == 0)
- io->ci_state = CIS_IT_STARTED;
- return result;
-}
-EXPORT_SYMBOL(cl_io_iter_init);
-
-/**
- * Finalizes io iteration.
- *
- * Calls cl_io_operations::cio_iter_fini() bottom-to-top.
- */
-void cl_io_iter_fini(const struct lu_env *env, struct cl_io *io)
-{
- const struct cl_io_slice *scan;
-
- LINVRNT(cl_io_is_loopable(io));
- LINVRNT(io->ci_state == CIS_UNLOCKED);
- LINVRNT(cl_io_invariant(io));
-
- cl_io_for_each_reverse(scan, io) {
- if (scan->cis_iop->op[io->ci_type].cio_iter_fini)
- scan->cis_iop->op[io->ci_type].cio_iter_fini(env, scan);
- }
- io->ci_state = CIS_IT_ENDED;
-}
-EXPORT_SYMBOL(cl_io_iter_fini);
-
-/**
- * Records that read or write io progressed \a nob bytes forward.
- */
-static void cl_io_rw_advance(const struct lu_env *env, struct cl_io *io,
- size_t nob)
-{
- const struct cl_io_slice *scan;
-
- LINVRNT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE ||
- nob == 0);
- LINVRNT(cl_io_is_loopable(io));
- LINVRNT(cl_io_invariant(io));
-
- io->u.ci_rw.crw_pos += nob;
- io->u.ci_rw.crw_count -= nob;
-
- /* layers have to be notified. */
- cl_io_for_each_reverse(scan, io) {
- if (scan->cis_iop->op[io->ci_type].cio_advance)
- scan->cis_iop->op[io->ci_type].cio_advance(env, scan,
- nob);
- }
-}
-
-/**
- * Adds a lock to a lockset.
- */
-int cl_io_lock_add(const struct lu_env *env, struct cl_io *io,
- struct cl_io_lock_link *link)
-{
- int result;
-
- if (cl_lockset_merge(&io->ci_lockset, &link->cill_descr)) {
- result = 1;
- } else {
- list_add(&link->cill_linkage, &io->ci_lockset.cls_todo);
- result = 0;
- }
- return result;
-}
-EXPORT_SYMBOL(cl_io_lock_add);
-
-static void cl_free_io_lock_link(const struct lu_env *env,
- struct cl_io_lock_link *link)
-{
- kfree(link);
-}
-
-/**
- * Allocates new lock link, and uses it to add a lock to a lockset.
- */
-int cl_io_lock_alloc_add(const struct lu_env *env, struct cl_io *io,
- struct cl_lock_descr *descr)
-{
- struct cl_io_lock_link *link;
- int result;
-
- link = kzalloc(sizeof(*link), GFP_NOFS);
- if (link) {
- link->cill_descr = *descr;
- link->cill_fini = cl_free_io_lock_link;
- result = cl_io_lock_add(env, io, link);
- if (result) /* lock match */
- link->cill_fini(env, link);
- } else {
- result = -ENOMEM;
- }
-
- return result;
-}
-EXPORT_SYMBOL(cl_io_lock_alloc_add);
-
-/**
- * Starts io by calling cl_io_operations::cio_start() top-to-bottom.
- */
-int cl_io_start(const struct lu_env *env, struct cl_io *io)
-{
- const struct cl_io_slice *scan;
- int result = 0;
-
- LINVRNT(cl_io_is_loopable(io));
- LINVRNT(io->ci_state == CIS_LOCKED);
- LINVRNT(cl_io_invariant(io));
-
- io->ci_state = CIS_IO_GOING;
- cl_io_for_each(scan, io) {
- if (!scan->cis_iop->op[io->ci_type].cio_start)
- continue;
- result = scan->cis_iop->op[io->ci_type].cio_start(env, scan);
- if (result != 0)
- break;
- }
- if (result >= 0)
- result = 0;
- return result;
-}
-EXPORT_SYMBOL(cl_io_start);
-
-/**
- * Wait until current io iteration is finished by calling
- * cl_io_operations::cio_end() bottom-to-top.
- */
-void cl_io_end(const struct lu_env *env, struct cl_io *io)
-{
- const struct cl_io_slice *scan;
-
- LINVRNT(cl_io_is_loopable(io));
- LINVRNT(io->ci_state == CIS_IO_GOING);
- LINVRNT(cl_io_invariant(io));
-
- cl_io_for_each_reverse(scan, io) {
- if (scan->cis_iop->op[io->ci_type].cio_end)
- scan->cis_iop->op[io->ci_type].cio_end(env, scan);
- /* TODO: error handling. */
- }
- io->ci_state = CIS_IO_FINISHED;
-}
-EXPORT_SYMBOL(cl_io_end);
-
-/**
- * Called by read io, to decide the readahead extent
- *
- * \see cl_io_operations::cio_read_ahead()
- */
-int cl_io_read_ahead(const struct lu_env *env, struct cl_io *io,
- pgoff_t start, struct cl_read_ahead *ra)
-{
- const struct cl_io_slice *scan;
- int result = 0;
-
- LINVRNT(io->ci_type == CIT_READ || io->ci_type == CIT_FAULT);
- LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED);
- LINVRNT(cl_io_invariant(io));
-
- cl_io_for_each(scan, io) {
- if (!scan->cis_iop->cio_read_ahead)
- continue;
-
- result = scan->cis_iop->cio_read_ahead(env, scan, start, ra);
- if (result)
- break;
- }
- return result > 0 ? 0 : result;
-}
-EXPORT_SYMBOL(cl_io_read_ahead);
-
-/**
- * Commit a list of contiguous pages into writeback cache.
- *
- * \returns 0 if all pages committed, or errcode if error occurred.
- * \see cl_io_operations::cio_commit_async()
- */
-int cl_io_commit_async(const struct lu_env *env, struct cl_io *io,
- struct cl_page_list *queue, int from, int to,
- cl_commit_cbt cb)
-{
- const struct cl_io_slice *scan;
- int result = 0;
-
- cl_io_for_each(scan, io) {
- if (!scan->cis_iop->cio_commit_async)
- continue;
- result = scan->cis_iop->cio_commit_async(env, scan, queue,
- from, to, cb);
- if (result != 0)
- break;
- }
- return result;
-}
-EXPORT_SYMBOL(cl_io_commit_async);
-
-/**
- * Submits a list of pages for immediate io.
- *
- * After the function gets returned, The submitted pages are moved to
- * queue->c2_qout queue, and queue->c2_qin contain both the pages don't need
- * to be submitted, and the pages are errant to submit.
- *
- * \returns 0 if at least one page was submitted, error code otherwise.
- * \see cl_io_operations::cio_submit()
- */
-int cl_io_submit_rw(const struct lu_env *env, struct cl_io *io,
- enum cl_req_type crt, struct cl_2queue *queue)
-{
- const struct cl_io_slice *scan;
- int result = 0;
-
- cl_io_for_each(scan, io) {
- if (!scan->cis_iop->cio_submit)
- continue;
- result = scan->cis_iop->cio_submit(env, scan, crt, queue);
- if (result != 0)
- break;
- }
- /*
- * If ->cio_submit() failed, no pages were sent.
- */
- LASSERT(ergo(result != 0, list_empty(&queue->c2_qout.pl_pages)));
- return result;
-}
-EXPORT_SYMBOL(cl_io_submit_rw);
-
-static void cl_page_list_assume(const struct lu_env *env,
- struct cl_io *io, struct cl_page_list *plist);
-
-/**
- * Submit a sync_io and wait for the IO to be finished, or error happens.
- * If \a timeout is zero, it means to wait for the IO unconditionally.
- */
-int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io,
- enum cl_req_type iot, struct cl_2queue *queue,
- long timeout)
-{
- struct cl_sync_io *anchor = &cl_env_info(env)->clt_anchor;
- struct cl_page *pg;
- int rc;
-
- cl_page_list_for_each(pg, &queue->c2_qin) {
- LASSERT(!pg->cp_sync_io);
- pg->cp_sync_io = anchor;
- }
-
- cl_sync_io_init(anchor, queue->c2_qin.pl_nr, &cl_sync_io_end);
- rc = cl_io_submit_rw(env, io, iot, queue);
- if (rc == 0) {
- /*
- * If some pages weren't sent for any reason (e.g.,
- * read found up-to-date pages in the cache, or write found
- * clean pages), count them as completed to avoid infinite
- * wait.
- */
- cl_page_list_for_each(pg, &queue->c2_qin) {
- pg->cp_sync_io = NULL;
- cl_sync_io_note(env, anchor, 1);
- }
-
- /* wait for the IO to be finished. */
- rc = cl_sync_io_wait(env, anchor, timeout);
- cl_page_list_assume(env, io, &queue->c2_qout);
- } else {
- LASSERT(list_empty(&queue->c2_qout.pl_pages));
- cl_page_list_for_each(pg, &queue->c2_qin)
- pg->cp_sync_io = NULL;
- }
- return rc;
-}
-EXPORT_SYMBOL(cl_io_submit_sync);
-
-/**
- * Main io loop.
- *
- * Pumps io through iterations calling
- *
- * - cl_io_iter_init()
- *
- * - cl_io_lock()
- *
- * - cl_io_start()
- *
- * - cl_io_end()
- *
- * - cl_io_unlock()
- *
- * - cl_io_iter_fini()
- *
- * repeatedly until there is no more io to do.
- */
-int cl_io_loop(const struct lu_env *env, struct cl_io *io)
-{
- int result = 0;
-
- LINVRNT(cl_io_is_loopable(io));
-
- do {
- size_t nob;
-
- io->ci_continue = 0;
- result = cl_io_iter_init(env, io);
- if (result == 0) {
- nob = io->ci_nob;
- result = cl_io_lock(env, io);
- if (result == 0) {
- /*
- * Notify layers that locks has been taken,
- * and do actual i/o.
- *
- * - llite: kms, short read;
- * - llite: generic_file_read();
- */
- result = cl_io_start(env, io);
- /*
- * Send any remaining pending
- * io, etc.
- *
- * - llite: ll_rw_stats_tally.
- */
- cl_io_end(env, io);
- cl_io_unlock(env, io);
- cl_io_rw_advance(env, io, io->ci_nob - nob);
- }
- }
- cl_io_iter_fini(env, io);
- } while (result == 0 && io->ci_continue);
- if (result == 0)
- result = io->ci_result;
- return result < 0 ? result : 0;
-}
-EXPORT_SYMBOL(cl_io_loop);
-
-/**
- * Adds io slice to the cl_io.
- *
- * This is called by cl_object_operations::coo_io_init() methods to add a
- * per-layer state to the io. New state is added at the end of
- * cl_io::ci_layers list, that is, it is at the bottom of the stack.
- *
- * \see cl_lock_slice_add(), cl_req_slice_add(), cl_page_slice_add()
- */
-void cl_io_slice_add(struct cl_io *io, struct cl_io_slice *slice,
- struct cl_object *obj,
- const struct cl_io_operations *ops)
-{
- struct list_head *linkage = &slice->cis_linkage;
-
- LASSERT((!linkage->prev && !linkage->next) ||
- list_empty(linkage));
-
- list_add_tail(linkage, &io->ci_layers);
- slice->cis_io = io;
- slice->cis_obj = obj;
- slice->cis_iop = ops;
-}
-EXPORT_SYMBOL(cl_io_slice_add);
-
-/**
- * Initializes page list.
- */
-void cl_page_list_init(struct cl_page_list *plist)
-{
- plist->pl_nr = 0;
- INIT_LIST_HEAD(&plist->pl_pages);
- plist->pl_owner = current;
-}
-EXPORT_SYMBOL(cl_page_list_init);
-
-/**
- * Adds a page to a page list.
- */
-void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page)
-{
- /* it would be better to check that page is owned by "current" io, but
- * it is not passed here.
- */
- LASSERT(page->cp_owner);
- LINVRNT(plist->pl_owner == current);
-
- LASSERT(list_empty(&page->cp_batch));
- list_add_tail(&page->cp_batch, &plist->pl_pages);
- ++plist->pl_nr;
- lu_ref_add_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist);
- cl_page_get(page);
-}
-EXPORT_SYMBOL(cl_page_list_add);
-
-/**
- * Removes a page from a page list.
- */
-void cl_page_list_del(const struct lu_env *env, struct cl_page_list *plist,
- struct cl_page *page)
-{
- LASSERT(plist->pl_nr > 0);
- LASSERT(cl_page_is_vmlocked(env, page));
- LINVRNT(plist->pl_owner == current);
-
- list_del_init(&page->cp_batch);
- --plist->pl_nr;
- lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist);
- cl_page_put(env, page);
-}
-EXPORT_SYMBOL(cl_page_list_del);
-
-/**
- * Moves a page from one page list to another.
- */
-void cl_page_list_move(struct cl_page_list *dst, struct cl_page_list *src,
- struct cl_page *page)
-{
- LASSERT(src->pl_nr > 0);
- LINVRNT(dst->pl_owner == current);
- LINVRNT(src->pl_owner == current);
-
- list_move_tail(&page->cp_batch, &dst->pl_pages);
- --src->pl_nr;
- ++dst->pl_nr;
- lu_ref_set_at(&page->cp_reference, &page->cp_queue_ref, "queue",
- src, dst);
-}
-EXPORT_SYMBOL(cl_page_list_move);
-
-/**
- * Moves a page from one page list to the head of another list.
- */
-void cl_page_list_move_head(struct cl_page_list *dst, struct cl_page_list *src,
- struct cl_page *page)
-{
- LASSERT(src->pl_nr > 0);
- LINVRNT(dst->pl_owner == current);
- LINVRNT(src->pl_owner == current);
-
- list_move(&page->cp_batch, &dst->pl_pages);
- --src->pl_nr;
- ++dst->pl_nr;
- lu_ref_set_at(&page->cp_reference, &page->cp_queue_ref, "queue",
- src, dst);
-}
-EXPORT_SYMBOL(cl_page_list_move_head);
-
-/**
- * splice the cl_page_list, just as list head does
- */
-void cl_page_list_splice(struct cl_page_list *list, struct cl_page_list *head)
-{
- struct cl_page *page;
- struct cl_page *tmp;
-
- LINVRNT(list->pl_owner == current);
- LINVRNT(head->pl_owner == current);
-
- cl_page_list_for_each_safe(page, tmp, list)
- cl_page_list_move(head, list, page);
-}
-EXPORT_SYMBOL(cl_page_list_splice);
-
-
-/**
- * Disowns pages in a queue.
- */
-void cl_page_list_disown(const struct lu_env *env,
- struct cl_io *io, struct cl_page_list *plist)
-{
- struct cl_page *page;
- struct cl_page *temp;
-
- LINVRNT(plist->pl_owner == current);
-
- cl_page_list_for_each_safe(page, temp, plist) {
- LASSERT(plist->pl_nr > 0);
-
- list_del_init(&page->cp_batch);
- --plist->pl_nr;
- /*
- * cl_page_disown0 rather than usual cl_page_disown() is used,
- * because pages are possibly in CPS_FREEING state already due
- * to the call to cl_page_list_discard().
- */
- /*
- * XXX cl_page_disown0() will fail if page is not locked.
- */
- cl_page_disown0(env, io, page);
- lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue",
- plist);
- cl_page_put(env, page);
- }
-}
-EXPORT_SYMBOL(cl_page_list_disown);
-
-/**
- * Releases pages from queue.
- */
-void cl_page_list_fini(const struct lu_env *env, struct cl_page_list *plist)
-{
- struct cl_page *page;
- struct cl_page *temp;
-
- LINVRNT(plist->pl_owner == current);
-
- cl_page_list_for_each_safe(page, temp, plist)
- cl_page_list_del(env, plist, page);
- LASSERT(plist->pl_nr == 0);
-}
-EXPORT_SYMBOL(cl_page_list_fini);
-
-/**
- * Assumes all pages in a queue.
- */
-static void cl_page_list_assume(const struct lu_env *env,
- struct cl_io *io, struct cl_page_list *plist)
-{
- struct cl_page *page;
-
- LINVRNT(plist->pl_owner == current);
-
- cl_page_list_for_each(page, plist)
- cl_page_assume(env, io, page);
-}
-
-/**
- * Discards all pages in a queue.
- */
-static void cl_page_list_discard(const struct lu_env *env, struct cl_io *io,
- struct cl_page_list *plist)
-{
- struct cl_page *page;
-
- LINVRNT(plist->pl_owner == current);
- cl_page_list_for_each(page, plist)
- cl_page_discard(env, io, page);
-}
-
-/**
- * Initialize dual page queue.
- */
-void cl_2queue_init(struct cl_2queue *queue)
-{
- cl_page_list_init(&queue->c2_qin);
- cl_page_list_init(&queue->c2_qout);
-}
-EXPORT_SYMBOL(cl_2queue_init);
-
-/**
- * Disown pages in both lists of a 2-queue.
- */
-void cl_2queue_disown(const struct lu_env *env,
- struct cl_io *io, struct cl_2queue *queue)
-{
- cl_page_list_disown(env, io, &queue->c2_qin);
- cl_page_list_disown(env, io, &queue->c2_qout);
-}
-EXPORT_SYMBOL(cl_2queue_disown);
-
-/**
- * Discard (truncate) pages in both lists of a 2-queue.
- */
-void cl_2queue_discard(const struct lu_env *env,
- struct cl_io *io, struct cl_2queue *queue)
-{
- cl_page_list_discard(env, io, &queue->c2_qin);
- cl_page_list_discard(env, io, &queue->c2_qout);
-}
-EXPORT_SYMBOL(cl_2queue_discard);
-
-/**
- * Finalize both page lists of a 2-queue.
- */
-void cl_2queue_fini(const struct lu_env *env, struct cl_2queue *queue)
-{
- cl_page_list_fini(env, &queue->c2_qout);
- cl_page_list_fini(env, &queue->c2_qin);
-}
-EXPORT_SYMBOL(cl_2queue_fini);
-
-/**
- * Initialize a 2-queue to contain \a page in its incoming page list.
- */
-void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page)
-{
- cl_2queue_init(queue);
- /*
- * Add a page to the incoming page list of 2-queue.
- */
- cl_page_list_add(&queue->c2_qin, page);
-}
-EXPORT_SYMBOL(cl_2queue_init_page);
-
-/**
- * Returns top-level io.
- *
- * \see cl_object_top()
- */
-struct cl_io *cl_io_top(struct cl_io *io)
-{
- while (io->ci_parent)
- io = io->ci_parent;
- return io;
-}
-EXPORT_SYMBOL(cl_io_top);
-
-/**
- * Fills in attributes that are passed to server together with transfer. Only
- * attributes from \a flags may be touched. This can be called multiple times
- * for the same request.
- */
-void cl_req_attr_set(const struct lu_env *env, struct cl_object *obj,
- struct cl_req_attr *attr)
-{
- struct cl_object *scan;
-
- cl_object_for_each(scan, obj) {
- if (scan->co_ops->coo_req_attr_set)
- scan->co_ops->coo_req_attr_set(env, scan, attr);
- }
-}
-EXPORT_SYMBOL(cl_req_attr_set);
-
-/* cl_sync_io_callback assumes the caller must call cl_sync_io_wait() to
- * wait for the IO to finish.
- */
-void cl_sync_io_end(const struct lu_env *env, struct cl_sync_io *anchor)
-{
- wake_up_all(&anchor->csi_waitq);
-
- /* it's safe to nuke or reuse anchor now */
- atomic_set(&anchor->csi_barrier, 0);
-}
-EXPORT_SYMBOL(cl_sync_io_end);
-
-/**
- * Initialize synchronous io wait anchor
- */
-void cl_sync_io_init(struct cl_sync_io *anchor, int nr,
- void (*end)(const struct lu_env *, struct cl_sync_io *))
-{
- memset(anchor, 0, sizeof(*anchor));
- init_waitqueue_head(&anchor->csi_waitq);
- atomic_set(&anchor->csi_sync_nr, nr);
- atomic_set(&anchor->csi_barrier, nr > 0);
- anchor->csi_sync_rc = 0;
- anchor->csi_end_io = end;
- LASSERT(end);
-}
-EXPORT_SYMBOL(cl_sync_io_init);
-
-/**
- * Wait until all IO completes. Transfer completion routine has to call
- * cl_sync_io_note() for every entity.
- */
-int cl_sync_io_wait(const struct lu_env *env, struct cl_sync_io *anchor,
- long timeout)
-{
- int rc = 1;
-
- LASSERT(timeout >= 0);
-
- if (timeout == 0)
- wait_event_idle(anchor->csi_waitq,
- atomic_read(&anchor->csi_sync_nr) == 0);
- else
- rc = wait_event_idle_timeout(anchor->csi_waitq,
- atomic_read(&anchor->csi_sync_nr) == 0,
- timeout * HZ);
- if (rc == 0) {
- rc = -ETIMEDOUT;
- CERROR("IO failed: %d, still wait for %d remaining entries\n",
- rc, atomic_read(&anchor->csi_sync_nr));
-
- wait_event_idle(anchor->csi_waitq,
- atomic_read(&anchor->csi_sync_nr) == 0);
- } else {
- rc = anchor->csi_sync_rc;
- }
- LASSERT(atomic_read(&anchor->csi_sync_nr) == 0);
-
- /* wait until cl_sync_io_note() has done wakeup */
- while (unlikely(atomic_read(&anchor->csi_barrier) != 0))
- cpu_relax();
-
-
- return rc;
-}
-EXPORT_SYMBOL(cl_sync_io_wait);
-
-/**
- * Indicate that transfer of a single page completed.
- */
-void cl_sync_io_note(const struct lu_env *env, struct cl_sync_io *anchor,
- int ioret)
-{
- if (anchor->csi_sync_rc == 0 && ioret < 0)
- anchor->csi_sync_rc = ioret;
- /*
- * Synchronous IO done without releasing page lock (e.g., as a part of
- * ->{prepare,commit}_write(). Completion is used to signal the end of
- * IO.
- */
- LASSERT(atomic_read(&anchor->csi_sync_nr) > 0);
- if (atomic_dec_and_test(&anchor->csi_sync_nr)) {
- LASSERT(anchor->csi_end_io);
- anchor->csi_end_io(env, anchor);
- /* Can't access anchor any more */
- }
-}
-EXPORT_SYMBOL(cl_sync_io_note);
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c
deleted file mode 100644
index 9ca29a26a38b..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c
+++ /dev/null
@@ -1,275 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * Client Extent Lock.
- *
- * Author: Nikita Danilov <nikita.danilov@sun.com>
- * Author: Jinshan Xiong <jinshan.xiong@intel.com>
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_fid.h>
-#include <linux/list.h>
-#include <cl_object.h>
-#include "cl_internal.h"
-
-static void cl_lock_trace0(int level, const struct lu_env *env,
- const char *prefix, const struct cl_lock *lock,
- const char *func, const int line)
-{
- struct cl_object_header *h = cl_object_header(lock->cll_descr.cld_obj);
-
- CDEBUG(level, "%s: %p (%p/%d) at %s():%d\n",
- prefix, lock, env, h->coh_nesting, func, line);
-}
-#define cl_lock_trace(level, env, prefix, lock) \
- cl_lock_trace0(level, env, prefix, lock, __func__, __LINE__)
-
-/**
- * Adds lock slice to the compound lock.
- *
- * This is called by cl_object_operations::coo_lock_init() methods to add a
- * per-layer state to the lock. New state is added at the end of
- * cl_lock::cll_layers list, that is, it is at the bottom of the stack.
- *
- * \see cl_req_slice_add(), cl_page_slice_add(), cl_io_slice_add()
- */
-void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice,
- struct cl_object *obj,
- const struct cl_lock_operations *ops)
-{
- slice->cls_lock = lock;
- list_add_tail(&slice->cls_linkage, &lock->cll_layers);
- slice->cls_obj = obj;
- slice->cls_ops = ops;
-}
-EXPORT_SYMBOL(cl_lock_slice_add);
-
-void cl_lock_fini(const struct lu_env *env, struct cl_lock *lock)
-{
- struct cl_lock_slice *slice;
- cl_lock_trace(D_DLMTRACE, env, "destroy lock", lock);
-
- while ((slice = list_first_entry_or_null(&lock->cll_layers,
- struct cl_lock_slice,
- cls_linkage)) != NULL) {
- list_del_init(lock->cll_layers.next);
- slice->cls_ops->clo_fini(env, slice);
- }
- POISON(lock, 0x5a, sizeof(*lock));
-}
-EXPORT_SYMBOL(cl_lock_fini);
-
-int cl_lock_init(const struct lu_env *env, struct cl_lock *lock,
- const struct cl_io *io)
-{
- struct cl_object *obj = lock->cll_descr.cld_obj;
- struct cl_object *scan;
- int result = 0;
-
- /* Make sure cl_lock::cll_descr is initialized. */
- LASSERT(obj);
-
- INIT_LIST_HEAD(&lock->cll_layers);
- list_for_each_entry(scan, &obj->co_lu.lo_header->loh_layers,
- co_lu.lo_linkage) {
- result = scan->co_ops->coo_lock_init(env, scan, lock, io);
- if (result != 0) {
- cl_lock_fini(env, lock);
- break;
- }
- }
-
- return result;
-}
-EXPORT_SYMBOL(cl_lock_init);
-
-/**
- * Returns a slice with a lock, corresponding to the given layer in the
- * device stack.
- *
- * \see cl_page_at()
- */
-const struct cl_lock_slice *cl_lock_at(const struct cl_lock *lock,
- const struct lu_device_type *dtype)
-{
- const struct cl_lock_slice *slice;
-
- list_for_each_entry(slice, &lock->cll_layers, cls_linkage) {
- if (slice->cls_obj->co_lu.lo_dev->ld_type == dtype)
- return slice;
- }
- return NULL;
-}
-EXPORT_SYMBOL(cl_lock_at);
-
-void cl_lock_cancel(const struct lu_env *env, struct cl_lock *lock)
-{
- const struct cl_lock_slice *slice;
-
- cl_lock_trace(D_DLMTRACE, env, "cancel lock", lock);
- list_for_each_entry_reverse(slice, &lock->cll_layers, cls_linkage) {
- if (slice->cls_ops->clo_cancel)
- slice->cls_ops->clo_cancel(env, slice);
- }
-}
-EXPORT_SYMBOL(cl_lock_cancel);
-
-/**
- * Enqueue a lock.
- * \param anchor: if we need to wait for resources before getting the lock,
- * use @anchor for the purpose.
- * \retval 0 enqueue successfully
- * \retval <0 error code
- */
-int cl_lock_enqueue(const struct lu_env *env, struct cl_io *io,
- struct cl_lock *lock, struct cl_sync_io *anchor)
-{
- const struct cl_lock_slice *slice;
- int rc = -ENOSYS;
-
- list_for_each_entry(slice, &lock->cll_layers, cls_linkage) {
- if (!slice->cls_ops->clo_enqueue)
- continue;
-
- rc = slice->cls_ops->clo_enqueue(env, slice, io, anchor);
- if (rc != 0)
- break;
- }
- return rc;
-}
-EXPORT_SYMBOL(cl_lock_enqueue);
-
-/**
- * Main high-level entry point of cl_lock interface that finds existing or
- * enqueues new lock matching given description.
- */
-int cl_lock_request(const struct lu_env *env, struct cl_io *io,
- struct cl_lock *lock)
-{
- struct cl_sync_io *anchor = NULL;
- __u32 enq_flags = lock->cll_descr.cld_enq_flags;
- int rc;
-
- rc = cl_lock_init(env, lock, io);
- if (rc < 0)
- return rc;
-
- if ((enq_flags & CEF_ASYNC) && !(enq_flags & CEF_AGL)) {
- anchor = &cl_env_info(env)->clt_anchor;
- cl_sync_io_init(anchor, 1, cl_sync_io_end);
- }
-
- rc = cl_lock_enqueue(env, io, lock, anchor);
-
- if (anchor) {
- int rc2;
-
- /* drop the reference count held at initialization time */
- cl_sync_io_note(env, anchor, 0);
- rc2 = cl_sync_io_wait(env, anchor, 0);
- if (rc2 < 0 && rc == 0)
- rc = rc2;
- }
-
- if (rc < 0)
- cl_lock_release(env, lock);
-
- return rc;
-}
-EXPORT_SYMBOL(cl_lock_request);
-
-/**
- * Releases a hold and a reference on a lock, obtained by cl_lock_hold().
- */
-void cl_lock_release(const struct lu_env *env, struct cl_lock *lock)
-{
- cl_lock_trace(D_DLMTRACE, env, "release lock", lock);
- cl_lock_cancel(env, lock);
- cl_lock_fini(env, lock);
-}
-EXPORT_SYMBOL(cl_lock_release);
-
-const char *cl_lock_mode_name(const enum cl_lock_mode mode)
-{
- static const char * const names[] = {
- [CLM_READ] = "R",
- [CLM_WRITE] = "W",
- [CLM_GROUP] = "G"
- };
- if (0 <= mode && mode < ARRAY_SIZE(names))
- return names[mode];
- else
- return "U";
-}
-EXPORT_SYMBOL(cl_lock_mode_name);
-
-/**
- * Prints human readable representation of a lock description.
- */
-void cl_lock_descr_print(const struct lu_env *env, void *cookie,
- lu_printer_t printer,
- const struct cl_lock_descr *descr)
-{
- const struct lu_fid *fid;
-
- fid = lu_object_fid(&descr->cld_obj->co_lu);
- (*printer)(env, cookie, DDESCR "@" DFID, PDESCR(descr), PFID(fid));
-}
-EXPORT_SYMBOL(cl_lock_descr_print);
-
-/**
- * Prints human readable representation of \a lock to the \a f.
- */
-void cl_lock_print(const struct lu_env *env, void *cookie,
- lu_printer_t printer, const struct cl_lock *lock)
-{
- const struct cl_lock_slice *slice;
-
- (*printer)(env, cookie, "lock@%p", lock);
- cl_lock_descr_print(env, cookie, printer, &lock->cll_descr);
- (*printer)(env, cookie, " {\n");
-
- list_for_each_entry(slice, &lock->cll_layers, cls_linkage) {
- (*printer)(env, cookie, " %s@%p: ",
- slice->cls_obj->co_lu.lo_dev->ld_type->ldt_name,
- slice);
- if (slice->cls_ops->clo_print)
- slice->cls_ops->clo_print(env, cookie, printer, slice);
- (*printer)(env, cookie, "\n");
- }
- (*printer)(env, cookie, "} lock@%p\n", lock);
-}
-EXPORT_SYMBOL(cl_lock_print);
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c
deleted file mode 100644
index 7809f6ae1809..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/cl_object.c
+++ /dev/null
@@ -1,1061 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * Client Lustre Object.
- *
- * Author: Nikita Danilov <nikita.danilov@sun.com>
- * Author: Jinshan Xiong <jinshan.xiong@intel.com>
- */
-
-/*
- * Locking.
- *
- * i_mutex
- * PG_locked
- * ->coh_attr_guard
- * ->ls_guard
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/libcfs/libcfs.h>
-/* class_put_type() */
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_fid.h>
-#include <linux/list.h>
-#include <linux/libcfs/libcfs_hash.h> /* for cfs_hash stuff */
-#include <cl_object.h>
-#include <lu_object.h>
-#include "cl_internal.h"
-
-static struct kmem_cache *cl_env_kmem;
-
-/** Lock class of cl_object_header::coh_attr_guard */
-static struct lock_class_key cl_attr_guard_class;
-
-/**
- * Initialize cl_object_header.
- */
-int cl_object_header_init(struct cl_object_header *h)
-{
- int result;
-
- result = lu_object_header_init(&h->coh_lu);
- if (result == 0) {
- spin_lock_init(&h->coh_attr_guard);
- lockdep_set_class(&h->coh_attr_guard, &cl_attr_guard_class);
- h->coh_page_bufsize = 0;
- }
- return result;
-}
-EXPORT_SYMBOL(cl_object_header_init);
-
-/**
- * Returns a cl_object with a given \a fid.
- *
- * Returns either cached or newly created object. Additional reference on the
- * returned object is acquired.
- *
- * \see lu_object_find(), cl_page_find(), cl_lock_find()
- */
-struct cl_object *cl_object_find(const struct lu_env *env,
- struct cl_device *cd, const struct lu_fid *fid,
- const struct cl_object_conf *c)
-{
- might_sleep();
- return lu2cl(lu_object_find_slice(env, cl2lu_dev(cd), fid, &c->coc_lu));
-}
-EXPORT_SYMBOL(cl_object_find);
-
-/**
- * Releases a reference on \a o.
- *
- * When last reference is released object is returned to the cache, unless
- * lu_object_header_flags::LU_OBJECT_HEARD_BANSHEE bit is set in its header.
- *
- * \see cl_page_put(), cl_lock_put().
- */
-void cl_object_put(const struct lu_env *env, struct cl_object *o)
-{
- lu_object_put(env, &o->co_lu);
-}
-EXPORT_SYMBOL(cl_object_put);
-
-/**
- * Acquire an additional reference to the object \a o.
- *
- * This can only be used to acquire _additional_ reference, i.e., caller
- * already has to possess at least one reference to \a o before calling this.
- *
- * \see cl_page_get(), cl_lock_get().
- */
-void cl_object_get(struct cl_object *o)
-{
- lu_object_get(&o->co_lu);
-}
-EXPORT_SYMBOL(cl_object_get);
-
-/**
- * Returns the top-object for a given \a o.
- *
- * \see cl_io_top()
- */
-struct cl_object *cl_object_top(struct cl_object *o)
-{
- struct cl_object_header *hdr = cl_object_header(o);
- struct cl_object *top;
-
- while (hdr->coh_parent)
- hdr = hdr->coh_parent;
-
- top = lu2cl(lu_object_top(&hdr->coh_lu));
- CDEBUG(D_TRACE, "%p -> %p\n", o, top);
- return top;
-}
-EXPORT_SYMBOL(cl_object_top);
-
-/**
- * Returns pointer to the lock protecting data-attributes for the given object
- * \a o.
- *
- * Data-attributes are protected by the cl_object_header::coh_attr_guard
- * spin-lock in the top-object.
- *
- * \see cl_attr, cl_object_attr_lock(), cl_object_operations::coo_attr_get().
- */
-static spinlock_t *cl_object_attr_guard(struct cl_object *o)
-{
- return &cl_object_header(cl_object_top(o))->coh_attr_guard;
-}
-
-/**
- * Locks data-attributes.
- *
- * Prevents data-attributes from changing, until lock is released by
- * cl_object_attr_unlock(). This has to be called before calls to
- * cl_object_attr_get(), cl_object_attr_update().
- */
-void cl_object_attr_lock(struct cl_object *o)
- __acquires(cl_object_attr_guard(o))
-{
- spin_lock(cl_object_attr_guard(o));
-}
-EXPORT_SYMBOL(cl_object_attr_lock);
-
-/**
- * Releases data-attributes lock, acquired by cl_object_attr_lock().
- */
-void cl_object_attr_unlock(struct cl_object *o)
- __releases(cl_object_attr_guard(o))
-{
- spin_unlock(cl_object_attr_guard(o));
-}
-EXPORT_SYMBOL(cl_object_attr_unlock);
-
-/**
- * Returns data-attributes of an object \a obj.
- *
- * Every layer is asked (by calling cl_object_operations::coo_attr_get())
- * top-to-bottom to fill in parts of \a attr that this layer is responsible
- * for.
- */
-int cl_object_attr_get(const struct lu_env *env, struct cl_object *obj,
- struct cl_attr *attr)
-{
- struct lu_object_header *top;
- int result;
-
- assert_spin_locked(cl_object_attr_guard(obj));
-
- top = obj->co_lu.lo_header;
- result = 0;
- list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) {
- if (obj->co_ops->coo_attr_get) {
- result = obj->co_ops->coo_attr_get(env, obj, attr);
- if (result != 0) {
- if (result > 0)
- result = 0;
- break;
- }
- }
- }
- return result;
-}
-EXPORT_SYMBOL(cl_object_attr_get);
-
-/**
- * Updates data-attributes of an object \a obj.
- *
- * Only attributes, mentioned in a validness bit-mask \a v are
- * updated. Calls cl_object_operations::coo_attr_update() on every layer,
- * bottom to top.
- */
-int cl_object_attr_update(const struct lu_env *env, struct cl_object *obj,
- const struct cl_attr *attr, unsigned int v)
-{
- struct lu_object_header *top;
- int result;
-
- assert_spin_locked(cl_object_attr_guard(obj));
-
- top = obj->co_lu.lo_header;
- result = 0;
- list_for_each_entry_reverse(obj, &top->loh_layers, co_lu.lo_linkage) {
- if (obj->co_ops->coo_attr_update) {
- result = obj->co_ops->coo_attr_update(env, obj, attr,
- v);
- if (result != 0) {
- if (result > 0)
- result = 0;
- break;
- }
- }
- }
- return result;
-}
-EXPORT_SYMBOL(cl_object_attr_update);
-
-/**
- * Notifies layers (bottom-to-top) that glimpse AST was received.
- *
- * Layers have to fill \a lvb fields with information that will be shipped
- * back to glimpse issuer.
- *
- * \see cl_lock_operations::clo_glimpse()
- */
-int cl_object_glimpse(const struct lu_env *env, struct cl_object *obj,
- struct ost_lvb *lvb)
-{
- struct lu_object_header *top;
- int result;
-
- top = obj->co_lu.lo_header;
- result = 0;
- list_for_each_entry_reverse(obj, &top->loh_layers, co_lu.lo_linkage) {
- if (obj->co_ops->coo_glimpse) {
- result = obj->co_ops->coo_glimpse(env, obj, lvb);
- if (result != 0)
- break;
- }
- }
- LU_OBJECT_HEADER(D_DLMTRACE, env, lu_object_top(top),
- "size: %llu mtime: %llu atime: %llu ctime: %llu blocks: %llu\n",
- lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime,
- lvb->lvb_ctime, lvb->lvb_blocks);
- return result;
-}
-EXPORT_SYMBOL(cl_object_glimpse);
-
-/**
- * Updates a configuration of an object \a obj.
- */
-int cl_conf_set(const struct lu_env *env, struct cl_object *obj,
- const struct cl_object_conf *conf)
-{
- struct lu_object_header *top;
- int result;
-
- top = obj->co_lu.lo_header;
- result = 0;
- list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) {
- if (obj->co_ops->coo_conf_set) {
- result = obj->co_ops->coo_conf_set(env, obj, conf);
- if (result != 0)
- break;
- }
- }
- return result;
-}
-EXPORT_SYMBOL(cl_conf_set);
-
-/**
- * Prunes caches of pages and locks for this object.
- */
-int cl_object_prune(const struct lu_env *env, struct cl_object *obj)
-{
- struct lu_object_header *top;
- struct cl_object *o;
- int result;
-
- top = obj->co_lu.lo_header;
- result = 0;
- list_for_each_entry(o, &top->loh_layers, co_lu.lo_linkage) {
- if (o->co_ops->coo_prune) {
- result = o->co_ops->coo_prune(env, o);
- if (result != 0)
- break;
- }
- }
-
- return result;
-}
-EXPORT_SYMBOL(cl_object_prune);
-
-/**
- * Get stripe information of this object.
- */
-int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj,
- struct lov_user_md __user *uarg)
-{
- struct lu_object_header *top;
- int result = 0;
-
- top = obj->co_lu.lo_header;
- list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) {
- if (obj->co_ops->coo_getstripe) {
- result = obj->co_ops->coo_getstripe(env, obj, uarg);
- if (result)
- break;
- }
- }
- return result;
-}
-EXPORT_SYMBOL(cl_object_getstripe);
-
-/**
- * Get fiemap extents from file object.
- *
- * \param env [in] lustre environment
- * \param obj [in] file object
- * \param key [in] fiemap request argument
- * \param fiemap [out] fiemap extents mapping retrived
- * \param buflen [in] max buffer length of @fiemap
- *
- * \retval 0 success
- * \retval < 0 error
- */
-int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj,
- struct ll_fiemap_info_key *key,
- struct fiemap *fiemap, size_t *buflen)
-{
- struct lu_object_header *top;
- int result = 0;
-
- top = obj->co_lu.lo_header;
- list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) {
- if (obj->co_ops->coo_fiemap) {
- result = obj->co_ops->coo_fiemap(env, obj, key, fiemap,
- buflen);
- if (result)
- break;
- }
- }
- return result;
-}
-EXPORT_SYMBOL(cl_object_fiemap);
-
-int cl_object_layout_get(const struct lu_env *env, struct cl_object *obj,
- struct cl_layout *cl)
-{
- struct lu_object_header *top = obj->co_lu.lo_header;
-
- list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) {
- if (obj->co_ops->coo_layout_get)
- return obj->co_ops->coo_layout_get(env, obj, cl);
- }
-
- return -EOPNOTSUPP;
-}
-EXPORT_SYMBOL(cl_object_layout_get);
-
-loff_t cl_object_maxbytes(struct cl_object *obj)
-{
- struct lu_object_header *top = obj->co_lu.lo_header;
- loff_t maxbytes = LLONG_MAX;
-
- list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) {
- if (obj->co_ops->coo_maxbytes)
- maxbytes = min_t(loff_t, obj->co_ops->coo_maxbytes(obj),
- maxbytes);
- }
-
- return maxbytes;
-}
-EXPORT_SYMBOL(cl_object_maxbytes);
-
-/**
- * Helper function removing all object locks, and marking object for
- * deletion. All object pages must have been deleted at this point.
- *
- * This is called by cl_inode_fini() and lov_object_delete() to destroy top-
- * and sub- objects respectively.
- */
-void cl_object_kill(const struct lu_env *env, struct cl_object *obj)
-{
- struct cl_object_header *hdr = cl_object_header(obj);
-
- set_bit(LU_OBJECT_HEARD_BANSHEE, &hdr->coh_lu.loh_flags);
-}
-EXPORT_SYMBOL(cl_object_kill);
-
-void cache_stats_init(struct cache_stats *cs, const char *name)
-{
- int i;
-
- cs->cs_name = name;
- for (i = 0; i < CS_NR; i++)
- atomic_set(&cs->cs_stats[i], 0);
-}
-
-static int cache_stats_print(const struct cache_stats *cs,
- struct seq_file *m, int h)
-{
- int i;
- /*
- * lookup hit total cached create
- * env: ...... ...... ...... ...... ......
- */
- if (h) {
- const char *names[CS_NR] = CS_NAMES;
-
- seq_printf(m, "%6s", " ");
- for (i = 0; i < CS_NR; i++)
- seq_printf(m, "%8s", names[i]);
- seq_printf(m, "\n");
- }
-
- seq_printf(m, "%5.5s:", cs->cs_name);
- for (i = 0; i < CS_NR; i++)
- seq_printf(m, "%8u", atomic_read(&cs->cs_stats[i]));
- return 0;
-}
-
-static void cl_env_percpu_refill(void);
-
-/**
- * Initialize client site.
- *
- * Perform common initialization (lu_site_init()), and initialize statistical
- * counters. Also perform global initializations on the first call.
- */
-int cl_site_init(struct cl_site *s, struct cl_device *d)
-{
- size_t i;
- int result;
-
- result = lu_site_init(&s->cs_lu, &d->cd_lu_dev);
- if (result == 0) {
- cache_stats_init(&s->cs_pages, "pages");
- for (i = 0; i < ARRAY_SIZE(s->cs_pages_state); ++i)
- atomic_set(&s->cs_pages_state[0], 0);
- cl_env_percpu_refill();
- }
- return result;
-}
-EXPORT_SYMBOL(cl_site_init);
-
-/**
- * Finalize client site. Dual to cl_site_init().
- */
-void cl_site_fini(struct cl_site *s)
-{
- lu_site_fini(&s->cs_lu);
-}
-EXPORT_SYMBOL(cl_site_fini);
-
-static struct cache_stats cl_env_stats = {
- .cs_name = "envs",
- .cs_stats = { ATOMIC_INIT(0), }
-};
-
-/**
- * Outputs client site statistical counters into a buffer. Suitable for
- * ll_rd_*()-style functions.
- */
-int cl_site_stats_print(const struct cl_site *site, struct seq_file *m)
-{
- size_t i;
- static const char * const pstate[] = {
- [CPS_CACHED] = "c",
- [CPS_OWNED] = "o",
- [CPS_PAGEOUT] = "w",
- [CPS_PAGEIN] = "r",
- [CPS_FREEING] = "f"
- };
-/*
- lookup hit total busy create
-pages: ...... ...... ...... ...... ...... [...... ...... ...... ......]
-locks: ...... ...... ...... ...... ...... [...... ...... ...... ...... ......]
- env: ...... ...... ...... ...... ......
- */
- lu_site_stats_print(&site->cs_lu, m);
- cache_stats_print(&site->cs_pages, m, 1);
- seq_puts(m, " [");
- for (i = 0; i < ARRAY_SIZE(site->cs_pages_state); ++i)
- seq_printf(m, "%s: %u ", pstate[i],
- atomic_read(&site->cs_pages_state[i]));
- seq_puts(m, "]\n");
- cache_stats_print(&cl_env_stats, m, 0);
- seq_puts(m, "\n");
- return 0;
-}
-EXPORT_SYMBOL(cl_site_stats_print);
-
-/*****************************************************************************
- *
- * lu_env handling on client.
- *
- */
-
-/**
- * The most efficient way is to store cl_env pointer in task specific
- * structures. On Linux, it wont' be easy to use task_struct->journal_info
- * because Lustre code may call into other fs which has certain assumptions
- * about journal_info. Currently following fields in task_struct are identified
- * can be used for this purpose:
- * - tux_info: only on RedHat kernel.
- * - ...
- * \note As long as we use task_struct to store cl_env, we assume that once
- * called into Lustre, we'll never call into the other part of the kernel
- * which will use those fields in task_struct without explicitly exiting
- * Lustre.
- *
- * If there's no space in task_struct is available, hash will be used.
- * bz20044, bz22683.
- */
-
-static unsigned int cl_envs_cached_max = 32; /* XXX: prototype: arbitrary limit
- * for now.
- */
-static struct cl_env_cache {
- rwlock_t cec_guard;
- unsigned int cec_count;
- struct list_head cec_envs;
-} *cl_envs = NULL;
-
-struct cl_env {
- void *ce_magic;
- struct lu_env ce_lu;
- struct lu_context ce_ses;
-
- /*
- * Linkage into global list of all client environments. Used for
- * garbage collection.
- */
- struct list_head ce_linkage;
- /*
- *
- */
- int ce_ref;
- /*
- * Debugging field: address of the caller who made original
- * allocation.
- */
- void *ce_debug;
-};
-
-#define CL_ENV_INC(counter)
-#define CL_ENV_DEC(counter)
-
-static void cl_env_init0(struct cl_env *cle, void *debug)
-{
- LASSERT(cle->ce_ref == 0);
- LASSERT(cle->ce_magic == &cl_env_init0);
- LASSERT(!cle->ce_debug);
-
- cle->ce_ref = 1;
- cle->ce_debug = debug;
- CL_ENV_INC(busy);
-}
-
-static struct lu_env *cl_env_new(__u32 ctx_tags, __u32 ses_tags, void *debug)
-{
- struct lu_env *env;
- struct cl_env *cle;
-
- cle = kmem_cache_zalloc(cl_env_kmem, GFP_NOFS);
- if (cle) {
- int rc;
-
- INIT_LIST_HEAD(&cle->ce_linkage);
- cle->ce_magic = &cl_env_init0;
- env = &cle->ce_lu;
- rc = lu_env_init(env, ctx_tags | LCT_CL_THREAD);
- if (rc == 0) {
- rc = lu_context_init(&cle->ce_ses,
- ses_tags | LCT_SESSION);
- if (rc == 0) {
- lu_context_enter(&cle->ce_ses);
- env->le_ses = &cle->ce_ses;
- cl_env_init0(cle, debug);
- } else {
- lu_env_fini(env);
- }
- }
- if (rc != 0) {
- kmem_cache_free(cl_env_kmem, cle);
- env = ERR_PTR(rc);
- } else {
- CL_ENV_INC(create);
- CL_ENV_INC(total);
- }
- } else {
- env = ERR_PTR(-ENOMEM);
- }
- return env;
-}
-
-static void cl_env_fini(struct cl_env *cle)
-{
- CL_ENV_DEC(total);
- lu_context_fini(&cle->ce_lu.le_ctx);
- lu_context_fini(&cle->ce_ses);
- kmem_cache_free(cl_env_kmem, cle);
-}
-
-static struct lu_env *cl_env_obtain(void *debug)
-{
- struct cl_env *cle;
- struct lu_env *env;
- int cpu = get_cpu();
-
- read_lock(&cl_envs[cpu].cec_guard);
- LASSERT(equi(cl_envs[cpu].cec_count == 0,
- list_empty(&cl_envs[cpu].cec_envs)));
- if (cl_envs[cpu].cec_count > 0) {
- int rc;
-
- cle = container_of(cl_envs[cpu].cec_envs.next, struct cl_env,
- ce_linkage);
- list_del_init(&cle->ce_linkage);
- cl_envs[cpu].cec_count--;
- read_unlock(&cl_envs[cpu].cec_guard);
- put_cpu();
-
- env = &cle->ce_lu;
- rc = lu_env_refill(env);
- if (rc == 0) {
- cl_env_init0(cle, debug);
- lu_context_enter(&env->le_ctx);
- lu_context_enter(&cle->ce_ses);
- } else {
- cl_env_fini(cle);
- env = ERR_PTR(rc);
- }
- } else {
- read_unlock(&cl_envs[cpu].cec_guard);
- put_cpu();
- env = cl_env_new(lu_context_tags_default,
- lu_session_tags_default, debug);
- }
- return env;
-}
-
-static inline struct cl_env *cl_env_container(struct lu_env *env)
-{
- return container_of(env, struct cl_env, ce_lu);
-}
-
-/**
- * Returns lu_env: if there already is an environment associated with the
- * current thread, it is returned, otherwise, new environment is allocated.
- *
- * Allocations are amortized through the global cache of environments.
- *
- * \param refcheck pointer to a counter used to detect environment leaks. In
- * the usual case cl_env_get() and cl_env_put() are called in the same lexical
- * scope and pointer to the same integer is passed as \a refcheck. This is
- * used to detect missed cl_env_put().
- *
- * \see cl_env_put()
- */
-struct lu_env *cl_env_get(u16 *refcheck)
-{
- struct lu_env *env;
-
- env = cl_env_obtain(__builtin_return_address(0));
- if (!IS_ERR(env)) {
- struct cl_env *cle;
-
- cle = cl_env_container(env);
- *refcheck = cle->ce_ref;
- CDEBUG(D_OTHER, "%d@%p\n", cle->ce_ref, cle);
- }
- return env;
-}
-EXPORT_SYMBOL(cl_env_get);
-
-/**
- * Forces an allocation of a fresh environment with given tags.
- *
- * \see cl_env_get()
- */
-struct lu_env *cl_env_alloc(u16 *refcheck, u32 tags)
-{
- struct lu_env *env;
-
- env = cl_env_new(tags, tags, __builtin_return_address(0));
- if (!IS_ERR(env)) {
- struct cl_env *cle;
-
- cle = cl_env_container(env);
- *refcheck = cle->ce_ref;
- CDEBUG(D_OTHER, "%d@%p\n", cle->ce_ref, cle);
- }
- return env;
-}
-EXPORT_SYMBOL(cl_env_alloc);
-
-static void cl_env_exit(struct cl_env *cle)
-{
- lu_context_exit(&cle->ce_lu.le_ctx);
- lu_context_exit(&cle->ce_ses);
-}
-
-/**
- * Finalizes and frees a given number of cached environments. This is done to
- * (1) free some memory (not currently hooked into VM), or (2) release
- * references to modules.
- */
-unsigned int cl_env_cache_purge(unsigned int nr)
-{
- struct cl_env *cle;
- unsigned int i;
-
- for_each_possible_cpu(i) {
- write_lock(&cl_envs[i].cec_guard);
- for (; !list_empty(&cl_envs[i].cec_envs) && nr > 0; --nr) {
- cle = container_of(cl_envs[i].cec_envs.next,
- struct cl_env, ce_linkage);
- list_del_init(&cle->ce_linkage);
- LASSERT(cl_envs[i].cec_count > 0);
- cl_envs[i].cec_count--;
- write_unlock(&cl_envs[i].cec_guard);
-
- cl_env_fini(cle);
- write_lock(&cl_envs[i].cec_guard);
- }
- LASSERT(equi(cl_envs[i].cec_count == 0,
- list_empty(&cl_envs[i].cec_envs)));
- write_unlock(&cl_envs[i].cec_guard);
- }
- return nr;
-}
-EXPORT_SYMBOL(cl_env_cache_purge);
-
-/**
- * Release an environment.
- *
- * Decrement \a env reference counter. When counter drops to 0, nothing in
- * this thread is using environment and it is returned to the allocation
- * cache, or freed straight away, if cache is large enough.
- */
-void cl_env_put(struct lu_env *env, u16 *refcheck)
-{
- struct cl_env *cle;
-
- cle = cl_env_container(env);
-
- LASSERT(cle->ce_ref > 0);
- LASSERT(ergo(refcheck, cle->ce_ref == *refcheck));
-
- CDEBUG(D_OTHER, "%d@%p\n", cle->ce_ref, cle);
- if (--cle->ce_ref == 0) {
- int cpu = get_cpu();
-
- CL_ENV_DEC(busy);
- cle->ce_debug = NULL;
- cl_env_exit(cle);
- /*
- * Don't bother to take a lock here.
- *
- * Return environment to the cache only when it was allocated
- * with the standard tags.
- */
- if (cl_envs[cpu].cec_count < cl_envs_cached_max &&
- (env->le_ctx.lc_tags & ~LCT_HAS_EXIT) == LCT_CL_THREAD &&
- (env->le_ses->lc_tags & ~LCT_HAS_EXIT) == LCT_SESSION) {
- read_lock(&cl_envs[cpu].cec_guard);
- list_add(&cle->ce_linkage, &cl_envs[cpu].cec_envs);
- cl_envs[cpu].cec_count++;
- read_unlock(&cl_envs[cpu].cec_guard);
- } else {
- cl_env_fini(cle);
- }
- put_cpu();
- }
-}
-EXPORT_SYMBOL(cl_env_put);
-
-/**
- * Converts struct ost_lvb to struct cl_attr.
- *
- * \see cl_attr2lvb
- */
-void cl_lvb2attr(struct cl_attr *attr, const struct ost_lvb *lvb)
-{
- attr->cat_size = lvb->lvb_size;
- attr->cat_mtime = lvb->lvb_mtime;
- attr->cat_atime = lvb->lvb_atime;
- attr->cat_ctime = lvb->lvb_ctime;
- attr->cat_blocks = lvb->lvb_blocks;
-}
-EXPORT_SYMBOL(cl_lvb2attr);
-
-static struct cl_env cl_env_percpu[NR_CPUS];
-
-static int cl_env_percpu_init(void)
-{
- struct cl_env *cle;
- int tags = LCT_REMEMBER | LCT_NOREF;
- int i, j;
- int rc = 0;
-
- for_each_possible_cpu(i) {
- struct lu_env *env;
-
- rwlock_init(&cl_envs[i].cec_guard);
- INIT_LIST_HEAD(&cl_envs[i].cec_envs);
- cl_envs[i].cec_count = 0;
-
- cle = &cl_env_percpu[i];
- env = &cle->ce_lu;
-
- INIT_LIST_HEAD(&cle->ce_linkage);
- cle->ce_magic = &cl_env_init0;
- rc = lu_env_init(env, LCT_CL_THREAD | tags);
- if (rc == 0) {
- rc = lu_context_init(&cle->ce_ses, LCT_SESSION | tags);
- if (rc == 0) {
- lu_context_enter(&cle->ce_ses);
- env->le_ses = &cle->ce_ses;
- } else {
- lu_env_fini(env);
- }
- }
- if (rc != 0)
- break;
- }
- if (rc != 0) {
- /* Indices 0 to i (excluding i) were correctly initialized,
- * thus we must uninitialize up to i, the rest are undefined.
- */
- for (j = 0; j < i; j++) {
- cle = &cl_env_percpu[j];
- lu_context_exit(&cle->ce_ses);
- lu_context_fini(&cle->ce_ses);
- lu_env_fini(&cle->ce_lu);
- }
- }
-
- return rc;
-}
-
-static void cl_env_percpu_fini(void)
-{
- int i;
-
- for_each_possible_cpu(i) {
- struct cl_env *cle = &cl_env_percpu[i];
-
- lu_context_exit(&cle->ce_ses);
- lu_context_fini(&cle->ce_ses);
- lu_env_fini(&cle->ce_lu);
- }
-}
-
-static void cl_env_percpu_refill(void)
-{
- int i;
-
- for_each_possible_cpu(i)
- lu_env_refill(&cl_env_percpu[i].ce_lu);
-}
-
-void cl_env_percpu_put(struct lu_env *env)
-{
- struct cl_env *cle;
- int cpu;
-
- cpu = smp_processor_id();
- cle = cl_env_container(env);
- LASSERT(cle == &cl_env_percpu[cpu]);
-
- cle->ce_ref--;
- LASSERT(cle->ce_ref == 0);
-
- CL_ENV_DEC(busy);
- cle->ce_debug = NULL;
-
- put_cpu();
-}
-EXPORT_SYMBOL(cl_env_percpu_put);
-
-struct lu_env *cl_env_percpu_get(void)
-{
- struct cl_env *cle;
-
- cle = &cl_env_percpu[get_cpu()];
- cl_env_init0(cle, __builtin_return_address(0));
-
- return &cle->ce_lu;
-}
-EXPORT_SYMBOL(cl_env_percpu_get);
-
-/*****************************************************************************
- *
- * Temporary prototype thing: mirror obd-devices into cl devices.
- *
- */
-
-struct cl_device *cl_type_setup(const struct lu_env *env, struct lu_site *site,
- struct lu_device_type *ldt,
- struct lu_device *next)
-{
- const char *typename;
- struct lu_device *d;
-
- typename = ldt->ldt_name;
- d = ldt->ldt_ops->ldto_device_alloc(env, ldt, NULL);
- if (!IS_ERR(d)) {
- int rc;
-
- if (site)
- d->ld_site = site;
- rc = ldt->ldt_ops->ldto_device_init(env, d, typename, next);
- if (rc == 0) {
- lu_device_get(d);
- lu_ref_add(&d->ld_reference,
- "lu-stack", &lu_site_init);
- } else {
- ldt->ldt_ops->ldto_device_free(env, d);
- CERROR("can't init device '%s', %d\n", typename, rc);
- d = ERR_PTR(rc);
- }
- } else {
- CERROR("Cannot allocate device: '%s'\n", typename);
- }
- return lu2cl_dev(d);
-}
-EXPORT_SYMBOL(cl_type_setup);
-
-/**
- * Finalize device stack by calling lu_stack_fini().
- */
-void cl_stack_fini(const struct lu_env *env, struct cl_device *cl)
-{
- lu_stack_fini(env, cl2lu_dev(cl));
-}
-EXPORT_SYMBOL(cl_stack_fini);
-
-static struct lu_context_key cl_key;
-
-struct cl_thread_info *cl_env_info(const struct lu_env *env)
-{
- return lu_context_key_get(&env->le_ctx, &cl_key);
-}
-
-/* defines cl0_key_{init,fini}() */
-LU_KEY_INIT_FINI(cl0, struct cl_thread_info);
-
-static void *cl_key_init(const struct lu_context *ctx,
- struct lu_context_key *key)
-{
- return cl0_key_init(ctx, key);
-}
-
-static void cl_key_fini(const struct lu_context *ctx,
- struct lu_context_key *key, void *data)
-{
- cl0_key_fini(ctx, key, data);
-}
-
-static struct lu_context_key cl_key = {
- .lct_tags = LCT_CL_THREAD,
- .lct_init = cl_key_init,
- .lct_fini = cl_key_fini,
-};
-
-static struct lu_kmem_descr cl_object_caches[] = {
- {
- .ckd_cache = &cl_env_kmem,
- .ckd_name = "cl_env_kmem",
- .ckd_size = sizeof(struct cl_env)
- },
- {
- .ckd_cache = NULL
- }
-};
-
-/**
- * Global initialization of cl-data. Create kmem caches, register
- * lu_context_key's, etc.
- *
- * \see cl_global_fini()
- */
-int cl_global_init(void)
-{
- int result;
-
- cl_envs = kcalloc(num_possible_cpus(), sizeof(*cl_envs), GFP_KERNEL);
- if (!cl_envs) {
- result = -ENOMEM;
- goto out;
- }
-
- result = lu_kmem_init(cl_object_caches);
- if (result)
- goto out_envs;
-
- LU_CONTEXT_KEY_INIT(&cl_key);
- result = lu_context_key_register(&cl_key);
- if (result)
- goto out_kmem;
-
- result = cl_env_percpu_init();
- if (result)
- /* no cl_env_percpu_fini on error */
- goto out_keys;
-
- return 0;
-
-out_keys:
- lu_context_key_degister(&cl_key);
-out_kmem:
- lu_kmem_fini(cl_object_caches);
-out_envs:
- kfree(cl_envs);
-out:
- return result;
-}
-
-/**
- * Finalization of global cl-data. Dual to cl_global_init().
- */
-void cl_global_fini(void)
-{
- cl_env_percpu_fini();
- lu_context_key_degister(&cl_key);
- lu_kmem_fini(cl_object_caches);
- kfree(cl_envs);
-}
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c
deleted file mode 100644
index d3b25667bc3a..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/cl_page.c
+++ /dev/null
@@ -1,1046 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * Client Lustre Page.
- *
- * Author: Nikita Danilov <nikita.danilov@sun.com>
- * Author: Jinshan Xiong <jinshan.xiong@intel.com>
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/libcfs/libcfs.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <linux/list.h>
-
-#include <cl_object.h>
-#include "cl_internal.h"
-
-static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg);
-
-# define PASSERT(env, page, expr) \
- do { \
- if (unlikely(!(expr))) { \
- CL_PAGE_DEBUG(D_ERROR, (env), (page), #expr "\n"); \
- LASSERT(0); \
- } \
- } while (0)
-
-# define PINVRNT(env, page, exp) \
- ((void)sizeof(env), (void)sizeof(page), (void)sizeof !!(exp))
-
-/**
- * Internal version of cl_page_get().
- *
- * This function can be used to obtain initial reference to previously
- * unreferenced cached object. It can be called only if concurrent page
- * reclamation is somehow prevented, e.g., by keeping a lock on a VM page,
- * associated with \a page.
- *
- * Use with care! Not exported.
- */
-static void cl_page_get_trust(struct cl_page *page)
-{
- LASSERT(atomic_read(&page->cp_ref) > 0);
- atomic_inc(&page->cp_ref);
-}
-
-/**
- * Returns a slice within a page, corresponding to the given layer in the
- * device stack.
- *
- * \see cl_lock_at()
- */
-static const struct cl_page_slice *
-cl_page_at_trusted(const struct cl_page *page,
- const struct lu_device_type *dtype)
-{
- const struct cl_page_slice *slice;
-
- list_for_each_entry(slice, &page->cp_layers, cpl_linkage) {
- if (slice->cpl_obj->co_lu.lo_dev->ld_type == dtype)
- return slice;
- }
- return NULL;
-}
-
-static void cl_page_free(const struct lu_env *env, struct cl_page *page)
-{
- struct cl_object *obj = page->cp_obj;
-
- PASSERT(env, page, list_empty(&page->cp_batch));
- PASSERT(env, page, !page->cp_owner);
- PASSERT(env, page, page->cp_state == CPS_FREEING);
-
- while (!list_empty(&page->cp_layers)) {
- struct cl_page_slice *slice;
-
- slice = list_entry(page->cp_layers.next,
- struct cl_page_slice, cpl_linkage);
- list_del_init(page->cp_layers.next);
- if (unlikely(slice->cpl_ops->cpo_fini))
- slice->cpl_ops->cpo_fini(env, slice);
- }
- lu_object_ref_del_at(&obj->co_lu, &page->cp_obj_ref, "cl_page", page);
- cl_object_put(env, obj);
- lu_ref_fini(&page->cp_reference);
- kfree(page);
-}
-
-/**
- * Helper function updating page state. This is the only place in the code
- * where cl_page::cp_state field is mutated.
- */
-static inline void cl_page_state_set_trust(struct cl_page *page,
- enum cl_page_state state)
-{
- /* bypass const. */
- *(enum cl_page_state *)&page->cp_state = state;
-}
-
-struct cl_page *cl_page_alloc(const struct lu_env *env,
- struct cl_object *o, pgoff_t ind,
- struct page *vmpage,
- enum cl_page_type type)
-{
- struct cl_page *page;
- struct lu_object_header *head;
-
- page = kzalloc(cl_object_header(o)->coh_page_bufsize, GFP_NOFS);
- if (page) {
- int result = 0;
-
- atomic_set(&page->cp_ref, 1);
- page->cp_obj = o;
- cl_object_get(o);
- lu_object_ref_add_at(&o->co_lu, &page->cp_obj_ref, "cl_page",
- page);
- page->cp_vmpage = vmpage;
- cl_page_state_set_trust(page, CPS_CACHED);
- page->cp_type = type;
- INIT_LIST_HEAD(&page->cp_layers);
- INIT_LIST_HEAD(&page->cp_batch);
- lu_ref_init(&page->cp_reference);
- head = o->co_lu.lo_header;
- list_for_each_entry(o, &head->loh_layers, co_lu.lo_linkage) {
- if (o->co_ops->coo_page_init) {
- result = o->co_ops->coo_page_init(env, o, page,
- ind);
- if (result != 0) {
- cl_page_delete0(env, page);
- cl_page_free(env, page);
- page = ERR_PTR(result);
- break;
- }
- }
- }
- } else {
- page = ERR_PTR(-ENOMEM);
- }
- return page;
-}
-
-/**
- * Returns a cl_page with index \a idx at the object \a o, and associated with
- * the VM page \a vmpage.
- *
- * This is the main entry point into the cl_page caching interface. First, a
- * cache (implemented as a per-object radix tree) is consulted. If page is
- * found there, it is returned immediately. Otherwise new page is allocated
- * and returned. In any case, additional reference to page is acquired.
- *
- * \see cl_object_find(), cl_lock_find()
- */
-struct cl_page *cl_page_find(const struct lu_env *env,
- struct cl_object *o,
- pgoff_t idx, struct page *vmpage,
- enum cl_page_type type)
-{
- struct cl_page *page = NULL;
- struct cl_object_header *hdr;
-
- LASSERT(type == CPT_CACHEABLE || type == CPT_TRANSIENT);
- might_sleep();
-
- hdr = cl_object_header(o);
-
- CDEBUG(D_PAGE, "%lu@" DFID " %p %lx %d\n",
- idx, PFID(&hdr->coh_lu.loh_fid), vmpage, vmpage->private, type);
- /* fast path. */
- if (type == CPT_CACHEABLE) {
- /*
- * vmpage lock is used to protect the child/parent
- * relationship
- */
- LASSERT(PageLocked(vmpage));
- /*
- * cl_vmpage_page() can be called here without any locks as
- *
- * - "vmpage" is locked (which prevents ->private from
- * concurrent updates), and
- *
- * - "o" cannot be destroyed while current thread holds a
- * reference on it.
- */
- page = cl_vmpage_page(vmpage, o);
-
- if (page)
- return page;
- }
-
- /* allocate and initialize cl_page */
- page = cl_page_alloc(env, o, idx, vmpage, type);
- return page;
-}
-EXPORT_SYMBOL(cl_page_find);
-
-static inline int cl_page_invariant(const struct cl_page *pg)
-{
- return cl_page_in_use_noref(pg);
-}
-
-static void cl_page_state_set0(const struct lu_env *env,
- struct cl_page *page, enum cl_page_state state)
-{
- enum cl_page_state old;
-
- /*
- * Matrix of allowed state transitions [old][new], for sanity
- * checking.
- */
- static const int allowed_transitions[CPS_NR][CPS_NR] = {
- [CPS_CACHED] = {
- [CPS_CACHED] = 0,
- [CPS_OWNED] = 1, /* io finds existing cached page */
- [CPS_PAGEIN] = 0,
- [CPS_PAGEOUT] = 1, /* write-out from the cache */
- [CPS_FREEING] = 1, /* eviction on the memory pressure */
- },
- [CPS_OWNED] = {
- [CPS_CACHED] = 1, /* release to the cache */
- [CPS_OWNED] = 0,
- [CPS_PAGEIN] = 1, /* start read immediately */
- [CPS_PAGEOUT] = 1, /* start write immediately */
- [CPS_FREEING] = 1, /* lock invalidation or truncate */
- },
- [CPS_PAGEIN] = {
- [CPS_CACHED] = 1, /* io completion */
- [CPS_OWNED] = 0,
- [CPS_PAGEIN] = 0,
- [CPS_PAGEOUT] = 0,
- [CPS_FREEING] = 0,
- },
- [CPS_PAGEOUT] = {
- [CPS_CACHED] = 1, /* io completion */
- [CPS_OWNED] = 0,
- [CPS_PAGEIN] = 0,
- [CPS_PAGEOUT] = 0,
- [CPS_FREEING] = 0,
- },
- [CPS_FREEING] = {
- [CPS_CACHED] = 0,
- [CPS_OWNED] = 0,
- [CPS_PAGEIN] = 0,
- [CPS_PAGEOUT] = 0,
- [CPS_FREEING] = 0,
- }
- };
-
- old = page->cp_state;
- PASSERT(env, page, allowed_transitions[old][state]);
- CL_PAGE_HEADER(D_TRACE, env, page, "%d -> %d\n", old, state);
- PASSERT(env, page, page->cp_state == old);
- PASSERT(env, page, equi(state == CPS_OWNED, page->cp_owner));
- cl_page_state_set_trust(page, state);
-}
-
-static void cl_page_state_set(const struct lu_env *env,
- struct cl_page *page, enum cl_page_state state)
-{
- cl_page_state_set0(env, page, state);
-}
-
-/**
- * Acquires an additional reference to a page.
- *
- * This can be called only by caller already possessing a reference to \a
- * page.
- *
- * \see cl_object_get(), cl_lock_get().
- */
-void cl_page_get(struct cl_page *page)
-{
- cl_page_get_trust(page);
-}
-EXPORT_SYMBOL(cl_page_get);
-
-/**
- * Releases a reference to a page.
- *
- * When last reference is released, page is returned to the cache, unless it
- * is in cl_page_state::CPS_FREEING state, in which case it is immediately
- * destroyed.
- *
- * \see cl_object_put(), cl_lock_put().
- */
-void cl_page_put(const struct lu_env *env, struct cl_page *page)
-{
- CL_PAGE_HEADER(D_TRACE, env, page, "%d\n",
- atomic_read(&page->cp_ref));
-
- if (atomic_dec_and_test(&page->cp_ref)) {
- LASSERT(page->cp_state == CPS_FREEING);
-
- LASSERT(atomic_read(&page->cp_ref) == 0);
- PASSERT(env, page, !page->cp_owner);
- PASSERT(env, page, list_empty(&page->cp_batch));
- /*
- * Page is no longer reachable by other threads. Tear
- * it down.
- */
- cl_page_free(env, page);
- }
-}
-EXPORT_SYMBOL(cl_page_put);
-
-/**
- * Returns a cl_page associated with a VM page, and given cl_object.
- */
-struct cl_page *cl_vmpage_page(struct page *vmpage, struct cl_object *obj)
-{
- struct cl_page *page;
-
- LASSERT(PageLocked(vmpage));
-
- /*
- * NOTE: absence of races and liveness of data are guaranteed by page
- * lock on a "vmpage". That works because object destruction has
- * bottom-to-top pass.
- */
-
- page = (struct cl_page *)vmpage->private;
- if (page) {
- cl_page_get_trust(page);
- LASSERT(page->cp_type == CPT_CACHEABLE);
- }
- return page;
-}
-EXPORT_SYMBOL(cl_vmpage_page);
-
-const struct cl_page_slice *cl_page_at(const struct cl_page *page,
- const struct lu_device_type *dtype)
-{
- return cl_page_at_trusted(page, dtype);
-}
-EXPORT_SYMBOL(cl_page_at);
-
-#define CL_PAGE_OP(opname) offsetof(struct cl_page_operations, opname)
-
-#define CL_PAGE_INVOKE(_env, _page, _op, _proto, ...) \
-({ \
- const struct lu_env *__env = (_env); \
- struct cl_page *__page = (_page); \
- const struct cl_page_slice *__scan; \
- int __result; \
- ptrdiff_t __op = (_op); \
- int (*__method)_proto; \
- \
- __result = 0; \
- list_for_each_entry(__scan, &__page->cp_layers, cpl_linkage) { \
- __method = *(void **)((char *)__scan->cpl_ops + __op); \
- if (__method) { \
- __result = (*__method)(__env, __scan, ## __VA_ARGS__); \
- if (__result != 0) \
- break; \
- } \
- } \
- if (__result > 0) \
- __result = 0; \
- __result; \
-})
-
-#define CL_PAGE_INVOID(_env, _page, _op, _proto, ...) \
-do { \
- const struct lu_env *__env = (_env); \
- struct cl_page *__page = (_page); \
- const struct cl_page_slice *__scan; \
- ptrdiff_t __op = (_op); \
- void (*__method)_proto; \
- \
- list_for_each_entry(__scan, &__page->cp_layers, cpl_linkage) { \
- __method = *(void **)((char *)__scan->cpl_ops + __op); \
- if (__method) \
- (*__method)(__env, __scan, ## __VA_ARGS__); \
- } \
-} while (0)
-
-#define CL_PAGE_INVOID_REVERSE(_env, _page, _op, _proto, ...) \
-do { \
- const struct lu_env *__env = (_env); \
- struct cl_page *__page = (_page); \
- const struct cl_page_slice *__scan; \
- ptrdiff_t __op = (_op); \
- void (*__method)_proto; \
- \
- list_for_each_entry_reverse(__scan, &__page->cp_layers, cpl_linkage) { \
- __method = *(void **)((char *)__scan->cpl_ops + __op); \
- if (__method) \
- (*__method)(__env, __scan, ## __VA_ARGS__); \
- } \
-} while (0)
-
-static int cl_page_invoke(const struct lu_env *env,
- struct cl_io *io, struct cl_page *page, ptrdiff_t op)
-
-{
- PINVRNT(env, page, cl_object_same(page->cp_obj, io->ci_obj));
- return CL_PAGE_INVOKE(env, page, op,
- (const struct lu_env *,
- const struct cl_page_slice *, struct cl_io *),
- io);
-}
-
-static void cl_page_invoid(const struct lu_env *env,
- struct cl_io *io, struct cl_page *page, ptrdiff_t op)
-
-{
- PINVRNT(env, page, cl_object_same(page->cp_obj, io->ci_obj));
- CL_PAGE_INVOID(env, page, op,
- (const struct lu_env *,
- const struct cl_page_slice *, struct cl_io *), io);
-}
-
-static void cl_page_owner_clear(struct cl_page *page)
-{
- if (page->cp_owner) {
- LASSERT(page->cp_owner->ci_owned_nr > 0);
- page->cp_owner->ci_owned_nr--;
- page->cp_owner = NULL;
- }
-}
-
-static void cl_page_owner_set(struct cl_page *page)
-{
- page->cp_owner->ci_owned_nr++;
-}
-
-void cl_page_disown0(const struct lu_env *env,
- struct cl_io *io, struct cl_page *pg)
-{
- enum cl_page_state state;
-
- state = pg->cp_state;
- PINVRNT(env, pg, state == CPS_OWNED || state == CPS_FREEING);
- PINVRNT(env, pg, cl_page_invariant(pg) || state == CPS_FREEING);
- cl_page_owner_clear(pg);
-
- if (state == CPS_OWNED)
- cl_page_state_set(env, pg, CPS_CACHED);
- /*
- * Completion call-backs are executed in the bottom-up order, so that
- * uppermost layer (llite), responsible for VFS/VM interaction runs
- * last and can release locks safely.
- */
- CL_PAGE_INVOID_REVERSE(env, pg, CL_PAGE_OP(cpo_disown),
- (const struct lu_env *,
- const struct cl_page_slice *, struct cl_io *),
- io);
-}
-
-/**
- * returns true, iff page is owned by the given io.
- */
-int cl_page_is_owned(const struct cl_page *pg, const struct cl_io *io)
-{
- struct cl_io *top = cl_io_top((struct cl_io *)io);
-
- LINVRNT(cl_object_same(pg->cp_obj, io->ci_obj));
- return pg->cp_state == CPS_OWNED && pg->cp_owner == top;
-}
-EXPORT_SYMBOL(cl_page_is_owned);
-
-/**
- * Try to own a page by IO.
- *
- * Waits until page is in cl_page_state::CPS_CACHED state, and then switch it
- * into cl_page_state::CPS_OWNED state.
- *
- * \pre !cl_page_is_owned(pg, io)
- * \post result == 0 iff cl_page_is_owned(pg, io)
- *
- * \retval 0 success
- *
- * \retval -ve failure, e.g., page was destroyed (and landed in
- * cl_page_state::CPS_FREEING instead of cl_page_state::CPS_CACHED).
- * or, page was owned by another thread, or in IO.
- *
- * \see cl_page_disown()
- * \see cl_page_operations::cpo_own()
- * \see cl_page_own_try()
- * \see cl_page_own
- */
-static int cl_page_own0(const struct lu_env *env, struct cl_io *io,
- struct cl_page *pg, int nonblock)
-{
- int result;
-
- PINVRNT(env, pg, !cl_page_is_owned(pg, io));
-
- io = cl_io_top(io);
-
- if (pg->cp_state == CPS_FREEING) {
- result = -ENOENT;
- } else {
- result = CL_PAGE_INVOKE(env, pg, CL_PAGE_OP(cpo_own),
- (const struct lu_env *,
- const struct cl_page_slice *,
- struct cl_io *, int),
- io, nonblock);
- if (result == 0) {
- PASSERT(env, pg, !pg->cp_owner);
- pg->cp_owner = cl_io_top(io);
- cl_page_owner_set(pg);
- if (pg->cp_state != CPS_FREEING) {
- cl_page_state_set(env, pg, CPS_OWNED);
- } else {
- cl_page_disown0(env, io, pg);
- result = -ENOENT;
- }
- }
- }
- PINVRNT(env, pg, ergo(result == 0, cl_page_invariant(pg)));
- return result;
-}
-
-/**
- * Own a page, might be blocked.
- *
- * \see cl_page_own0()
- */
-int cl_page_own(const struct lu_env *env, struct cl_io *io, struct cl_page *pg)
-{
- return cl_page_own0(env, io, pg, 0);
-}
-EXPORT_SYMBOL(cl_page_own);
-
-/**
- * Nonblock version of cl_page_own().
- *
- * \see cl_page_own0()
- */
-int cl_page_own_try(const struct lu_env *env, struct cl_io *io,
- struct cl_page *pg)
-{
- return cl_page_own0(env, io, pg, 1);
-}
-EXPORT_SYMBOL(cl_page_own_try);
-
-/**
- * Assume page ownership.
- *
- * Called when page is already locked by the hosting VM.
- *
- * \pre !cl_page_is_owned(pg, io)
- * \post cl_page_is_owned(pg, io)
- *
- * \see cl_page_operations::cpo_assume()
- */
-void cl_page_assume(const struct lu_env *env,
- struct cl_io *io, struct cl_page *pg)
-{
- PINVRNT(env, pg, cl_object_same(pg->cp_obj, io->ci_obj));
-
- io = cl_io_top(io);
-
- cl_page_invoid(env, io, pg, CL_PAGE_OP(cpo_assume));
- PASSERT(env, pg, !pg->cp_owner);
- pg->cp_owner = cl_io_top(io);
- cl_page_owner_set(pg);
- cl_page_state_set(env, pg, CPS_OWNED);
-}
-EXPORT_SYMBOL(cl_page_assume);
-
-/**
- * Releases page ownership without unlocking the page.
- *
- * Moves page into cl_page_state::CPS_CACHED without releasing a lock on the
- * underlying VM page (as VM is supposed to do this itself).
- *
- * \pre cl_page_is_owned(pg, io)
- * \post !cl_page_is_owned(pg, io)
- *
- * \see cl_page_assume()
- */
-void cl_page_unassume(const struct lu_env *env,
- struct cl_io *io, struct cl_page *pg)
-{
- PINVRNT(env, pg, cl_page_is_owned(pg, io));
- PINVRNT(env, pg, cl_page_invariant(pg));
-
- io = cl_io_top(io);
- cl_page_owner_clear(pg);
- cl_page_state_set(env, pg, CPS_CACHED);
- CL_PAGE_INVOID_REVERSE(env, pg, CL_PAGE_OP(cpo_unassume),
- (const struct lu_env *,
- const struct cl_page_slice *, struct cl_io *),
- io);
-}
-EXPORT_SYMBOL(cl_page_unassume);
-
-/**
- * Releases page ownership.
- *
- * Moves page into cl_page_state::CPS_CACHED.
- *
- * \pre cl_page_is_owned(pg, io)
- * \post !cl_page_is_owned(pg, io)
- *
- * \see cl_page_own()
- * \see cl_page_operations::cpo_disown()
- */
-void cl_page_disown(const struct lu_env *env,
- struct cl_io *io, struct cl_page *pg)
-{
- PINVRNT(env, pg, cl_page_is_owned(pg, io) ||
- pg->cp_state == CPS_FREEING);
-
- io = cl_io_top(io);
- cl_page_disown0(env, io, pg);
-}
-EXPORT_SYMBOL(cl_page_disown);
-
-/**
- * Called when page is to be removed from the object, e.g., as a result of
- * truncate.
- *
- * Calls cl_page_operations::cpo_discard() top-to-bottom.
- *
- * \pre cl_page_is_owned(pg, io)
- *
- * \see cl_page_operations::cpo_discard()
- */
-void cl_page_discard(const struct lu_env *env,
- struct cl_io *io, struct cl_page *pg)
-{
- PINVRNT(env, pg, cl_page_is_owned(pg, io));
- PINVRNT(env, pg, cl_page_invariant(pg));
-
- cl_page_invoid(env, io, pg, CL_PAGE_OP(cpo_discard));
-}
-EXPORT_SYMBOL(cl_page_discard);
-
-/**
- * Version of cl_page_delete() that can be called for not fully constructed
- * pages, e.g,. in a error handling cl_page_find()->cl_page_delete0()
- * path. Doesn't check page invariant.
- */
-static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg)
-{
- PASSERT(env, pg, pg->cp_state != CPS_FREEING);
-
- /*
- * Sever all ways to obtain new pointers to @pg.
- */
- cl_page_owner_clear(pg);
-
- cl_page_state_set0(env, pg, CPS_FREEING);
-
- CL_PAGE_INVOID_REVERSE(env, pg, CL_PAGE_OP(cpo_delete),
- (const struct lu_env *,
- const struct cl_page_slice *));
-}
-
-/**
- * Called when a decision is made to throw page out of memory.
- *
- * Notifies all layers about page destruction by calling
- * cl_page_operations::cpo_delete() method top-to-bottom.
- *
- * Moves page into cl_page_state::CPS_FREEING state (this is the only place
- * where transition to this state happens).
- *
- * Eliminates all venues through which new references to the page can be
- * obtained:
- *
- * - removes page from the radix trees,
- *
- * - breaks linkage from VM page to cl_page.
- *
- * Once page reaches cl_page_state::CPS_FREEING, all remaining references will
- * drain after some time, at which point page will be recycled.
- *
- * \pre VM page is locked
- * \post pg->cp_state == CPS_FREEING
- *
- * \see cl_page_operations::cpo_delete()
- */
-void cl_page_delete(const struct lu_env *env, struct cl_page *pg)
-{
- PINVRNT(env, pg, cl_page_invariant(pg));
- cl_page_delete0(env, pg);
-}
-EXPORT_SYMBOL(cl_page_delete);
-
-/**
- * Marks page up-to-date.
- *
- * Call cl_page_operations::cpo_export() through all layers top-to-bottom. The
- * layer responsible for VM interaction has to mark/clear page as up-to-date
- * by the \a uptodate argument.
- *
- * \see cl_page_operations::cpo_export()
- */
-void cl_page_export(const struct lu_env *env, struct cl_page *pg, int uptodate)
-{
- PINVRNT(env, pg, cl_page_invariant(pg));
- CL_PAGE_INVOID(env, pg, CL_PAGE_OP(cpo_export),
- (const struct lu_env *,
- const struct cl_page_slice *, int), uptodate);
-}
-EXPORT_SYMBOL(cl_page_export);
-
-/**
- * Returns true, iff \a pg is VM locked in a suitable sense by the calling
- * thread.
- */
-int cl_page_is_vmlocked(const struct lu_env *env, const struct cl_page *pg)
-{
- int result;
- const struct cl_page_slice *slice;
-
- slice = container_of(pg->cp_layers.next,
- const struct cl_page_slice, cpl_linkage);
- PASSERT(env, pg, slice->cpl_ops->cpo_is_vmlocked);
- /*
- * Call ->cpo_is_vmlocked() directly instead of going through
- * CL_PAGE_INVOKE(), because cl_page_is_vmlocked() is used by
- * cl_page_invariant().
- */
- result = slice->cpl_ops->cpo_is_vmlocked(env, slice);
- PASSERT(env, pg, result == -EBUSY || result == -ENODATA);
- return result == -EBUSY;
-}
-EXPORT_SYMBOL(cl_page_is_vmlocked);
-
-static enum cl_page_state cl_req_type_state(enum cl_req_type crt)
-{
- return crt == CRT_WRITE ? CPS_PAGEOUT : CPS_PAGEIN;
-}
-
-static void cl_page_io_start(const struct lu_env *env,
- struct cl_page *pg, enum cl_req_type crt)
-{
- /*
- * Page is queued for IO, change its state.
- */
- cl_page_owner_clear(pg);
- cl_page_state_set(env, pg, cl_req_type_state(crt));
-}
-
-/**
- * Prepares page for immediate transfer. cl_page_operations::cpo_prep() is
- * called top-to-bottom. Every layer either agrees to submit this page (by
- * returning 0), or requests to omit this page (by returning -EALREADY). Layer
- * handling interactions with the VM also has to inform VM that page is under
- * transfer now.
- */
-int cl_page_prep(const struct lu_env *env, struct cl_io *io,
- struct cl_page *pg, enum cl_req_type crt)
-{
- int result;
-
- PINVRNT(env, pg, cl_page_is_owned(pg, io));
- PINVRNT(env, pg, cl_page_invariant(pg));
- PINVRNT(env, pg, crt < CRT_NR);
-
- /*
- * XXX this has to be called bottom-to-top, so that llite can set up
- * PG_writeback without risking other layers deciding to skip this
- * page.
- */
- if (crt >= CRT_NR)
- return -EINVAL;
- result = cl_page_invoke(env, io, pg, CL_PAGE_OP(io[crt].cpo_prep));
- if (result == 0)
- cl_page_io_start(env, pg, crt);
-
- CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, result);
- return result;
-}
-EXPORT_SYMBOL(cl_page_prep);
-
-/**
- * Notify layers about transfer completion.
- *
- * Invoked by transfer sub-system (which is a part of osc) to notify layers
- * that a transfer, of which this page is a part of has completed.
- *
- * Completion call-backs are executed in the bottom-up order, so that
- * uppermost layer (llite), responsible for the VFS/VM interaction runs last
- * and can release locks safely.
- *
- * \pre pg->cp_state == CPS_PAGEIN || pg->cp_state == CPS_PAGEOUT
- * \post pg->cp_state == CPS_CACHED
- *
- * \see cl_page_operations::cpo_completion()
- */
-void cl_page_completion(const struct lu_env *env,
- struct cl_page *pg, enum cl_req_type crt, int ioret)
-{
- struct cl_sync_io *anchor = pg->cp_sync_io;
-
- PASSERT(env, pg, crt < CRT_NR);
- PASSERT(env, pg, pg->cp_state == cl_req_type_state(crt));
-
- CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, ioret);
-
- cl_page_state_set(env, pg, CPS_CACHED);
- if (crt >= CRT_NR)
- return;
- CL_PAGE_INVOID_REVERSE(env, pg, CL_PAGE_OP(io[crt].cpo_completion),
- (const struct lu_env *,
- const struct cl_page_slice *, int), ioret);
- if (anchor) {
- LASSERT(pg->cp_sync_io == anchor);
- pg->cp_sync_io = NULL;
- cl_sync_io_note(env, anchor, ioret);
- }
-}
-EXPORT_SYMBOL(cl_page_completion);
-
-/**
- * Notify layers that transfer formation engine decided to yank this page from
- * the cache and to make it a part of a transfer.
- *
- * \pre pg->cp_state == CPS_CACHED
- * \post pg->cp_state == CPS_PAGEIN || pg->cp_state == CPS_PAGEOUT
- *
- * \see cl_page_operations::cpo_make_ready()
- */
-int cl_page_make_ready(const struct lu_env *env, struct cl_page *pg,
- enum cl_req_type crt)
-{
- int result;
-
- PINVRNT(env, pg, crt < CRT_NR);
-
- if (crt >= CRT_NR)
- return -EINVAL;
- result = CL_PAGE_INVOKE(env, pg, CL_PAGE_OP(io[crt].cpo_make_ready),
- (const struct lu_env *,
- const struct cl_page_slice *));
- if (result == 0) {
- PASSERT(env, pg, pg->cp_state == CPS_CACHED);
- cl_page_io_start(env, pg, crt);
- }
- CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, result);
- return result;
-}
-EXPORT_SYMBOL(cl_page_make_ready);
-
-/**
- * Called if a pge is being written back by kernel's intention.
- *
- * \pre cl_page_is_owned(pg, io)
- * \post ergo(result == 0, pg->cp_state == CPS_PAGEOUT)
- *
- * \see cl_page_operations::cpo_flush()
- */
-int cl_page_flush(const struct lu_env *env, struct cl_io *io,
- struct cl_page *pg)
-{
- int result;
-
- PINVRNT(env, pg, cl_page_is_owned(pg, io));
- PINVRNT(env, pg, cl_page_invariant(pg));
-
- result = cl_page_invoke(env, io, pg, CL_PAGE_OP(cpo_flush));
-
- CL_PAGE_HEADER(D_TRACE, env, pg, "%d\n", result);
- return result;
-}
-EXPORT_SYMBOL(cl_page_flush);
-
-/**
- * Tells transfer engine that only part of a page is to be transmitted.
- *
- * \see cl_page_operations::cpo_clip()
- */
-void cl_page_clip(const struct lu_env *env, struct cl_page *pg,
- int from, int to)
-{
- PINVRNT(env, pg, cl_page_invariant(pg));
-
- CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", from, to);
- CL_PAGE_INVOID(env, pg, CL_PAGE_OP(cpo_clip),
- (const struct lu_env *,
- const struct cl_page_slice *, int, int),
- from, to);
-}
-EXPORT_SYMBOL(cl_page_clip);
-
-/**
- * Prints human readable representation of \a pg to the \a f.
- */
-void cl_page_header_print(const struct lu_env *env, void *cookie,
- lu_printer_t printer, const struct cl_page *pg)
-{
- (*printer)(env, cookie,
- "page@%p[%d %p %d %d %p]\n",
- pg, atomic_read(&pg->cp_ref), pg->cp_obj,
- pg->cp_state, pg->cp_type,
- pg->cp_owner);
-}
-EXPORT_SYMBOL(cl_page_header_print);
-
-/**
- * Prints human readable representation of \a pg to the \a f.
- */
-void cl_page_print(const struct lu_env *env, void *cookie,
- lu_printer_t printer, const struct cl_page *pg)
-{
- cl_page_header_print(env, cookie, printer, pg);
- CL_PAGE_INVOKE(env, (struct cl_page *)pg, CL_PAGE_OP(cpo_print),
- (const struct lu_env *env,
- const struct cl_page_slice *slice,
- void *cookie, lu_printer_t p), cookie, printer);
- (*printer)(env, cookie, "end page@%p\n", pg);
-}
-EXPORT_SYMBOL(cl_page_print);
-
-/**
- * Cancel a page which is still in a transfer.
- */
-int cl_page_cancel(const struct lu_env *env, struct cl_page *page)
-{
- return CL_PAGE_INVOKE(env, page, CL_PAGE_OP(cpo_cancel),
- (const struct lu_env *,
- const struct cl_page_slice *));
-}
-
-/**
- * Converts a byte offset within object \a obj into a page index.
- */
-loff_t cl_offset(const struct cl_object *obj, pgoff_t idx)
-{
- /*
- * XXX for now.
- */
- return (loff_t)idx << PAGE_SHIFT;
-}
-EXPORT_SYMBOL(cl_offset);
-
-/**
- * Converts a page index into a byte offset within object \a obj.
- */
-pgoff_t cl_index(const struct cl_object *obj, loff_t offset)
-{
- /*
- * XXX for now.
- */
- return offset >> PAGE_SHIFT;
-}
-EXPORT_SYMBOL(cl_index);
-
-size_t cl_page_size(const struct cl_object *obj)
-{
- return 1UL << PAGE_SHIFT;
-}
-EXPORT_SYMBOL(cl_page_size);
-
-/**
- * Adds page slice to the compound page.
- *
- * This is called by cl_object_operations::coo_page_init() methods to add a
- * per-layer state to the page. New state is added at the end of
- * cl_page::cp_layers list, that is, it is at the bottom of the stack.
- *
- * \see cl_lock_slice_add(), cl_req_slice_add(), cl_io_slice_add()
- */
-void cl_page_slice_add(struct cl_page *page, struct cl_page_slice *slice,
- struct cl_object *obj, pgoff_t index,
- const struct cl_page_operations *ops)
-{
- list_add_tail(&slice->cpl_linkage, &page->cp_layers);
- slice->cpl_obj = obj;
- slice->cpl_index = index;
- slice->cpl_ops = ops;
- slice->cpl_page = page;
-}
-EXPORT_SYMBOL(cl_page_slice_add);
-
-/**
- * Allocate and initialize cl_cache, called by ll_init_sbi().
- */
-struct cl_client_cache *cl_cache_init(unsigned long lru_page_max)
-{
- struct cl_client_cache *cache = NULL;
-
- cache = kzalloc(sizeof(*cache), GFP_KERNEL);
- if (!cache)
- return NULL;
-
- /* Initialize cache data */
- atomic_set(&cache->ccc_users, 1);
- cache->ccc_lru_max = lru_page_max;
- atomic_long_set(&cache->ccc_lru_left, lru_page_max);
- spin_lock_init(&cache->ccc_lru_lock);
- INIT_LIST_HEAD(&cache->ccc_lru);
-
- atomic_long_set(&cache->ccc_unstable_nr, 0);
- init_waitqueue_head(&cache->ccc_unstable_waitq);
-
- return cache;
-}
-EXPORT_SYMBOL(cl_cache_init);
-
-/**
- * Increase cl_cache refcount
- */
-void cl_cache_incref(struct cl_client_cache *cache)
-{
- atomic_inc(&cache->ccc_users);
-}
-EXPORT_SYMBOL(cl_cache_incref);
-
-/**
- * Decrease cl_cache refcount and free the cache if refcount=0.
- * Since llite, lov and osc all hold cl_cache refcount,
- * the free will not cause race. (LU-6173)
- */
-void cl_cache_decref(struct cl_client_cache *cache)
-{
- if (atomic_dec_and_test(&cache->ccc_users))
- kfree(cache);
-}
-EXPORT_SYMBOL(cl_cache_decref);
diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c
deleted file mode 100644
index 3e24b76f6301..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/class_obd.c
+++ /dev/null
@@ -1,535 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-# include <linux/atomic.h>
-
-#include <obd_support.h>
-#include <obd_class.h>
-#include <uapi/linux/lnet/lnetctl.h>
-#include <lustre_debug.h>
-#include <lprocfs_status.h>
-#include <linux/list.h>
-#include <cl_object.h>
-#include <uapi/linux/lustre/lustre_ioctl.h>
-#include "llog_internal.h"
-
-struct obd_device *obd_devs[MAX_OBD_DEVICES];
-struct list_head obd_types;
-DEFINE_RWLOCK(obd_dev_lock);
-
-/* The following are visible and mutable through /sys/fs/lustre. */
-unsigned int obd_debug_peer_on_timeout;
-EXPORT_SYMBOL(obd_debug_peer_on_timeout);
-unsigned int obd_dump_on_timeout;
-EXPORT_SYMBOL(obd_dump_on_timeout);
-unsigned int obd_dump_on_eviction;
-EXPORT_SYMBOL(obd_dump_on_eviction);
-unsigned long obd_max_dirty_pages;
-EXPORT_SYMBOL(obd_max_dirty_pages);
-atomic_long_t obd_dirty_pages;
-EXPORT_SYMBOL(obd_dirty_pages);
-unsigned int obd_timeout = OBD_TIMEOUT_DEFAULT; /* seconds */
-EXPORT_SYMBOL(obd_timeout);
-unsigned int obd_timeout_set;
-EXPORT_SYMBOL(obd_timeout_set);
-/* Adaptive timeout defs here instead of ptlrpc module for /sys/fs/ access */
-unsigned int at_min;
-EXPORT_SYMBOL(at_min);
-unsigned int at_max = 600;
-EXPORT_SYMBOL(at_max);
-unsigned int at_history = 600;
-EXPORT_SYMBOL(at_history);
-int at_early_margin = 5;
-EXPORT_SYMBOL(at_early_margin);
-int at_extra = 30;
-EXPORT_SYMBOL(at_extra);
-
-atomic_long_t obd_dirty_transit_pages;
-EXPORT_SYMBOL(obd_dirty_transit_pages);
-
-char obd_jobid_var[JOBSTATS_JOBID_VAR_MAX_LEN + 1] = JOBSTATS_DISABLE;
-char obd_jobid_node[LUSTRE_JOBID_SIZE + 1];
-
-/* Get jobid of current process from stored variable or calculate
- * it from pid and user_id.
- *
- * Historically this was also done by reading the environment variable
- * stored in between the "env_start" & "env_end" of task struct.
- * This is now deprecated.
- */
-int lustre_get_jobid(char *jobid)
-{
- memset(jobid, 0, LUSTRE_JOBID_SIZE);
- /* Jobstats isn't enabled */
- if (strcmp(obd_jobid_var, JOBSTATS_DISABLE) == 0)
- return 0;
-
- /* Use process name + fsuid as jobid */
- if (strcmp(obd_jobid_var, JOBSTATS_PROCNAME_UID) == 0) {
- snprintf(jobid, LUSTRE_JOBID_SIZE, "%s.%u",
- current_comm(),
- from_kuid(&init_user_ns, current_fsuid()));
- return 0;
- }
-
- /* Whole node dedicated to single job */
- if (strcmp(obd_jobid_var, JOBSTATS_NODELOCAL) == 0) {
- strcpy(jobid, obd_jobid_node);
- return 0;
- }
-
- return -ENOENT;
-}
-EXPORT_SYMBOL(lustre_get_jobid);
-
-static int class_resolve_dev_name(__u32 len, const char *name)
-{
- int rc;
- int dev;
-
- if (!len || !name) {
- CERROR("No name passed,!\n");
- rc = -EINVAL;
- goto out;
- }
- if (name[len - 1] != 0) {
- CERROR("Name not nul terminated!\n");
- rc = -EINVAL;
- goto out;
- }
-
- CDEBUG(D_IOCTL, "device name %s\n", name);
- dev = class_name2dev(name);
- if (dev == -1) {
- CDEBUG(D_IOCTL, "No device for name %s!\n", name);
- rc = -EINVAL;
- goto out;
- }
-
- CDEBUG(D_IOCTL, "device name %s, dev %d\n", name, dev);
- rc = dev;
-
-out:
- return rc;
-}
-
-int class_handle_ioctl(unsigned int cmd, unsigned long arg)
-{
- char *buf = NULL;
- struct obd_ioctl_data *data;
- struct libcfs_debug_ioctl_data *debug_data;
- struct obd_device *obd = NULL;
- int err = 0, len = 0;
-
- /* only for debugging */
- if (cmd == LIBCFS_IOC_DEBUG_MASK) {
- debug_data = (struct libcfs_debug_ioctl_data *)arg;
- libcfs_subsystem_debug = debug_data->subs;
- libcfs_debug = debug_data->debug;
- return 0;
- }
-
- CDEBUG(D_IOCTL, "cmd = %x\n", cmd);
- if (obd_ioctl_getdata(&buf, &len, (void __user *)arg)) {
- CERROR("OBD ioctl: data error\n");
- return -EINVAL;
- }
- data = (struct obd_ioctl_data *)buf;
-
- switch (cmd) {
- case OBD_IOC_PROCESS_CFG: {
- struct lustre_cfg *lcfg;
-
- if (!data->ioc_plen1 || !data->ioc_pbuf1) {
- CERROR("No config buffer passed!\n");
- err = -EINVAL;
- goto out;
- }
- lcfg = kzalloc(data->ioc_plen1, GFP_NOFS);
- if (!lcfg) {
- err = -ENOMEM;
- goto out;
- }
- if (copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1))
- err = -EFAULT;
- if (!err)
- err = lustre_cfg_sanity_check(lcfg, data->ioc_plen1);
- if (!err)
- err = class_process_config(lcfg);
-
- kfree(lcfg);
- goto out;
- }
-
- case OBD_GET_VERSION:
- if (!data->ioc_inlbuf1) {
- CERROR("No buffer passed in ioctl\n");
- err = -EINVAL;
- goto out;
- }
-
- if (strlen(LUSTRE_VERSION_STRING) + 1 > data->ioc_inllen1) {
- CERROR("ioctl buffer too small to hold version\n");
- err = -EINVAL;
- goto out;
- }
-
- memcpy(data->ioc_bulk, LUSTRE_VERSION_STRING,
- strlen(LUSTRE_VERSION_STRING) + 1);
-
- if (copy_to_user((void __user *)arg, data, len))
- err = -EFAULT;
- goto out;
-
- case OBD_IOC_NAME2DEV: {
- /* Resolve a device name. This does not change the
- * currently selected device.
- */
- int dev;
-
- dev = class_resolve_dev_name(data->ioc_inllen1,
- data->ioc_inlbuf1);
- data->ioc_dev = dev;
- if (dev < 0) {
- err = -EINVAL;
- goto out;
- }
-
- if (copy_to_user((void __user *)arg, data, sizeof(*data)))
- err = -EFAULT;
- goto out;
- }
-
- case OBD_IOC_UUID2DEV: {
- /* Resolve a device uuid. This does not change the
- * currently selected device.
- */
- int dev;
- struct obd_uuid uuid;
-
- if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
- CERROR("No UUID passed!\n");
- err = -EINVAL;
- goto out;
- }
- if (data->ioc_inlbuf1[data->ioc_inllen1 - 1] != 0) {
- CERROR("UUID not NUL terminated!\n");
- err = -EINVAL;
- goto out;
- }
-
- CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
- obd_str2uuid(&uuid, data->ioc_inlbuf1);
- dev = class_uuid2dev(&uuid);
- data->ioc_dev = dev;
- if (dev == -1) {
- CDEBUG(D_IOCTL, "No device for UUID %s!\n",
- data->ioc_inlbuf1);
- err = -EINVAL;
- goto out;
- }
-
- CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
- dev);
-
- if (copy_to_user((void __user *)arg, data, sizeof(*data)))
- err = -EFAULT;
- goto out;
- }
-
- case OBD_IOC_GETDEVICE: {
- int index = data->ioc_count;
- char *status, *str;
-
- if (!data->ioc_inlbuf1) {
- CERROR("No buffer passed in ioctl\n");
- err = -EINVAL;
- goto out;
- }
- if (data->ioc_inllen1 < 128) {
- CERROR("ioctl buffer too small to hold version\n");
- err = -EINVAL;
- goto out;
- }
-
- obd = class_num2obd(index);
- if (!obd) {
- err = -ENOENT;
- goto out;
- }
-
- if (obd->obd_stopping)
- status = "ST";
- else if (obd->obd_set_up)
- status = "UP";
- else if (obd->obd_attached)
- status = "AT";
- else
- status = "--";
- str = (char *)data->ioc_bulk;
- snprintf(str, len - sizeof(*data), "%3d %s %s %s %s %d",
- (int)index, status, obd->obd_type->typ_name,
- obd->obd_name, obd->obd_uuid.uuid,
- atomic_read(&obd->obd_refcount));
-
- if (copy_to_user((void __user *)arg, data, len))
- err = -EFAULT;
- goto out;
- }
- }
-
- if (data->ioc_dev == OBD_DEV_BY_DEVNAME) {
- if (data->ioc_inllen4 <= 0 || !data->ioc_inlbuf4) {
- err = -EINVAL;
- goto out;
- }
- if (strnlen(data->ioc_inlbuf4, MAX_OBD_NAME) >= MAX_OBD_NAME) {
- err = -EINVAL;
- goto out;
- }
- obd = class_name2obd(data->ioc_inlbuf4);
- } else if (data->ioc_dev < class_devno_max()) {
- obd = class_num2obd(data->ioc_dev);
- } else {
- CERROR("OBD ioctl: No device\n");
- err = -EINVAL;
- goto out;
- }
-
- if (!obd) {
- CERROR("OBD ioctl : No Device %d\n", data->ioc_dev);
- err = -EINVAL;
- goto out;
- }
- LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
-
- if (!obd->obd_set_up || obd->obd_stopping) {
- CERROR("OBD ioctl: device not setup %d\n", data->ioc_dev);
- err = -EINVAL;
- goto out;
- }
-
- switch (cmd) {
- case OBD_IOC_NO_TRANSNO: {
- if (!obd->obd_attached) {
- CERROR("Device %d not attached\n", obd->obd_minor);
- err = -ENODEV;
- goto out;
- }
- CDEBUG(D_HA, "%s: disabling committed-transno notification\n",
- obd->obd_name);
- obd->obd_no_transno = 1;
- err = 0;
- goto out;
- }
-
- default: {
- err = obd_iocontrol(cmd, obd->obd_self_export, len, data, NULL);
- if (err)
- goto out;
-
- if (copy_to_user((void __user *)arg, data, len))
- err = -EFAULT;
- goto out;
- }
- }
-
- out:
- kvfree(buf);
- return err;
-} /* class_handle_ioctl */
-
-#define OBD_INIT_CHECK
-static int obd_init_checks(void)
-{
- __u64 u64val, div64val;
- char buf[64];
- int len, ret = 0;
-
- CDEBUG(D_INFO, "LPU64=%s, LPD64=%s, LPX64=%s\n", "%llu", "%lld",
- "%#llx");
-
- CDEBUG(D_INFO, "OBD_OBJECT_EOF = %#llx\n", (__u64)OBD_OBJECT_EOF);
-
- u64val = OBD_OBJECT_EOF;
- CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = %#llx\n", u64val);
- if (u64val != OBD_OBJECT_EOF) {
- CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
- u64val, (int)sizeof(u64val));
- ret = -EINVAL;
- }
- len = snprintf(buf, sizeof(buf), "%#llx", u64val);
- if (len != 18) {
- CWARN("LPX64 wrong length! strlen(%s)=%d != 18\n", buf, len);
- ret = -EINVAL;
- }
-
- div64val = OBD_OBJECT_EOF;
- CDEBUG(D_INFO, "u64val OBD_OBJECT_EOF = %#llx\n", u64val);
- if (u64val != OBD_OBJECT_EOF) {
- CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
- u64val, (int)sizeof(u64val));
- ret = -EOVERFLOW;
- }
- if (u64val >> 8 != OBD_OBJECT_EOF >> 8) {
- CERROR("__u64 %#llx(%d) != 0xffffffffffffffff\n",
- u64val, (int)sizeof(u64val));
- return -EOVERFLOW;
- }
- if (do_div(div64val, 256) != (u64val & 255)) {
- CERROR("do_div(%#llx,256) != %llu\n", u64val, u64val & 255);
- return -EOVERFLOW;
- }
- if (u64val >> 8 != div64val) {
- CERROR("do_div(%#llx,256) %llu != %llu\n",
- u64val, div64val, u64val >> 8);
- return -EOVERFLOW;
- }
- len = snprintf(buf, sizeof(buf), "%#llx", u64val);
- if (len != 18) {
- CWARN("LPX64 wrong length! strlen(%s)=%d != 18\n", buf, len);
- ret = -EINVAL;
- }
- len = snprintf(buf, sizeof(buf), "%llu", u64val);
- if (len != 20) {
- CWARN("LPU64 wrong length! strlen(%s)=%d != 20\n", buf, len);
- ret = -EINVAL;
- }
- len = snprintf(buf, sizeof(buf), "%lld", u64val);
- if (len != 2) {
- CWARN("LPD64 wrong length! strlen(%s)=%d != 2\n", buf, len);
- ret = -EINVAL;
- }
- if ((u64val & ~PAGE_MASK) >= PAGE_SIZE) {
- CWARN("mask failed: u64val %llu >= %llu\n", u64val,
- (__u64)PAGE_SIZE);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int __init obdclass_init(void)
-{
- int i, err;
-
- LCONSOLE_INFO("Lustre: Build Version: " LUSTRE_VERSION_STRING "\n");
-
- spin_lock_init(&obd_types_lock);
- obd_zombie_impexp_init();
-
- err = obd_init_checks();
- if (err)
- return err;
-
- class_init_uuidlist();
- err = class_handle_init();
- if (err)
- return err;
-
- INIT_LIST_HEAD(&obd_types);
-
- err = misc_register(&obd_psdev);
- if (err) {
- CERROR("cannot register %d err %d\n", OBD_DEV_MINOR, err);
- return err;
- }
-
- /* This struct is already zeroed for us (static global) */
- for (i = 0; i < class_devno_max(); i++)
- obd_devs[i] = NULL;
-
- /* Default the dirty page cache cap to 1/2 of system memory.
- * For clients with less memory, a larger fraction is needed
- * for other purposes (mostly for BGL).
- */
- if (totalram_pages <= 512 << (20 - PAGE_SHIFT))
- obd_max_dirty_pages = totalram_pages / 4;
- else
- obd_max_dirty_pages = totalram_pages / 2;
-
- err = obd_init_caches();
- if (err)
- return err;
-
- err = class_procfs_init();
- if (err)
- return err;
-
- err = obd_sysctl_init();
- if (err)
- return err;
-
- err = lu_global_init();
- if (err)
- return err;
-
- err = cl_global_init();
- if (err != 0)
- return err;
-
- err = llog_info_init();
- if (err)
- return err;
-
- err = lustre_register_fs();
-
- return err;
-}
-
-static void obdclass_exit(void)
-{
- lustre_unregister_fs();
-
- misc_deregister(&obd_psdev);
- llog_info_fini();
- cl_global_fini();
- lu_global_fini();
-
- obd_cleanup_caches();
-
- class_procfs_clean();
-
- class_handle_cleanup();
- class_exit_uuidlist();
- obd_zombie_impexp_stop();
-}
-
-MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
-MODULE_DESCRIPTION("Lustre Class Driver");
-MODULE_VERSION(LUSTRE_VERSION_STRING);
-MODULE_LICENSE("GPL");
-
-module_init(obdclass_init);
-module_exit(obdclass_exit);
diff --git a/drivers/staging/lustre/lustre/obdclass/debug.c b/drivers/staging/lustre/lustre/obdclass/debug.c
deleted file mode 100644
index 2156a82a613a..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/debug.c
+++ /dev/null
@@ -1,96 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/debug.c
- *
- * Helper routines for dumping data structs for debugging.
- */
-
-#define DEBUG_SUBSYSTEM D_OTHER
-
-#include <asm/unaligned.h>
-
-#include <obd_support.h>
-#include <lustre_debug.h>
-#include <lustre_net.h>
-
-#define LPDS sizeof(__u64)
-int block_debug_setup(void *addr, int len, __u64 off, __u64 id)
-{
- LASSERT(addr);
-
- put_unaligned_le64(off, addr);
- put_unaligned_le64(id, addr + LPDS);
- addr += len - LPDS - LPDS;
- put_unaligned_le64(off, addr);
- put_unaligned_le64(id, addr + LPDS);
-
- return 0;
-}
-EXPORT_SYMBOL(block_debug_setup);
-
-int block_debug_check(char *who, void *addr, int end, __u64 off, __u64 id)
-{
- __u64 ne_off;
- int err = 0;
-
- LASSERT(addr);
-
- ne_off = le64_to_cpu(off);
- id = le64_to_cpu(id);
- if (memcmp(addr, (char *)&ne_off, LPDS)) {
- CDEBUG(D_ERROR, "%s: id %#llx offset %llu off: %#llx != %#llx\n",
- who, id, off, *(__u64 *)addr, ne_off);
- err = -EINVAL;
- }
- if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
- CDEBUG(D_ERROR, "%s: id %#llx offset %llu id: %#llx != %#llx\n",
- who, id, off, *(__u64 *)(addr + LPDS), id);
- err = -EINVAL;
- }
-
- addr += end - LPDS - LPDS;
- if (memcmp(addr, (char *)&ne_off, LPDS)) {
- CDEBUG(D_ERROR, "%s: id %#llx offset %llu end off: %#llx != %#llx\n",
- who, id, off, *(__u64 *)addr, ne_off);
- err = -EINVAL;
- }
- if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
- CDEBUG(D_ERROR, "%s: id %#llx offset %llu end id: %#llx != %#llx\n",
- who, id, off, *(__u64 *)(addr + LPDS), id);
- err = -EINVAL;
- }
-
- return err;
-}
-EXPORT_SYMBOL(block_debug_check);
-#undef LPDS
diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c
deleted file mode 100644
index 63ccbabb4c5a..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/genops.c
+++ /dev/null
@@ -1,1514 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/genops.c
- *
- * These are the only exported functions, they provide some generic
- * infrastructure for managing object devices
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-#include <obd_class.h>
-#include <lprocfs_status.h>
-#include <lustre_kernelcomm.h>
-
-spinlock_t obd_types_lock;
-
-static struct kmem_cache *obd_device_cachep;
-struct kmem_cache *obdo_cachep;
-EXPORT_SYMBOL(obdo_cachep);
-static struct kmem_cache *import_cachep;
-
-static struct workqueue_struct *zombie_wq;
-static void obd_zombie_export_add(struct obd_export *exp);
-static void obd_zombie_import_add(struct obd_import *imp);
-
-int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
-EXPORT_SYMBOL(ptlrpc_put_connection_superhack);
-
-/*
- * support functions: we could use inter-module communication, but this
- * is more portable to other OS's
- */
-static struct obd_device *obd_device_alloc(void)
-{
- struct obd_device *obd;
-
- obd = kmem_cache_zalloc(obd_device_cachep, GFP_NOFS);
- if (obd)
- obd->obd_magic = OBD_DEVICE_MAGIC;
- return obd;
-}
-
-static void obd_device_free(struct obd_device *obd)
-{
- LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "obd %p obd_magic %08x != %08x\n",
- obd, obd->obd_magic, OBD_DEVICE_MAGIC);
- if (obd->obd_namespace) {
- CERROR("obd %p: namespace %p was not properly cleaned up (obd_force=%d)!\n",
- obd, obd->obd_namespace, obd->obd_force);
- LBUG();
- }
- lu_ref_fini(&obd->obd_reference);
- kmem_cache_free(obd_device_cachep, obd);
-}
-
-static struct obd_type *class_search_type(const char *name)
-{
- struct list_head *tmp;
- struct obd_type *type;
-
- spin_lock(&obd_types_lock);
- list_for_each(tmp, &obd_types) {
- type = list_entry(tmp, struct obd_type, typ_chain);
- if (strcmp(type->typ_name, name) == 0) {
- spin_unlock(&obd_types_lock);
- return type;
- }
- }
- spin_unlock(&obd_types_lock);
- return NULL;
-}
-
-static struct obd_type *class_get_type(const char *name)
-{
- struct obd_type *type = class_search_type(name);
-
- if (!type) {
- const char *modname = name;
-
- if (!request_module("%s", modname)) {
- CDEBUG(D_INFO, "Loaded module '%s'\n", modname);
- type = class_search_type(name);
- } else {
- LCONSOLE_ERROR_MSG(0x158, "Can't load module '%s'\n",
- modname);
- }
- }
- if (type) {
- spin_lock(&type->obd_type_lock);
- type->typ_refcnt++;
- try_module_get(type->typ_dt_ops->owner);
- spin_unlock(&type->obd_type_lock);
- }
- return type;
-}
-
-void class_put_type(struct obd_type *type)
-{
- LASSERT(type);
- spin_lock(&type->obd_type_lock);
- type->typ_refcnt--;
- module_put(type->typ_dt_ops->owner);
- spin_unlock(&type->obd_type_lock);
-}
-
-#define CLASS_MAX_NAME 1024
-
-int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
- const char *name,
- struct lu_device_type *ldt)
-{
- struct obd_type *type;
- int rc;
-
- /* sanity check */
- LASSERT(strnlen(name, CLASS_MAX_NAME) < CLASS_MAX_NAME);
-
- if (class_search_type(name)) {
- CDEBUG(D_IOCTL, "Type %s already registered\n", name);
- return -EEXIST;
- }
-
- rc = -ENOMEM;
- type = kzalloc(sizeof(*type), GFP_NOFS);
- if (!type)
- return rc;
-
- type->typ_dt_ops = kzalloc(sizeof(*type->typ_dt_ops), GFP_NOFS);
- type->typ_md_ops = kzalloc(sizeof(*type->typ_md_ops), GFP_NOFS);
- type->typ_name = kzalloc(strlen(name) + 1, GFP_NOFS);
-
- if (!type->typ_dt_ops ||
- !type->typ_md_ops ||
- !type->typ_name)
- goto failed;
-
- *type->typ_dt_ops = *dt_ops;
- /* md_ops is optional */
- if (md_ops)
- *type->typ_md_ops = *md_ops;
- strcpy(type->typ_name, name);
- spin_lock_init(&type->obd_type_lock);
-
- type->typ_debugfs_entry = ldebugfs_register(type->typ_name,
- debugfs_lustre_root,
- NULL, type);
- if (IS_ERR_OR_NULL(type->typ_debugfs_entry)) {
- rc = type->typ_debugfs_entry ? PTR_ERR(type->typ_debugfs_entry)
- : -ENOMEM;
- type->typ_debugfs_entry = NULL;
- goto failed;
- }
-
- type->typ_kobj = kobject_create_and_add(type->typ_name, lustre_kobj);
- if (!type->typ_kobj) {
- rc = -ENOMEM;
- goto failed;
- }
-
- if (ldt) {
- type->typ_lu = ldt;
- rc = lu_device_type_init(ldt);
- if (rc != 0)
- goto failed;
- }
-
- spin_lock(&obd_types_lock);
- list_add(&type->typ_chain, &obd_types);
- spin_unlock(&obd_types_lock);
-
- return 0;
-
- failed:
- if (type->typ_kobj)
- kobject_put(type->typ_kobj);
- kfree(type->typ_name);
- kfree(type->typ_md_ops);
- kfree(type->typ_dt_ops);
- kfree(type);
- return rc;
-}
-EXPORT_SYMBOL(class_register_type);
-
-int class_unregister_type(const char *name)
-{
- struct obd_type *type = class_search_type(name);
-
- if (!type) {
- CERROR("unknown obd type\n");
- return -EINVAL;
- }
-
- if (type->typ_refcnt) {
- CERROR("type %s has refcount (%d)\n", name, type->typ_refcnt);
- /* This is a bad situation, let's make the best of it */
- /* Remove ops, but leave the name for debugging */
- kfree(type->typ_dt_ops);
- kfree(type->typ_md_ops);
- return -EBUSY;
- }
-
- if (type->typ_kobj)
- kobject_put(type->typ_kobj);
-
- if (!IS_ERR_OR_NULL(type->typ_debugfs_entry))
- ldebugfs_remove(&type->typ_debugfs_entry);
-
- if (type->typ_lu)
- lu_device_type_fini(type->typ_lu);
-
- spin_lock(&obd_types_lock);
- list_del(&type->typ_chain);
- spin_unlock(&obd_types_lock);
- kfree(type->typ_name);
- kfree(type->typ_dt_ops);
- kfree(type->typ_md_ops);
- kfree(type);
- return 0;
-} /* class_unregister_type */
-EXPORT_SYMBOL(class_unregister_type);
-
-/**
- * Create a new obd device.
- *
- * Find an empty slot in ::obd_devs[], create a new obd device in it.
- *
- * \param[in] type_name obd device type string.
- * \param[in] name obd device name.
- *
- * \retval NULL if create fails, otherwise return the obd device
- * pointer created.
- */
-struct obd_device *class_newdev(const char *type_name, const char *name)
-{
- struct obd_device *result = NULL;
- struct obd_device *newdev;
- struct obd_type *type = NULL;
- int i;
- int new_obd_minor = 0;
-
- if (strlen(name) >= MAX_OBD_NAME) {
- CERROR("name/uuid must be < %u bytes long\n", MAX_OBD_NAME);
- return ERR_PTR(-EINVAL);
- }
-
- type = class_get_type(type_name);
- if (!type) {
- CERROR("OBD: unknown type: %s\n", type_name);
- return ERR_PTR(-ENODEV);
- }
-
- newdev = obd_device_alloc();
- if (!newdev) {
- result = ERR_PTR(-ENOMEM);
- goto out_type;
- }
-
- LASSERT(newdev->obd_magic == OBD_DEVICE_MAGIC);
-
- write_lock(&obd_dev_lock);
- for (i = 0; i < class_devno_max(); i++) {
- struct obd_device *obd = class_num2obd(i);
-
- if (obd && (strcmp(name, obd->obd_name) == 0)) {
- CERROR("Device %s already exists at %d, won't add\n",
- name, i);
- if (result) {
- LASSERTF(result->obd_magic == OBD_DEVICE_MAGIC,
- "%p obd_magic %08x != %08x\n", result,
- result->obd_magic, OBD_DEVICE_MAGIC);
- LASSERTF(result->obd_minor == new_obd_minor,
- "%p obd_minor %d != %d\n", result,
- result->obd_minor, new_obd_minor);
-
- obd_devs[result->obd_minor] = NULL;
- result->obd_name[0] = '\0';
- }
- result = ERR_PTR(-EEXIST);
- break;
- }
- if (!result && !obd) {
- result = newdev;
- result->obd_minor = i;
- new_obd_minor = i;
- result->obd_type = type;
- strncpy(result->obd_name, name,
- sizeof(result->obd_name) - 1);
- obd_devs[i] = result;
- }
- }
- write_unlock(&obd_dev_lock);
-
- if (!result && i >= class_devno_max()) {
- CERROR("all %u OBD devices used, increase MAX_OBD_DEVICES\n",
- class_devno_max());
- result = ERR_PTR(-EOVERFLOW);
- goto out;
- }
-
- if (IS_ERR(result))
- goto out;
-
- CDEBUG(D_IOCTL, "Adding new device %s (%p)\n",
- result->obd_name, result);
-
- return result;
-out:
- obd_device_free(newdev);
-out_type:
- class_put_type(type);
- return result;
-}
-
-void class_release_dev(struct obd_device *obd)
-{
- struct obd_type *obd_type = obd->obd_type;
-
- LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "%p obd_magic %08x != %08x\n",
- obd, obd->obd_magic, OBD_DEVICE_MAGIC);
- LASSERTF(obd == obd_devs[obd->obd_minor], "obd %p != obd_devs[%d] %p\n",
- obd, obd->obd_minor, obd_devs[obd->obd_minor]);
- LASSERT(obd_type);
-
- CDEBUG(D_INFO, "Release obd device %s at %d obd_type name =%s\n",
- obd->obd_name, obd->obd_minor, obd->obd_type->typ_name);
-
- write_lock(&obd_dev_lock);
- obd_devs[obd->obd_minor] = NULL;
- write_unlock(&obd_dev_lock);
- obd_device_free(obd);
-
- class_put_type(obd_type);
-}
-
-int class_name2dev(const char *name)
-{
- int i;
-
- if (!name)
- return -1;
-
- read_lock(&obd_dev_lock);
- for (i = 0; i < class_devno_max(); i++) {
- struct obd_device *obd = class_num2obd(i);
-
- if (obd && strcmp(name, obd->obd_name) == 0) {
- /* Make sure we finished attaching before we give
- * out any references
- */
- LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
- if (obd->obd_attached) {
- read_unlock(&obd_dev_lock);
- return i;
- }
- break;
- }
- }
- read_unlock(&obd_dev_lock);
-
- return -1;
-}
-
-struct obd_device *class_name2obd(const char *name)
-{
- int dev = class_name2dev(name);
-
- if (dev < 0 || dev > class_devno_max())
- return NULL;
- return class_num2obd(dev);
-}
-EXPORT_SYMBOL(class_name2obd);
-
-int class_uuid2dev(struct obd_uuid *uuid)
-{
- int i;
-
- read_lock(&obd_dev_lock);
- for (i = 0; i < class_devno_max(); i++) {
- struct obd_device *obd = class_num2obd(i);
-
- if (obd && obd_uuid_equals(uuid, &obd->obd_uuid)) {
- LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
- read_unlock(&obd_dev_lock);
- return i;
- }
- }
- read_unlock(&obd_dev_lock);
-
- return -1;
-}
-
-/**
- * Get obd device from ::obd_devs[]
- *
- * \param num [in] array index
- *
- * \retval NULL if ::obd_devs[\a num] does not contains an obd device
- * otherwise return the obd device there.
- */
-struct obd_device *class_num2obd(int num)
-{
- struct obd_device *obd = NULL;
-
- if (num < class_devno_max()) {
- obd = obd_devs[num];
- if (!obd)
- return NULL;
-
- LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
- "%p obd_magic %08x != %08x\n",
- obd, obd->obd_magic, OBD_DEVICE_MAGIC);
- LASSERTF(obd->obd_minor == num,
- "%p obd_minor %0d != %0d\n",
- obd, obd->obd_minor, num);
- }
-
- return obd;
-}
-
-/* Search for a client OBD connected to tgt_uuid. If grp_uuid is
- * specified, then only the client with that uuid is returned,
- * otherwise any client connected to the tgt is returned.
- */
-struct obd_device *class_find_client_obd(struct obd_uuid *tgt_uuid,
- const char *typ_name,
- struct obd_uuid *grp_uuid)
-{
- int i;
-
- read_lock(&obd_dev_lock);
- for (i = 0; i < class_devno_max(); i++) {
- struct obd_device *obd = class_num2obd(i);
-
- if (!obd)
- continue;
- if ((strncmp(obd->obd_type->typ_name, typ_name,
- strlen(typ_name)) == 0)) {
- if (obd_uuid_equals(tgt_uuid,
- &obd->u.cli.cl_target_uuid) &&
- ((grp_uuid) ? obd_uuid_equals(grp_uuid,
- &obd->obd_uuid) : 1)) {
- read_unlock(&obd_dev_lock);
- return obd;
- }
- }
- }
- read_unlock(&obd_dev_lock);
-
- return NULL;
-}
-EXPORT_SYMBOL(class_find_client_obd);
-
-/* Iterate the obd_device list looking devices have grp_uuid. Start
- * searching at *next, and if a device is found, the next index to look
- * at is saved in *next. If next is NULL, then the first matching device
- * will always be returned.
- */
-struct obd_device *class_devices_in_group(struct obd_uuid *grp_uuid, int *next)
-{
- int i;
-
- if (!next)
- i = 0;
- else if (*next >= 0 && *next < class_devno_max())
- i = *next;
- else
- return NULL;
-
- read_lock(&obd_dev_lock);
- for (; i < class_devno_max(); i++) {
- struct obd_device *obd = class_num2obd(i);
-
- if (!obd)
- continue;
- if (obd_uuid_equals(grp_uuid, &obd->obd_uuid)) {
- if (next)
- *next = i + 1;
- read_unlock(&obd_dev_lock);
- return obd;
- }
- }
- read_unlock(&obd_dev_lock);
-
- return NULL;
-}
-EXPORT_SYMBOL(class_devices_in_group);
-
-/**
- * to notify sptlrpc log for \a fsname has changed, let every relevant OBD
- * adjust sptlrpc settings accordingly.
- */
-int class_notify_sptlrpc_conf(const char *fsname, int namelen)
-{
- struct obd_device *obd;
- const char *type;
- int i, rc = 0, rc2;
-
- LASSERT(namelen > 0);
-
- read_lock(&obd_dev_lock);
- for (i = 0; i < class_devno_max(); i++) {
- obd = class_num2obd(i);
-
- if (!obd || obd->obd_set_up == 0 || obd->obd_stopping)
- continue;
-
- /* only notify mdc, osc, mdt, ost */
- type = obd->obd_type->typ_name;
- if (strcmp(type, LUSTRE_MDC_NAME) != 0 &&
- strcmp(type, LUSTRE_OSC_NAME) != 0 &&
- strcmp(type, LUSTRE_MDT_NAME) != 0 &&
- strcmp(type, LUSTRE_OST_NAME) != 0)
- continue;
-
- if (strncmp(obd->obd_name, fsname, namelen))
- continue;
-
- class_incref(obd, __func__, obd);
- read_unlock(&obd_dev_lock);
- rc2 = obd_set_info_async(NULL, obd->obd_self_export,
- sizeof(KEY_SPTLRPC_CONF),
- KEY_SPTLRPC_CONF, 0, NULL, NULL);
- rc = rc ? rc : rc2;
- class_decref(obd, __func__, obd);
- read_lock(&obd_dev_lock);
- }
- read_unlock(&obd_dev_lock);
- return rc;
-}
-EXPORT_SYMBOL(class_notify_sptlrpc_conf);
-
-void obd_cleanup_caches(void)
-{
- kmem_cache_destroy(obd_device_cachep);
- obd_device_cachep = NULL;
- kmem_cache_destroy(obdo_cachep);
- obdo_cachep = NULL;
- kmem_cache_destroy(import_cachep);
- import_cachep = NULL;
-}
-
-int obd_init_caches(void)
-{
- LASSERT(!obd_device_cachep);
- obd_device_cachep = kmem_cache_create("ll_obd_dev_cache",
- sizeof(struct obd_device),
- 0, 0, NULL);
- if (!obd_device_cachep)
- goto out;
-
- LASSERT(!obdo_cachep);
- obdo_cachep = kmem_cache_create("ll_obdo_cache", sizeof(struct obdo),
- 0, 0, NULL);
- if (!obdo_cachep)
- goto out;
-
- LASSERT(!import_cachep);
- import_cachep = kmem_cache_create("ll_import_cache",
- sizeof(struct obd_import),
- 0, 0, NULL);
- if (!import_cachep)
- goto out;
-
- return 0;
- out:
- obd_cleanup_caches();
- return -ENOMEM;
-}
-
-/* map connection to client */
-struct obd_export *class_conn2export(struct lustre_handle *conn)
-{
- struct obd_export *export;
-
- if (!conn) {
- CDEBUG(D_CACHE, "looking for null handle\n");
- return NULL;
- }
-
- if (conn->cookie == -1) { /* this means assign a new connection */
- CDEBUG(D_CACHE, "want a new connection\n");
- return NULL;
- }
-
- CDEBUG(D_INFO, "looking for export cookie %#llx\n", conn->cookie);
- export = class_handle2object(conn->cookie, NULL);
- return export;
-}
-EXPORT_SYMBOL(class_conn2export);
-
-struct obd_device *class_exp2obd(struct obd_export *exp)
-{
- if (exp)
- return exp->exp_obd;
- return NULL;
-}
-EXPORT_SYMBOL(class_exp2obd);
-
-struct obd_import *class_exp2cliimp(struct obd_export *exp)
-{
- struct obd_device *obd = exp->exp_obd;
-
- if (!obd)
- return NULL;
- return obd->u.cli.cl_import;
-}
-EXPORT_SYMBOL(class_exp2cliimp);
-
-/* Export management functions */
-static void class_export_destroy(struct obd_export *exp)
-{
- struct obd_device *obd = exp->exp_obd;
-
- LASSERT_ATOMIC_ZERO(&exp->exp_refcount);
- LASSERT(obd);
-
- CDEBUG(D_IOCTL, "destroying export %p/%s for %s\n", exp,
- exp->exp_client_uuid.uuid, obd->obd_name);
-
- /* "Local" exports (lctl, LOV->{mdc,osc}) have no connection. */
- if (exp->exp_connection)
- ptlrpc_put_connection_superhack(exp->exp_connection);
-
- LASSERT(list_empty(&exp->exp_outstanding_replies));
- LASSERT(list_empty(&exp->exp_uncommitted_replies));
- LASSERT(list_empty(&exp->exp_req_replay_queue));
- LASSERT(list_empty(&exp->exp_hp_rpcs));
- obd_destroy_export(exp);
- class_decref(obd, "export", exp);
-
- OBD_FREE_RCU(exp, sizeof(*exp), &exp->exp_handle);
-}
-
-static void export_handle_addref(void *export)
-{
- class_export_get(export);
-}
-
-static struct portals_handle_ops export_handle_ops = {
- .hop_addref = export_handle_addref,
- .hop_free = NULL,
-};
-
-struct obd_export *class_export_get(struct obd_export *exp)
-{
- atomic_inc(&exp->exp_refcount);
- CDEBUG(D_INFO, "GETting export %p : new refcount %d\n", exp,
- atomic_read(&exp->exp_refcount));
- return exp;
-}
-EXPORT_SYMBOL(class_export_get);
-
-void class_export_put(struct obd_export *exp)
-{
- LASSERT_ATOMIC_GT_LT(&exp->exp_refcount, 0, LI_POISON);
- CDEBUG(D_INFO, "PUTting export %p : new refcount %d\n", exp,
- atomic_read(&exp->exp_refcount) - 1);
-
- if (atomic_dec_and_test(&exp->exp_refcount)) {
- LASSERT(!list_empty(&exp->exp_obd_chain));
- CDEBUG(D_IOCTL, "final put %p/%s\n",
- exp, exp->exp_client_uuid.uuid);
-
- /* release nid stat refererence */
- lprocfs_exp_cleanup(exp);
-
- obd_zombie_export_add(exp);
- }
-}
-EXPORT_SYMBOL(class_export_put);
-
-static void obd_zombie_exp_cull(struct work_struct *ws)
-{
- struct obd_export *export = container_of(ws, struct obd_export, exp_zombie_work);
-
- class_export_destroy(export);
-}
-
-/* Creates a new export, adds it to the hash table, and returns a
- * pointer to it. The refcount is 2: one for the hash reference, and
- * one for the pointer returned by this function.
- */
-struct obd_export *class_new_export(struct obd_device *obd,
- struct obd_uuid *cluuid)
-{
- struct obd_export *export;
- struct cfs_hash *hash = NULL;
- int rc = 0;
-
- export = kzalloc(sizeof(*export), GFP_NOFS);
- if (!export)
- return ERR_PTR(-ENOMEM);
-
- export->exp_conn_cnt = 0;
- export->exp_lock_hash = NULL;
- export->exp_flock_hash = NULL;
- atomic_set(&export->exp_refcount, 2);
- atomic_set(&export->exp_rpc_count, 0);
- atomic_set(&export->exp_cb_count, 0);
- atomic_set(&export->exp_locks_count, 0);
-#if LUSTRE_TRACKS_LOCK_EXP_REFS
- INIT_LIST_HEAD(&export->exp_locks_list);
- spin_lock_init(&export->exp_locks_list_guard);
-#endif
- atomic_set(&export->exp_replay_count, 0);
- export->exp_obd = obd;
- INIT_LIST_HEAD(&export->exp_outstanding_replies);
- spin_lock_init(&export->exp_uncommitted_replies_lock);
- INIT_LIST_HEAD(&export->exp_uncommitted_replies);
- INIT_LIST_HEAD(&export->exp_req_replay_queue);
- INIT_LIST_HEAD(&export->exp_handle.h_link);
- INIT_LIST_HEAD(&export->exp_hp_rpcs);
- class_handle_hash(&export->exp_handle, &export_handle_ops);
- spin_lock_init(&export->exp_lock);
- spin_lock_init(&export->exp_rpc_lock);
- INIT_HLIST_NODE(&export->exp_uuid_hash);
- spin_lock_init(&export->exp_bl_list_lock);
- INIT_LIST_HEAD(&export->exp_bl_list);
- INIT_WORK(&export->exp_zombie_work, obd_zombie_exp_cull);
-
- export->exp_sp_peer = LUSTRE_SP_ANY;
- export->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
- export->exp_client_uuid = *cluuid;
- obd_init_export(export);
-
- spin_lock(&obd->obd_dev_lock);
- /* shouldn't happen, but might race */
- if (obd->obd_stopping) {
- rc = -ENODEV;
- goto exit_unlock;
- }
-
- hash = cfs_hash_getref(obd->obd_uuid_hash);
- if (!hash) {
- rc = -ENODEV;
- goto exit_unlock;
- }
- spin_unlock(&obd->obd_dev_lock);
-
- if (!obd_uuid_equals(cluuid, &obd->obd_uuid)) {
- rc = cfs_hash_add_unique(hash, cluuid, &export->exp_uuid_hash);
- if (rc != 0) {
- LCONSOLE_WARN("%s: denying duplicate export for %s, %d\n",
- obd->obd_name, cluuid->uuid, rc);
- rc = -EALREADY;
- goto exit_err;
- }
- }
-
- spin_lock(&obd->obd_dev_lock);
- if (obd->obd_stopping) {
- cfs_hash_del(hash, cluuid, &export->exp_uuid_hash);
- rc = -ENODEV;
- goto exit_unlock;
- }
-
- class_incref(obd, "export", export);
- list_add(&export->exp_obd_chain, &export->exp_obd->obd_exports);
- export->exp_obd->obd_num_exports++;
- spin_unlock(&obd->obd_dev_lock);
- cfs_hash_putref(hash);
- return export;
-
-exit_unlock:
- spin_unlock(&obd->obd_dev_lock);
-exit_err:
- if (hash)
- cfs_hash_putref(hash);
- class_handle_unhash(&export->exp_handle);
- LASSERT(hlist_unhashed(&export->exp_uuid_hash));
- obd_destroy_export(export);
- kfree(export);
- return ERR_PTR(rc);
-}
-EXPORT_SYMBOL(class_new_export);
-
-void class_unlink_export(struct obd_export *exp)
-{
- class_handle_unhash(&exp->exp_handle);
-
- spin_lock(&exp->exp_obd->obd_dev_lock);
- /* delete an uuid-export hashitem from hashtables */
- if (!hlist_unhashed(&exp->exp_uuid_hash))
- cfs_hash_del(exp->exp_obd->obd_uuid_hash,
- &exp->exp_client_uuid,
- &exp->exp_uuid_hash);
-
- list_move(&exp->exp_obd_chain, &exp->exp_obd->obd_unlinked_exports);
- exp->exp_obd->obd_num_exports--;
- spin_unlock(&exp->exp_obd->obd_dev_lock);
- class_export_put(exp);
-}
-
-/* Import management functions */
-static void class_import_destroy(struct obd_import *imp)
-{
- CDEBUG(D_IOCTL, "destroying import %p for %s\n", imp,
- imp->imp_obd->obd_name);
-
- LASSERT_ATOMIC_ZERO(&imp->imp_refcount);
-
- ptlrpc_put_connection_superhack(imp->imp_connection);
-
- while (!list_empty(&imp->imp_conn_list)) {
- struct obd_import_conn *imp_conn;
-
- imp_conn = list_entry(imp->imp_conn_list.next,
- struct obd_import_conn, oic_item);
- list_del_init(&imp_conn->oic_item);
- ptlrpc_put_connection_superhack(imp_conn->oic_conn);
- kfree(imp_conn);
- }
-
- LASSERT(!imp->imp_sec);
- class_decref(imp->imp_obd, "import", imp);
- OBD_FREE_RCU(imp, sizeof(*imp), &imp->imp_handle);
-}
-
-static void import_handle_addref(void *import)
-{
- class_import_get(import);
-}
-
-static struct portals_handle_ops import_handle_ops = {
- .hop_addref = import_handle_addref,
- .hop_free = NULL,
-};
-
-struct obd_import *class_import_get(struct obd_import *import)
-{
- atomic_inc(&import->imp_refcount);
- CDEBUG(D_INFO, "import %p refcount=%d obd=%s\n", import,
- atomic_read(&import->imp_refcount),
- import->imp_obd->obd_name);
- return import;
-}
-EXPORT_SYMBOL(class_import_get);
-
-void class_import_put(struct obd_import *imp)
-{
- LASSERT_ATOMIC_GT_LT(&imp->imp_refcount, 0, LI_POISON);
-
- CDEBUG(D_INFO, "import %p refcount=%d obd=%s\n", imp,
- atomic_read(&imp->imp_refcount) - 1,
- imp->imp_obd->obd_name);
-
- if (atomic_dec_and_test(&imp->imp_refcount)) {
- CDEBUG(D_INFO, "final put import %p\n", imp);
- obd_zombie_import_add(imp);
- }
-
- /* catch possible import put race */
- LASSERT_ATOMIC_GE_LT(&imp->imp_refcount, 0, LI_POISON);
-}
-EXPORT_SYMBOL(class_import_put);
-
-static void init_imp_at(struct imp_at *at)
-{
- int i;
-
- at_init(&at->iat_net_latency, 0, 0);
- for (i = 0; i < IMP_AT_MAX_PORTALS; i++) {
- /* max service estimates are tracked on the server side, so
- * don't use the AT history here, just use the last reported
- * val. (But keep hist for proc histogram, worst_ever)
- */
- at_init(&at->iat_service_estimate[i], INITIAL_CONNECT_TIMEOUT,
- AT_FLG_NOHIST);
- }
-}
-
-static void obd_zombie_imp_cull(struct work_struct *ws)
-{
- struct obd_import *import = container_of(ws, struct obd_import, imp_zombie_work);
-
- class_import_destroy(import);
-}
-
-struct obd_import *class_new_import(struct obd_device *obd)
-{
- struct obd_import *imp;
-
- imp = kzalloc(sizeof(*imp), GFP_NOFS);
- if (!imp)
- return NULL;
-
- INIT_LIST_HEAD(&imp->imp_pinger_chain);
- INIT_LIST_HEAD(&imp->imp_replay_list);
- INIT_LIST_HEAD(&imp->imp_sending_list);
- INIT_LIST_HEAD(&imp->imp_delayed_list);
- INIT_LIST_HEAD(&imp->imp_committed_list);
- INIT_LIST_HEAD(&imp->imp_unreplied_list);
- imp->imp_known_replied_xid = 0;
- imp->imp_replay_cursor = &imp->imp_committed_list;
- spin_lock_init(&imp->imp_lock);
- imp->imp_last_success_conn = 0;
- imp->imp_state = LUSTRE_IMP_NEW;
- imp->imp_obd = class_incref(obd, "import", imp);
- mutex_init(&imp->imp_sec_mutex);
- init_waitqueue_head(&imp->imp_recovery_waitq);
- INIT_WORK(&imp->imp_zombie_work, obd_zombie_imp_cull);
-
- atomic_set(&imp->imp_refcount, 2);
- atomic_set(&imp->imp_unregistering, 0);
- atomic_set(&imp->imp_inflight, 0);
- atomic_set(&imp->imp_replay_inflight, 0);
- atomic_set(&imp->imp_inval_count, 0);
- INIT_LIST_HEAD(&imp->imp_conn_list);
- INIT_LIST_HEAD(&imp->imp_handle.h_link);
- class_handle_hash(&imp->imp_handle, &import_handle_ops);
- init_imp_at(&imp->imp_at);
-
- /* the default magic is V2, will be used in connect RPC, and
- * then adjusted according to the flags in request/reply.
- */
- imp->imp_msg_magic = LUSTRE_MSG_MAGIC_V2;
-
- return imp;
-}
-EXPORT_SYMBOL(class_new_import);
-
-void class_destroy_import(struct obd_import *import)
-{
- LASSERT(import);
- LASSERT(import != LP_POISON);
-
- class_handle_unhash(&import->imp_handle);
-
- spin_lock(&import->imp_lock);
- import->imp_generation++;
- spin_unlock(&import->imp_lock);
- class_import_put(import);
-}
-EXPORT_SYMBOL(class_destroy_import);
-
-#if LUSTRE_TRACKS_LOCK_EXP_REFS
-
-void __class_export_add_lock_ref(struct obd_export *exp, struct ldlm_lock *lock)
-{
- spin_lock(&exp->exp_locks_list_guard);
-
- LASSERT(lock->l_exp_refs_nr >= 0);
-
- if (lock->l_exp_refs_target && lock->l_exp_refs_target != exp) {
- LCONSOLE_WARN("setting export %p for lock %p which already has export %p\n",
- exp, lock, lock->l_exp_refs_target);
- }
- if ((lock->l_exp_refs_nr++) == 0) {
- list_add(&lock->l_exp_refs_link, &exp->exp_locks_list);
- lock->l_exp_refs_target = exp;
- }
- CDEBUG(D_INFO, "lock = %p, export = %p, refs = %u\n",
- lock, exp, lock->l_exp_refs_nr);
- spin_unlock(&exp->exp_locks_list_guard);
-}
-
-void __class_export_del_lock_ref(struct obd_export *exp, struct ldlm_lock *lock)
-{
- spin_lock(&exp->exp_locks_list_guard);
- LASSERT(lock->l_exp_refs_nr > 0);
- if (lock->l_exp_refs_target != exp) {
- LCONSOLE_WARN("lock %p, mismatching export pointers: %p, %p\n",
- lock, lock->l_exp_refs_target, exp);
- }
- if (-- lock->l_exp_refs_nr == 0) {
- list_del_init(&lock->l_exp_refs_link);
- lock->l_exp_refs_target = NULL;
- }
- CDEBUG(D_INFO, "lock = %p, export = %p, refs = %u\n",
- lock, exp, lock->l_exp_refs_nr);
- spin_unlock(&exp->exp_locks_list_guard);
-}
-#endif
-
-/* A connection defines an export context in which preallocation can
- * be managed. This releases the export pointer reference, and returns
- * the export handle, so the export refcount is 1 when this function
- * returns.
- */
-int class_connect(struct lustre_handle *conn, struct obd_device *obd,
- struct obd_uuid *cluuid)
-{
- struct obd_export *export;
-
- LASSERT(conn);
- LASSERT(obd);
- LASSERT(cluuid);
-
- export = class_new_export(obd, cluuid);
- if (IS_ERR(export))
- return PTR_ERR(export);
-
- conn->cookie = export->exp_handle.h_cookie;
- class_export_put(export);
-
- CDEBUG(D_IOCTL, "connect: client %s, cookie %#llx\n",
- cluuid->uuid, conn->cookie);
- return 0;
-}
-EXPORT_SYMBOL(class_connect);
-
-/* This function removes 1-3 references from the export:
- * 1 - for export pointer passed
- * and if disconnect really need
- * 2 - removing from hash
- * 3 - in client_unlink_export
- * The export pointer passed to this function can destroyed
- */
-int class_disconnect(struct obd_export *export)
-{
- int already_disconnected;
-
- if (!export) {
- CWARN("attempting to free NULL export %p\n", export);
- return -EINVAL;
- }
-
- spin_lock(&export->exp_lock);
- already_disconnected = export->exp_disconnected;
- export->exp_disconnected = 1;
- spin_unlock(&export->exp_lock);
-
- /* class_cleanup(), abort_recovery(), and class_fail_export()
- * all end up in here, and if any of them race we shouldn't
- * call extra class_export_puts().
- */
- if (already_disconnected)
- goto no_disconn;
-
- CDEBUG(D_IOCTL, "disconnect: cookie %#llx\n",
- export->exp_handle.h_cookie);
-
- class_unlink_export(export);
-no_disconn:
- class_export_put(export);
- return 0;
-}
-EXPORT_SYMBOL(class_disconnect);
-
-void class_fail_export(struct obd_export *exp)
-{
- int rc, already_failed;
-
- spin_lock(&exp->exp_lock);
- already_failed = exp->exp_failed;
- exp->exp_failed = 1;
- spin_unlock(&exp->exp_lock);
-
- if (already_failed) {
- CDEBUG(D_HA, "disconnecting dead export %p/%s; skipping\n",
- exp, exp->exp_client_uuid.uuid);
- return;
- }
-
- CDEBUG(D_HA, "disconnecting export %p/%s\n",
- exp, exp->exp_client_uuid.uuid);
-
- if (obd_dump_on_timeout)
- libcfs_debug_dumplog();
-
- /* need for safe call CDEBUG after obd_disconnect */
- class_export_get(exp);
-
- /* Most callers into obd_disconnect are removing their own reference
- * (request, for example) in addition to the one from the hash table.
- * We don't have such a reference here, so make one.
- */
- class_export_get(exp);
- rc = obd_disconnect(exp);
- if (rc)
- CERROR("disconnecting export %p failed: %d\n", exp, rc);
- else
- CDEBUG(D_HA, "disconnected export %p/%s\n",
- exp, exp->exp_client_uuid.uuid);
- class_export_put(exp);
-}
-EXPORT_SYMBOL(class_fail_export);
-
-#if LUSTRE_TRACKS_LOCK_EXP_REFS
-void (*class_export_dump_hook)(struct obd_export *) = NULL;
-#endif
-
-/**
- * Add export to the obd_zombie thread and notify it.
- */
-static void obd_zombie_export_add(struct obd_export *exp)
-{
- spin_lock(&exp->exp_obd->obd_dev_lock);
- LASSERT(!list_empty(&exp->exp_obd_chain));
- list_del_init(&exp->exp_obd_chain);
- spin_unlock(&exp->exp_obd->obd_dev_lock);
- queue_work(zombie_wq, &exp->exp_zombie_work);
-}
-
-/**
- * Add import to the obd_zombie thread and notify it.
- */
-static void obd_zombie_import_add(struct obd_import *imp)
-{
- LASSERT(!imp->imp_sec);
- queue_work(zombie_wq, &imp->imp_zombie_work);
-}
-
-/**
- * wait when obd_zombie import/export queues become empty
- */
-void obd_zombie_barrier(void)
-{
- flush_workqueue(zombie_wq);
-}
-EXPORT_SYMBOL(obd_zombie_barrier);
-
-/**
- * start destroy zombie import/export thread
- */
-int obd_zombie_impexp_init(void)
-{
- zombie_wq = alloc_workqueue("obd_zombid", 0, 0);
- if (!zombie_wq)
- return -ENOMEM;
-
- return 0;
-}
-
-/**
- * stop destroy zombie import/export thread
- */
-void obd_zombie_impexp_stop(void)
-{
- destroy_workqueue(zombie_wq);
-}
-
-struct obd_request_slot_waiter {
- struct list_head orsw_entry;
- wait_queue_head_t orsw_waitq;
- bool orsw_signaled;
-};
-
-static bool obd_request_slot_avail(struct client_obd *cli,
- struct obd_request_slot_waiter *orsw)
-{
- bool avail;
-
- spin_lock(&cli->cl_loi_list_lock);
- avail = !!list_empty(&orsw->orsw_entry);
- spin_unlock(&cli->cl_loi_list_lock);
-
- return avail;
-};
-
-/*
- * For network flow control, the RPC sponsor needs to acquire a credit
- * before sending the RPC. The credits count for a connection is defined
- * by the "cl_max_rpcs_in_flight". If all the credits are occpuied, then
- * the subsequent RPC sponsors need to wait until others released their
- * credits, or the administrator increased the "cl_max_rpcs_in_flight".
- */
-int obd_get_request_slot(struct client_obd *cli)
-{
- struct obd_request_slot_waiter orsw;
- int rc;
-
- spin_lock(&cli->cl_loi_list_lock);
- if (cli->cl_r_in_flight < cli->cl_max_rpcs_in_flight) {
- cli->cl_r_in_flight++;
- spin_unlock(&cli->cl_loi_list_lock);
- return 0;
- }
-
- init_waitqueue_head(&orsw.orsw_waitq);
- list_add_tail(&orsw.orsw_entry, &cli->cl_loi_read_list);
- orsw.orsw_signaled = false;
- spin_unlock(&cli->cl_loi_list_lock);
-
- rc = l_wait_event_abortable(orsw.orsw_waitq,
- obd_request_slot_avail(cli, &orsw) ||
- orsw.orsw_signaled);
-
- /*
- * Here, we must take the lock to avoid the on-stack 'orsw' to be
- * freed but other (such as obd_put_request_slot) is using it.
- */
- spin_lock(&cli->cl_loi_list_lock);
- if (rc) {
- if (!orsw.orsw_signaled) {
- if (list_empty(&orsw.orsw_entry))
- cli->cl_r_in_flight--;
- else
- list_del(&orsw.orsw_entry);
- }
- }
-
- if (orsw.orsw_signaled) {
- LASSERT(list_empty(&orsw.orsw_entry));
-
- rc = -EINTR;
- }
- spin_unlock(&cli->cl_loi_list_lock);
-
- return rc;
-}
-EXPORT_SYMBOL(obd_get_request_slot);
-
-void obd_put_request_slot(struct client_obd *cli)
-{
- struct obd_request_slot_waiter *orsw;
-
- spin_lock(&cli->cl_loi_list_lock);
- cli->cl_r_in_flight--;
-
- /* If there is free slot, wakeup the first waiter. */
- if (!list_empty(&cli->cl_loi_read_list) &&
- likely(cli->cl_r_in_flight < cli->cl_max_rpcs_in_flight)) {
- orsw = list_entry(cli->cl_loi_read_list.next,
- struct obd_request_slot_waiter, orsw_entry);
- list_del_init(&orsw->orsw_entry);
- cli->cl_r_in_flight++;
- wake_up(&orsw->orsw_waitq);
- }
- spin_unlock(&cli->cl_loi_list_lock);
-}
-EXPORT_SYMBOL(obd_put_request_slot);
-
-__u32 obd_get_max_rpcs_in_flight(struct client_obd *cli)
-{
- return cli->cl_max_rpcs_in_flight;
-}
-EXPORT_SYMBOL(obd_get_max_rpcs_in_flight);
-
-int obd_set_max_rpcs_in_flight(struct client_obd *cli, __u32 max)
-{
- struct obd_request_slot_waiter *orsw;
- const char *typ_name;
- __u32 old;
- int diff;
- int rc;
- int i;
-
- if (max > OBD_MAX_RIF_MAX || max < 1)
- return -ERANGE;
-
- typ_name = cli->cl_import->imp_obd->obd_type->typ_name;
- if (!strcmp(typ_name, LUSTRE_MDC_NAME)) {
- /*
- * adjust max_mod_rpcs_in_flight to ensure it is always
- * strictly lower that max_rpcs_in_flight
- */
- if (max < 2) {
- CERROR("%s: cannot set max_rpcs_in_flight to 1 because it must be higher than max_mod_rpcs_in_flight value\n",
- cli->cl_import->imp_obd->obd_name);
- return -ERANGE;
- }
- if (max <= cli->cl_max_mod_rpcs_in_flight) {
- rc = obd_set_max_mod_rpcs_in_flight(cli, max - 1);
- if (rc)
- return rc;
- }
- }
-
- spin_lock(&cli->cl_loi_list_lock);
- old = cli->cl_max_rpcs_in_flight;
- cli->cl_max_rpcs_in_flight = max;
- diff = max - old;
-
- /* We increase the max_rpcs_in_flight, then wakeup some waiters. */
- for (i = 0; i < diff; i++) {
- if (list_empty(&cli->cl_loi_read_list))
- break;
-
- orsw = list_entry(cli->cl_loi_read_list.next,
- struct obd_request_slot_waiter, orsw_entry);
- list_del_init(&orsw->orsw_entry);
- cli->cl_r_in_flight++;
- wake_up(&orsw->orsw_waitq);
- }
- spin_unlock(&cli->cl_loi_list_lock);
-
- return 0;
-}
-EXPORT_SYMBOL(obd_set_max_rpcs_in_flight);
-
-int obd_set_max_mod_rpcs_in_flight(struct client_obd *cli, __u16 max)
-{
- struct obd_connect_data *ocd;
- u16 maxmodrpcs;
- u16 prev;
-
- if (max > OBD_MAX_RIF_MAX || max < 1)
- return -ERANGE;
-
- /* cannot exceed or equal max_rpcs_in_flight */
- if (max >= cli->cl_max_rpcs_in_flight) {
- CERROR("%s: can't set max_mod_rpcs_in_flight to a value (%hu) higher or equal to max_rpcs_in_flight value (%u)\n",
- cli->cl_import->imp_obd->obd_name,
- max, cli->cl_max_rpcs_in_flight);
- return -ERANGE;
- }
-
- /* cannot exceed max modify RPCs in flight supported by the server */
- ocd = &cli->cl_import->imp_connect_data;
- if (ocd->ocd_connect_flags & OBD_CONNECT_MULTIMODRPCS)
- maxmodrpcs = ocd->ocd_maxmodrpcs;
- else
- maxmodrpcs = 1;
- if (max > maxmodrpcs) {
- CERROR("%s: can't set max_mod_rpcs_in_flight to a value (%hu) higher than max_mod_rpcs_per_client value (%hu) returned by the server at connection\n",
- cli->cl_import->imp_obd->obd_name,
- max, maxmodrpcs);
- return -ERANGE;
- }
-
- spin_lock(&cli->cl_mod_rpcs_lock);
-
- prev = cli->cl_max_mod_rpcs_in_flight;
- cli->cl_max_mod_rpcs_in_flight = max;
-
- /* wakeup waiters if limit has been increased */
- if (cli->cl_max_mod_rpcs_in_flight > prev)
- wake_up(&cli->cl_mod_rpcs_waitq);
-
- spin_unlock(&cli->cl_mod_rpcs_lock);
-
- return 0;
-}
-EXPORT_SYMBOL(obd_set_max_mod_rpcs_in_flight);
-
-#define pct(a, b) (b ? (a * 100) / b : 0)
-
-int obd_mod_rpc_stats_seq_show(struct client_obd *cli, struct seq_file *seq)
-{
- unsigned long mod_tot = 0, mod_cum;
- struct timespec64 now;
- int i;
-
- ktime_get_real_ts64(&now);
-
- spin_lock(&cli->cl_mod_rpcs_lock);
-
- seq_printf(seq, "snapshot_time: %llu.%9lu (secs.nsecs)\n",
- (s64)now.tv_sec, (unsigned long)now.tv_nsec);
- seq_printf(seq, "modify_RPCs_in_flight: %hu\n",
- cli->cl_mod_rpcs_in_flight);
-
- seq_puts(seq, "\n\t\t\tmodify\n");
- seq_puts(seq, "rpcs in flight rpcs %% cum %%\n");
-
- mod_tot = lprocfs_oh_sum(&cli->cl_mod_rpcs_hist);
-
- mod_cum = 0;
- for (i = 0; i < OBD_HIST_MAX; i++) {
- unsigned long mod = cli->cl_mod_rpcs_hist.oh_buckets[i];
-
- mod_cum += mod;
- seq_printf(seq, "%d:\t\t%10lu %3lu %3lu\n",
- i, mod, pct(mod, mod_tot),
- pct(mod_cum, mod_tot));
- if (mod_cum == mod_tot)
- break;
- }
-
- spin_unlock(&cli->cl_mod_rpcs_lock);
-
- return 0;
-}
-EXPORT_SYMBOL(obd_mod_rpc_stats_seq_show);
-#undef pct
-
-/*
- * The number of modify RPCs sent in parallel is limited
- * because the server has a finite number of slots per client to
- * store request result and ensure reply reconstruction when needed.
- * On the client, this limit is stored in cl_max_mod_rpcs_in_flight
- * that takes into account server limit and cl_max_rpcs_in_flight
- * value.
- * On the MDC client, to avoid a potential deadlock (see Bugzilla 3462),
- * one close request is allowed above the maximum.
- */
-static inline bool obd_mod_rpc_slot_avail_locked(struct client_obd *cli,
- bool close_req)
-{
- bool avail;
-
- /* A slot is available if
- * - number of modify RPCs in flight is less than the max
- * - it's a close RPC and no other close request is in flight
- */
- avail = cli->cl_mod_rpcs_in_flight < cli->cl_max_mod_rpcs_in_flight ||
- (close_req && !cli->cl_close_rpcs_in_flight);
-
- return avail;
-}
-
-static inline bool obd_mod_rpc_slot_avail(struct client_obd *cli,
- bool close_req)
-{
- bool avail;
-
- spin_lock(&cli->cl_mod_rpcs_lock);
- avail = obd_mod_rpc_slot_avail_locked(cli, close_req);
- spin_unlock(&cli->cl_mod_rpcs_lock);
- return avail;
-}
-
-/* Get a modify RPC slot from the obd client @cli according
- * to the kind of operation @opc that is going to be sent
- * and the intent @it of the operation if it applies.
- * If the maximum number of modify RPCs in flight is reached
- * the thread is put to sleep.
- * Returns the tag to be set in the request message. Tag 0
- * is reserved for non-modifying requests.
- */
-u16 obd_get_mod_rpc_slot(struct client_obd *cli, __u32 opc,
- struct lookup_intent *it)
-{
- bool close_req = false;
- u16 i, max;
-
- /* read-only metadata RPCs don't consume a slot on MDT
- * for reply reconstruction
- */
- if (it && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP ||
- it->it_op == IT_LAYOUT || it->it_op == IT_READDIR))
- return 0;
-
- if (opc == MDS_CLOSE)
- close_req = true;
-
- do {
- spin_lock(&cli->cl_mod_rpcs_lock);
- max = cli->cl_max_mod_rpcs_in_flight;
- if (obd_mod_rpc_slot_avail_locked(cli, close_req)) {
- /* there is a slot available */
- cli->cl_mod_rpcs_in_flight++;
- if (close_req)
- cli->cl_close_rpcs_in_flight++;
- lprocfs_oh_tally(&cli->cl_mod_rpcs_hist,
- cli->cl_mod_rpcs_in_flight);
- /* find a free tag */
- i = find_first_zero_bit(cli->cl_mod_tag_bitmap,
- max + 1);
- LASSERT(i < OBD_MAX_RIF_MAX);
- LASSERT(!test_and_set_bit(i, cli->cl_mod_tag_bitmap));
- spin_unlock(&cli->cl_mod_rpcs_lock);
- /* tag 0 is reserved for non-modify RPCs */
- return i + 1;
- }
- spin_unlock(&cli->cl_mod_rpcs_lock);
-
- CDEBUG(D_RPCTRACE, "%s: sleeping for a modify RPC slot opc %u, max %hu\n",
- cli->cl_import->imp_obd->obd_name, opc, max);
-
- wait_event_idle(cli->cl_mod_rpcs_waitq,
- obd_mod_rpc_slot_avail(cli, close_req));
- } while (true);
-}
-EXPORT_SYMBOL(obd_get_mod_rpc_slot);
-
-/*
- * Put a modify RPC slot from the obd client @cli according
- * to the kind of operation @opc that has been sent and the
- * intent @it of the operation if it applies.
- */
-void obd_put_mod_rpc_slot(struct client_obd *cli, u32 opc,
- struct lookup_intent *it, u16 tag)
-{
- bool close_req = false;
-
- if (it && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP ||
- it->it_op == IT_LAYOUT || it->it_op == IT_READDIR))
- return;
-
- if (opc == MDS_CLOSE)
- close_req = true;
-
- spin_lock(&cli->cl_mod_rpcs_lock);
- cli->cl_mod_rpcs_in_flight--;
- if (close_req)
- cli->cl_close_rpcs_in_flight--;
- /* release the tag in the bitmap */
- LASSERT(tag - 1 < OBD_MAX_RIF_MAX);
- LASSERT(test_and_clear_bit(tag - 1, cli->cl_mod_tag_bitmap) != 0);
- spin_unlock(&cli->cl_mod_rpcs_lock);
- wake_up(&cli->cl_mod_rpcs_waitq);
-}
-EXPORT_SYMBOL(obd_put_mod_rpc_slot);
diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c
deleted file mode 100644
index b9bf81607bbf..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c
+++ /dev/null
@@ -1,238 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * Author: Nathan Rutman <nathan.rutman@sun.com>
- *
- * Kernel <-> userspace communication routines.
- * Using pipes for all arches.
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-#define D_KUC D_OTHER
-
-#include <obd_support.h>
-#include <lustre_kernelcomm.h>
-
-/**
- * libcfs_kkuc_msg_put - send an message from kernel to userspace
- * @param fp to send the message to
- * @param payload Payload data. First field of payload is always
- * struct kuc_hdr
- */
-int libcfs_kkuc_msg_put(struct file *filp, void *payload)
-{
- struct kuc_hdr *kuch = (struct kuc_hdr *)payload;
- ssize_t count = kuch->kuc_msglen;
- loff_t offset = 0;
- int rc = -ENXIO;
-
- if (IS_ERR_OR_NULL(filp))
- return -EBADF;
-
- if (kuch->kuc_magic != KUC_MAGIC) {
- CERROR("KernelComm: bad magic %x\n", kuch->kuc_magic);
- return rc;
- }
-
- while (count > 0) {
- rc = kernel_write(filp, payload, count, &offset);
- if (rc < 0)
- break;
- count -= rc;
- payload += rc;
- rc = 0;
- }
-
- if (rc < 0)
- CWARN("message send failed (%d)\n", rc);
- else
- CDEBUG(D_KUC, "Sent message rc=%d, fp=%p\n", rc, filp);
-
- return rc;
-}
-EXPORT_SYMBOL(libcfs_kkuc_msg_put);
-
-/*
- * Broadcast groups are global across all mounted filesystems;
- * i.e. registering for a group on 1 fs will get messages for that
- * group from any fs
- */
-/** A single group registration has a uid and a file pointer */
-struct kkuc_reg {
- struct list_head kr_chain;
- int kr_uid;
- struct file *kr_fp;
- char kr_data[0];
-};
-
-static struct list_head kkuc_groups[KUC_GRP_MAX + 1] = {};
-/* Protect message sending against remove and adds */
-static DECLARE_RWSEM(kg_sem);
-
-/** Add a receiver to a broadcast group
- * @param filp pipe to write into
- * @param uid identifier for this receiver
- * @param group group number
- * @param data user data
- */
-int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group,
- void *data, size_t data_len)
-{
- struct kkuc_reg *reg;
-
- if (group > KUC_GRP_MAX) {
- CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group);
- return -EINVAL;
- }
-
- /* fput in group_rem */
- if (!filp)
- return -EBADF;
-
- /* freed in group_rem */
- reg = kmalloc(sizeof(*reg) + data_len, 0);
- if (!reg)
- return -ENOMEM;
-
- reg->kr_fp = filp;
- reg->kr_uid = uid;
- memcpy(reg->kr_data, data, data_len);
-
- down_write(&kg_sem);
- if (!kkuc_groups[group].next)
- INIT_LIST_HEAD(&kkuc_groups[group]);
- list_add(&reg->kr_chain, &kkuc_groups[group]);
- up_write(&kg_sem);
-
- CDEBUG(D_KUC, "Added uid=%d fp=%p to group %d\n", uid, filp, group);
-
- return 0;
-}
-EXPORT_SYMBOL(libcfs_kkuc_group_add);
-
-int libcfs_kkuc_group_rem(int uid, unsigned int group)
-{
- struct kkuc_reg *reg, *next;
-
- if (!kkuc_groups[group].next)
- return 0;
-
- if (!uid) {
- /* Broadcast a shutdown message */
- struct kuc_hdr lh;
-
- lh.kuc_magic = KUC_MAGIC;
- lh.kuc_transport = KUC_TRANSPORT_GENERIC;
- lh.kuc_msgtype = KUC_MSG_SHUTDOWN;
- lh.kuc_msglen = sizeof(lh);
- libcfs_kkuc_group_put(group, &lh);
- }
-
- down_write(&kg_sem);
- list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) {
- if (!uid || (uid == reg->kr_uid)) {
- list_del(&reg->kr_chain);
- CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n",
- reg->kr_uid, reg->kr_fp, group);
- if (reg->kr_fp)
- fput(reg->kr_fp);
- kfree(reg);
- }
- }
- up_write(&kg_sem);
-
- return 0;
-}
-EXPORT_SYMBOL(libcfs_kkuc_group_rem);
-
-int libcfs_kkuc_group_put(unsigned int group, void *payload)
-{
- struct kkuc_reg *reg;
- int rc = 0;
- int one_success = 0;
-
- down_write(&kg_sem);
- list_for_each_entry(reg, &kkuc_groups[group], kr_chain) {
- if (reg->kr_fp) {
- rc = libcfs_kkuc_msg_put(reg->kr_fp, payload);
- if (!rc) {
- one_success = 1;
- } else if (rc == -EPIPE) {
- fput(reg->kr_fp);
- reg->kr_fp = NULL;
- }
- }
- }
- up_write(&kg_sem);
-
- /*
- * don't return an error if the message has been delivered
- * at least to one agent
- */
- if (one_success)
- rc = 0;
-
- return rc;
-}
-EXPORT_SYMBOL(libcfs_kkuc_group_put);
-
-/**
- * Calls a callback function for each link of the given kuc group.
- * @param group the group to call the function on.
- * @param cb_func the function to be called.
- * @param cb_arg extra argument to be passed to the callback function.
- */
-int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func,
- void *cb_arg)
-{
- struct kkuc_reg *reg;
- int rc = 0;
-
- if (group > KUC_GRP_MAX) {
- CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group);
- return -EINVAL;
- }
-
- /* no link for this group */
- if (!kkuc_groups[group].next)
- return 0;
-
- down_read(&kg_sem);
- list_for_each_entry(reg, &kkuc_groups[group], kr_chain) {
- if (reg->kr_fp)
- rc = cb_func(reg->kr_data, cb_arg);
- }
- up_read(&kg_sem);
-
- return rc;
-}
-EXPORT_SYMBOL(libcfs_kkuc_group_foreach);
diff --git a/drivers/staging/lustre/lustre/obdclass/linkea.c b/drivers/staging/lustre/lustre/obdclass/linkea.c
deleted file mode 100644
index 74c99ee216bb..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/linkea.c
+++ /dev/null
@@ -1,249 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2013, 2014, Intel Corporation.
- * Use is subject to license terms.
- *
- * Author: Di Wang <di.wang@intel.com>
- */
-
-#include <uapi/linux/lustre/lustre_idl.h>
-#include <obd.h>
-#include <lustre_linkea.h>
-
-int linkea_data_new(struct linkea_data *ldata, struct lu_buf *buf)
-{
- buf->lb_buf = kzalloc(PAGE_SIZE, GFP_NOFS);
- if (!buf->lb_buf)
- return -ENOMEM;
- buf->lb_len = PAGE_SIZE;
- ldata->ld_buf = buf;
- ldata->ld_leh = ldata->ld_buf->lb_buf;
- ldata->ld_leh->leh_magic = LINK_EA_MAGIC;
- ldata->ld_leh->leh_len = sizeof(struct link_ea_header);
- ldata->ld_leh->leh_reccount = 0;
- ldata->ld_leh->leh_overflow_time = 0;
- ldata->ld_leh->leh_padding = 0;
- return 0;
-}
-EXPORT_SYMBOL(linkea_data_new);
-
-int linkea_init(struct linkea_data *ldata)
-{
- struct link_ea_header *leh;
-
- LASSERT(ldata->ld_buf);
- leh = ldata->ld_buf->lb_buf;
- if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) {
- leh->leh_magic = LINK_EA_MAGIC;
- leh->leh_reccount = __swab32(leh->leh_reccount);
- leh->leh_len = __swab64(leh->leh_len);
- leh->leh_overflow_time = __swab32(leh->leh_overflow_time);
- leh->leh_padding = __swab32(leh->leh_padding);
- /* individual entries are swabbed by linkea_entry_unpack() */
- }
-
- if (leh->leh_magic != LINK_EA_MAGIC)
- return -EINVAL;
-
- if (leh->leh_reccount == 0 && leh->leh_overflow_time == 0)
- return -ENODATA;
-
- ldata->ld_leh = leh;
- return 0;
-}
-EXPORT_SYMBOL(linkea_init);
-
-int linkea_init_with_rec(struct linkea_data *ldata)
-{
- int rc;
-
- rc = linkea_init(ldata);
- if (!rc && ldata->ld_leh->leh_reccount == 0)
- rc = -ENODATA;
-
- return rc;
-}
-EXPORT_SYMBOL(linkea_init_with_rec);
-
-/**
- * Pack a link_ea_entry.
- * All elements are stored as chars to avoid alignment issues.
- * Numbers are always big-endian
- * \retval record length
- */
-int linkea_entry_pack(struct link_ea_entry *lee, const struct lu_name *lname,
- const struct lu_fid *pfid)
-{
- struct lu_fid tmpfid;
- int reclen;
-
- tmpfid = *pfid;
- if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_CRASH))
- tmpfid.f_ver = ~0;
- fid_cpu_to_be(&tmpfid, &tmpfid);
- memcpy(&lee->lee_parent_fid, &tmpfid, sizeof(tmpfid));
- memcpy(lee->lee_name, lname->ln_name, lname->ln_namelen);
- reclen = sizeof(struct link_ea_entry) + lname->ln_namelen;
-
- lee->lee_reclen[0] = (reclen >> 8) & 0xff;
- lee->lee_reclen[1] = reclen & 0xff;
- return reclen;
-}
-EXPORT_SYMBOL(linkea_entry_pack);
-
-void linkea_entry_unpack(const struct link_ea_entry *lee, int *reclen,
- struct lu_name *lname, struct lu_fid *pfid)
-{
- LASSERT(lee);
-
- *reclen = (lee->lee_reclen[0] << 8) | lee->lee_reclen[1];
- memcpy(pfid, &lee->lee_parent_fid, sizeof(*pfid));
- fid_be_to_cpu(pfid, pfid);
- if (lname) {
- lname->ln_name = lee->lee_name;
- lname->ln_namelen = *reclen - sizeof(struct link_ea_entry);
- }
-}
-EXPORT_SYMBOL(linkea_entry_unpack);
-
-/**
- * Add a record to the end of link ea buf
- **/
-int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname,
- const struct lu_fid *pfid)
-{
- struct link_ea_header *leh = ldata->ld_leh;
- int reclen;
-
- LASSERT(leh);
-
- if (!lname || !pfid)
- return -EINVAL;
-
- reclen = lname->ln_namelen + sizeof(struct link_ea_entry);
- if (unlikely(leh->leh_len + reclen > MAX_LINKEA_SIZE)) {
- /*
- * Use 32-bits to save the overflow time, although it will
- * shrink the ktime_get_real_seconds() returned 64-bits value
- * to 32-bits value, it is still quite large and can be used
- * for about 140 years. That is enough.
- */
- leh->leh_overflow_time = ktime_get_real_seconds();
- if (unlikely(leh->leh_overflow_time == 0))
- leh->leh_overflow_time++;
-
- CDEBUG(D_INODE, "No enough space to hold linkea entry '" DFID ": %.*s' at %u\n",
- PFID(pfid), lname->ln_namelen,
- lname->ln_name, leh->leh_overflow_time);
- return 0;
- }
-
- if (leh->leh_len + reclen > ldata->ld_buf->lb_len) {
- /* Note: this never happens as MAX_LINKEA_SIZE is 4096, while
- * the initial allocation is PAGE_SIZE.
- */
- void *b = krealloc(ldata->ld_buf->lb_buf, leh->leh_len + reclen, GFP_NOFS);
- if (!b)
- return -ENOMEM;
-
- ldata->ld_buf->lb_len = leh->leh_len + reclen;
- leh = ldata->ld_leh = ldata->ld_buf->lb_buf = b;
- }
-
- ldata->ld_lee = ldata->ld_buf->lb_buf + leh->leh_len;
- ldata->ld_reclen = linkea_entry_pack(ldata->ld_lee, lname, pfid);
- leh->leh_len += ldata->ld_reclen;
- leh->leh_reccount++;
- CDEBUG(D_INODE, "New link_ea name '" DFID ":%.*s' is added\n",
- PFID(pfid), lname->ln_namelen, lname->ln_name);
- return 0;
-}
-EXPORT_SYMBOL(linkea_add_buf);
-
-/** Del the current record from the link ea buf */
-void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname)
-{
- LASSERT(ldata->ld_leh && ldata->ld_lee);
- LASSERT(ldata->ld_leh->leh_reccount > 0);
-
- ldata->ld_leh->leh_reccount--;
- ldata->ld_leh->leh_len -= ldata->ld_reclen;
- memmove(ldata->ld_lee, (char *)ldata->ld_lee + ldata->ld_reclen,
- (char *)ldata->ld_leh + ldata->ld_leh->leh_len -
- (char *)ldata->ld_lee);
- CDEBUG(D_INODE, "Old link_ea name '%.*s' is removed\n",
- lname->ln_namelen, lname->ln_name);
-
- if ((char *)ldata->ld_lee >= ((char *)ldata->ld_leh +
- ldata->ld_leh->leh_len))
- ldata->ld_lee = NULL;
-}
-EXPORT_SYMBOL(linkea_del_buf);
-
-/**
- * Check if such a link exists in linkEA.
- *
- * \param ldata link data the search to be done on
- * \param lname name in the parent's directory entry pointing to this object
- * \param pfid parent fid the link to be found for
- *
- * \retval 0 success
- * \retval -ENOENT link does not exist
- * \retval -ve on error
- */
-int linkea_links_find(struct linkea_data *ldata, const struct lu_name *lname,
- const struct lu_fid *pfid)
-{
- struct lu_name tmpname;
- struct lu_fid tmpfid;
- int count;
-
- LASSERT(ldata->ld_leh);
-
- /* link #0, if leh_reccount == 0 we skip the loop and return -ENOENT */
- if (likely(ldata->ld_leh->leh_reccount > 0))
- ldata->ld_lee = (struct link_ea_entry *)(ldata->ld_leh + 1);
-
- for (count = 0; count < ldata->ld_leh->leh_reccount; count++) {
- linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen,
- &tmpname, &tmpfid);
- if (tmpname.ln_namelen == lname->ln_namelen &&
- lu_fid_eq(&tmpfid, pfid) &&
- (strncmp(tmpname.ln_name, lname->ln_name,
- tmpname.ln_namelen) == 0))
- break;
- ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee +
- ldata->ld_reclen);
- }
-
- if (count == ldata->ld_leh->leh_reccount) {
- CDEBUG(D_INODE, "Old link_ea name '%.*s' not found\n",
- lname->ln_namelen, lname->ln_name);
- ldata->ld_lee = NULL;
- ldata->ld_reclen = 0;
- return -ENOENT;
- }
- return 0;
-}
-EXPORT_SYMBOL(linkea_links_find);
diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
deleted file mode 100644
index 7bceee7f121e..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
+++ /dev/null
@@ -1,531 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/linux/linux-module.c
- *
- * Object Devices Class Driver
- * These are the only exported functions, they provide some generic
- * infrastructure for managing object devices
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/lp.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/skbuff.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/list.h>
-#include <linux/highmem.h>
-#include <linux/io.h>
-#include <asm/ioctls.h>
-#include <linux/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/seq_file.h>
-#include <linux/kobject.h>
-
-#include <linux/libcfs/libcfs.h>
-#include <uapi/linux/lnet/lnetctl.h>
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lprocfs_status.h>
-#include <uapi/linux/lustre/lustre_ioctl.h>
-#include <uapi/linux/lustre/lustre_ver.h>
-
-#define OBD_MAX_IOCTL_BUFFER 8192
-
-static int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
-{
- if (data->ioc_len > BIT(30)) {
- CERROR("OBD ioctl: ioc_len larger than 1<<30\n");
- return 1;
- }
-
- if (data->ioc_inllen1 > BIT(30)) {
- CERROR("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
- return 1;
- }
-
- if (data->ioc_inllen2 > BIT(30)) {
- CERROR("OBD ioctl: ioc_inllen2 larger than 1<<30\n");
- return 1;
- }
-
- if (data->ioc_inllen3 > BIT(30)) {
- CERROR("OBD ioctl: ioc_inllen3 larger than 1<<30\n");
- return 1;
- }
-
- if (data->ioc_inllen4 > BIT(30)) {
- CERROR("OBD ioctl: ioc_inllen4 larger than 1<<30\n");
- return 1;
- }
-
- if (data->ioc_inlbuf1 && data->ioc_inllen1 == 0) {
- CERROR("OBD ioctl: inlbuf1 pointer but 0 length\n");
- return 1;
- }
-
- if (data->ioc_inlbuf2 && data->ioc_inllen2 == 0) {
- CERROR("OBD ioctl: inlbuf2 pointer but 0 length\n");
- return 1;
- }
-
- if (data->ioc_inlbuf3 && data->ioc_inllen3 == 0) {
- CERROR("OBD ioctl: inlbuf3 pointer but 0 length\n");
- return 1;
- }
-
- if (data->ioc_inlbuf4 && data->ioc_inllen4 == 0) {
- CERROR("OBD ioctl: inlbuf4 pointer but 0 length\n");
- return 1;
- }
-
- if (data->ioc_pbuf1 && data->ioc_plen1 == 0) {
- CERROR("OBD ioctl: pbuf1 pointer but 0 length\n");
- return 1;
- }
-
- if (data->ioc_pbuf2 && data->ioc_plen2 == 0) {
- CERROR("OBD ioctl: pbuf2 pointer but 0 length\n");
- return 1;
- }
-
- if (!data->ioc_pbuf1 && data->ioc_plen1 != 0) {
- CERROR("OBD ioctl: plen1 set but NULL pointer\n");
- return 1;
- }
-
- if (!data->ioc_pbuf2 && data->ioc_plen2 != 0) {
- CERROR("OBD ioctl: plen2 set but NULL pointer\n");
- return 1;
- }
-
- if (obd_ioctl_packlen(data) > data->ioc_len) {
- CERROR("OBD ioctl: packlen exceeds ioc_len (%d > %d)\n",
- obd_ioctl_packlen(data), data->ioc_len);
- return 1;
- }
-
- return 0;
-}
-
-/* buffer MUST be at least the size of obd_ioctl_hdr */
-int obd_ioctl_getdata(char **buf, int *len, void __user *arg)
-{
- struct obd_ioctl_hdr hdr;
- struct obd_ioctl_data *data;
- int err;
- int offset = 0;
-
- if (copy_from_user(&hdr, arg, sizeof(hdr)))
- return -EFAULT;
-
- if (hdr.ioc_version != OBD_IOCTL_VERSION) {
- CERROR("Version mismatch kernel (%x) vs application (%x)\n",
- OBD_IOCTL_VERSION, hdr.ioc_version);
- return -EINVAL;
- }
-
- if (hdr.ioc_len > OBD_MAX_IOCTL_BUFFER) {
- CERROR("User buffer len %d exceeds %d max buffer\n",
- hdr.ioc_len, OBD_MAX_IOCTL_BUFFER);
- return -EINVAL;
- }
-
- if (hdr.ioc_len < sizeof(struct obd_ioctl_data)) {
- CERROR("User buffer too small for ioctl (%d)\n", hdr.ioc_len);
- return -EINVAL;
- }
-
- /* When there are lots of processes calling vmalloc on multi-core
- * system, the high lock contention will hurt performance badly,
- * obdfilter-survey is an example, which relies on ioctl. So we'd
- * better avoid vmalloc on ioctl path. LU-66
- */
- *buf = kvzalloc(hdr.ioc_len, GFP_KERNEL);
- if (!*buf) {
- CERROR("Cannot allocate control buffer of len %d\n",
- hdr.ioc_len);
- return -EINVAL;
- }
- *len = hdr.ioc_len;
- data = (struct obd_ioctl_data *)*buf;
-
- if (copy_from_user(*buf, arg, hdr.ioc_len)) {
- err = -EFAULT;
- goto free_buf;
- }
- if (hdr.ioc_len != data->ioc_len) {
- err = -EINVAL;
- goto free_buf;
- }
-
- if (obd_ioctl_is_invalid(data)) {
- CERROR("ioctl not correctly formatted\n");
- err = -EINVAL;
- goto free_buf;
- }
-
- if (data->ioc_inllen1) {
- data->ioc_inlbuf1 = &data->ioc_bulk[0];
- offset += cfs_size_round(data->ioc_inllen1);
- }
-
- if (data->ioc_inllen2) {
- data->ioc_inlbuf2 = &data->ioc_bulk[0] + offset;
- offset += cfs_size_round(data->ioc_inllen2);
- }
-
- if (data->ioc_inllen3) {
- data->ioc_inlbuf3 = &data->ioc_bulk[0] + offset;
- offset += cfs_size_round(data->ioc_inllen3);
- }
-
- if (data->ioc_inllen4)
- data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset;
-
- return 0;
-
-free_buf:
- kvfree(*buf);
- return err;
-}
-EXPORT_SYMBOL(obd_ioctl_getdata);
-
-/* opening /dev/obd */
-static int obd_class_open(struct inode *inode, struct file *file)
-{
- try_module_get(THIS_MODULE);
- return 0;
-}
-
-/* closing /dev/obd */
-static int obd_class_release(struct inode *inode, struct file *file)
-{
- module_put(THIS_MODULE);
- return 0;
-}
-
-/* to control /dev/obd */
-static long obd_class_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- int err = 0;
-
- /* Allow non-root access for OBD_IOC_PING_TARGET - used by lfs check */
- if (!capable(CAP_SYS_ADMIN) && (cmd != OBD_IOC_PING_TARGET))
- return err = -EACCES;
- if ((cmd & 0xffffff00) == ((int)'T') << 8) /* ignore all tty ioctls */
- return err = -ENOTTY;
-
- err = class_handle_ioctl(cmd, (unsigned long)arg);
-
- return err;
-}
-
-/* declare character device */
-static const struct file_operations obd_psdev_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = obd_class_ioctl, /* unlocked_ioctl */
- .open = obd_class_open, /* open */
- .release = obd_class_release, /* release */
-};
-
-/* modules setup */
-struct miscdevice obd_psdev = {
- .minor = OBD_DEV_MINOR,
- .name = OBD_DEV_NAME,
- .fops = &obd_psdev_fops,
-};
-
-static ssize_t version_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%s\n", LUSTRE_VERSION_STRING);
-}
-
-static ssize_t pinger_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%s\n", "on");
-}
-
-static ssize_t
-health_check_show(struct kobject *kobj, struct attribute *attr, char *buf)
-{
- bool healthy = true;
- int i;
- size_t len = 0;
-
- if (libcfs_catastrophe)
- return sprintf(buf, "LBUG\n");
-
- read_lock(&obd_dev_lock);
- for (i = 0; i < class_devno_max(); i++) {
- struct obd_device *obd;
-
- obd = class_num2obd(i);
- if (!obd || !obd->obd_attached || !obd->obd_set_up)
- continue;
-
- LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
- if (obd->obd_stopping)
- continue;
-
- class_incref(obd, __func__, current);
- read_unlock(&obd_dev_lock);
-
- if (obd_health_check(NULL, obd))
- healthy = false;
- class_decref(obd, __func__, current);
- read_lock(&obd_dev_lock);
- }
- read_unlock(&obd_dev_lock);
-
- if (healthy)
- len = sprintf(buf, "healthy\n");
- else
- len = sprintf(buf, "NOT HEALTHY\n");
-
- return len;
-}
-
-static ssize_t jobid_var_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%s\n", obd_jobid_var);
-}
-
-static ssize_t jobid_var_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer,
- size_t count)
-{
- if (!count || count > JOBSTATS_JOBID_VAR_MAX_LEN)
- return -EINVAL;
-
- memset(obd_jobid_var, 0, JOBSTATS_JOBID_VAR_MAX_LEN + 1);
-
- memcpy(obd_jobid_var, buffer, count);
-
- /* Trim the trailing '\n' if any */
- if (obd_jobid_var[count - 1] == '\n')
- obd_jobid_var[count - 1] = 0;
-
- return count;
-}
-
-static ssize_t jobid_name_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%s\n", obd_jobid_node);
-}
-
-static ssize_t jobid_name_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer,
- size_t count)
-{
- if (!count || count > LUSTRE_JOBID_SIZE)
- return -EINVAL;
-
- memcpy(obd_jobid_node, buffer, count);
-
- obd_jobid_node[count] = 0;
-
- /* Trim the trailing '\n' if any */
- if (obd_jobid_node[count - 1] == '\n')
- obd_jobid_node[count - 1] = 0;
-
- return count;
-}
-
-/* Root for /sys/kernel/debug/lustre */
-struct dentry *debugfs_lustre_root;
-EXPORT_SYMBOL_GPL(debugfs_lustre_root);
-
-LUSTRE_RO_ATTR(version);
-LUSTRE_RO_ATTR(pinger);
-LUSTRE_RO_ATTR(health_check);
-LUSTRE_RW_ATTR(jobid_var);
-LUSTRE_RW_ATTR(jobid_name);
-
-static struct attribute *lustre_attrs[] = {
- &lustre_attr_version.attr,
- &lustre_attr_pinger.attr,
- &lustre_attr_health_check.attr,
- &lustre_attr_jobid_name.attr,
- &lustre_attr_jobid_var.attr,
- NULL,
-};
-
-static void *obd_device_list_seq_start(struct seq_file *p, loff_t *pos)
-{
- if (*pos >= class_devno_max())
- return NULL;
-
- return pos;
-}
-
-static void obd_device_list_seq_stop(struct seq_file *p, void *v)
-{
-}
-
-static void *obd_device_list_seq_next(struct seq_file *p, void *v, loff_t *pos)
-{
- ++*pos;
- if (*pos >= class_devno_max())
- return NULL;
-
- return pos;
-}
-
-static int obd_device_list_seq_show(struct seq_file *p, void *v)
-{
- loff_t index = *(loff_t *)v;
- struct obd_device *obd = class_num2obd((int)index);
- char *status;
-
- if (!obd)
- return 0;
-
- LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
- if (obd->obd_stopping)
- status = "ST";
- else if (obd->obd_inactive)
- status = "IN";
- else if (obd->obd_set_up)
- status = "UP";
- else if (obd->obd_attached)
- status = "AT";
- else
- status = "--";
-
- seq_printf(p, "%3d %s %s %s %s %d\n",
- (int)index, status, obd->obd_type->typ_name,
- obd->obd_name, obd->obd_uuid.uuid,
- atomic_read(&obd->obd_refcount));
- return 0;
-}
-
-static const struct seq_operations obd_device_list_sops = {
- .start = obd_device_list_seq_start,
- .stop = obd_device_list_seq_stop,
- .next = obd_device_list_seq_next,
- .show = obd_device_list_seq_show,
-};
-
-static int obd_device_list_open(struct inode *inode, struct file *file)
-{
- struct seq_file *seq;
- int rc = seq_open(file, &obd_device_list_sops);
-
- if (rc)
- return rc;
-
- seq = file->private_data;
- seq->private = inode->i_private;
-
- return 0;
-}
-
-static const struct file_operations obd_device_list_fops = {
- .owner = THIS_MODULE,
- .open = obd_device_list_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-struct kobject *lustre_kobj;
-EXPORT_SYMBOL_GPL(lustre_kobj);
-
-static const struct attribute_group lustre_attr_group = {
- .attrs = lustre_attrs,
-};
-
-int class_procfs_init(void)
-{
- int rc = -ENOMEM;
- struct dentry *file;
-
- lustre_kobj = kobject_create_and_add("lustre", fs_kobj);
- if (!lustre_kobj)
- goto out;
-
- /* Create the files associated with this kobject */
- rc = sysfs_create_group(lustre_kobj, &lustre_attr_group);
- if (rc) {
- kobject_put(lustre_kobj);
- goto out;
- }
-
- debugfs_lustre_root = debugfs_create_dir("lustre", NULL);
- if (IS_ERR_OR_NULL(debugfs_lustre_root)) {
- rc = debugfs_lustre_root ? PTR_ERR(debugfs_lustre_root)
- : -ENOMEM;
- debugfs_lustre_root = NULL;
- sysfs_remove_group(lustre_kobj, &lustre_attr_group);
- kobject_put(lustre_kobj);
- goto out;
- }
-
- file = debugfs_create_file("devices", 0444, debugfs_lustre_root, NULL,
- &obd_device_list_fops);
- if (IS_ERR_OR_NULL(file)) {
- rc = file ? PTR_ERR(file) : -ENOMEM;
- sysfs_remove_group(lustre_kobj, &lustre_attr_group);
- kobject_put(lustre_kobj);
- goto out;
- }
-out:
- return rc;
-}
-
-int class_procfs_clean(void)
-{
- debugfs_remove_recursive(debugfs_lustre_root);
-
- debugfs_lustre_root = NULL;
-
- sysfs_remove_group(lustre_kobj, &lustre_attr_group);
- kobject_put(lustre_kobj);
-
- return 0;
-}
diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
deleted file mode 100644
index e5e8687784ee..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
+++ /dev/null
@@ -1,162 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/sysctl.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/ctype.h>
-#include <linux/bitops.h>
-#include <linux/uaccess.h>
-#include <linux/utsname.h>
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <obd_support.h>
-#include <lprocfs_status.h>
-#include <obd_class.h>
-
-struct static_lustre_uintvalue_attr {
- struct {
- struct attribute attr;
- ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
- char *buf);
- ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t len);
- } u;
- int *value;
-};
-
-static ssize_t static_uintvalue_show(struct kobject *kobj,
- struct attribute *attr,
- char *buf)
-{
- struct static_lustre_uintvalue_attr *lattr = (void *)attr;
-
- return sprintf(buf, "%d\n", *lattr->value);
-}
-
-static ssize_t static_uintvalue_store(struct kobject *kobj,
- struct attribute *attr,
- const char *buffer, size_t count)
-{
- struct static_lustre_uintvalue_attr *lattr = (void *)attr;
- int rc;
- unsigned int val;
-
- rc = kstrtouint(buffer, 10, &val);
- if (rc)
- return rc;
-
- *lattr->value = val;
-
- return count;
-}
-
-#define LUSTRE_STATIC_UINT_ATTR(name, value) \
-static struct static_lustre_uintvalue_attr lustre_sattr_##name = \
- {__ATTR(name, 0644, \
- static_uintvalue_show, \
- static_uintvalue_store),\
- value }
-
-LUSTRE_STATIC_UINT_ATTR(timeout, &obd_timeout);
-
-static ssize_t max_dirty_mb_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%lu\n",
- obd_max_dirty_pages / (1 << (20 - PAGE_SHIFT)));
-}
-
-static ssize_t max_dirty_mb_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
-{
- int rc;
- unsigned long val;
-
- rc = kstrtoul(buffer, 10, &val);
- if (rc)
- return rc;
-
- val *= 1 << (20 - PAGE_SHIFT); /* convert to pages */
-
- if (val > ((totalram_pages / 10) * 9)) {
- /* Somebody wants to assign too much memory to dirty pages */
- return -EINVAL;
- }
-
- if (val < 4 << (20 - PAGE_SHIFT)) {
- /* Less than 4 Mb for dirty cache is also bad */
- return -EINVAL;
- }
-
- obd_max_dirty_pages = val;
-
- return count;
-}
-LUSTRE_RW_ATTR(max_dirty_mb);
-
-LUSTRE_STATIC_UINT_ATTR(debug_peer_on_timeout, &obd_debug_peer_on_timeout);
-LUSTRE_STATIC_UINT_ATTR(dump_on_timeout, &obd_dump_on_timeout);
-LUSTRE_STATIC_UINT_ATTR(dump_on_eviction, &obd_dump_on_eviction);
-LUSTRE_STATIC_UINT_ATTR(at_min, &at_min);
-LUSTRE_STATIC_UINT_ATTR(at_max, &at_max);
-LUSTRE_STATIC_UINT_ATTR(at_extra, &at_extra);
-LUSTRE_STATIC_UINT_ATTR(at_early_margin, &at_early_margin);
-LUSTRE_STATIC_UINT_ATTR(at_history, &at_history);
-
-static struct attribute *lustre_attrs[] = {
- &lustre_sattr_timeout.u.attr,
- &lustre_attr_max_dirty_mb.attr,
- &lustre_sattr_debug_peer_on_timeout.u.attr,
- &lustre_sattr_dump_on_timeout.u.attr,
- &lustre_sattr_dump_on_eviction.u.attr,
- &lustre_sattr_at_min.u.attr,
- &lustre_sattr_at_max.u.attr,
- &lustre_sattr_at_extra.u.attr,
- &lustre_sattr_at_early_margin.u.attr,
- &lustre_sattr_at_history.u.attr,
- NULL,
-};
-
-static const struct attribute_group lustre_attr_group = {
- .attrs = lustre_attrs,
-};
-
-int obd_sysctl_init(void)
-{
- return sysfs_create_group(lustre_kobj, &lustre_attr_group);
-}
diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c
deleted file mode 100644
index 693e1129f1f9..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/llog.c
+++ /dev/null
@@ -1,523 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/llog.c
- *
- * OST<->MDS recovery logging infrastructure.
- * Invariants in implementation:
- * - we do not share logs among different OST<->MDS connections, so that
- * if an OST or MDS fails it need only look at log(s) relevant to itself
- *
- * Author: Andreas Dilger <adilger@clusterfs.com>
- * Author: Alex Zhuravlev <bzzz@whamcloud.com>
- * Author: Mikhail Pershin <tappro@whamcloud.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LOG
-
-#include <llog_swab.h>
-#include <lustre_log.h>
-#include <obd_class.h>
-#include "llog_internal.h"
-
-/*
- * Allocate a new log or catalog handle
- * Used inside llog_open().
- */
-static struct llog_handle *llog_alloc_handle(void)
-{
- struct llog_handle *loghandle;
-
- loghandle = kzalloc(sizeof(*loghandle), GFP_NOFS);
- if (!loghandle)
- return NULL;
-
- init_rwsem(&loghandle->lgh_lock);
- spin_lock_init(&loghandle->lgh_hdr_lock);
- INIT_LIST_HEAD(&loghandle->u.phd.phd_entry);
- atomic_set(&loghandle->lgh_refcount, 1);
-
- return loghandle;
-}
-
-/*
- * Free llog handle and header data if exists. Used in llog_close() only
- */
-static void llog_free_handle(struct llog_handle *loghandle)
-{
- /* failed llog_init_handle */
- if (!loghandle->lgh_hdr)
- goto out;
-
- if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN)
- LASSERT(list_empty(&loghandle->u.phd.phd_entry));
- else if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)
- LASSERT(list_empty(&loghandle->u.chd.chd_head));
- kvfree(loghandle->lgh_hdr);
-out:
- kfree(loghandle);
-}
-
-void llog_handle_get(struct llog_handle *loghandle)
-{
- atomic_inc(&loghandle->lgh_refcount);
-}
-
-void llog_handle_put(struct llog_handle *loghandle)
-{
- LASSERT(atomic_read(&loghandle->lgh_refcount) > 0);
- if (atomic_dec_and_test(&loghandle->lgh_refcount))
- llog_free_handle(loghandle);
-}
-
-static int llog_read_header(const struct lu_env *env,
- struct llog_handle *handle,
- struct obd_uuid *uuid)
-{
- struct llog_operations *lop;
- int rc;
-
- rc = llog_handle2ops(handle, &lop);
- if (rc)
- return rc;
-
- if (!lop->lop_read_header)
- return -EOPNOTSUPP;
-
- rc = lop->lop_read_header(env, handle);
- if (rc == LLOG_EEMPTY) {
- struct llog_log_hdr *llh = handle->lgh_hdr;
- size_t len;
-
- /* lrh_len should be initialized in llog_init_handle */
- handle->lgh_last_idx = 0; /* header is record with index 0 */
- llh->llh_count = 1; /* for the header record */
- llh->llh_hdr.lrh_type = LLOG_HDR_MAGIC;
- LASSERT(handle->lgh_ctxt->loc_chunk_size >= LLOG_MIN_CHUNK_SIZE);
- llh->llh_hdr.lrh_len = handle->lgh_ctxt->loc_chunk_size;
- llh->llh_hdr.lrh_index = 0;
- llh->llh_timestamp = ktime_get_real_seconds();
- if (uuid)
- memcpy(&llh->llh_tgtuuid, uuid,
- sizeof(llh->llh_tgtuuid));
- llh->llh_bitmap_offset = offsetof(typeof(*llh), llh_bitmap);
- /*
- * Since update llog header might also call this function,
- * let's reset the bitmap to 0 here
- */
- len = llh->llh_hdr.lrh_len - llh->llh_bitmap_offset;
- memset(LLOG_HDR_BITMAP(llh), 0, len - sizeof(llh->llh_tail));
- ext2_set_bit(0, LLOG_HDR_BITMAP(llh));
- LLOG_HDR_TAIL(llh)->lrt_len = llh->llh_hdr.lrh_len;
- LLOG_HDR_TAIL(llh)->lrt_index = llh->llh_hdr.lrh_index;
- rc = 0;
- }
- return rc;
-}
-
-int llog_init_handle(const struct lu_env *env, struct llog_handle *handle,
- int flags, struct obd_uuid *uuid)
-{
- int chunk_size = handle->lgh_ctxt->loc_chunk_size;
- enum llog_flag fmt = flags & LLOG_F_EXT_MASK;
- struct llog_log_hdr *llh;
- int rc;
-
- LASSERT(!handle->lgh_hdr);
-
- LASSERT(chunk_size >= LLOG_MIN_CHUNK_SIZE);
- llh = kvzalloc(sizeof(*llh), GFP_KERNEL);
- if (!llh)
- return -ENOMEM;
- handle->lgh_hdr = llh;
- handle->lgh_hdr_size = chunk_size;
- /* first assign flags to use llog_client_ops */
- llh->llh_flags = flags;
- rc = llog_read_header(env, handle, uuid);
- if (rc == 0) {
- if (unlikely((llh->llh_flags & LLOG_F_IS_PLAIN &&
- flags & LLOG_F_IS_CAT) ||
- (llh->llh_flags & LLOG_F_IS_CAT &&
- flags & LLOG_F_IS_PLAIN))) {
- CERROR("%s: llog type is %s but initializing %s\n",
- handle->lgh_ctxt->loc_obd->obd_name,
- llh->llh_flags & LLOG_F_IS_CAT ?
- "catalog" : "plain",
- flags & LLOG_F_IS_CAT ? "catalog" : "plain");
- rc = -EINVAL;
- goto out;
- } else if (llh->llh_flags &
- (LLOG_F_IS_PLAIN | LLOG_F_IS_CAT)) {
- /*
- * it is possible to open llog without specifying llog
- * type so it is taken from llh_flags
- */
- flags = llh->llh_flags;
- } else {
- /* for some reason the llh_flags has no type set */
- CERROR("llog type is not specified!\n");
- rc = -EINVAL;
- goto out;
- }
- if (unlikely(uuid &&
- !obd_uuid_equals(uuid, &llh->llh_tgtuuid))) {
- CERROR("%s: llog uuid mismatch: %s/%s\n",
- handle->lgh_ctxt->loc_obd->obd_name,
- (char *)uuid->uuid,
- (char *)llh->llh_tgtuuid.uuid);
- rc = -EEXIST;
- goto out;
- }
- }
- if (flags & LLOG_F_IS_CAT) {
- LASSERT(list_empty(&handle->u.chd.chd_head));
- INIT_LIST_HEAD(&handle->u.chd.chd_head);
- llh->llh_size = sizeof(struct llog_logid_rec);
- llh->llh_flags |= LLOG_F_IS_FIXSIZE;
- } else if (!(flags & LLOG_F_IS_PLAIN)) {
- CERROR("%s: unknown flags: %#x (expected %#x or %#x)\n",
- handle->lgh_ctxt->loc_obd->obd_name,
- flags, LLOG_F_IS_CAT, LLOG_F_IS_PLAIN);
- rc = -EINVAL;
- }
- llh->llh_flags |= fmt;
-out:
- if (rc) {
- kvfree(llh);
- handle->lgh_hdr = NULL;
- }
- return rc;
-}
-EXPORT_SYMBOL(llog_init_handle);
-
-static int llog_process_thread(void *arg)
-{
- struct llog_process_info *lpi = arg;
- struct llog_handle *loghandle = lpi->lpi_loghandle;
- struct llog_log_hdr *llh = loghandle->lgh_hdr;
- struct llog_process_cat_data *cd = lpi->lpi_catdata;
- char *buf;
- u64 cur_offset, tmp_offset;
- int chunk_size;
- int rc = 0, index = 1, last_index;
- int saved_index = 0;
- int last_called_index = 0;
-
- if (!llh)
- return -EINVAL;
-
- cur_offset = llh->llh_hdr.lrh_len;
- chunk_size = llh->llh_hdr.lrh_len;
- /* expect chunk_size to be power of two */
- LASSERT(is_power_of_2(chunk_size));
-
- buf = kvzalloc(chunk_size, GFP_NOFS);
- if (!buf) {
- lpi->lpi_rc = -ENOMEM;
- return 0;
- }
-
- if (cd) {
- last_called_index = cd->lpcd_first_idx;
- index = cd->lpcd_first_idx + 1;
- }
- if (cd && cd->lpcd_last_idx)
- last_index = cd->lpcd_last_idx;
- else
- last_index = LLOG_HDR_BITMAP_SIZE(llh) - 1;
-
- while (rc == 0) {
- unsigned int buf_offset = 0;
- struct llog_rec_hdr *rec;
- bool partial_chunk;
- off_t chunk_offset;
-
- /* skip records not set in bitmap */
- while (index <= last_index &&
- !ext2_test_bit(index, LLOG_HDR_BITMAP(llh)))
- ++index;
-
- if (index > last_index)
- break;
-
- CDEBUG(D_OTHER, "index: %d last_index %d\n",
- index, last_index);
-repeat:
- /* get the buf with our target record; avoid old garbage */
- memset(buf, 0, chunk_size);
- rc = llog_next_block(lpi->lpi_env, loghandle, &saved_index,
- index, &cur_offset, buf, chunk_size);
- if (rc)
- goto out;
-
- /*
- * NB: after llog_next_block() call the cur_offset is the
- * offset of the next block after read one.
- * The absolute offset of the current chunk is calculated
- * from cur_offset value and stored in chunk_offset variable.
- */
- tmp_offset = cur_offset;
- if (do_div(tmp_offset, chunk_size)) {
- partial_chunk = true;
- chunk_offset = cur_offset & ~(chunk_size - 1);
- } else {
- partial_chunk = false;
- chunk_offset = cur_offset - chunk_size;
- }
-
- /* NB: when rec->lrh_len is accessed it is already swabbed
- * since it is used at the "end" of the loop and the rec
- * swabbing is done at the beginning of the loop.
- */
- for (rec = (struct llog_rec_hdr *)(buf + buf_offset);
- (char *)rec < buf + chunk_size;
- rec = llog_rec_hdr_next(rec)) {
- CDEBUG(D_OTHER, "processing rec 0x%p type %#x\n",
- rec, rec->lrh_type);
-
- if (LLOG_REC_HDR_NEEDS_SWABBING(rec))
- lustre_swab_llog_rec(rec);
-
- CDEBUG(D_OTHER, "after swabbing, type=%#x idx=%d\n",
- rec->lrh_type, rec->lrh_index);
-
- /*
- * for partial chunk the end of it is zeroed, check
- * for index 0 to distinguish it.
- */
- if (partial_chunk && !rec->lrh_index) {
- /* concurrent llog_add() might add new records
- * while llog_processing, check this is not
- * the case and re-read the current chunk
- * otherwise.
- */
- if (index > loghandle->lgh_last_idx) {
- rc = 0;
- goto out;
- }
- CDEBUG(D_OTHER, "Re-read last llog buffer for new records, index %u, last %u\n",
- index, loghandle->lgh_last_idx);
- /* save offset inside buffer for the re-read */
- buf_offset = (char *)rec - (char *)buf;
- cur_offset = chunk_offset;
- goto repeat;
- }
-
- if (!rec->lrh_len || rec->lrh_len > chunk_size) {
- CWARN("invalid length %d in llog record for index %d/%d\n",
- rec->lrh_len,
- rec->lrh_index, index);
- rc = -EINVAL;
- goto out;
- }
-
- if (rec->lrh_index < index) {
- CDEBUG(D_OTHER, "skipping lrh_index %d\n",
- rec->lrh_index);
- continue;
- }
-
- if (rec->lrh_index != index) {
- CERROR("%s: Invalid record: index %u but expected %u\n",
- loghandle->lgh_ctxt->loc_obd->obd_name,
- rec->lrh_index, index);
- rc = -ERANGE;
- goto out;
- }
-
- CDEBUG(D_OTHER,
- "lrh_index: %d lrh_len: %d (%d remains)\n",
- rec->lrh_index, rec->lrh_len,
- (int)(buf + chunk_size - (char *)rec));
-
- loghandle->lgh_cur_idx = rec->lrh_index;
- loghandle->lgh_cur_offset = (char *)rec - (char *)buf +
- chunk_offset;
-
- /* if set, process the callback on this record */
- if (ext2_test_bit(index, LLOG_HDR_BITMAP(llh))) {
- rc = lpi->lpi_cb(lpi->lpi_env, loghandle, rec,
- lpi->lpi_cbdata);
- last_called_index = index;
- if (rc)
- goto out;
- }
-
- /* exit if the last index is reached */
- if (index >= last_index) {
- rc = 0;
- goto out;
- }
- index++;
- }
- }
-
-out:
- if (cd)
- cd->lpcd_last_idx = last_called_index;
-
- kfree(buf);
- lpi->lpi_rc = rc;
- return 0;
-}
-
-static int llog_process_thread_daemonize(void *arg)
-{
- struct llog_process_info *lpi = arg;
- struct lu_env env;
- int rc;
-
- unshare_fs_struct();
-
- /* client env has no keys, tags is just 0 */
- rc = lu_env_init(&env, LCT_LOCAL | LCT_MG_THREAD);
- if (rc)
- goto out;
- lpi->lpi_env = &env;
-
- rc = llog_process_thread(arg);
-
- lu_env_fini(&env);
-out:
- complete(&lpi->lpi_completion);
- return rc;
-}
-
-int llog_process_or_fork(const struct lu_env *env,
- struct llog_handle *loghandle,
- llog_cb_t cb, void *data, void *catdata, bool fork)
-{
- struct llog_process_info *lpi;
- int rc;
-
- lpi = kzalloc(sizeof(*lpi), GFP_NOFS);
- if (!lpi)
- return -ENOMEM;
- lpi->lpi_loghandle = loghandle;
- lpi->lpi_cb = cb;
- lpi->lpi_cbdata = data;
- lpi->lpi_catdata = catdata;
-
- if (fork) {
- struct task_struct *task;
-
- /* The new thread can't use parent env,
- * init the new one in llog_process_thread_daemonize.
- */
- lpi->lpi_env = NULL;
- init_completion(&lpi->lpi_completion);
- task = kthread_run(llog_process_thread_daemonize, lpi,
- "llog_process_thread");
- if (IS_ERR(task)) {
- rc = PTR_ERR(task);
- CERROR("%s: cannot start thread: rc = %d\n",
- loghandle->lgh_ctxt->loc_obd->obd_name, rc);
- goto out_lpi;
- }
- wait_for_completion(&lpi->lpi_completion);
- } else {
- lpi->lpi_env = env;
- llog_process_thread(lpi);
- }
- rc = lpi->lpi_rc;
-out_lpi:
- kfree(lpi);
- return rc;
-}
-EXPORT_SYMBOL(llog_process_or_fork);
-
-int llog_process(const struct lu_env *env, struct llog_handle *loghandle,
- llog_cb_t cb, void *data, void *catdata)
-{
- return llog_process_or_fork(env, loghandle, cb, data, catdata, true);
-}
-EXPORT_SYMBOL(llog_process);
-
-int llog_open(const struct lu_env *env, struct llog_ctxt *ctxt,
- struct llog_handle **lgh, struct llog_logid *logid,
- char *name, enum llog_open_param open_param)
-{
- const struct cred *old_cred = NULL;
- int rc;
-
- LASSERT(ctxt);
- LASSERT(ctxt->loc_logops);
-
- if (!ctxt->loc_logops->lop_open) {
- *lgh = NULL;
- return -EOPNOTSUPP;
- }
-
- *lgh = llog_alloc_handle();
- if (!*lgh)
- return -ENOMEM;
- (*lgh)->lgh_ctxt = ctxt;
- (*lgh)->lgh_logops = ctxt->loc_logops;
-
- if (cap_raised(current_cap(), CAP_SYS_RESOURCE)) {
- struct cred *cred = prepare_creds();
-
- if (cred) {
- cap_raise(cred->cap_effective, CAP_SYS_RESOURCE);
- old_cred = override_creds(cred);
- }
- }
- rc = ctxt->loc_logops->lop_open(env, *lgh, logid, name, open_param);
- if (old_cred)
- revert_creds(old_cred);
-
- if (rc) {
- llog_free_handle(*lgh);
- *lgh = NULL;
- }
- return rc;
-}
-EXPORT_SYMBOL(llog_open);
-
-int llog_close(const struct lu_env *env, struct llog_handle *loghandle)
-{
- struct llog_operations *lop;
- int rc;
-
- rc = llog_handle2ops(loghandle, &lop);
- if (rc)
- goto out;
- if (!lop->lop_close) {
- rc = -EOPNOTSUPP;
- goto out;
- }
- rc = lop->lop_close(env, loghandle);
-out:
- llog_handle_put(loghandle);
- return rc;
-}
-EXPORT_SYMBOL(llog_close);
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c
deleted file mode 100644
index d9c63adff206..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c
+++ /dev/null
@@ -1,236 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/llog_cat.c
- *
- * OST<->MDS recovery logging infrastructure.
- *
- * Invariants in implementation:
- * - we do not share logs among different OST<->MDS connections, so that
- * if an OST or MDS fails it need only look at log(s) relevant to itself
- *
- * Author: Andreas Dilger <adilger@clusterfs.com>
- * Author: Alexey Zhuravlev <alexey.zhuravlev@intel.com>
- * Author: Mikhail Pershin <mike.pershin@intel.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LOG
-
-#include <obd_class.h>
-
-#include "llog_internal.h"
-
-/* Open an existent log handle and add it to the open list.
- * This log handle will be closed when all of the records in it are removed.
- *
- * Assumes caller has already pushed us into the kernel context and is locking.
- * We return a lock on the handle to ensure nobody yanks it from us.
- *
- * This takes extra reference on llog_handle via llog_handle_get() and require
- * this reference to be put by caller using llog_handle_put()
- */
-static int llog_cat_id2handle(const struct lu_env *env,
- struct llog_handle *cathandle,
- struct llog_handle **res,
- struct llog_logid *logid)
-{
- struct llog_handle *loghandle;
- enum llog_flag fmt;
- int rc = 0;
-
- if (!cathandle)
- return -EBADF;
-
- fmt = cathandle->lgh_hdr->llh_flags & LLOG_F_EXT_MASK;
- down_write(&cathandle->lgh_lock);
- list_for_each_entry(loghandle, &cathandle->u.chd.chd_head,
- u.phd.phd_entry) {
- struct llog_logid *cgl = &loghandle->lgh_id;
-
- if (ostid_id(&cgl->lgl_oi) == ostid_id(&logid->lgl_oi) &&
- ostid_seq(&cgl->lgl_oi) == ostid_seq(&logid->lgl_oi)) {
- if (cgl->lgl_ogen != logid->lgl_ogen) {
- CERROR("%s: log " DOSTID " generation %x != %x\n",
- loghandle->lgh_ctxt->loc_obd->obd_name,
- POSTID(&logid->lgl_oi), cgl->lgl_ogen,
- logid->lgl_ogen);
- continue;
- }
- loghandle->u.phd.phd_cat_handle = cathandle;
- up_write(&cathandle->lgh_lock);
- rc = 0;
- goto out;
- }
- }
- up_write(&cathandle->lgh_lock);
-
- rc = llog_open(env, cathandle->lgh_ctxt, &loghandle, logid, NULL,
- LLOG_OPEN_EXISTS);
- if (rc < 0) {
- CERROR("%s: error opening log id " DOSTID ":%x: rc = %d\n",
- cathandle->lgh_ctxt->loc_obd->obd_name,
- POSTID(&logid->lgl_oi), logid->lgl_ogen, rc);
- return rc;
- }
-
- rc = llog_init_handle(env, loghandle, fmt | LLOG_F_IS_PLAIN, NULL);
- if (rc < 0) {
- llog_close(env, loghandle);
- loghandle = NULL;
- return rc;
- }
-
- down_write(&cathandle->lgh_lock);
- list_add_tail(&loghandle->u.phd.phd_entry, &cathandle->u.chd.chd_head);
- up_write(&cathandle->lgh_lock);
-
- loghandle->u.phd.phd_cat_handle = cathandle;
- loghandle->u.phd.phd_cookie.lgc_lgl = cathandle->lgh_id;
- loghandle->u.phd.phd_cookie.lgc_index =
- loghandle->lgh_hdr->llh_cat_idx;
-out:
- llog_handle_get(loghandle);
- *res = loghandle;
- return 0;
-}
-
-int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle)
-{
- struct llog_handle *loghandle, *n;
-
- list_for_each_entry_safe(loghandle, n, &cathandle->u.chd.chd_head,
- u.phd.phd_entry) {
- /* unlink open-not-created llogs */
- list_del_init(&loghandle->u.phd.phd_entry);
- llog_close(env, loghandle);
- }
- /* if handle was stored in ctxt, remove it too */
- if (cathandle->lgh_ctxt->loc_handle == cathandle)
- cathandle->lgh_ctxt->loc_handle = NULL;
- return llog_close(env, cathandle);
-}
-EXPORT_SYMBOL(llog_cat_close);
-
-static int llog_cat_process_cb(const struct lu_env *env,
- struct llog_handle *cat_llh,
- struct llog_rec_hdr *rec, void *data)
-{
- struct llog_process_data *d = data;
- struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
- struct llog_handle *llh;
- int rc;
-
- if (rec->lrh_type != LLOG_LOGID_MAGIC) {
- CERROR("invalid record in catalog\n");
- return -EINVAL;
- }
- CDEBUG(D_HA, "processing log " DOSTID ":%x at index %u of catalog "
- DOSTID "\n", POSTID(&lir->lid_id.lgl_oi), lir->lid_id.lgl_ogen,
- rec->lrh_index, POSTID(&cat_llh->lgh_id.lgl_oi));
-
- rc = llog_cat_id2handle(env, cat_llh, &llh, &lir->lid_id);
- if (rc) {
- CERROR("%s: cannot find handle for llog " DOSTID ": %d\n",
- cat_llh->lgh_ctxt->loc_obd->obd_name,
- POSTID(&lir->lid_id.lgl_oi), rc);
- return rc;
- }
-
- if (rec->lrh_index < d->lpd_startcat)
- /* Skip processing of the logs until startcat */
- rc = 0;
- else if (d->lpd_startidx > 0) {
- struct llog_process_cat_data cd;
-
- cd.lpcd_first_idx = d->lpd_startidx;
- cd.lpcd_last_idx = 0;
- rc = llog_process_or_fork(env, llh, d->lpd_cb, d->lpd_data,
- &cd, false);
- /* Continue processing the next log from idx 0 */
- d->lpd_startidx = 0;
- } else {
- rc = llog_process_or_fork(env, llh, d->lpd_cb, d->lpd_data,
- NULL, false);
- }
-
- llog_handle_put(llh);
-
- return rc;
-}
-
-static int llog_cat_process_or_fork(const struct lu_env *env,
- struct llog_handle *cat_llh,
- llog_cb_t cb, void *data, int startcat,
- int startidx, bool fork)
-{
- struct llog_process_data d;
- struct llog_log_hdr *llh = cat_llh->lgh_hdr;
- int rc;
-
- LASSERT(llh->llh_flags & LLOG_F_IS_CAT);
- d.lpd_data = data;
- d.lpd_cb = cb;
- d.lpd_startcat = startcat;
- d.lpd_startidx = startidx;
-
- if (llh->llh_cat_idx > cat_llh->lgh_last_idx) {
- struct llog_process_cat_data cd;
-
- CWARN("catlog " DOSTID " crosses index zero\n",
- POSTID(&cat_llh->lgh_id.lgl_oi));
-
- cd.lpcd_first_idx = llh->llh_cat_idx;
- cd.lpcd_last_idx = 0;
- rc = llog_process_or_fork(env, cat_llh, llog_cat_process_cb,
- &d, &cd, fork);
- if (rc != 0)
- return rc;
-
- cd.lpcd_first_idx = 0;
- cd.lpcd_last_idx = cat_llh->lgh_last_idx;
- rc = llog_process_or_fork(env, cat_llh, llog_cat_process_cb,
- &d, &cd, fork);
- } else {
- rc = llog_process_or_fork(env, cat_llh, llog_cat_process_cb,
- &d, NULL, fork);
- }
-
- return rc;
-}
-
-int llog_cat_process(const struct lu_env *env, struct llog_handle *cat_llh,
- llog_cb_t cb, void *data, int startcat, int startidx)
-{
- return llog_cat_process_or_fork(env, cat_llh, cb, data, startcat,
- startidx, false);
-}
-EXPORT_SYMBOL(llog_cat_process);
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_internal.h b/drivers/staging/lustre/lustre/obdclass/llog_internal.h
deleted file mode 100644
index 4991d4e589dc..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/llog_internal.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#ifndef __LLOG_INTERNAL_H__
-#define __LLOG_INTERNAL_H__
-
-#include <lustre_log.h>
-
-struct llog_process_info {
- struct llog_handle *lpi_loghandle;
- llog_cb_t lpi_cb;
- void *lpi_cbdata;
- void *lpi_catdata;
- int lpi_rc;
- struct completion lpi_completion;
- const struct lu_env *lpi_env;
-
-};
-
-struct llog_thread_info {
- struct lu_attr lgi_attr;
- struct lu_fid lgi_fid;
- struct lu_buf lgi_buf;
- loff_t lgi_off;
- struct llog_rec_hdr lgi_lrh;
- struct llog_rec_tail lgi_tail;
-};
-
-extern struct lu_context_key llog_thread_key;
-
-int llog_info_init(void);
-void llog_info_fini(void);
-
-void llog_handle_get(struct llog_handle *loghandle);
-void llog_handle_put(struct llog_handle *loghandle);
-int class_config_dump_handler(const struct lu_env *env,
- struct llog_handle *handle,
- struct llog_rec_hdr *rec, void *data);
-int llog_process_or_fork(const struct lu_env *env,
- struct llog_handle *loghandle,
- llog_cb_t cb, void *data, void *catdata, bool fork);
-int llog_cat_cleanup(const struct lu_env *env, struct llog_handle *cathandle,
- struct llog_handle *loghandle, int index);
-
-static inline struct llog_rec_hdr *llog_rec_hdr_next(struct llog_rec_hdr *rec)
-{
- return (struct llog_rec_hdr *)((char *)rec + rec->lrh_len);
-}
-#endif
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_obd.c b/drivers/staging/lustre/lustre/obdclass/llog_obd.c
deleted file mode 100644
index 26aea114a29b..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/llog_obd.c
+++ /dev/null
@@ -1,225 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LOG
-
-#include <obd_class.h>
-#include <lustre_log.h>
-#include "llog_internal.h"
-
-/* helper functions for calling the llog obd methods */
-static struct llog_ctxt *llog_new_ctxt(struct obd_device *obd)
-{
- struct llog_ctxt *ctxt;
-
- ctxt = kzalloc(sizeof(*ctxt), GFP_NOFS);
- if (!ctxt)
- return NULL;
-
- ctxt->loc_obd = obd;
- atomic_set(&ctxt->loc_refcount, 1);
-
- return ctxt;
-}
-
-static void llog_ctxt_destroy(struct llog_ctxt *ctxt)
-{
- if (ctxt->loc_exp) {
- class_export_put(ctxt->loc_exp);
- ctxt->loc_exp = NULL;
- }
- if (ctxt->loc_imp) {
- class_import_put(ctxt->loc_imp);
- ctxt->loc_imp = NULL;
- }
- kfree(ctxt);
-}
-
-int __llog_ctxt_put(const struct lu_env *env, struct llog_ctxt *ctxt)
-{
- struct obd_llog_group *olg = ctxt->loc_olg;
- struct obd_device *obd;
- int rc = 0;
-
- spin_lock(&olg->olg_lock);
- if (!atomic_dec_and_test(&ctxt->loc_refcount)) {
- spin_unlock(&olg->olg_lock);
- return rc;
- }
- olg->olg_ctxts[ctxt->loc_idx] = NULL;
- spin_unlock(&olg->olg_lock);
-
- obd = ctxt->loc_obd;
- spin_lock(&obd->obd_dev_lock);
- /* sync with llog ctxt user thread */
- spin_unlock(&obd->obd_dev_lock);
-
- /* obd->obd_starting is needed for the case of cleanup
- * in error case while obd is starting up.
- */
- LASSERTF(obd->obd_starting == 1 ||
- obd->obd_stopping == 1 || obd->obd_set_up == 0,
- "wrong obd state: %d/%d/%d\n", !!obd->obd_starting,
- !!obd->obd_stopping, !!obd->obd_set_up);
-
- /* cleanup the llog ctxt here */
- if (CTXTP(ctxt, cleanup))
- rc = CTXTP(ctxt, cleanup)(env, ctxt);
-
- llog_ctxt_destroy(ctxt);
- wake_up(&olg->olg_waitq);
- return rc;
-}
-EXPORT_SYMBOL(__llog_ctxt_put);
-
-int llog_cleanup(const struct lu_env *env, struct llog_ctxt *ctxt)
-{
- struct obd_llog_group *olg;
- int rc, idx;
-
- olg = ctxt->loc_olg;
- LASSERT(olg);
- LASSERT(olg != LP_POISON);
-
- idx = ctxt->loc_idx;
-
- /*
- * Banlance the ctxt get when calling llog_cleanup()
- */
- LASSERT(atomic_read(&ctxt->loc_refcount) < LI_POISON);
- LASSERT(atomic_read(&ctxt->loc_refcount) > 1);
- llog_ctxt_put(ctxt);
-
- /*
- * Try to free the ctxt.
- */
- rc = __llog_ctxt_put(env, ctxt);
- if (rc)
- CERROR("Error %d while cleaning up ctxt %p\n",
- rc, ctxt);
-
- l_wait_event_abortable(olg->olg_waitq,
- llog_group_ctxt_null(olg, idx));
-
- return rc;
-}
-EXPORT_SYMBOL(llog_cleanup);
-
-int llog_setup(const struct lu_env *env, struct obd_device *obd,
- struct obd_llog_group *olg, int index,
- struct obd_device *disk_obd, struct llog_operations *op)
-{
- struct llog_ctxt *ctxt;
- int rc = 0;
-
- if (index < 0 || index >= LLOG_MAX_CTXTS)
- return -EINVAL;
-
- LASSERT(olg);
-
- ctxt = llog_new_ctxt(obd);
- if (!ctxt)
- return -ENOMEM;
-
- ctxt->loc_obd = obd;
- ctxt->loc_olg = olg;
- ctxt->loc_idx = index;
- ctxt->loc_logops = op;
- mutex_init(&ctxt->loc_mutex);
- ctxt->loc_exp = class_export_get(disk_obd->obd_self_export);
- ctxt->loc_flags = LLOG_CTXT_FLAG_UNINITIALIZED;
- ctxt->loc_chunk_size = LLOG_MIN_CHUNK_SIZE;
-
- rc = llog_group_set_ctxt(olg, ctxt, index);
- if (rc) {
- llog_ctxt_destroy(ctxt);
- if (rc == -EEXIST) {
- ctxt = llog_group_get_ctxt(olg, index);
- if (ctxt) {
- /*
- * mds_lov_update_desc() might call here multiple
- * times. So if the llog is already set up then
- * don't to do it again.
- */
- CDEBUG(D_CONFIG, "obd %s ctxt %d already set up\n",
- obd->obd_name, index);
- LASSERT(ctxt->loc_olg == olg);
- LASSERT(ctxt->loc_obd == obd);
- LASSERT(ctxt->loc_exp == disk_obd->obd_self_export);
- LASSERT(ctxt->loc_logops == op);
- llog_ctxt_put(ctxt);
- }
- rc = 0;
- }
- return rc;
- }
-
- if (op->lop_setup) {
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LLOG_SETUP))
- rc = -EOPNOTSUPP;
- else
- rc = op->lop_setup(env, obd, olg, index, disk_obd);
- }
-
- if (rc) {
- CERROR("%s: ctxt %d lop_setup=%p failed: rc = %d\n",
- obd->obd_name, index, op->lop_setup, rc);
- llog_group_clear_ctxt(olg, index);
- llog_ctxt_destroy(ctxt);
- } else {
- CDEBUG(D_CONFIG, "obd %s ctxt %d is initialized\n",
- obd->obd_name, index);
- ctxt->loc_flags &= ~LLOG_CTXT_FLAG_UNINITIALIZED;
- }
-
- return rc;
-}
-EXPORT_SYMBOL(llog_setup);
-
-/* context key constructor/destructor: llog_key_init, llog_key_fini */
-LU_KEY_INIT_FINI(llog, struct llog_thread_info);
-/* context key: llog_thread_key */
-LU_CONTEXT_KEY_DEFINE(llog, LCT_MD_THREAD | LCT_MG_THREAD | LCT_LOCAL);
-LU_KEY_INIT_GENERIC(llog);
-
-int llog_info_init(void)
-{
- llog_key_init_generic(&llog_thread_key, NULL);
- lu_context_key_register(&llog_thread_key);
- return 0;
-}
-
-void llog_info_fini(void)
-{
- lu_context_key_degister(&llog_thread_key);
-}
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c
deleted file mode 100644
index b431c3408fe4..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c
+++ /dev/null
@@ -1,412 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/llog_swab.c
- *
- * Swabbing of llog datatypes (from disk or over the wire).
- *
- * Author: jacob berkman <jacob@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LOG
-
-#include <llog_swab.h>
-#include <lustre_log.h>
-
-static void print_llogd_body(struct llogd_body *d)
-{
- CDEBUG(D_OTHER, "llogd body: %p\n", d);
- CDEBUG(D_OTHER, "\tlgd_logid.lgl_oi: " DOSTID "\n",
- POSTID(&d->lgd_logid.lgl_oi));
- CDEBUG(D_OTHER, "\tlgd_logid.lgl_ogen: %#x\n", d->lgd_logid.lgl_ogen);
- CDEBUG(D_OTHER, "\tlgd_ctxt_idx: %#x\n", d->lgd_ctxt_idx);
- CDEBUG(D_OTHER, "\tlgd_llh_flags: %#x\n", d->lgd_llh_flags);
- CDEBUG(D_OTHER, "\tlgd_index: %#x\n", d->lgd_index);
- CDEBUG(D_OTHER, "\tlgd_saved_index: %#x\n", d->lgd_saved_index);
- CDEBUG(D_OTHER, "\tlgd_len: %#x\n", d->lgd_len);
- CDEBUG(D_OTHER, "\tlgd_cur_offset: %#llx\n", d->lgd_cur_offset);
-}
-
-void lustre_swab_lu_fid(struct lu_fid *fid)
-{
- __swab64s(&fid->f_seq);
- __swab32s(&fid->f_oid);
- __swab32s(&fid->f_ver);
-}
-EXPORT_SYMBOL(lustre_swab_lu_fid);
-
-void lustre_swab_ost_id(struct ost_id *oid)
-{
- if (fid_seq_is_mdt0(oid->oi.oi_seq)) {
- __swab64s(&oid->oi.oi_id);
- __swab64s(&oid->oi.oi_seq);
- } else {
- lustre_swab_lu_fid(&oid->oi_fid);
- }
-}
-EXPORT_SYMBOL(lustre_swab_ost_id);
-
-static void lustre_swab_llog_id(struct llog_logid *log_id)
-{
- __swab64s(&log_id->lgl_oi.oi.oi_id);
- __swab64s(&log_id->lgl_oi.oi.oi_seq);
- __swab32s(&log_id->lgl_ogen);
-}
-
-void lustre_swab_llogd_body(struct llogd_body *d)
-{
- print_llogd_body(d);
- lustre_swab_llog_id(&d->lgd_logid);
- __swab32s(&d->lgd_ctxt_idx);
- __swab32s(&d->lgd_llh_flags);
- __swab32s(&d->lgd_index);
- __swab32s(&d->lgd_saved_index);
- __swab32s(&d->lgd_len);
- __swab64s(&d->lgd_cur_offset);
- print_llogd_body(d);
-}
-EXPORT_SYMBOL(lustre_swab_llogd_body);
-
-void lustre_swab_llogd_conn_body(struct llogd_conn_body *d)
-{
- __swab64s(&d->lgdc_gen.mnt_cnt);
- __swab64s(&d->lgdc_gen.conn_cnt);
- lustre_swab_llog_id(&d->lgdc_logid);
- __swab32s(&d->lgdc_ctxt_idx);
-}
-EXPORT_SYMBOL(lustre_swab_llogd_conn_body);
-
-static void lustre_swab_ll_fid(struct ll_fid *fid)
-{
- __swab64s(&fid->id);
- __swab32s(&fid->generation);
- __swab32s(&fid->f_type);
-}
-
-void lustre_swab_lu_seq_range(struct lu_seq_range *range)
-{
- __swab64s(&range->lsr_start);
- __swab64s(&range->lsr_end);
- __swab32s(&range->lsr_index);
- __swab32s(&range->lsr_flags);
-}
-EXPORT_SYMBOL(lustre_swab_lu_seq_range);
-
-void lustre_swab_llog_rec(struct llog_rec_hdr *rec)
-{
- struct llog_rec_tail *tail = NULL;
-
- __swab32s(&rec->lrh_len);
- __swab32s(&rec->lrh_index);
- __swab32s(&rec->lrh_type);
- __swab32s(&rec->lrh_id);
-
- switch (rec->lrh_type) {
- case OST_SZ_REC:
- {
- struct llog_size_change_rec *lsc =
- (struct llog_size_change_rec *)rec;
-
- lustre_swab_ll_fid(&lsc->lsc_fid);
- __swab32s(&lsc->lsc_ioepoch);
- tail = &lsc->lsc_tail;
- break;
- }
- case MDS_UNLINK_REC:
- {
- struct llog_unlink_rec *lur = (struct llog_unlink_rec *)rec;
-
- __swab64s(&lur->lur_oid);
- __swab32s(&lur->lur_oseq);
- __swab32s(&lur->lur_count);
- tail = &lur->lur_tail;
- break;
- }
- case MDS_UNLINK64_REC:
- {
- struct llog_unlink64_rec *lur =
- (struct llog_unlink64_rec *)rec;
-
- lustre_swab_lu_fid(&lur->lur_fid);
- __swab32s(&lur->lur_count);
- tail = &lur->lur_tail;
- break;
- }
- case CHANGELOG_REC:
- {
- struct llog_changelog_rec *cr =
- (struct llog_changelog_rec *)rec;
-
- __swab16s(&cr->cr.cr_namelen);
- __swab16s(&cr->cr.cr_flags);
- __swab32s(&cr->cr.cr_type);
- __swab64s(&cr->cr.cr_index);
- __swab64s(&cr->cr.cr_prev);
- __swab64s(&cr->cr.cr_time);
- lustre_swab_lu_fid(&cr->cr.cr_tfid);
- lustre_swab_lu_fid(&cr->cr.cr_pfid);
- if (cr->cr.cr_flags & CLF_RENAME) {
- struct changelog_ext_rename *rnm =
- changelog_rec_rename(&cr->cr);
-
- lustre_swab_lu_fid(&rnm->cr_sfid);
- lustre_swab_lu_fid(&rnm->cr_spfid);
- }
- /*
- * Because the tail follows a variable-length structure we need
- * to compute its location at runtime
- */
- tail = (struct llog_rec_tail *)((char *)&cr->cr +
- changelog_rec_size(&cr->cr) +
- cr->cr.cr_namelen);
- break;
- }
-
- case CHANGELOG_USER_REC:
- {
- struct llog_changelog_user_rec *cur =
- (struct llog_changelog_user_rec *)rec;
-
- __swab32s(&cur->cur_id);
- __swab64s(&cur->cur_endrec);
- tail = &cur->cur_tail;
- break;
- }
-
- case HSM_AGENT_REC: {
- struct llog_agent_req_rec *arr =
- (struct llog_agent_req_rec *)rec;
-
- __swab32s(&arr->arr_hai.hai_len);
- __swab32s(&arr->arr_hai.hai_action);
- lustre_swab_lu_fid(&arr->arr_hai.hai_fid);
- lustre_swab_lu_fid(&arr->arr_hai.hai_dfid);
- __swab64s(&arr->arr_hai.hai_cookie);
- __swab64s(&arr->arr_hai.hai_extent.offset);
- __swab64s(&arr->arr_hai.hai_extent.length);
- __swab64s(&arr->arr_hai.hai_gid);
- /* no swabing for opaque data */
- /* hai_data[0]; */
- break;
- }
-
- case MDS_SETATTR64_REC:
- {
- struct llog_setattr64_rec *lsr =
- (struct llog_setattr64_rec *)rec;
-
- lustre_swab_ost_id(&lsr->lsr_oi);
- __swab32s(&lsr->lsr_uid);
- __swab32s(&lsr->lsr_uid_h);
- __swab32s(&lsr->lsr_gid);
- __swab32s(&lsr->lsr_gid_h);
- __swab64s(&lsr->lsr_valid);
- tail = &lsr->lsr_tail;
- break;
- }
- case OBD_CFG_REC:
- /* these are swabbed as they are consumed */
- break;
- case LLOG_HDR_MAGIC:
- {
- struct llog_log_hdr *llh = (struct llog_log_hdr *)rec;
-
- __swab64s(&llh->llh_timestamp);
- __swab32s(&llh->llh_count);
- __swab32s(&llh->llh_bitmap_offset);
- __swab32s(&llh->llh_flags);
- __swab32s(&llh->llh_size);
- __swab32s(&llh->llh_cat_idx);
- tail = LLOG_HDR_TAIL(llh);
- break;
- }
- case LLOG_LOGID_MAGIC:
- {
- struct llog_logid_rec *lid = (struct llog_logid_rec *)rec;
-
- lustre_swab_llog_id(&lid->lid_id);
- tail = &lid->lid_tail;
- break;
- }
- case LLOG_GEN_REC:
- {
- struct llog_gen_rec *lgr = (struct llog_gen_rec *)rec;
-
- __swab64s(&lgr->lgr_gen.mnt_cnt);
- __swab64s(&lgr->lgr_gen.conn_cnt);
- tail = &lgr->lgr_tail;
- break;
- }
- case LLOG_PAD_MAGIC:
- break;
- default:
- CERROR("Unknown llog rec type %#x swabbing rec %p\n",
- rec->lrh_type, rec);
- }
-
- if (tail) {
- __swab32s(&tail->lrt_len);
- __swab32s(&tail->lrt_index);
- }
-}
-EXPORT_SYMBOL(lustre_swab_llog_rec);
-
-static void print_llog_hdr(struct llog_log_hdr *h)
-{
- CDEBUG(D_OTHER, "llog header: %p\n", h);
- CDEBUG(D_OTHER, "\tllh_hdr.lrh_index: %#x\n", h->llh_hdr.lrh_index);
- CDEBUG(D_OTHER, "\tllh_hdr.lrh_len: %#x\n", h->llh_hdr.lrh_len);
- CDEBUG(D_OTHER, "\tllh_hdr.lrh_type: %#x\n", h->llh_hdr.lrh_type);
- CDEBUG(D_OTHER, "\tllh_timestamp: %#llx\n", h->llh_timestamp);
- CDEBUG(D_OTHER, "\tllh_count: %#x\n", h->llh_count);
- CDEBUG(D_OTHER, "\tllh_bitmap_offset: %#x\n", h->llh_bitmap_offset);
- CDEBUG(D_OTHER, "\tllh_flags: %#x\n", h->llh_flags);
- CDEBUG(D_OTHER, "\tllh_size: %#x\n", h->llh_size);
- CDEBUG(D_OTHER, "\tllh_cat_idx: %#x\n", h->llh_cat_idx);
- CDEBUG(D_OTHER, "\tllh_tail.lrt_index: %#x\n",
- LLOG_HDR_TAIL(h)->lrt_index);
- CDEBUG(D_OTHER, "\tllh_tail.lrt_len: %#x\n",
- LLOG_HDR_TAIL(h)->lrt_len);
-}
-
-void lustre_swab_llog_hdr(struct llog_log_hdr *h)
-{
- print_llog_hdr(h);
-
- lustre_swab_llog_rec(&h->llh_hdr);
-
- print_llog_hdr(h);
-}
-EXPORT_SYMBOL(lustre_swab_llog_hdr);
-
-static void print_lustre_cfg(struct lustre_cfg *lcfg)
-{
- int i;
-
- if (!(libcfs_debug & D_OTHER)) /* don't loop on nothing */
- return;
- CDEBUG(D_OTHER, "lustre_cfg: %p\n", lcfg);
- CDEBUG(D_OTHER, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
-
- CDEBUG(D_OTHER, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
- CDEBUG(D_OTHER, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
- CDEBUG(D_OTHER, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
- CDEBUG(D_OTHER, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
-
- CDEBUG(D_OTHER, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
- if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
- for (i = 0; i < lcfg->lcfg_bufcount; i++)
- CDEBUG(D_OTHER, "\tlcfg->lcfg_buflens[%d]: %d\n",
- i, lcfg->lcfg_buflens[i]);
-}
-
-void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg)
-{
- int i;
-
- __swab32s(&lcfg->lcfg_version);
-
- if (lcfg->lcfg_version != LUSTRE_CFG_VERSION) {
- CERROR("not swabbing lustre_cfg version %#x (expecting %#x)\n",
- lcfg->lcfg_version, LUSTRE_CFG_VERSION);
- return;
- }
-
- __swab32s(&lcfg->lcfg_command);
- __swab32s(&lcfg->lcfg_num);
- __swab32s(&lcfg->lcfg_flags);
- __swab64s(&lcfg->lcfg_nid);
- __swab32s(&lcfg->lcfg_bufcount);
- for (i = 0; i < lcfg->lcfg_bufcount && i < LUSTRE_CFG_MAX_BUFCOUNT; i++)
- __swab32s(&lcfg->lcfg_buflens[i]);
-
- print_lustre_cfg(lcfg);
-}
-
-/* used only for compatibility with old on-disk cfg_marker data */
-struct cfg_marker32 {
- __u32 cm_step;
- __u32 cm_flags;
- __u32 cm_vers;
- __u32 padding;
- __u32 cm_createtime;
- __u32 cm_canceltime;
- char cm_tgtname[MTI_NAME_MAXLEN];
- char cm_comment[MTI_NAME_MAXLEN];
-};
-
-#define MTI_NAMELEN32 (MTI_NAME_MAXLEN - \
- (sizeof(struct cfg_marker) - sizeof(struct cfg_marker32)))
-
-void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size)
-{
- struct cfg_marker32 *cm32 = (struct cfg_marker32 *)marker;
-
- if (swab) {
- __swab32s(&marker->cm_step);
- __swab32s(&marker->cm_flags);
- __swab32s(&marker->cm_vers);
- }
- if (size == sizeof(*cm32)) {
- __u32 createtime, canceltime;
- /* There was a problem with the original declaration of
- * cfg_marker on 32-bit systems because it used time_t as
- * a wire protocol structure, and didn't verify this in
- * wirecheck. We now have to convert the offsets of the
- * later fields in order to work on 32- and 64-bit systems.
- *
- * Fortunately, the cm_comment field has no functional use
- * so can be sacrificed when converting the timestamp size.
- *
- * Overwrite fields from the end first, so they are not
- * clobbered, and use memmove() instead of memcpy() because
- * the source and target buffers overlap. bug 16771
- */
- createtime = cm32->cm_createtime;
- canceltime = cm32->cm_canceltime;
- memmove(marker->cm_comment, cm32->cm_comment, MTI_NAMELEN32);
- marker->cm_comment[MTI_NAMELEN32 - 1] = '\0';
- memmove(marker->cm_tgtname, cm32->cm_tgtname,
- sizeof(marker->cm_tgtname));
- if (swab) {
- __swab32s(&createtime);
- __swab32s(&canceltime);
- }
- marker->cm_createtime = createtime;
- marker->cm_canceltime = canceltime;
- CDEBUG(D_CONFIG, "Find old cfg_marker(Srv32b,Clt64b) for target %s, converting\n",
- marker->cm_tgtname);
- } else if (swab) {
- __swab64s(&marker->cm_createtime);
- __swab64s(&marker->cm_canceltime);
- }
-}
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_counters.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_counters.c
deleted file mode 100644
index c83b7d7f8e72..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_counters.c
+++ /dev/null
@@ -1,133 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, 2013, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/lprocfs_counters.c
- *
- * Lustre lprocfs counter routines
- *
- * Author: Andreas Dilger <andreas.dilger@intel.com>
- */
-
-#include <linux/module.h>
-#include <lprocfs_status.h>
-#include <obd_support.h>
-
-void lprocfs_counter_add(struct lprocfs_stats *stats, int idx, long amount)
-{
- struct lprocfs_counter *percpu_cntr;
- struct lprocfs_counter_header *header;
- int smp_id;
- unsigned long flags = 0;
-
- if (!stats)
- return;
-
- LASSERTF(0 <= idx && idx < stats->ls_num,
- "idx %d, ls_num %hu\n", idx, stats->ls_num);
-
- /* With per-client stats, statistics are allocated only for
- * single CPU area, so the smp_id should be 0 always.
- */
- smp_id = lprocfs_stats_lock(stats, LPROCFS_GET_SMP_ID, &flags);
- if (smp_id < 0)
- return;
-
- header = &stats->ls_cnt_header[idx];
- percpu_cntr = lprocfs_stats_counter_get(stats, smp_id, idx);
- percpu_cntr->lc_count++;
-
- if (header->lc_config & LPROCFS_CNTR_AVGMINMAX) {
- /*
- * lprocfs_counter_add() can be called in interrupt context,
- * as memory allocation could trigger memory shrinker call
- * ldlm_pool_shrink(), which calls lprocfs_counter_add().
- * LU-1727.
- *
- */
- if (in_interrupt() &&
- (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
- percpu_cntr->lc_sum_irq += amount;
- else
- percpu_cntr->lc_sum += amount;
-
- if (header->lc_config & LPROCFS_CNTR_STDDEV)
- percpu_cntr->lc_sumsquare += (__s64)amount * amount;
- if (amount < percpu_cntr->lc_min)
- percpu_cntr->lc_min = amount;
- if (amount > percpu_cntr->lc_max)
- percpu_cntr->lc_max = amount;
- }
- lprocfs_stats_unlock(stats, LPROCFS_GET_SMP_ID, &flags);
-}
-EXPORT_SYMBOL(lprocfs_counter_add);
-
-void lprocfs_counter_sub(struct lprocfs_stats *stats, int idx, long amount)
-{
- struct lprocfs_counter *percpu_cntr;
- struct lprocfs_counter_header *header;
- int smp_id;
- unsigned long flags = 0;
-
- if (!stats)
- return;
-
- LASSERTF(0 <= idx && idx < stats->ls_num,
- "idx %d, ls_num %hu\n", idx, stats->ls_num);
-
- /* With per-client stats, statistics are allocated only for
- * single CPU area, so the smp_id should be 0 always.
- */
- smp_id = lprocfs_stats_lock(stats, LPROCFS_GET_SMP_ID, &flags);
- if (smp_id < 0)
- return;
-
- header = &stats->ls_cnt_header[idx];
- percpu_cntr = lprocfs_stats_counter_get(stats, smp_id, idx);
- if (header->lc_config & LPROCFS_CNTR_AVGMINMAX) {
- /*
- * Sometimes we use RCU callbacks to free memory which calls
- * lprocfs_counter_sub(), and RCU callbacks may execute in
- * softirq context - right now that's the only case we're in
- * softirq context here, use separate counter for that.
- * bz20650.
- *
- */
- if (in_interrupt() &&
- (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
- percpu_cntr->lc_sum_irq -= amount;
- else
- percpu_cntr->lc_sum -= amount;
- }
- lprocfs_stats_unlock(stats, LPROCFS_GET_SMP_ID, &flags);
-}
-EXPORT_SYMBOL(lprocfs_counter_sub);
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
deleted file mode 100644
index 2ed350527398..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
+++ /dev/null
@@ -1,1810 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/lprocfs_status.c
- *
- * Author: Hariharan Thantry <thantry@users.sourceforge.net>
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <obd_class.h>
-#include <lprocfs_status.h>
-#include <uapi/linux/lustre/lustre_idl.h>
-#include <linux/seq_file.h>
-#include <linux/ctype.h>
-
-static const char * const obd_connect_names[] = {
- "read_only",
- "lov_index",
- "connect_from_mds",
- "write_grant",
- "server_lock",
- "version",
- "request_portal",
- "acl",
- "xattr",
- "create_on_write",
- "truncate_lock",
- "initial_transno",
- "inode_bit_locks",
- "join_file(obsolete)",
- "getattr_by_fid",
- "no_oh_for_devices",
- "remote_client",
- "remote_client_by_force",
- "max_byte_per_rpc",
- "64bit_qdata",
- "mds_capability",
- "oss_capability",
- "early_lock_cancel",
- "som",
- "adaptive_timeouts",
- "lru_resize",
- "mds_mds_connection",
- "real_conn",
- "change_qunit_size",
- "alt_checksum_algorithm",
- "fid_is_enabled",
- "version_recovery",
- "pools",
- "grant_shrink",
- "skip_orphan",
- "large_ea",
- "full20",
- "layout_lock",
- "64bithash",
- "object_max_bytes",
- "imp_recov",
- "jobstats",
- "umask",
- "einprogress",
- "grant_param",
- "flock_owner",
- "lvb_type",
- "nanoseconds_times",
- "lightweight_conn",
- "short_io",
- "pingless",
- "flock_deadlock",
- "disp_stripe",
- "open_by_fid",
- "lfsck",
- "unknown",
- "unlink_close",
- "multi_mod_rpcs",
- "dir_stripe",
- "subtree",
- "lock_ahead",
- "bulk_mbits",
- "compact_obdo",
- "second_flags",
- NULL
-};
-
-int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
-{
- __u64 mask = 1;
- int i, ret = 0;
-
- for (i = 0; obd_connect_names[i]; i++, mask <<= 1) {
- if (flags & mask)
- ret += snprintf(page + ret, count - ret, "%s%s",
- ret ? sep : "", obd_connect_names[i]);
- }
- if (flags & ~(mask - 1))
- ret += snprintf(page + ret, count - ret,
- "%sunknown flags %#llx",
- ret ? sep : "", flags & ~(mask - 1));
- return ret;
-}
-EXPORT_SYMBOL(obd_connect_flags2str);
-
-static void obd_connect_data_seqprint(struct seq_file *m,
- struct obd_connect_data *ocd)
-{
- u64 flags;
-
- LASSERT(ocd);
- flags = ocd->ocd_connect_flags;
-
- seq_printf(m, " connect_data:\n"
- " flags: %llx\n"
- " instance: %u\n",
- ocd->ocd_connect_flags,
- ocd->ocd_instance);
- if (flags & OBD_CONNECT_VERSION)
- seq_printf(m, " target_version: %u.%u.%u.%u\n",
- OBD_OCD_VERSION_MAJOR(ocd->ocd_version),
- OBD_OCD_VERSION_MINOR(ocd->ocd_version),
- OBD_OCD_VERSION_PATCH(ocd->ocd_version),
- OBD_OCD_VERSION_FIX(ocd->ocd_version));
- if (flags & OBD_CONNECT_MDS)
- seq_printf(m, " mdt_index: %d\n", ocd->ocd_group);
- if (flags & OBD_CONNECT_GRANT)
- seq_printf(m, " initial_grant: %d\n", ocd->ocd_grant);
- if (flags & OBD_CONNECT_INDEX)
- seq_printf(m, " target_index: %u\n", ocd->ocd_index);
- if (flags & OBD_CONNECT_BRW_SIZE)
- seq_printf(m, " max_brw_size: %d\n", ocd->ocd_brw_size);
- if (flags & OBD_CONNECT_IBITS)
- seq_printf(m, " ibits_known: %llx\n",
- ocd->ocd_ibits_known);
- if (flags & OBD_CONNECT_GRANT_PARAM)
- seq_printf(m, " grant_block_size: %d\n"
- " grant_inode_size: %d\n"
- " grant_extent_overhead: %d\n",
- ocd->ocd_blocksize,
- ocd->ocd_inodespace,
- ocd->ocd_grant_extent);
- if (flags & OBD_CONNECT_TRANSNO)
- seq_printf(m, " first_transno: %llx\n",
- ocd->ocd_transno);
- if (flags & OBD_CONNECT_CKSUM)
- seq_printf(m, " cksum_types: %#x\n",
- ocd->ocd_cksum_types);
- if (flags & OBD_CONNECT_MAX_EASIZE)
- seq_printf(m, " max_easize: %d\n", ocd->ocd_max_easize);
- if (flags & OBD_CONNECT_MAXBYTES)
- seq_printf(m, " max_object_bytes: %llx\n",
- ocd->ocd_maxbytes);
- if (flags & OBD_CONNECT_MULTIMODRPCS)
- seq_printf(m, " max_mod_rpcs: %hu\n",
- ocd->ocd_maxmodrpcs);
-}
-
-int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
- int mult)
-{
- long decimal_val, frac_val;
- int prtn;
-
- if (count < 10)
- return -EINVAL;
-
- decimal_val = val / mult;
- prtn = snprintf(buffer, count, "%ld", decimal_val);
- frac_val = val % mult;
-
- if (prtn < (count - 4) && frac_val > 0) {
- long temp_frac;
- int i, temp_mult = 1, frac_bits = 0;
-
- temp_frac = frac_val * 10;
- buffer[prtn++] = '.';
- while (frac_bits < 2 && (temp_frac / mult) < 1) {
- /* only reserved 2 bits fraction */
- buffer[prtn++] = '0';
- temp_frac *= 10;
- frac_bits++;
- }
- /*
- * Need to think these cases :
- * 1. #echo x.00 > /sys/xxx output result : x
- * 2. #echo x.0x > /sys/xxx output result : x.0x
- * 3. #echo x.x0 > /sys/xxx output result : x.x
- * 4. #echo x.xx > /sys/xxx output result : x.xx
- * Only reserved 2 bits fraction.
- */
- for (i = 0; i < (5 - prtn); i++)
- temp_mult *= 10;
-
- frac_bits = min((int)count - prtn, 3 - frac_bits);
- prtn += snprintf(buffer + prtn, frac_bits, "%ld",
- frac_val * temp_mult / mult);
-
- prtn--;
- while (buffer[prtn] < '1' || buffer[prtn] > '9') {
- prtn--;
- if (buffer[prtn] == '.') {
- prtn--;
- break;
- }
- }
- prtn++;
- }
- buffer[prtn++] = '\n';
- return prtn;
-}
-EXPORT_SYMBOL(lprocfs_read_frac_helper);
-
-int lprocfs_write_frac_helper(const char __user *buffer, unsigned long count,
- int *val, int mult)
-{
- char kernbuf[20], *end, *pbuf;
-
- if (count > (sizeof(kernbuf) - 1))
- return -EINVAL;
-
- if (copy_from_user(kernbuf, buffer, count))
- return -EFAULT;
-
- kernbuf[count] = '\0';
- pbuf = kernbuf;
- if (*pbuf == '-') {
- mult = -mult;
- pbuf++;
- }
-
- *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
- if (pbuf == end)
- return -EINVAL;
-
- if (end && *end == '.') {
- int temp_val, pow = 1;
- int i;
-
- pbuf = end + 1;
- if (strlen(pbuf) > 5)
- pbuf[5] = '\0'; /*only allow 5bits fractional*/
-
- temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
-
- if (pbuf < end) {
- for (i = 0; i < (end - pbuf); i++)
- pow *= 10;
-
- *val += temp_val / pow;
- }
- }
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_write_frac_helper);
-
-static int lprocfs_no_percpu_stats;
-module_param(lprocfs_no_percpu_stats, int, 0644);
-MODULE_PARM_DESC(lprocfs_no_percpu_stats, "Do not alloc percpu data for lprocfs stats");
-
-#define MAX_STRING_SIZE 128
-
-int lprocfs_single_release(struct inode *inode, struct file *file)
-{
- return single_release(inode, file);
-}
-EXPORT_SYMBOL(lprocfs_single_release);
-
-int lprocfs_seq_release(struct inode *inode, struct file *file)
-{
- return seq_release(inode, file);
-}
-EXPORT_SYMBOL(lprocfs_seq_release);
-
-/* lprocfs API calls */
-
-struct dentry *ldebugfs_add_simple(struct dentry *root,
- char *name, void *data,
- const struct file_operations *fops)
-{
- struct dentry *entry;
- umode_t mode = 0;
-
- if (!root || !name || !fops)
- return ERR_PTR(-EINVAL);
-
- if (fops->read)
- mode = 0444;
- if (fops->write)
- mode |= 0200;
- entry = debugfs_create_file(name, mode, root, data, fops);
- if (IS_ERR_OR_NULL(entry)) {
- CERROR("LprocFS: No memory to create <debugfs> entry %s\n", name);
- return entry ?: ERR_PTR(-ENOMEM);
- }
- return entry;
-}
-EXPORT_SYMBOL_GPL(ldebugfs_add_simple);
-
-static const struct file_operations lprocfs_generic_fops = { };
-
-int ldebugfs_add_vars(struct dentry *parent,
- struct lprocfs_vars *list,
- void *data)
-{
- if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(list))
- return -EINVAL;
-
- while (list->name) {
- struct dentry *entry;
- umode_t mode = 0;
-
- if (list->proc_mode != 0000) {
- mode = list->proc_mode;
- } else if (list->fops) {
- if (list->fops->read)
- mode = 0444;
- if (list->fops->write)
- mode |= 0200;
- }
- entry = debugfs_create_file(list->name, mode, parent,
- list->data ?: data,
- list->fops ?: &lprocfs_generic_fops
- );
- if (IS_ERR_OR_NULL(entry))
- return entry ? PTR_ERR(entry) : -ENOMEM;
- list++;
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(ldebugfs_add_vars);
-
-void ldebugfs_remove(struct dentry **entryp)
-{
- debugfs_remove_recursive(*entryp);
- *entryp = NULL;
-}
-EXPORT_SYMBOL_GPL(ldebugfs_remove);
-
-struct dentry *ldebugfs_register(const char *name,
- struct dentry *parent,
- struct lprocfs_vars *list, void *data)
-{
- struct dentry *entry;
-
- entry = debugfs_create_dir(name, parent);
- if (IS_ERR_OR_NULL(entry)) {
- entry = entry ?: ERR_PTR(-ENOMEM);
- goto out;
- }
-
- if (!IS_ERR_OR_NULL(list)) {
- int rc;
-
- rc = ldebugfs_add_vars(entry, list, data);
- if (rc != 0) {
- debugfs_remove(entry);
- entry = ERR_PTR(rc);
- }
- }
-out:
- return entry;
-}
-EXPORT_SYMBOL_GPL(ldebugfs_register);
-
-/* Generic callbacks */
-static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
-
- return sprintf(buf, "%s\n", obd->obd_uuid.uuid);
-}
-LUSTRE_RO_ATTR(uuid);
-
-static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
- struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
- if (!rc)
- return sprintf(buf, "%u\n", osfs.os_bsize);
-
- return rc;
-}
-LUSTRE_RO_ATTR(blocksize);
-
-static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
- struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
- if (!rc) {
- __u32 blk_size = osfs.os_bsize >> 10;
- __u64 result = osfs.os_blocks;
-
- while (blk_size >>= 1)
- result <<= 1;
-
- return sprintf(buf, "%llu\n", result);
- }
-
- return rc;
-}
-LUSTRE_RO_ATTR(kbytestotal);
-
-static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
- struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
- if (!rc) {
- __u32 blk_size = osfs.os_bsize >> 10;
- __u64 result = osfs.os_bfree;
-
- while (blk_size >>= 1)
- result <<= 1;
-
- return sprintf(buf, "%llu\n", result);
- }
-
- return rc;
-}
-LUSTRE_RO_ATTR(kbytesfree);
-
-static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
- struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
- if (!rc) {
- __u32 blk_size = osfs.os_bsize >> 10;
- __u64 result = osfs.os_bavail;
-
- while (blk_size >>= 1)
- result <<= 1;
-
- return sprintf(buf, "%llu\n", result);
- }
-
- return rc;
-}
-LUSTRE_RO_ATTR(kbytesavail);
-
-static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
- struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
- if (!rc)
- return sprintf(buf, "%llu\n", osfs.os_files);
-
- return rc;
-}
-LUSTRE_RO_ATTR(filestotal);
-
-static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
- struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
- if (!rc)
- return sprintf(buf, "%llu\n", osfs.os_ffree);
-
- return rc;
-}
-LUSTRE_RO_ATTR(filesfree);
-
-int lprocfs_rd_server_uuid(struct seq_file *m, void *data)
-{
- struct obd_device *obd = data;
- struct obd_import *imp;
- char *imp_state_name = NULL;
- int rc;
-
- LASSERT(obd);
- rc = lprocfs_climp_check(obd);
- if (rc)
- return rc;
-
- imp = obd->u.cli.cl_import;
- imp_state_name = ptlrpc_import_state_name(imp->imp_state);
- seq_printf(m, "%s\t%s%s\n",
- obd2cli_tgt(obd), imp_state_name,
- imp->imp_deactive ? "\tDEACTIVATED" : "");
-
- up_read(&obd->u.cli.cl_sem);
-
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_rd_server_uuid);
-
-int lprocfs_rd_conn_uuid(struct seq_file *m, void *data)
-{
- struct obd_device *obd = data;
- struct ptlrpc_connection *conn;
- int rc;
-
- LASSERT(obd);
-
- rc = lprocfs_climp_check(obd);
- if (rc)
- return rc;
-
- conn = obd->u.cli.cl_import->imp_connection;
- if (conn && obd->u.cli.cl_import)
- seq_printf(m, "%s\n", conn->c_remote_uuid.uuid);
- else
- seq_puts(m, "<none>\n");
-
- up_read(&obd->u.cli.cl_sem);
-
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
-
-/**
- * Lock statistics structure for access, possibly only on this CPU.
- *
- * The statistics struct may be allocated with per-CPU structures for
- * efficient concurrent update (usually only on server-wide stats), or
- * as a single global struct (e.g. for per-client or per-job statistics),
- * so the required locking depends on the type of structure allocated.
- *
- * For per-CPU statistics, pin the thread to the current cpuid so that
- * will only access the statistics for that CPU. If the stats structure
- * for the current CPU has not been allocated (or previously freed),
- * allocate it now. The per-CPU statistics do not need locking since
- * the thread is pinned to the CPU during update.
- *
- * For global statistics, lock the stats structure to prevent concurrent update.
- *
- * \param[in] stats statistics structure to lock
- * \param[in] opc type of operation:
- * LPROCFS_GET_SMP_ID: "lock" and return current CPU index
- * for incrementing statistics for that CPU
- * LPROCFS_GET_NUM_CPU: "lock" and return number of used
- * CPU indices to iterate over all indices
- * \param[out] flags CPU interrupt saved state for IRQ-safe locking
- *
- * \retval cpuid of current thread or number of allocated structs
- * \retval negative on error (only for opc LPROCFS_GET_SMP_ID + per-CPU stats)
- */
-int lprocfs_stats_lock(struct lprocfs_stats *stats,
- enum lprocfs_stats_lock_ops opc,
- unsigned long *flags)
-{
- if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) {
- if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
- spin_lock_irqsave(&stats->ls_lock, *flags);
- else
- spin_lock(&stats->ls_lock);
- return opc == LPROCFS_GET_NUM_CPU ? 1 : 0;
- }
-
- switch (opc) {
- case LPROCFS_GET_SMP_ID: {
- unsigned int cpuid = get_cpu();
-
- if (unlikely(!stats->ls_percpu[cpuid])) {
- int rc = lprocfs_stats_alloc_one(stats, cpuid);
-
- if (rc < 0) {
- put_cpu();
- return rc;
- }
- }
- return cpuid;
- }
- case LPROCFS_GET_NUM_CPU:
- return stats->ls_biggest_alloc_num;
- default:
- LBUG();
- }
-}
-
-/**
- * Unlock statistics structure after access.
- *
- * Unlock the lock acquired via lprocfs_stats_lock() for global statistics,
- * or unpin this thread from the current cpuid for per-CPU statistics.
- *
- * This function must be called using the same arguments as used when calling
- * lprocfs_stats_lock() so that the correct operation can be performed.
- *
- * \param[in] stats statistics structure to unlock
- * \param[in] opc type of operation (current cpuid or number of structs)
- * \param[in] flags CPU interrupt saved state for IRQ-safe locking
- */
-void lprocfs_stats_unlock(struct lprocfs_stats *stats,
- enum lprocfs_stats_lock_ops opc,
- unsigned long *flags)
-{
- if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) {
- if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
- spin_unlock_irqrestore(&stats->ls_lock, *flags);
- else
- spin_unlock(&stats->ls_lock);
- } else if (opc == LPROCFS_GET_SMP_ID) {
- put_cpu();
- }
-}
-
-/** add up per-cpu counters */
-void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
- struct lprocfs_counter *cnt)
-{
- unsigned int num_entry;
- struct lprocfs_counter *percpu_cntr;
- int i;
- unsigned long flags = 0;
-
- memset(cnt, 0, sizeof(*cnt));
-
- if (!stats) {
- /* set count to 1 to avoid divide-by-zero errs in callers */
- cnt->lc_count = 1;
- return;
- }
-
- cnt->lc_min = LC_MIN_INIT;
-
- num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
-
- for (i = 0; i < num_entry; i++) {
- if (!stats->ls_percpu[i])
- continue;
- percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
-
- cnt->lc_count += percpu_cntr->lc_count;
- cnt->lc_sum += percpu_cntr->lc_sum;
- if (percpu_cntr->lc_min < cnt->lc_min)
- cnt->lc_min = percpu_cntr->lc_min;
- if (percpu_cntr->lc_max > cnt->lc_max)
- cnt->lc_max = percpu_cntr->lc_max;
- cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
- }
-
- lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
-}
-
-/**
- * Append a space separated list of current set flags to str.
- */
-#define flag2str(flag, first) \
- do { \
- if (imp->imp_##flag) \
- seq_printf(m, "%s" #flag, first ? "" : ", "); \
- } while (0)
-static int obd_import_flags2str(struct obd_import *imp, struct seq_file *m)
-{
- bool first = true;
-
- if (imp->imp_obd->obd_no_recov) {
- seq_puts(m, "no_recov");
- first = false;
- }
-
- flag2str(invalid, first);
- first = false;
- flag2str(deactive, first);
- flag2str(replayable, first);
- flag2str(pingable, first);
- return 0;
-}
-
-#undef flags2str
-
-static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep)
-{
- __u64 mask = 1;
- int i;
- bool first = true;
-
- for (i = 0; obd_connect_names[i]; i++, mask <<= 1) {
- if (flags & mask) {
- seq_printf(m, "%s%s",
- first ? sep : "", obd_connect_names[i]);
- first = false;
- }
- }
- if (flags & ~(mask - 1))
- seq_printf(m, "%sunknown flags %#llx",
- first ? sep : "", flags & ~(mask - 1));
-}
-
-int lprocfs_rd_import(struct seq_file *m, void *data)
-{
- char nidstr[LNET_NIDSTR_SIZE];
- struct lprocfs_counter ret;
- struct lprocfs_counter_header *header;
- struct obd_device *obd = data;
- struct obd_import *imp;
- struct obd_import_conn *conn;
- struct obd_connect_data *ocd;
- int j;
- int k;
- int rw = 0;
- int rc;
-
- LASSERT(obd);
- rc = lprocfs_climp_check(obd);
- if (rc)
- return rc;
-
- imp = obd->u.cli.cl_import;
- ocd = &imp->imp_connect_data;
-
- seq_printf(m, "import:\n"
- " name: %s\n"
- " target: %s\n"
- " state: %s\n"
- " instance: %u\n"
- " connect_flags: [ ",
- obd->obd_name,
- obd2cli_tgt(obd),
- ptlrpc_import_state_name(imp->imp_state),
- imp->imp_connect_data.ocd_instance);
- obd_connect_seq_flags2str(m, imp->imp_connect_data.ocd_connect_flags,
- ", ");
- seq_puts(m, " ]\n");
- obd_connect_data_seqprint(m, ocd);
- seq_puts(m, " import_flags: [ ");
- obd_import_flags2str(imp, m);
-
- seq_puts(m,
- " ]\n"
- " connection:\n"
- " failover_nids: [ ");
- spin_lock(&imp->imp_lock);
- j = 0;
- list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
- libcfs_nid2str_r(conn->oic_conn->c_peer.nid,
- nidstr, sizeof(nidstr));
- seq_printf(m, "%s%s", j ? ", " : "", nidstr);
- j++;
- }
- if (imp->imp_connection)
- libcfs_nid2str_r(imp->imp_connection->c_peer.nid,
- nidstr, sizeof(nidstr));
- else
- strncpy(nidstr, "<none>", sizeof(nidstr));
- seq_printf(m,
- " ]\n"
- " current_connection: %s\n"
- " connection_attempts: %u\n"
- " generation: %u\n"
- " in-progress_invalidations: %u\n",
- nidstr,
- imp->imp_conn_cnt,
- imp->imp_generation,
- atomic_read(&imp->imp_inval_count));
- spin_unlock(&imp->imp_lock);
-
- if (!obd->obd_svc_stats)
- goto out_climp;
-
- header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
- lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
- if (ret.lc_count != 0) {
- /* first argument to do_div MUST be __u64 */
- __u64 sum = ret.lc_sum;
-
- do_div(sum, ret.lc_count);
- ret.lc_sum = sum;
- } else {
- ret.lc_sum = 0;
- }
- seq_printf(m,
- " rpcs:\n"
- " inflight: %u\n"
- " unregistering: %u\n"
- " timeouts: %u\n"
- " avg_waittime: %llu %s\n",
- atomic_read(&imp->imp_inflight),
- atomic_read(&imp->imp_unregistering),
- atomic_read(&imp->imp_timeouts),
- ret.lc_sum, header->lc_units);
-
- k = 0;
- for (j = 0; j < IMP_AT_MAX_PORTALS; j++) {
- if (imp->imp_at.iat_portal[j] == 0)
- break;
- k = max_t(unsigned int, k,
- at_get(&imp->imp_at.iat_service_estimate[j]));
- }
- seq_printf(m,
- " service_estimates:\n"
- " services: %u sec\n"
- " network: %u sec\n",
- k,
- at_get(&imp->imp_at.iat_net_latency));
-
- seq_printf(m,
- " transactions:\n"
- " last_replay: %llu\n"
- " peer_committed: %llu\n"
- " last_checked: %llu\n",
- imp->imp_last_replay_transno,
- imp->imp_peer_committed_transno,
- imp->imp_last_transno_checked);
-
- /* avg data rates */
- for (rw = 0; rw <= 1; rw++) {
- lprocfs_stats_collect(obd->obd_svc_stats,
- PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
- &ret);
- if (ret.lc_sum > 0 && ret.lc_count > 0) {
- /* first argument to do_div MUST be __u64 */
- __u64 sum = ret.lc_sum;
-
- do_div(sum, ret.lc_count);
- ret.lc_sum = sum;
- seq_printf(m,
- " %s_data_averages:\n"
- " bytes_per_rpc: %llu\n",
- rw ? "write" : "read",
- ret.lc_sum);
- }
- k = (int)ret.lc_sum;
- j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
- header = &obd->obd_svc_stats->ls_cnt_header[j];
- lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
- if (ret.lc_sum > 0 && ret.lc_count != 0) {
- /* first argument to do_div MUST be __u64 */
- __u64 sum = ret.lc_sum;
-
- do_div(sum, ret.lc_count);
- ret.lc_sum = sum;
- seq_printf(m,
- " %s_per_rpc: %llu\n",
- header->lc_units, ret.lc_sum);
- j = (int)ret.lc_sum;
- if (j > 0)
- seq_printf(m,
- " MB_per_sec: %u.%.02u\n",
- k / j, (100 * k / j) % 100);
- }
- }
-
-out_climp:
- up_read(&obd->u.cli.cl_sem);
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_rd_import);
-
-int lprocfs_rd_state(struct seq_file *m, void *data)
-{
- struct obd_device *obd = data;
- struct obd_import *imp;
- int j, k, rc;
-
- LASSERT(obd);
- rc = lprocfs_climp_check(obd);
- if (rc)
- return rc;
-
- imp = obd->u.cli.cl_import;
-
- seq_printf(m, "current_state: %s\n",
- ptlrpc_import_state_name(imp->imp_state));
- seq_puts(m, "state_history:\n");
- k = imp->imp_state_hist_idx;
- for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
- struct import_state_hist *ish =
- &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
- if (ish->ish_state == 0)
- continue;
- seq_printf(m, " - [ %lld, %s ]\n", (s64)ish->ish_time,
- ptlrpc_import_state_name(ish->ish_state));
- }
-
- up_read(&obd->u.cli.cl_sem);
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_rd_state);
-
-int lprocfs_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at)
-{
- int i;
-
- for (i = 0; i < AT_BINS; i++)
- seq_printf(m, "%3u ", at->at_hist[i]);
- seq_puts(m, "\n");
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_at_hist_helper);
-
-/* See also ptlrpc_lprocfs_rd_timeouts */
-int lprocfs_rd_timeouts(struct seq_file *m, void *data)
-{
- struct obd_device *obd = data;
- struct obd_import *imp;
- unsigned int cur, worst;
- time64_t now, worstt;
- struct dhms ts;
- int i, rc;
-
- LASSERT(obd);
- rc = lprocfs_climp_check(obd);
- if (rc)
- return rc;
-
- imp = obd->u.cli.cl_import;
-
- now = ktime_get_real_seconds();
-
- /* Some network health info for kicks */
- s2dhms(&ts, now - imp->imp_last_reply_time);
- seq_printf(m, "%-10s : %lld, " DHMS_FMT " ago\n",
- "last reply", (s64)imp->imp_last_reply_time, DHMS_VARS(&ts));
-
- cur = at_get(&imp->imp_at.iat_net_latency);
- worst = imp->imp_at.iat_net_latency.at_worst_ever;
- worstt = imp->imp_at.iat_net_latency.at_worst_time;
- s2dhms(&ts, now - worstt);
- seq_printf(m, "%-10s : cur %3u worst %3u (at %lld, " DHMS_FMT " ago) ",
- "network", cur, worst, (s64)worstt, DHMS_VARS(&ts));
- lprocfs_at_hist_helper(m, &imp->imp_at.iat_net_latency);
-
- for (i = 0; i < IMP_AT_MAX_PORTALS; i++) {
- if (imp->imp_at.iat_portal[i] == 0)
- break;
- cur = at_get(&imp->imp_at.iat_service_estimate[i]);
- worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
- worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
- s2dhms(&ts, now - worstt);
- seq_printf(m, "portal %-2d : cur %3u worst %3u (at %lld, "
- DHMS_FMT " ago) ", imp->imp_at.iat_portal[i],
- cur, worst, (s64)worstt, DHMS_VARS(&ts));
- lprocfs_at_hist_helper(m, &imp->imp_at.iat_service_estimate[i]);
- }
-
- up_read(&obd->u.cli.cl_sem);
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_rd_timeouts);
-
-int lprocfs_rd_connect_flags(struct seq_file *m, void *data)
-{
- struct obd_device *obd = data;
- __u64 flags;
- int rc;
-
- rc = lprocfs_climp_check(obd);
- if (rc)
- return rc;
-
- flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
- seq_printf(m, "flags=%#llx\n", flags);
- obd_connect_seq_flags2str(m, flags, "\n");
- seq_puts(m, "\n");
- up_read(&obd->u.cli.cl_sem);
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_rd_connect_flags);
-
-static struct attribute *obd_def_attrs[] = {
- &lustre_attr_blocksize.attr,
- &lustre_attr_kbytestotal.attr,
- &lustre_attr_kbytesfree.attr,
- &lustre_attr_kbytesavail.attr,
- &lustre_attr_filestotal.attr,
- &lustre_attr_filesfree.attr,
- &lustre_attr_uuid.attr,
- NULL,
-};
-
-static void obd_sysfs_release(struct kobject *kobj)
-{
- struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
-
- complete(&obd->obd_kobj_unregister);
-}
-
-static struct kobj_type obd_ktype = {
- .default_attrs = obd_def_attrs,
- .sysfs_ops = &lustre_sysfs_ops,
- .release = obd_sysfs_release,
-};
-
-int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list,
- const struct attribute_group *attrs)
-{
- int rc = 0;
-
- init_completion(&obd->obd_kobj_unregister);
- rc = kobject_init_and_add(&obd->obd_kobj, &obd_ktype,
- obd->obd_type->typ_kobj,
- "%s", obd->obd_name);
- if (rc)
- return rc;
-
- if (attrs) {
- rc = sysfs_create_group(&obd->obd_kobj, attrs);
- if (rc) {
- kobject_put(&obd->obd_kobj);
- return rc;
- }
- }
-
- obd->obd_debugfs_entry = ldebugfs_register(obd->obd_name,
- obd->obd_type->typ_debugfs_entry,
- list, obd);
- if (IS_ERR_OR_NULL(obd->obd_debugfs_entry)) {
- rc = obd->obd_debugfs_entry ? PTR_ERR(obd->obd_debugfs_entry)
- : -ENOMEM;
- CERROR("error %d setting up lprocfs for %s\n",
- rc, obd->obd_name);
- obd->obd_debugfs_entry = NULL;
- }
-
- return rc;
-}
-EXPORT_SYMBOL_GPL(lprocfs_obd_setup);
-
-int lprocfs_obd_cleanup(struct obd_device *obd)
-{
- if (!obd)
- return -EINVAL;
-
- if (!IS_ERR_OR_NULL(obd->obd_debugfs_entry))
- ldebugfs_remove(&obd->obd_debugfs_entry);
-
- kobject_put(&obd->obd_kobj);
- wait_for_completion(&obd->obd_kobj_unregister);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(lprocfs_obd_cleanup);
-
-int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
-{
- struct lprocfs_counter *cntr;
- unsigned int percpusize;
- int rc = -ENOMEM;
- unsigned long flags = 0;
- int i;
-
- LASSERT(!stats->ls_percpu[cpuid]);
- LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
-
- percpusize = lprocfs_stats_counter_size(stats);
- stats->ls_percpu[cpuid] = kzalloc(percpusize, GFP_ATOMIC);
- if (stats->ls_percpu[cpuid]) {
- rc = 0;
- if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
- if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
- spin_lock_irqsave(&stats->ls_lock, flags);
- else
- spin_lock(&stats->ls_lock);
- if (stats->ls_biggest_alloc_num <= cpuid)
- stats->ls_biggest_alloc_num = cpuid + 1;
- if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
- spin_unlock_irqrestore(&stats->ls_lock, flags);
- else
- spin_unlock(&stats->ls_lock);
- }
- /* initialize the ls_percpu[cpuid] non-zero counter */
- for (i = 0; i < stats->ls_num; ++i) {
- cntr = lprocfs_stats_counter_get(stats, cpuid, i);
- cntr->lc_min = LC_MIN_INIT;
- }
- }
- return rc;
-}
-
-struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
- enum lprocfs_stats_flags flags)
-{
- struct lprocfs_stats *stats;
- unsigned int num_entry;
- unsigned int percpusize = 0;
- int i;
-
- if (num == 0)
- return NULL;
-
- if (lprocfs_no_percpu_stats != 0)
- flags |= LPROCFS_STATS_FLAG_NOPERCPU;
-
- if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
- num_entry = 1;
- else
- num_entry = num_possible_cpus();
-
- /* alloc percpu pointers for all possible cpu slots */
- stats = kvzalloc(offsetof(typeof(*stats), ls_percpu[num_entry]),
- GFP_KERNEL);
- if (!stats)
- return NULL;
-
- stats->ls_num = num;
- stats->ls_flags = flags;
- spin_lock_init(&stats->ls_lock);
-
- /* alloc num of counter headers */
- stats->ls_cnt_header = kvmalloc_array(stats->ls_num,
- sizeof(struct lprocfs_counter_header),
- GFP_KERNEL | __GFP_ZERO);
- if (!stats->ls_cnt_header)
- goto fail;
-
- if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
- /* contains only one set counters */
- percpusize = lprocfs_stats_counter_size(stats);
- stats->ls_percpu[0] = kzalloc(percpusize, GFP_ATOMIC);
- if (!stats->ls_percpu[0])
- goto fail;
- stats->ls_biggest_alloc_num = 1;
- } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
- /* alloc all percpu data */
- for (i = 0; i < num_entry; ++i)
- if (lprocfs_stats_alloc_one(stats, i) < 0)
- goto fail;
- }
-
- return stats;
-
-fail:
- lprocfs_free_stats(&stats);
- return NULL;
-}
-EXPORT_SYMBOL(lprocfs_alloc_stats);
-
-void lprocfs_free_stats(struct lprocfs_stats **statsh)
-{
- struct lprocfs_stats *stats = *statsh;
- unsigned int num_entry;
- unsigned int percpusize;
- unsigned int i;
-
- if (!stats || stats->ls_num == 0)
- return;
- *statsh = NULL;
-
- if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
- num_entry = 1;
- else
- num_entry = num_possible_cpus();
-
- percpusize = lprocfs_stats_counter_size(stats);
- for (i = 0; i < num_entry; i++)
- kfree(stats->ls_percpu[i]);
- kvfree(stats->ls_cnt_header);
- kvfree(stats);
-}
-EXPORT_SYMBOL(lprocfs_free_stats);
-
-__u64 lprocfs_stats_collector(struct lprocfs_stats *stats, int idx,
- enum lprocfs_fields_flags field)
-{
- unsigned int i;
- unsigned int num_cpu;
- unsigned long flags = 0;
- __u64 ret = 0;
-
- LASSERT(stats);
-
- num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
- for (i = 0; i < num_cpu; i++) {
- if (!stats->ls_percpu[i])
- continue;
- ret += lprocfs_read_helper(
- lprocfs_stats_counter_get(stats, i, idx),
- &stats->ls_cnt_header[idx], stats->ls_flags,
- field);
- }
- lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
- return ret;
-}
-EXPORT_SYMBOL(lprocfs_stats_collector);
-
-void lprocfs_clear_stats(struct lprocfs_stats *stats)
-{
- struct lprocfs_counter *percpu_cntr;
- int i;
- int j;
- unsigned int num_entry;
- unsigned long flags = 0;
-
- num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
-
- for (i = 0; i < num_entry; i++) {
- if (!stats->ls_percpu[i])
- continue;
- for (j = 0; j < stats->ls_num; j++) {
- percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
- percpu_cntr->lc_count = 0;
- percpu_cntr->lc_min = LC_MIN_INIT;
- percpu_cntr->lc_max = 0;
- percpu_cntr->lc_sumsquare = 0;
- percpu_cntr->lc_sum = 0;
- if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
- percpu_cntr->lc_sum_irq = 0;
- }
- }
-
- lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
-}
-EXPORT_SYMBOL(lprocfs_clear_stats);
-
-static ssize_t lprocfs_stats_seq_write(struct file *file,
- const char __user *buf,
- size_t len, loff_t *off)
-{
- struct seq_file *seq = file->private_data;
- struct lprocfs_stats *stats = seq->private;
-
- lprocfs_clear_stats(stats);
-
- return len;
-}
-
-static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
-{
- struct lprocfs_stats *stats = p->private;
-
- return (*pos < stats->ls_num) ? pos : NULL;
-}
-
-static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
-{
-}
-
-static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
-{
- (*pos)++;
- return lprocfs_stats_seq_start(p, pos);
-}
-
-/* seq file export of one lprocfs counter */
-static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
-{
- struct lprocfs_stats *stats = p->private;
- struct lprocfs_counter_header *hdr;
- struct lprocfs_counter ctr;
- int idx = *(loff_t *)v;
-
- if (idx == 0) {
- struct timespec64 now;
-
- ktime_get_real_ts64(&now);
- seq_printf(p, "%-25s %llu.%9lu secs.usecs\n",
- "snapshot_time",
- (s64)now.tv_sec, (unsigned long)now.tv_nsec);
- }
-
- hdr = &stats->ls_cnt_header[idx];
- lprocfs_stats_collect(stats, idx, &ctr);
-
- if (ctr.lc_count != 0) {
- seq_printf(p, "%-25s %lld samples [%s]",
- hdr->lc_name, ctr.lc_count, hdr->lc_units);
-
- if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
- (ctr.lc_count > 0)) {
- seq_printf(p, " %lld %lld %lld",
- ctr.lc_min, ctr.lc_max, ctr.lc_sum);
- if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
- seq_printf(p, " %lld", ctr.lc_sumsquare);
- }
- seq_putc(p, '\n');
- }
-
- return 0;
-}
-
-static const struct seq_operations lprocfs_stats_seq_sops = {
- .start = lprocfs_stats_seq_start,
- .stop = lprocfs_stats_seq_stop,
- .next = lprocfs_stats_seq_next,
- .show = lprocfs_stats_seq_show,
-};
-
-static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
-{
- struct seq_file *seq;
- int rc;
-
- rc = seq_open(file, &lprocfs_stats_seq_sops);
- if (rc)
- return rc;
-
- seq = file->private_data;
- seq->private = inode->i_private;
-
- return 0;
-}
-
-static const struct file_operations lprocfs_stats_seq_fops = {
- .owner = THIS_MODULE,
- .open = lprocfs_stats_seq_open,
- .read = seq_read,
- .write = lprocfs_stats_seq_write,
- .llseek = seq_lseek,
- .release = lprocfs_seq_release,
-};
-
-int ldebugfs_register_stats(struct dentry *parent, const char *name,
- struct lprocfs_stats *stats)
-{
- struct dentry *entry;
-
- LASSERT(!IS_ERR_OR_NULL(parent));
-
- entry = debugfs_create_file(name, 0644, parent, stats,
- &lprocfs_stats_seq_fops);
- if (IS_ERR_OR_NULL(entry))
- return entry ? PTR_ERR(entry) : -ENOMEM;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(ldebugfs_register_stats);
-
-void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
- unsigned int conf, const char *name,
- const char *units)
-{
- struct lprocfs_counter_header *header;
- struct lprocfs_counter *percpu_cntr;
- unsigned long flags = 0;
- unsigned int i;
- unsigned int num_cpu;
-
- header = &stats->ls_cnt_header[index];
- LASSERTF(header, "Failed to allocate stats header:[%d]%s/%s\n",
- index, name, units);
-
- header->lc_config = conf;
- header->lc_name = name;
- header->lc_units = units;
-
- num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
- for (i = 0; i < num_cpu; ++i) {
- if (!stats->ls_percpu[i])
- continue;
- percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
- percpu_cntr->lc_count = 0;
- percpu_cntr->lc_min = LC_MIN_INIT;
- percpu_cntr->lc_max = 0;
- percpu_cntr->lc_sumsquare = 0;
- percpu_cntr->lc_sum = 0;
- if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
- percpu_cntr->lc_sum_irq = 0;
- }
- lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
-}
-EXPORT_SYMBOL(lprocfs_counter_init);
-
-int lprocfs_exp_cleanup(struct obd_export *exp)
-{
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_exp_cleanup);
-
-__s64 lprocfs_read_helper(struct lprocfs_counter *lc,
- struct lprocfs_counter_header *header,
- enum lprocfs_stats_flags flags,
- enum lprocfs_fields_flags field)
-{
- __s64 ret = 0;
-
- if (!lc || !header)
- return 0;
-
- switch (field) {
- case LPROCFS_FIELDS_FLAGS_CONFIG:
- ret = header->lc_config;
- break;
- case LPROCFS_FIELDS_FLAGS_SUM:
- ret = lc->lc_sum;
- if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
- ret += lc->lc_sum_irq;
- break;
- case LPROCFS_FIELDS_FLAGS_MIN:
- ret = lc->lc_min;
- break;
- case LPROCFS_FIELDS_FLAGS_MAX:
- ret = lc->lc_max;
- break;
- case LPROCFS_FIELDS_FLAGS_AVG:
- ret = (lc->lc_max - lc->lc_min) / 2;
- break;
- case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
- ret = lc->lc_sumsquare;
- break;
- case LPROCFS_FIELDS_FLAGS_COUNT:
- ret = lc->lc_count;
- break;
- default:
- break;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_read_helper);
-
-int lprocfs_write_helper(const char __user *buffer, unsigned long count,
- int *val)
-{
- return lprocfs_write_frac_helper(buffer, count, val, 1);
-}
-EXPORT_SYMBOL(lprocfs_write_helper);
-
-int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count,
- __u64 *val)
-{
- return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
-}
-EXPORT_SYMBOL(lprocfs_write_u64_helper);
-
-int lprocfs_write_frac_u64_helper(const char __user *buffer,
- unsigned long count, __u64 *val, int mult)
-{
- char kernbuf[22], *end, *pbuf;
- __u64 whole, frac = 0, units;
- unsigned int frac_d = 1;
- int sign = 1;
-
- if (count > (sizeof(kernbuf) - 1))
- return -EINVAL;
-
- if (copy_from_user(kernbuf, buffer, count))
- return -EFAULT;
-
- kernbuf[count] = '\0';
- pbuf = kernbuf;
- if (*pbuf == '-') {
- sign = -1;
- pbuf++;
- }
-
- whole = simple_strtoull(pbuf, &end, 10);
- if (pbuf == end)
- return -EINVAL;
-
- if (*end == '.') {
- int i;
-
- pbuf = end + 1;
-
- /* need to limit frac_d to a __u32 */
- if (strlen(pbuf) > 10)
- pbuf[10] = '\0';
-
- frac = simple_strtoull(pbuf, &end, 10);
- /* count decimal places */
- for (i = 0; i < (end - pbuf); i++)
- frac_d *= 10;
- }
-
- units = 1;
- if (end) {
- switch (tolower(*end)) {
- case 'p':
- units <<= 10;
- /* fall through */
- case 't':
- units <<= 10;
- /* fall through */
- case 'g':
- units <<= 10;
- /* fall through */
- case 'm':
- units <<= 10;
- /* fall through */
- case 'k':
- units <<= 10;
- }
- }
- /* Specified units override the multiplier */
- if (units > 1)
- mult = units;
-
- frac *= mult;
- do_div(frac, frac_d);
- *val = sign * (whole * mult + frac);
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
-
-static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
-{
- size_t l2;
-
- l2 = strlen(s2);
- if (!l2)
- return (char *)s1;
- while (len >= l2) {
- len--;
- if (!memcmp(s1, s2, l2))
- return (char *)s1;
- s1++;
- }
- return NULL;
-}
-
-/**
- * Find the string \a name in the input \a buffer, and return a pointer to the
- * value immediately following \a name, reducing \a count appropriately.
- * If \a name is not found the original \a buffer is returned.
- */
-char *lprocfs_find_named_value(const char *buffer, const char *name,
- size_t *count)
-{
- char *val;
- size_t buflen = *count;
-
- /* there is no strnstr() in rhel5 and ubuntu kernels */
- val = lprocfs_strnstr(buffer, name, buflen);
- if (!val)
- return (char *)buffer;
-
- val += strlen(name); /* skip prefix */
- while (val < buffer + buflen && isspace(*val)) /* skip separator */
- val++;
-
- *count = 0;
- while (val < buffer + buflen && isalnum(*val)) {
- ++*count;
- ++val;
- }
-
- return val - *count;
-}
-EXPORT_SYMBOL(lprocfs_find_named_value);
-
-int ldebugfs_seq_create(struct dentry *parent, const char *name,
- umode_t mode, const struct file_operations *seq_fops,
- void *data)
-{
- struct dentry *entry;
-
- /* Disallow secretly (un)writable entries. */
- LASSERT((!seq_fops->write) == ((mode & 0222) == 0));
-
- entry = debugfs_create_file(name, mode, parent, data, seq_fops);
- if (IS_ERR_OR_NULL(entry))
- return entry ? PTR_ERR(entry) : -ENOMEM;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(ldebugfs_seq_create);
-
-int ldebugfs_obd_seq_create(struct obd_device *dev,
- const char *name,
- umode_t mode,
- const struct file_operations *seq_fops,
- void *data)
-{
- return ldebugfs_seq_create(dev->obd_debugfs_entry, name,
- mode, seq_fops, data);
-}
-EXPORT_SYMBOL_GPL(ldebugfs_obd_seq_create);
-
-void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
-{
- if (value >= OBD_HIST_MAX)
- value = OBD_HIST_MAX - 1;
-
- spin_lock(&oh->oh_lock);
- oh->oh_buckets[value]++;
- spin_unlock(&oh->oh_lock);
-}
-EXPORT_SYMBOL(lprocfs_oh_tally);
-
-void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
-{
- unsigned int val = 0;
-
- if (likely(value != 0))
- val = min(fls(value - 1), OBD_HIST_MAX);
-
- lprocfs_oh_tally(oh, val);
-}
-EXPORT_SYMBOL(lprocfs_oh_tally_log2);
-
-unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
-{
- unsigned long ret = 0;
- int i;
-
- for (i = 0; i < OBD_HIST_MAX; i++)
- ret += oh->oh_buckets[i];
- return ret;
-}
-EXPORT_SYMBOL(lprocfs_oh_sum);
-
-void lprocfs_oh_clear(struct obd_histogram *oh)
-{
- spin_lock(&oh->oh_lock);
- memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
- spin_unlock(&oh->oh_lock);
-}
-EXPORT_SYMBOL(lprocfs_oh_clear);
-
-int lprocfs_wr_root_squash(const char __user *buffer, unsigned long count,
- struct root_squash_info *squash, char *name)
-{
- char kernbuf[64], *tmp, *errmsg;
- unsigned long uid, gid;
- int rc;
-
- if (count >= sizeof(kernbuf)) {
- errmsg = "string too long";
- rc = -EINVAL;
- goto failed_noprint;
- }
- if (copy_from_user(kernbuf, buffer, count)) {
- errmsg = "bad address";
- rc = -EFAULT;
- goto failed_noprint;
- }
- kernbuf[count] = '\0';
-
- /* look for uid gid separator */
- tmp = strchr(kernbuf, ':');
- if (!tmp) {
- errmsg = "needs uid:gid format";
- rc = -EINVAL;
- goto failed;
- }
- *tmp = '\0';
- tmp++;
-
- /* parse uid */
- if (kstrtoul(kernbuf, 0, &uid) != 0) {
- errmsg = "bad uid";
- rc = -EINVAL;
- goto failed;
- }
- /* parse gid */
- if (kstrtoul(tmp, 0, &gid) != 0) {
- errmsg = "bad gid";
- rc = -EINVAL;
- goto failed;
- }
-
- squash->rsi_uid = uid;
- squash->rsi_gid = gid;
-
- LCONSOLE_INFO("%s: root_squash is set to %u:%u\n",
- name, squash->rsi_uid, squash->rsi_gid);
- return count;
-
-failed:
- if (tmp) {
- tmp--;
- *tmp = ':';
- }
- CWARN("%s: failed to set root_squash to \"%s\", %s, rc = %d\n",
- name, kernbuf, errmsg, rc);
- return rc;
-failed_noprint:
- CWARN("%s: failed to set root_squash due to %s, rc = %d\n",
- name, errmsg, rc);
- return rc;
-}
-EXPORT_SYMBOL(lprocfs_wr_root_squash);
-
-int lprocfs_wr_nosquash_nids(const char __user *buffer, unsigned long count,
- struct root_squash_info *squash, char *name)
-{
- char *kernbuf = NULL, *errmsg;
- struct list_head tmp;
- int len = count;
- int rc;
-
- if (count > 4096) {
- errmsg = "string too long";
- rc = -EINVAL;
- goto failed;
- }
-
- kernbuf = kzalloc(count + 1, GFP_NOFS);
- if (!kernbuf) {
- errmsg = "no memory";
- rc = -ENOMEM;
- goto failed;
- }
-
- if (copy_from_user(kernbuf, buffer, count)) {
- errmsg = "bad address";
- rc = -EFAULT;
- goto failed;
- }
- kernbuf[count] = '\0';
-
- if (count > 0 && kernbuf[count - 1] == '\n')
- len = count - 1;
-
- if ((len == 4 && !strncmp(kernbuf, "NONE", len)) ||
- (len == 5 && !strncmp(kernbuf, "clear", len))) {
- /* empty string is special case */
- down_write(&squash->rsi_sem);
- if (!list_empty(&squash->rsi_nosquash_nids))
- cfs_free_nidlist(&squash->rsi_nosquash_nids);
- up_write(&squash->rsi_sem);
- LCONSOLE_INFO("%s: nosquash_nids is cleared\n", name);
- kfree(kernbuf);
- return count;
- }
-
- INIT_LIST_HEAD(&tmp);
- if (cfs_parse_nidlist(kernbuf, count, &tmp) <= 0) {
- errmsg = "can't parse";
- rc = -EINVAL;
- goto failed;
- }
- LCONSOLE_INFO("%s: nosquash_nids set to %s\n",
- name, kernbuf);
- kfree(kernbuf);
- kernbuf = NULL;
-
- down_write(&squash->rsi_sem);
- if (!list_empty(&squash->rsi_nosquash_nids))
- cfs_free_nidlist(&squash->rsi_nosquash_nids);
- list_splice(&tmp, &squash->rsi_nosquash_nids);
- up_write(&squash->rsi_sem);
-
- return count;
-
-failed:
- if (kernbuf) {
- CWARN("%s: failed to set nosquash_nids to \"%s\", %s rc = %d\n",
- name, kernbuf, errmsg, rc);
- kfree(kernbuf);
- kernbuf = NULL;
- } else {
- CWARN("%s: failed to set nosquash_nids due to %s rc = %d\n",
- name, errmsg, rc);
- }
- return rc;
-}
-EXPORT_SYMBOL(lprocfs_wr_nosquash_nids);
-
-static ssize_t lustre_attr_show(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- struct lustre_attr *a = container_of(attr, struct lustre_attr, attr);
-
- return a->show ? a->show(kobj, attr, buf) : 0;
-}
-
-static ssize_t lustre_attr_store(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t len)
-{
- struct lustre_attr *a = container_of(attr, struct lustre_attr, attr);
-
- return a->store ? a->store(kobj, attr, buf, len) : len;
-}
-
-const struct sysfs_ops lustre_sysfs_ops = {
- .show = lustre_attr_show,
- .store = lustre_attr_store,
-};
-EXPORT_SYMBOL_GPL(lustre_sysfs_ops);
diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c
deleted file mode 100644
index 3ae16e8501c2..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/lu_object.c
+++ /dev/null
@@ -1,2058 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/lu_object.c
- *
- * Lustre Object.
- * These are the only exported functions, they provide some generic
- * infrastructure for managing object devices
- *
- * Author: Nikita Danilov <nikita.danilov@sun.com>
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/libcfs/libcfs.h>
-
-#include <linux/module.h>
-
-/* hash_long() */
-#include <linux/libcfs/libcfs_hash.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lustre_disk.h>
-#include <lustre_fid.h>
-#include <lu_object.h>
-#include <cl_object.h>
-#include <lu_ref.h>
-#include <linux/list.h>
-
-enum {
- LU_CACHE_PERCENT_MAX = 50,
- LU_CACHE_PERCENT_DEFAULT = 20
-};
-
-#define LU_CACHE_NR_MAX_ADJUST 512
-#define LU_CACHE_NR_UNLIMITED -1
-#define LU_CACHE_NR_DEFAULT LU_CACHE_NR_UNLIMITED
-#define LU_CACHE_NR_LDISKFS_LIMIT LU_CACHE_NR_UNLIMITED
-#define LU_CACHE_NR_ZFS_LIMIT 256
-
-#define LU_SITE_BITS_MIN 12
-#define LU_SITE_BITS_MAX 24
-#define LU_SITE_BITS_MAX_CL 19
-/**
- * total 256 buckets, we don't want too many buckets because:
- * - consume too much memory
- * - avoid unbalanced LRU list
- */
-#define LU_SITE_BKT_BITS 8
-
-static unsigned int lu_cache_percent = LU_CACHE_PERCENT_DEFAULT;
-module_param(lu_cache_percent, int, 0644);
-MODULE_PARM_DESC(lu_cache_percent, "Percentage of memory to be used as lu_object cache");
-
-static long lu_cache_nr = LU_CACHE_NR_DEFAULT;
-module_param(lu_cache_nr, long, 0644);
-MODULE_PARM_DESC(lu_cache_nr, "Maximum number of objects in lu_object cache");
-
-static void lu_object_free(const struct lu_env *env, struct lu_object *o);
-static __u32 ls_stats_read(struct lprocfs_stats *stats, int idx);
-
-/**
- * Decrease reference counter on object. If last reference is freed, return
- * object to the cache, unless lu_object_is_dying(o) holds. In the latter
- * case, free object immediately.
- */
-void lu_object_put(const struct lu_env *env, struct lu_object *o)
-{
- struct lu_site_bkt_data *bkt;
- struct lu_object_header *top;
- struct lu_site *site;
- struct lu_object *orig;
- struct cfs_hash_bd bd;
- const struct lu_fid *fid;
-
- top = o->lo_header;
- site = o->lo_dev->ld_site;
- orig = o;
-
- /*
- * till we have full fids-on-OST implemented anonymous objects
- * are possible in OSP. such an object isn't listed in the site
- * so we should not remove it from the site.
- */
- fid = lu_object_fid(o);
- if (fid_is_zero(fid)) {
- LASSERT(!top->loh_hash.next && !top->loh_hash.pprev);
- LASSERT(list_empty(&top->loh_lru));
- if (!atomic_dec_and_test(&top->loh_ref))
- return;
- list_for_each_entry_reverse(o, &top->loh_layers, lo_linkage) {
- if (o->lo_ops->loo_object_release)
- o->lo_ops->loo_object_release(env, o);
- }
- lu_object_free(env, orig);
- return;
- }
-
- cfs_hash_bd_get(site->ls_obj_hash, &top->loh_fid, &bd);
- bkt = cfs_hash_bd_extra_get(site->ls_obj_hash, &bd);
-
- if (!cfs_hash_bd_dec_and_lock(site->ls_obj_hash, &bd, &top->loh_ref)) {
- if (lu_object_is_dying(top)) {
- /*
- * somebody may be waiting for this, currently only
- * used for cl_object, see cl_object_put_last().
- */
- wake_up_all(&bkt->lsb_marche_funebre);
- }
- return;
- }
-
- /*
- * When last reference is released, iterate over object
- * layers, and notify them that object is no longer busy.
- */
- list_for_each_entry_reverse(o, &top->loh_layers, lo_linkage) {
- if (o->lo_ops->loo_object_release)
- o->lo_ops->loo_object_release(env, o);
- }
-
- if (!lu_object_is_dying(top)) {
- LASSERT(list_empty(&top->loh_lru));
- list_add_tail(&top->loh_lru, &bkt->lsb_lru);
- bkt->lsb_lru_len++;
- percpu_counter_inc(&site->ls_lru_len_counter);
- CDEBUG(D_INODE, "Add %p to site lru. hash: %p, bkt: %p, lru_len: %ld\n",
- o, site->ls_obj_hash, bkt, bkt->lsb_lru_len);
- cfs_hash_bd_unlock(site->ls_obj_hash, &bd, 1);
- return;
- }
-
- /*
- * If object is dying (will not be cached), then removed it
- * from hash table and LRU.
- *
- * This is done with hash table and LRU lists locked. As the only
- * way to acquire first reference to previously unreferenced
- * object is through hash-table lookup (lu_object_find()),
- * or LRU scanning (lu_site_purge()), that are done under hash-table
- * and LRU lock, no race with concurrent object lookup is possible
- * and we can safely destroy object below.
- */
- if (!test_and_set_bit(LU_OBJECT_UNHASHED, &top->loh_flags))
- cfs_hash_bd_del_locked(site->ls_obj_hash, &bd, &top->loh_hash);
- cfs_hash_bd_unlock(site->ls_obj_hash, &bd, 1);
- /*
- * Object was already removed from hash and lru above, can
- * kill it.
- */
- lu_object_free(env, orig);
-}
-EXPORT_SYMBOL(lu_object_put);
-
-/**
- * Kill the object and take it out of LRU cache.
- * Currently used by client code for layout change.
- */
-void lu_object_unhash(const struct lu_env *env, struct lu_object *o)
-{
- struct lu_object_header *top;
-
- top = o->lo_header;
- set_bit(LU_OBJECT_HEARD_BANSHEE, &top->loh_flags);
- if (!test_and_set_bit(LU_OBJECT_UNHASHED, &top->loh_flags)) {
- struct lu_site *site = o->lo_dev->ld_site;
- struct cfs_hash *obj_hash = site->ls_obj_hash;
- struct cfs_hash_bd bd;
-
- cfs_hash_bd_get_and_lock(obj_hash, &top->loh_fid, &bd, 1);
- if (!list_empty(&top->loh_lru)) {
- struct lu_site_bkt_data *bkt;
-
- list_del_init(&top->loh_lru);
- bkt = cfs_hash_bd_extra_get(obj_hash, &bd);
- bkt->lsb_lru_len--;
- percpu_counter_dec(&site->ls_lru_len_counter);
- }
- cfs_hash_bd_del_locked(obj_hash, &bd, &top->loh_hash);
- cfs_hash_bd_unlock(obj_hash, &bd, 1);
- }
-}
-EXPORT_SYMBOL(lu_object_unhash);
-
-/**
- * Allocate new object.
- *
- * This follows object creation protocol, described in the comment within
- * struct lu_device_operations definition.
- */
-static struct lu_object *lu_object_alloc(const struct lu_env *env,
- struct lu_device *dev,
- const struct lu_fid *f,
- const struct lu_object_conf *conf)
-{
- struct lu_object *scan;
- struct lu_object *top;
- struct list_head *layers;
- unsigned int init_mask = 0;
- unsigned int init_flag;
- int clean;
- int result;
-
- /*
- * Create top-level object slice. This will also create
- * lu_object_header.
- */
- top = dev->ld_ops->ldo_object_alloc(env, NULL, dev);
- if (!top)
- return ERR_PTR(-ENOMEM);
- if (IS_ERR(top))
- return top;
- /*
- * This is the only place where object fid is assigned. It's constant
- * after this point.
- */
- top->lo_header->loh_fid = *f;
- layers = &top->lo_header->loh_layers;
-
- do {
- /*
- * Call ->loo_object_init() repeatedly, until no more new
- * object slices are created.
- */
- clean = 1;
- init_flag = 1;
- list_for_each_entry(scan, layers, lo_linkage) {
- if (init_mask & init_flag)
- goto next;
- clean = 0;
- scan->lo_header = top->lo_header;
- result = scan->lo_ops->loo_object_init(env, scan, conf);
- if (result != 0) {
- lu_object_free(env, top);
- return ERR_PTR(result);
- }
- init_mask |= init_flag;
-next:
- init_flag <<= 1;
- }
- } while (!clean);
-
- list_for_each_entry_reverse(scan, layers, lo_linkage) {
- if (scan->lo_ops->loo_object_start) {
- result = scan->lo_ops->loo_object_start(env, scan);
- if (result != 0) {
- lu_object_free(env, top);
- return ERR_PTR(result);
- }
- }
- }
-
- lprocfs_counter_incr(dev->ld_site->ls_stats, LU_SS_CREATED);
- return top;
-}
-
-/**
- * Free an object.
- */
-static void lu_object_free(const struct lu_env *env, struct lu_object *o)
-{
- struct lu_site_bkt_data *bkt;
- struct lu_site *site;
- struct lu_object *scan;
- struct list_head *layers;
- struct list_head splice;
-
- site = o->lo_dev->ld_site;
- layers = &o->lo_header->loh_layers;
- bkt = lu_site_bkt_from_fid(site, &o->lo_header->loh_fid);
- /*
- * First call ->loo_object_delete() method to release all resources.
- */
- list_for_each_entry_reverse(scan, layers, lo_linkage) {
- if (scan->lo_ops->loo_object_delete)
- scan->lo_ops->loo_object_delete(env, scan);
- }
-
- /*
- * Then, splice object layers into stand-alone list, and call
- * ->loo_object_free() on all layers to free memory. Splice is
- * necessary, because lu_object_header is freed together with the
- * top-level slice.
- */
- INIT_LIST_HEAD(&splice);
- list_splice_init(layers, &splice);
- while (!list_empty(&splice)) {
- /*
- * Free layers in bottom-to-top order, so that object header
- * lives as long as possible and ->loo_object_free() methods
- * can look at its contents.
- */
- o = container_of0(splice.prev, struct lu_object, lo_linkage);
- list_del_init(&o->lo_linkage);
- o->lo_ops->loo_object_free(env, o);
- }
-
- if (waitqueue_active(&bkt->lsb_marche_funebre))
- wake_up_all(&bkt->lsb_marche_funebre);
-}
-
-/**
- * Free \a nr objects from the cold end of the site LRU list.
- * if canblock is false, then don't block awaiting for another
- * instance of lu_site_purge() to complete
- */
-int lu_site_purge_objects(const struct lu_env *env, struct lu_site *s,
- int nr, bool canblock)
-{
- struct lu_object_header *h;
- struct lu_object_header *temp;
- struct lu_site_bkt_data *bkt;
- struct cfs_hash_bd bd;
- struct cfs_hash_bd bd2;
- struct list_head dispose;
- int did_sth;
- unsigned int start = 0;
- int count;
- int bnr;
- unsigned int i;
-
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_NO_LRU))
- return 0;
-
- INIT_LIST_HEAD(&dispose);
- /*
- * Under LRU list lock, scan LRU list and move unreferenced objects to
- * the dispose list, removing them from LRU and hash table.
- */
- if (nr != ~0)
- start = s->ls_purge_start;
- bnr = (nr == ~0) ? -1 : nr / (int)CFS_HASH_NBKT(s->ls_obj_hash) + 1;
- again:
- /*
- * It doesn't make any sense to make purge threads parallel, that can
- * only bring troubles to us. See LU-5331.
- */
- if (canblock)
- mutex_lock(&s->ls_purge_mutex);
- else if (!mutex_trylock(&s->ls_purge_mutex))
- goto out;
-
- did_sth = 0;
- cfs_hash_for_each_bucket(s->ls_obj_hash, &bd, i) {
- if (i < start)
- continue;
- count = bnr;
- cfs_hash_bd_lock(s->ls_obj_hash, &bd, 1);
- bkt = cfs_hash_bd_extra_get(s->ls_obj_hash, &bd);
-
- list_for_each_entry_safe(h, temp, &bkt->lsb_lru, loh_lru) {
- LASSERT(atomic_read(&h->loh_ref) == 0);
-
- cfs_hash_bd_get(s->ls_obj_hash, &h->loh_fid, &bd2);
- LASSERT(bd.bd_bucket == bd2.bd_bucket);
-
- cfs_hash_bd_del_locked(s->ls_obj_hash,
- &bd2, &h->loh_hash);
- list_move(&h->loh_lru, &dispose);
- bkt->lsb_lru_len--;
- percpu_counter_dec(&s->ls_lru_len_counter);
- if (did_sth == 0)
- did_sth = 1;
-
- if (nr != ~0 && --nr == 0)
- break;
-
- if (count > 0 && --count == 0)
- break;
- }
- cfs_hash_bd_unlock(s->ls_obj_hash, &bd, 1);
- cond_resched();
- /*
- * Free everything on the dispose list. This is safe against
- * races due to the reasons described in lu_object_put().
- */
- while (!list_empty(&dispose)) {
- h = container_of0(dispose.next,
- struct lu_object_header, loh_lru);
- list_del_init(&h->loh_lru);
- lu_object_free(env, lu_object_top(h));
- lprocfs_counter_incr(s->ls_stats, LU_SS_LRU_PURGED);
- }
-
- if (nr == 0)
- break;
- }
- mutex_unlock(&s->ls_purge_mutex);
-
- if (nr != 0 && did_sth && start != 0) {
- start = 0; /* restart from the first bucket */
- goto again;
- }
- /* race on s->ls_purge_start, but nobody cares */
- s->ls_purge_start = i % CFS_HASH_NBKT(s->ls_obj_hash);
-out:
- return nr;
-}
-EXPORT_SYMBOL(lu_site_purge_objects);
-
-/*
- * Object printing.
- *
- * Code below has to jump through certain loops to output object description
- * into libcfs_debug_msg-based log. The problem is that lu_object_print()
- * composes object description from strings that are parts of _lines_ of
- * output (i.e., strings that are not terminated by newline). This doesn't fit
- * very well into libcfs_debug_msg() interface that assumes that each message
- * supplied to it is a self-contained output line.
- *
- * To work around this, strings are collected in a temporary buffer
- * (implemented as a value of lu_cdebug_key key), until terminating newline
- * character is detected.
- *
- */
-
-enum {
- /**
- * Maximal line size.
- *
- * XXX overflow is not handled correctly.
- */
- LU_CDEBUG_LINE = 512
-};
-
-struct lu_cdebug_data {
- /**
- * Temporary buffer.
- */
- char lck_area[LU_CDEBUG_LINE];
-};
-
-/* context key constructor/destructor: lu_global_key_init, lu_global_key_fini */
-LU_KEY_INIT_FINI(lu_global, struct lu_cdebug_data);
-
-/**
- * Key, holding temporary buffer. This key is registered very early by
- * lu_global_init().
- */
-static struct lu_context_key lu_global_key = {
- .lct_tags = LCT_MD_THREAD | LCT_DT_THREAD |
- LCT_MG_THREAD | LCT_CL_THREAD | LCT_LOCAL,
- .lct_init = lu_global_key_init,
- .lct_fini = lu_global_key_fini
-};
-
-/**
- * Printer function emitting messages through libcfs_debug_msg().
- */
-int lu_cdebug_printer(const struct lu_env *env,
- void *cookie, const char *format, ...)
-{
- struct libcfs_debug_msg_data *msgdata = cookie;
- struct lu_cdebug_data *key;
- int used;
- int complete;
- va_list args;
-
- va_start(args, format);
-
- key = lu_context_key_get(&env->le_ctx, &lu_global_key);
-
- used = strlen(key->lck_area);
- complete = format[strlen(format) - 1] == '\n';
- /*
- * Append new chunk to the buffer.
- */
- vsnprintf(key->lck_area + used,
- ARRAY_SIZE(key->lck_area) - used, format, args);
- if (complete) {
- if (cfs_cdebug_show(msgdata->msg_mask, msgdata->msg_subsys))
- libcfs_debug_msg(msgdata, "%s\n", key->lck_area);
- key->lck_area[0] = 0;
- }
- va_end(args);
- return 0;
-}
-EXPORT_SYMBOL(lu_cdebug_printer);
-
-/**
- * Print object header.
- */
-void lu_object_header_print(const struct lu_env *env, void *cookie,
- lu_printer_t printer,
- const struct lu_object_header *hdr)
-{
- (*printer)(env, cookie, "header@%p[%#lx, %d, " DFID "%s%s%s]",
- hdr, hdr->loh_flags, atomic_read(&hdr->loh_ref),
- PFID(&hdr->loh_fid),
- hlist_unhashed(&hdr->loh_hash) ? "" : " hash",
- list_empty((struct list_head *)&hdr->loh_lru) ? \
- "" : " lru",
- hdr->loh_attr & LOHA_EXISTS ? " exist":"");
-}
-EXPORT_SYMBOL(lu_object_header_print);
-
-/**
- * Print human readable representation of the \a o to the \a printer.
- */
-void lu_object_print(const struct lu_env *env, void *cookie,
- lu_printer_t printer, const struct lu_object *o)
-{
- static const char ruler[] = "........................................";
- struct lu_object_header *top;
- int depth = 4;
-
- top = o->lo_header;
- lu_object_header_print(env, cookie, printer, top);
- (*printer)(env, cookie, "{\n");
-
- list_for_each_entry(o, &top->loh_layers, lo_linkage) {
- /*
- * print `.' \a depth times followed by type name and address
- */
- (*printer)(env, cookie, "%*.*s%s@%p", depth, depth, ruler,
- o->lo_dev->ld_type->ldt_name, o);
-
- if (o->lo_ops->loo_object_print)
- (*o->lo_ops->loo_object_print)(env, cookie, printer, o);
-
- (*printer)(env, cookie, "\n");
- }
-
- (*printer)(env, cookie, "} header@%p\n", top);
-}
-EXPORT_SYMBOL(lu_object_print);
-
-static struct lu_object *htable_lookup(struct lu_site *s,
- struct cfs_hash_bd *bd,
- const struct lu_fid *f,
- wait_queue_entry_t *waiter,
- __u64 *version)
-{
- struct lu_site_bkt_data *bkt;
- struct lu_object_header *h;
- struct hlist_node *hnode;
- __u64 ver = cfs_hash_bd_version_get(bd);
-
- if (*version == ver)
- return ERR_PTR(-ENOENT);
-
- *version = ver;
- bkt = cfs_hash_bd_extra_get(s->ls_obj_hash, bd);
- /* cfs_hash_bd_peek_locked is a somehow "internal" function
- * of cfs_hash, it doesn't add refcount on object.
- */
- hnode = cfs_hash_bd_peek_locked(s->ls_obj_hash, bd, (void *)f);
- if (!hnode) {
- lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_MISS);
- return ERR_PTR(-ENOENT);
- }
-
- h = container_of0(hnode, struct lu_object_header, loh_hash);
- if (likely(!lu_object_is_dying(h))) {
- cfs_hash_get(s->ls_obj_hash, hnode);
- lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_HIT);
- if (!list_empty(&h->loh_lru)) {
- list_del_init(&h->loh_lru);
- bkt->lsb_lru_len--;
- percpu_counter_dec(&s->ls_lru_len_counter);
- }
- return lu_object_top(h);
- }
-
- /*
- * Lookup found an object being destroyed this object cannot be
- * returned (to assure that references to dying objects are eventually
- * drained), and moreover, lookup has to wait until object is freed.
- */
-
- init_waitqueue_entry(waiter, current);
- add_wait_queue(&bkt->lsb_marche_funebre, waiter);
- set_current_state(TASK_UNINTERRUPTIBLE);
- lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_DEATH_RACE);
- return ERR_PTR(-EAGAIN);
-}
-
-/**
- * Search cache for an object with the fid \a f. If such object is found,
- * return it. Otherwise, create new object, insert it into cache and return
- * it. In any case, additional reference is acquired on the returned object.
- */
-static struct lu_object *lu_object_find(const struct lu_env *env,
- struct lu_device *dev,
- const struct lu_fid *f,
- const struct lu_object_conf *conf)
-{
- return lu_object_find_at(env, dev->ld_site->ls_top_dev, f, conf);
-}
-
-/*
- * Limit the lu_object cache to a maximum of lu_cache_nr objects. Because
- * the calculation for the number of objects to reclaim is not covered by
- * a lock the maximum number of objects is capped by LU_CACHE_MAX_ADJUST.
- * This ensures that many concurrent threads will not accidentally purge
- * the entire cache.
- */
-static void lu_object_limit(const struct lu_env *env, struct lu_device *dev)
-{
- __u64 size, nr;
-
- if (lu_cache_nr == LU_CACHE_NR_UNLIMITED)
- return;
-
- size = cfs_hash_size_get(dev->ld_site->ls_obj_hash);
- nr = (__u64)lu_cache_nr;
- if (size <= nr)
- return;
-
- lu_site_purge_objects(env, dev->ld_site,
- min_t(__u64, size - nr, LU_CACHE_NR_MAX_ADJUST),
- false);
-}
-
-static struct lu_object *lu_object_new(const struct lu_env *env,
- struct lu_device *dev,
- const struct lu_fid *f,
- const struct lu_object_conf *conf)
-{
- struct lu_object *o;
- struct cfs_hash *hs;
- struct cfs_hash_bd bd;
-
- o = lu_object_alloc(env, dev, f, conf);
- if (IS_ERR(o))
- return o;
-
- hs = dev->ld_site->ls_obj_hash;
- cfs_hash_bd_get_and_lock(hs, (void *)f, &bd, 1);
- cfs_hash_bd_add_locked(hs, &bd, &o->lo_header->loh_hash);
- cfs_hash_bd_unlock(hs, &bd, 1);
-
- lu_object_limit(env, dev);
-
- return o;
-}
-
-/**
- * Core logic of lu_object_find*() functions.
- */
-static struct lu_object *lu_object_find_try(const struct lu_env *env,
- struct lu_device *dev,
- const struct lu_fid *f,
- const struct lu_object_conf *conf,
- wait_queue_entry_t *waiter)
-{
- struct lu_object *o;
- struct lu_object *shadow;
- struct lu_site *s;
- struct cfs_hash *hs;
- struct cfs_hash_bd bd;
- __u64 version = 0;
-
- /*
- * This uses standard index maintenance protocol:
- *
- * - search index under lock, and return object if found;
- * - otherwise, unlock index, allocate new object;
- * - lock index and search again;
- * - if nothing is found (usual case), insert newly created
- * object into index;
- * - otherwise (race: other thread inserted object), free
- * object just allocated.
- * - unlock index;
- * - return object.
- *
- * For "LOC_F_NEW" case, we are sure the object is new established.
- * It is unnecessary to perform lookup-alloc-lookup-insert, instead,
- * just alloc and insert directly.
- *
- * If dying object is found during index search, add @waiter to the
- * site wait-queue and return ERR_PTR(-EAGAIN).
- */
- if (conf && conf->loc_flags & LOC_F_NEW)
- return lu_object_new(env, dev, f, conf);
-
- s = dev->ld_site;
- hs = s->ls_obj_hash;
- cfs_hash_bd_get_and_lock(hs, (void *)f, &bd, 1);
- o = htable_lookup(s, &bd, f, waiter, &version);
- cfs_hash_bd_unlock(hs, &bd, 1);
- if (!IS_ERR(o) || PTR_ERR(o) != -ENOENT)
- return o;
-
- /*
- * Allocate new object. This may result in rather complicated
- * operations, including fld queries, inode loading, etc.
- */
- o = lu_object_alloc(env, dev, f, conf);
- if (IS_ERR(o))
- return o;
-
- LASSERT(lu_fid_eq(lu_object_fid(o), f));
-
- cfs_hash_bd_lock(hs, &bd, 1);
-
- shadow = htable_lookup(s, &bd, f, waiter, &version);
- if (likely(PTR_ERR(shadow) == -ENOENT)) {
- cfs_hash_bd_add_locked(hs, &bd, &o->lo_header->loh_hash);
- cfs_hash_bd_unlock(hs, &bd, 1);
-
- lu_object_limit(env, dev);
-
- return o;
- }
-
- lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_RACE);
- cfs_hash_bd_unlock(hs, &bd, 1);
- lu_object_free(env, o);
- return shadow;
-}
-
-/**
- * Much like lu_object_find(), but top level device of object is specifically
- * \a dev rather than top level device of the site. This interface allows
- * objects of different "stacking" to be created within the same site.
- */
-struct lu_object *lu_object_find_at(const struct lu_env *env,
- struct lu_device *dev,
- const struct lu_fid *f,
- const struct lu_object_conf *conf)
-{
- struct lu_site_bkt_data *bkt;
- struct lu_object *obj;
- wait_queue_entry_t wait;
-
- while (1) {
- obj = lu_object_find_try(env, dev, f, conf, &wait);
- if (obj != ERR_PTR(-EAGAIN))
- return obj;
- /*
- * lu_object_find_try() already added waiter into the
- * wait queue.
- */
- schedule();
- bkt = lu_site_bkt_from_fid(dev->ld_site, (void *)f);
- remove_wait_queue(&bkt->lsb_marche_funebre, &wait);
- }
-}
-EXPORT_SYMBOL(lu_object_find_at);
-
-/**
- * Find object with given fid, and return its slice belonging to given device.
- */
-struct lu_object *lu_object_find_slice(const struct lu_env *env,
- struct lu_device *dev,
- const struct lu_fid *f,
- const struct lu_object_conf *conf)
-{
- struct lu_object *top;
- struct lu_object *obj;
-
- top = lu_object_find(env, dev, f, conf);
- if (IS_ERR(top))
- return top;
-
- obj = lu_object_locate(top->lo_header, dev->ld_type);
- if (unlikely(!obj)) {
- lu_object_put(env, top);
- obj = ERR_PTR(-ENOENT);
- }
-
- return obj;
-}
-EXPORT_SYMBOL(lu_object_find_slice);
-
-/**
- * Global list of all device types.
- */
-static LIST_HEAD(lu_device_types);
-
-int lu_device_type_init(struct lu_device_type *ldt)
-{
- int result = 0;
-
- atomic_set(&ldt->ldt_device_nr, 0);
- INIT_LIST_HEAD(&ldt->ldt_linkage);
- if (ldt->ldt_ops->ldto_init)
- result = ldt->ldt_ops->ldto_init(ldt);
-
- if (!result) {
- spin_lock(&obd_types_lock);
- list_add(&ldt->ldt_linkage, &lu_device_types);
- spin_unlock(&obd_types_lock);
- }
-
- return result;
-}
-EXPORT_SYMBOL(lu_device_type_init);
-
-void lu_device_type_fini(struct lu_device_type *ldt)
-{
- spin_lock(&obd_types_lock);
- list_del_init(&ldt->ldt_linkage);
- spin_unlock(&obd_types_lock);
- if (ldt->ldt_ops->ldto_fini)
- ldt->ldt_ops->ldto_fini(ldt);
-}
-EXPORT_SYMBOL(lu_device_type_fini);
-
-/**
- * Global list of all sites on this node
- */
-static LIST_HEAD(lu_sites);
-static DECLARE_RWSEM(lu_sites_guard);
-
-/**
- * Global environment used by site shrinker.
- */
-static struct lu_env lu_shrink_env;
-
-struct lu_site_print_arg {
- struct lu_env *lsp_env;
- void *lsp_cookie;
- lu_printer_t lsp_printer;
-};
-
-static int
-lu_site_obj_print(struct cfs_hash *hs, struct cfs_hash_bd *bd,
- struct hlist_node *hnode, void *data)
-{
- struct lu_site_print_arg *arg = (struct lu_site_print_arg *)data;
- struct lu_object_header *h;
-
- h = hlist_entry(hnode, struct lu_object_header, loh_hash);
- if (!list_empty(&h->loh_layers)) {
- const struct lu_object *o;
-
- o = lu_object_top(h);
- lu_object_print(arg->lsp_env, arg->lsp_cookie,
- arg->lsp_printer, o);
- } else {
- lu_object_header_print(arg->lsp_env, arg->lsp_cookie,
- arg->lsp_printer, h);
- }
- return 0;
-}
-
-/**
- * Print all objects in \a s.
- */
-void lu_site_print(const struct lu_env *env, struct lu_site *s, void *cookie,
- lu_printer_t printer)
-{
- struct lu_site_print_arg arg = {
- .lsp_env = (struct lu_env *)env,
- .lsp_cookie = cookie,
- .lsp_printer = printer,
- };
-
- cfs_hash_for_each(s->ls_obj_hash, lu_site_obj_print, &arg);
-}
-EXPORT_SYMBOL(lu_site_print);
-
-/**
- * Return desired hash table order.
- */
-static unsigned long lu_htable_order(struct lu_device *top)
-{
- unsigned long bits_max = LU_SITE_BITS_MAX;
- unsigned long cache_size;
- unsigned long bits;
-
- if (!strcmp(top->ld_type->ldt_name, LUSTRE_VVP_NAME))
- bits_max = LU_SITE_BITS_MAX_CL;
-
- /*
- * Calculate hash table size, assuming that we want reasonable
- * performance when 20% of total memory is occupied by cache of
- * lu_objects.
- *
- * Size of lu_object is (arbitrary) taken as 1K (together with inode).
- */
- cache_size = totalram_pages;
-
-#if BITS_PER_LONG == 32
- /* limit hashtable size for lowmem systems to low RAM */
- if (cache_size > 1 << (30 - PAGE_SHIFT))
- cache_size = 1 << (30 - PAGE_SHIFT) * 3 / 4;
-#endif
-
- /* clear off unreasonable cache setting. */
- if (lu_cache_percent == 0 || lu_cache_percent > LU_CACHE_PERCENT_MAX) {
- CWARN("obdclass: invalid lu_cache_percent: %u, it must be in the range of (0, %u]. Will use default value: %u.\n",
- lu_cache_percent, LU_CACHE_PERCENT_MAX,
- LU_CACHE_PERCENT_DEFAULT);
-
- lu_cache_percent = LU_CACHE_PERCENT_DEFAULT;
- }
- cache_size = cache_size / 100 * lu_cache_percent *
- (PAGE_SIZE / 1024);
-
- for (bits = 1; (1 << bits) < cache_size; ++bits)
- ;
- return clamp_t(typeof(bits), bits, LU_SITE_BITS_MIN, bits_max);
-}
-
-static unsigned int lu_obj_hop_hash(struct cfs_hash *hs,
- const void *key, unsigned int mask)
-{
- struct lu_fid *fid = (struct lu_fid *)key;
- __u32 hash;
-
- hash = fid_flatten32(fid);
- hash += (hash >> 4) + (hash << 12); /* mixing oid and seq */
- hash = hash_long(hash, hs->hs_bkt_bits);
-
- /* give me another random factor */
- hash -= hash_long((unsigned long)hs, fid_oid(fid) % 11 + 3);
-
- hash <<= hs->hs_cur_bits - hs->hs_bkt_bits;
- hash |= (fid_seq(fid) + fid_oid(fid)) & (CFS_HASH_NBKT(hs) - 1);
-
- return hash & mask;
-}
-
-static void *lu_obj_hop_object(struct hlist_node *hnode)
-{
- return hlist_entry(hnode, struct lu_object_header, loh_hash);
-}
-
-static void *lu_obj_hop_key(struct hlist_node *hnode)
-{
- struct lu_object_header *h;
-
- h = hlist_entry(hnode, struct lu_object_header, loh_hash);
- return &h->loh_fid;
-}
-
-static int lu_obj_hop_keycmp(const void *key, struct hlist_node *hnode)
-{
- struct lu_object_header *h;
-
- h = hlist_entry(hnode, struct lu_object_header, loh_hash);
- return lu_fid_eq(&h->loh_fid, (struct lu_fid *)key);
-}
-
-static void lu_obj_hop_get(struct cfs_hash *hs, struct hlist_node *hnode)
-{
- struct lu_object_header *h;
-
- h = hlist_entry(hnode, struct lu_object_header, loh_hash);
- atomic_inc(&h->loh_ref);
-}
-
-static void lu_obj_hop_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
-{
- LBUG(); /* we should never called it */
-}
-
-static struct cfs_hash_ops lu_site_hash_ops = {
- .hs_hash = lu_obj_hop_hash,
- .hs_key = lu_obj_hop_key,
- .hs_keycmp = lu_obj_hop_keycmp,
- .hs_object = lu_obj_hop_object,
- .hs_get = lu_obj_hop_get,
- .hs_put_locked = lu_obj_hop_put_locked,
-};
-
-static void lu_dev_add_linkage(struct lu_site *s, struct lu_device *d)
-{
- spin_lock(&s->ls_ld_lock);
- if (list_empty(&d->ld_linkage))
- list_add(&d->ld_linkage, &s->ls_ld_linkage);
- spin_unlock(&s->ls_ld_lock);
-}
-
-/**
- * Initialize site \a s, with \a d as the top level device.
- */
-int lu_site_init(struct lu_site *s, struct lu_device *top)
-{
- struct lu_site_bkt_data *bkt;
- struct cfs_hash_bd bd;
- unsigned long bits;
- unsigned long i;
- char name[16];
- int rc;
-
- memset(s, 0, sizeof(*s));
- mutex_init(&s->ls_purge_mutex);
-
- rc = percpu_counter_init(&s->ls_lru_len_counter, 0, GFP_NOFS);
- if (rc)
- return -ENOMEM;
-
- snprintf(name, sizeof(name), "lu_site_%s", top->ld_type->ldt_name);
- for (bits = lu_htable_order(top); bits >= LU_SITE_BITS_MIN; bits--) {
- s->ls_obj_hash = cfs_hash_create(name, bits, bits,
- bits - LU_SITE_BKT_BITS,
- sizeof(*bkt), 0, 0,
- &lu_site_hash_ops,
- CFS_HASH_SPIN_BKTLOCK |
- CFS_HASH_NO_ITEMREF |
- CFS_HASH_DEPTH |
- CFS_HASH_ASSERT_EMPTY |
- CFS_HASH_COUNTER);
- if (s->ls_obj_hash)
- break;
- }
-
- if (!s->ls_obj_hash) {
- CERROR("failed to create lu_site hash with bits: %lu\n", bits);
- return -ENOMEM;
- }
-
- cfs_hash_for_each_bucket(s->ls_obj_hash, &bd, i) {
- bkt = cfs_hash_bd_extra_get(s->ls_obj_hash, &bd);
- INIT_LIST_HEAD(&bkt->lsb_lru);
- init_waitqueue_head(&bkt->lsb_marche_funebre);
- }
-
- s->ls_stats = lprocfs_alloc_stats(LU_SS_LAST_STAT, 0);
- if (!s->ls_stats) {
- cfs_hash_putref(s->ls_obj_hash);
- s->ls_obj_hash = NULL;
- return -ENOMEM;
- }
-
- lprocfs_counter_init(s->ls_stats, LU_SS_CREATED,
- 0, "created", "created");
- lprocfs_counter_init(s->ls_stats, LU_SS_CACHE_HIT,
- 0, "cache_hit", "cache_hit");
- lprocfs_counter_init(s->ls_stats, LU_SS_CACHE_MISS,
- 0, "cache_miss", "cache_miss");
- lprocfs_counter_init(s->ls_stats, LU_SS_CACHE_RACE,
- 0, "cache_race", "cache_race");
- lprocfs_counter_init(s->ls_stats, LU_SS_CACHE_DEATH_RACE,
- 0, "cache_death_race", "cache_death_race");
- lprocfs_counter_init(s->ls_stats, LU_SS_LRU_PURGED,
- 0, "lru_purged", "lru_purged");
-
- INIT_LIST_HEAD(&s->ls_linkage);
- s->ls_top_dev = top;
- top->ld_site = s;
- lu_device_get(top);
- lu_ref_add(&top->ld_reference, "site-top", s);
-
- INIT_LIST_HEAD(&s->ls_ld_linkage);
- spin_lock_init(&s->ls_ld_lock);
-
- lu_dev_add_linkage(s, top);
-
- return 0;
-}
-EXPORT_SYMBOL(lu_site_init);
-
-/**
- * Finalize \a s and release its resources.
- */
-void lu_site_fini(struct lu_site *s)
-{
- down_write(&lu_sites_guard);
- list_del_init(&s->ls_linkage);
- up_write(&lu_sites_guard);
-
- percpu_counter_destroy(&s->ls_lru_len_counter);
-
- if (s->ls_obj_hash) {
- cfs_hash_putref(s->ls_obj_hash);
- s->ls_obj_hash = NULL;
- }
-
- if (s->ls_top_dev) {
- s->ls_top_dev->ld_site = NULL;
- lu_ref_del(&s->ls_top_dev->ld_reference, "site-top", s);
- lu_device_put(s->ls_top_dev);
- s->ls_top_dev = NULL;
- }
-
- if (s->ls_stats)
- lprocfs_free_stats(&s->ls_stats);
-}
-EXPORT_SYMBOL(lu_site_fini);
-
-/**
- * Called when initialization of stack for this site is completed.
- */
-int lu_site_init_finish(struct lu_site *s)
-{
- int result;
-
- down_write(&lu_sites_guard);
- result = lu_context_refill(&lu_shrink_env.le_ctx);
- if (result == 0)
- list_add(&s->ls_linkage, &lu_sites);
- up_write(&lu_sites_guard);
- return result;
-}
-EXPORT_SYMBOL(lu_site_init_finish);
-
-/**
- * Acquire additional reference on device \a d
- */
-void lu_device_get(struct lu_device *d)
-{
- atomic_inc(&d->ld_ref);
-}
-EXPORT_SYMBOL(lu_device_get);
-
-/**
- * Release reference on device \a d.
- */
-void lu_device_put(struct lu_device *d)
-{
- LASSERT(atomic_read(&d->ld_ref) > 0);
- atomic_dec(&d->ld_ref);
-}
-EXPORT_SYMBOL(lu_device_put);
-
-/**
- * Initialize device \a d of type \a t.
- */
-int lu_device_init(struct lu_device *d, struct lu_device_type *t)
-{
- if (atomic_inc_return(&t->ldt_device_nr) == 1 &&
- t->ldt_ops->ldto_start)
- t->ldt_ops->ldto_start(t);
-
- memset(d, 0, sizeof(*d));
- atomic_set(&d->ld_ref, 0);
- d->ld_type = t;
- lu_ref_init(&d->ld_reference);
- INIT_LIST_HEAD(&d->ld_linkage);
- return 0;
-}
-EXPORT_SYMBOL(lu_device_init);
-
-/**
- * Finalize device \a d.
- */
-void lu_device_fini(struct lu_device *d)
-{
- struct lu_device_type *t = d->ld_type;
-
- if (d->ld_obd) {
- d->ld_obd->obd_lu_dev = NULL;
- d->ld_obd = NULL;
- }
-
- lu_ref_fini(&d->ld_reference);
- LASSERTF(atomic_read(&d->ld_ref) == 0,
- "Refcount is %u\n", atomic_read(&d->ld_ref));
- LASSERT(atomic_read(&t->ldt_device_nr) > 0);
-
- if (atomic_dec_and_test(&t->ldt_device_nr) &&
- t->ldt_ops->ldto_stop)
- t->ldt_ops->ldto_stop(t);
-}
-EXPORT_SYMBOL(lu_device_fini);
-
-/**
- * Initialize object \a o that is part of compound object \a h and was created
- * by device \a d.
- */
-int lu_object_init(struct lu_object *o, struct lu_object_header *h,
- struct lu_device *d)
-{
- memset(o, 0, sizeof(*o));
- o->lo_header = h;
- o->lo_dev = d;
- lu_device_get(d);
- lu_ref_add_at(&d->ld_reference, &o->lo_dev_ref, "lu_object", o);
- INIT_LIST_HEAD(&o->lo_linkage);
-
- return 0;
-}
-EXPORT_SYMBOL(lu_object_init);
-
-/**
- * Finalize object and release its resources.
- */
-void lu_object_fini(struct lu_object *o)
-{
- struct lu_device *dev = o->lo_dev;
-
- LASSERT(list_empty(&o->lo_linkage));
-
- if (dev) {
- lu_ref_del_at(&dev->ld_reference, &o->lo_dev_ref,
- "lu_object", o);
- lu_device_put(dev);
- o->lo_dev = NULL;
- }
-}
-EXPORT_SYMBOL(lu_object_fini);
-
-/**
- * Add object \a o as first layer of compound object \a h
- *
- * This is typically called by the ->ldo_object_alloc() method of top-level
- * device.
- */
-void lu_object_add_top(struct lu_object_header *h, struct lu_object *o)
-{
- list_move(&o->lo_linkage, &h->loh_layers);
-}
-EXPORT_SYMBOL(lu_object_add_top);
-
-/**
- * Add object \a o as a layer of compound object, going after \a before.
- *
- * This is typically called by the ->ldo_object_alloc() method of \a
- * before->lo_dev.
- */
-void lu_object_add(struct lu_object *before, struct lu_object *o)
-{
- list_move(&o->lo_linkage, &before->lo_linkage);
-}
-EXPORT_SYMBOL(lu_object_add);
-
-/**
- * Initialize compound object.
- */
-int lu_object_header_init(struct lu_object_header *h)
-{
- memset(h, 0, sizeof(*h));
- atomic_set(&h->loh_ref, 1);
- INIT_HLIST_NODE(&h->loh_hash);
- INIT_LIST_HEAD(&h->loh_lru);
- INIT_LIST_HEAD(&h->loh_layers);
- lu_ref_init(&h->loh_reference);
- return 0;
-}
-EXPORT_SYMBOL(lu_object_header_init);
-
-/**
- * Finalize compound object.
- */
-void lu_object_header_fini(struct lu_object_header *h)
-{
- LASSERT(list_empty(&h->loh_layers));
- LASSERT(list_empty(&h->loh_lru));
- LASSERT(hlist_unhashed(&h->loh_hash));
- lu_ref_fini(&h->loh_reference);
-}
-EXPORT_SYMBOL(lu_object_header_fini);
-
-/**
- * Given a compound object, find its slice, corresponding to the device type
- * \a dtype.
- */
-struct lu_object *lu_object_locate(struct lu_object_header *h,
- const struct lu_device_type *dtype)
-{
- struct lu_object *o;
-
- list_for_each_entry(o, &h->loh_layers, lo_linkage) {
- if (o->lo_dev->ld_type == dtype)
- return o;
- }
- return NULL;
-}
-EXPORT_SYMBOL(lu_object_locate);
-
-/**
- * Finalize and free devices in the device stack.
- *
- * Finalize device stack by purging object cache, and calling
- * lu_device_type_operations::ldto_device_fini() and
- * lu_device_type_operations::ldto_device_free() on all devices in the stack.
- */
-void lu_stack_fini(const struct lu_env *env, struct lu_device *top)
-{
- struct lu_site *site = top->ld_site;
- struct lu_device *scan;
- struct lu_device *next;
-
- lu_site_purge(env, site, ~0);
- for (scan = top; scan; scan = next) {
- next = scan->ld_type->ldt_ops->ldto_device_fini(env, scan);
- lu_ref_del(&scan->ld_reference, "lu-stack", &lu_site_init);
- lu_device_put(scan);
- }
-
- /* purge again. */
- lu_site_purge(env, site, ~0);
-
- for (scan = top; scan; scan = next) {
- const struct lu_device_type *ldt = scan->ld_type;
- struct obd_type *type;
-
- next = ldt->ldt_ops->ldto_device_free(env, scan);
- type = ldt->ldt_obd_type;
- if (type) {
- type->typ_refcnt--;
- class_put_type(type);
- }
- }
-}
-
-enum {
- /**
- * Maximal number of tld slots.
- */
- LU_CONTEXT_KEY_NR = 40
-};
-
-static struct lu_context_key *lu_keys[LU_CONTEXT_KEY_NR] = { NULL, };
-
-static DEFINE_SPINLOCK(lu_keys_guard);
-static atomic_t lu_key_initing_cnt = ATOMIC_INIT(0);
-
-/**
- * Global counter incremented whenever key is registered, unregistered,
- * revived or quiesced. This is used to void unnecessary calls to
- * lu_context_refill(). No locking is provided, as initialization and shutdown
- * are supposed to be externally serialized.
- */
-static unsigned int key_set_version;
-
-/**
- * Register new key.
- */
-int lu_context_key_register(struct lu_context_key *key)
-{
- int result;
- unsigned int i;
-
- LASSERT(key->lct_init);
- LASSERT(key->lct_fini);
- LASSERT(key->lct_tags != 0);
-
- result = -ENFILE;
- spin_lock(&lu_keys_guard);
- for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) {
- if (!lu_keys[i]) {
- key->lct_index = i;
- atomic_set(&key->lct_used, 1);
- lu_keys[i] = key;
- lu_ref_init(&key->lct_reference);
- result = 0;
- ++key_set_version;
- break;
- }
- }
- spin_unlock(&lu_keys_guard);
- return result;
-}
-EXPORT_SYMBOL(lu_context_key_register);
-
-static void key_fini(struct lu_context *ctx, int index)
-{
- if (ctx->lc_value && ctx->lc_value[index]) {
- struct lu_context_key *key;
-
- key = lu_keys[index];
- LASSERT(atomic_read(&key->lct_used) > 1);
-
- key->lct_fini(ctx, key, ctx->lc_value[index]);
- lu_ref_del(&key->lct_reference, "ctx", ctx);
- atomic_dec(&key->lct_used);
-
- if ((ctx->lc_tags & LCT_NOREF) == 0)
- module_put(key->lct_owner);
- ctx->lc_value[index] = NULL;
- }
-}
-
-/**
- * Deregister key.
- */
-void lu_context_key_degister(struct lu_context_key *key)
-{
- LASSERT(atomic_read(&key->lct_used) >= 1);
- LINVRNT(0 <= key->lct_index && key->lct_index < ARRAY_SIZE(lu_keys));
-
- lu_context_key_quiesce(key);
-
- ++key_set_version;
- spin_lock(&lu_keys_guard);
- key_fini(&lu_shrink_env.le_ctx, key->lct_index);
-
- /**
- * Wait until all transient contexts referencing this key have
- * run lu_context_key::lct_fini() method.
- */
- while (atomic_read(&key->lct_used) > 1) {
- spin_unlock(&lu_keys_guard);
- CDEBUG(D_INFO, "%s: \"%s\" %p, %d\n",
- __func__, module_name(key->lct_owner),
- key, atomic_read(&key->lct_used));
- schedule();
- spin_lock(&lu_keys_guard);
- }
- if (lu_keys[key->lct_index]) {
- lu_keys[key->lct_index] = NULL;
- lu_ref_fini(&key->lct_reference);
- }
- spin_unlock(&lu_keys_guard);
-
- LASSERTF(atomic_read(&key->lct_used) == 1,
- "key has instances: %d\n",
- atomic_read(&key->lct_used));
-}
-EXPORT_SYMBOL(lu_context_key_degister);
-
-/**
- * Register a number of keys. This has to be called after all keys have been
- * initialized by a call to LU_CONTEXT_KEY_INIT().
- */
-int lu_context_key_register_many(struct lu_context_key *k, ...)
-{
- struct lu_context_key *key = k;
- va_list args;
- int result;
-
- va_start(args, k);
- do {
- result = lu_context_key_register(key);
- if (result)
- break;
- key = va_arg(args, struct lu_context_key *);
- } while (key);
- va_end(args);
-
- if (result != 0) {
- va_start(args, k);
- while (k != key) {
- lu_context_key_degister(k);
- k = va_arg(args, struct lu_context_key *);
- }
- va_end(args);
- }
-
- return result;
-}
-EXPORT_SYMBOL(lu_context_key_register_many);
-
-/**
- * De-register a number of keys. This is a dual to
- * lu_context_key_register_many().
- */
-void lu_context_key_degister_many(struct lu_context_key *k, ...)
-{
- va_list args;
-
- va_start(args, k);
- do {
- lu_context_key_degister(k);
- k = va_arg(args, struct lu_context_key*);
- } while (k);
- va_end(args);
-}
-EXPORT_SYMBOL(lu_context_key_degister_many);
-
-/**
- * Revive a number of keys.
- */
-void lu_context_key_revive_many(struct lu_context_key *k, ...)
-{
- va_list args;
-
- va_start(args, k);
- do {
- lu_context_key_revive(k);
- k = va_arg(args, struct lu_context_key*);
- } while (k);
- va_end(args);
-}
-EXPORT_SYMBOL(lu_context_key_revive_many);
-
-/**
- * Quiescent a number of keys.
- */
-void lu_context_key_quiesce_many(struct lu_context_key *k, ...)
-{
- va_list args;
-
- va_start(args, k);
- do {
- lu_context_key_quiesce(k);
- k = va_arg(args, struct lu_context_key*);
- } while (k);
- va_end(args);
-}
-EXPORT_SYMBOL(lu_context_key_quiesce_many);
-
-/**
- * Return value associated with key \a key in context \a ctx.
- */
-void *lu_context_key_get(const struct lu_context *ctx,
- const struct lu_context_key *key)
-{
- LINVRNT(ctx->lc_state == LCS_ENTERED);
- LINVRNT(0 <= key->lct_index && key->lct_index < ARRAY_SIZE(lu_keys));
- LASSERT(lu_keys[key->lct_index] == key);
- return ctx->lc_value[key->lct_index];
-}
-EXPORT_SYMBOL(lu_context_key_get);
-
-/**
- * List of remembered contexts. XXX document me.
- */
-static LIST_HEAD(lu_context_remembered);
-
-/**
- * Destroy \a key in all remembered contexts. This is used to destroy key
- * values in "shared" contexts (like service threads), when a module owning
- * the key is about to be unloaded.
- */
-void lu_context_key_quiesce(struct lu_context_key *key)
-{
- struct lu_context *ctx;
-
- if (!(key->lct_tags & LCT_QUIESCENT)) {
- /*
- * XXX memory barrier has to go here.
- */
- spin_lock(&lu_keys_guard);
- key->lct_tags |= LCT_QUIESCENT;
-
- /**
- * Wait until all lu_context_key::lct_init() methods
- * have completed.
- */
- while (atomic_read(&lu_key_initing_cnt) > 0) {
- spin_unlock(&lu_keys_guard);
- CDEBUG(D_INFO, "%s: \"%s\" %p, %d (%d)\n",
- __func__,
- module_name(key->lct_owner),
- key, atomic_read(&key->lct_used),
- atomic_read(&lu_key_initing_cnt));
- schedule();
- spin_lock(&lu_keys_guard);
- }
-
- list_for_each_entry(ctx, &lu_context_remembered, lc_remember)
- key_fini(ctx, key->lct_index);
- spin_unlock(&lu_keys_guard);
- ++key_set_version;
- }
-}
-
-void lu_context_key_revive(struct lu_context_key *key)
-{
- key->lct_tags &= ~LCT_QUIESCENT;
- ++key_set_version;
-}
-
-static void keys_fini(struct lu_context *ctx)
-{
- unsigned int i;
-
- if (!ctx->lc_value)
- return;
-
- for (i = 0; i < ARRAY_SIZE(lu_keys); ++i)
- key_fini(ctx, i);
-
- kfree(ctx->lc_value);
- ctx->lc_value = NULL;
-}
-
-static int keys_fill(struct lu_context *ctx)
-{
- unsigned int i;
-
- /*
- * A serialisation with lu_context_key_quiesce() is needed, but some
- * "key->lct_init()" are calling kernel memory allocation routine and
- * can't be called while holding a spin_lock.
- * "lu_keys_guard" is held while incrementing "lu_key_initing_cnt"
- * to ensure the start of the serialisation.
- * An atomic_t variable is still used, in order not to reacquire the
- * lock when decrementing the counter.
- */
- spin_lock(&lu_keys_guard);
- atomic_inc(&lu_key_initing_cnt);
- spin_unlock(&lu_keys_guard);
-
- LINVRNT(ctx->lc_value);
- for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) {
- struct lu_context_key *key;
-
- key = lu_keys[i];
- if (!ctx->lc_value[i] && key &&
- (key->lct_tags & ctx->lc_tags) &&
- /*
- * Don't create values for a LCT_QUIESCENT key, as this
- * will pin module owning a key.
- */
- !(key->lct_tags & LCT_QUIESCENT)) {
- void *value;
-
- LINVRNT(key->lct_init);
- LINVRNT(key->lct_index == i);
-
- if (!(ctx->lc_tags & LCT_NOREF) &&
- !try_module_get(key->lct_owner)) {
- /* module is unloading, skip this key */
- continue;
- }
-
- value = key->lct_init(ctx, key);
- if (unlikely(IS_ERR(value))) {
- atomic_dec(&lu_key_initing_cnt);
- return PTR_ERR(value);
- }
-
- lu_ref_add_atomic(&key->lct_reference, "ctx", ctx);
- atomic_inc(&key->lct_used);
- /*
- * This is the only place in the code, where an
- * element of ctx->lc_value[] array is set to non-NULL
- * value.
- */
- ctx->lc_value[i] = value;
- if (key->lct_exit)
- ctx->lc_tags |= LCT_HAS_EXIT;
- }
- ctx->lc_version = key_set_version;
- }
- atomic_dec(&lu_key_initing_cnt);
- return 0;
-}
-
-static int keys_init(struct lu_context *ctx)
-{
- ctx->lc_value = kcalloc(ARRAY_SIZE(lu_keys), sizeof(ctx->lc_value[0]),
- GFP_NOFS);
- if (likely(ctx->lc_value))
- return keys_fill(ctx);
-
- return -ENOMEM;
-}
-
-/**
- * Initialize context data-structure. Create values for all keys.
- */
-int lu_context_init(struct lu_context *ctx, __u32 tags)
-{
- int rc;
-
- memset(ctx, 0, sizeof(*ctx));
- ctx->lc_state = LCS_INITIALIZED;
- ctx->lc_tags = tags;
- if (tags & LCT_REMEMBER) {
- spin_lock(&lu_keys_guard);
- list_add(&ctx->lc_remember, &lu_context_remembered);
- spin_unlock(&lu_keys_guard);
- } else {
- INIT_LIST_HEAD(&ctx->lc_remember);
- }
-
- rc = keys_init(ctx);
- if (rc != 0)
- lu_context_fini(ctx);
-
- return rc;
-}
-EXPORT_SYMBOL(lu_context_init);
-
-/**
- * Finalize context data-structure. Destroy key values.
- */
-void lu_context_fini(struct lu_context *ctx)
-{
- LINVRNT(ctx->lc_state == LCS_INITIALIZED || ctx->lc_state == LCS_LEFT);
- ctx->lc_state = LCS_FINALIZED;
-
- if ((ctx->lc_tags & LCT_REMEMBER) == 0) {
- LASSERT(list_empty(&ctx->lc_remember));
- keys_fini(ctx);
-
- } else { /* could race with key degister */
- spin_lock(&lu_keys_guard);
- keys_fini(ctx);
- list_del_init(&ctx->lc_remember);
- spin_unlock(&lu_keys_guard);
- }
-}
-EXPORT_SYMBOL(lu_context_fini);
-
-/**
- * Called before entering context.
- */
-void lu_context_enter(struct lu_context *ctx)
-{
- LINVRNT(ctx->lc_state == LCS_INITIALIZED || ctx->lc_state == LCS_LEFT);
- ctx->lc_state = LCS_ENTERED;
-}
-EXPORT_SYMBOL(lu_context_enter);
-
-/**
- * Called after exiting from \a ctx
- */
-void lu_context_exit(struct lu_context *ctx)
-{
- unsigned int i;
-
- LINVRNT(ctx->lc_state == LCS_ENTERED);
- ctx->lc_state = LCS_LEFT;
- if (ctx->lc_tags & LCT_HAS_EXIT && ctx->lc_value) {
- for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) {
- /* could race with key quiescency */
- if (ctx->lc_tags & LCT_REMEMBER)
- spin_lock(&lu_keys_guard);
- if (ctx->lc_value[i]) {
- struct lu_context_key *key;
-
- key = lu_keys[i];
- if (key->lct_exit)
- key->lct_exit(ctx,
- key, ctx->lc_value[i]);
- }
- if (ctx->lc_tags & LCT_REMEMBER)
- spin_unlock(&lu_keys_guard);
- }
- }
-}
-EXPORT_SYMBOL(lu_context_exit);
-
-/**
- * Allocate for context all missing keys that were registered after context
- * creation. key_set_version is only changed in rare cases when modules
- * are loaded and removed.
- */
-int lu_context_refill(struct lu_context *ctx)
-{
- return likely(ctx->lc_version == key_set_version) ? 0 : keys_fill(ctx);
-}
-
-/**
- * lu_ctx_tags/lu_ses_tags will be updated if there are new types of
- * obd being added. Currently, this is only used on client side, specifically
- * for echo device client, for other stack (like ptlrpc threads), context are
- * predefined when the lu_device type are registered, during the module probe
- * phase.
- */
-__u32 lu_context_tags_default;
-__u32 lu_session_tags_default;
-
-int lu_env_init(struct lu_env *env, __u32 tags)
-{
- int result;
-
- env->le_ses = NULL;
- result = lu_context_init(&env->le_ctx, tags);
- if (likely(result == 0))
- lu_context_enter(&env->le_ctx);
- return result;
-}
-EXPORT_SYMBOL(lu_env_init);
-
-void lu_env_fini(struct lu_env *env)
-{
- lu_context_exit(&env->le_ctx);
- lu_context_fini(&env->le_ctx);
- env->le_ses = NULL;
-}
-EXPORT_SYMBOL(lu_env_fini);
-
-int lu_env_refill(struct lu_env *env)
-{
- int result;
-
- result = lu_context_refill(&env->le_ctx);
- if (result == 0 && env->le_ses)
- result = lu_context_refill(env->le_ses);
- return result;
-}
-EXPORT_SYMBOL(lu_env_refill);
-
-struct lu_site_stats {
- unsigned int lss_populated;
- unsigned int lss_max_search;
- unsigned int lss_total;
- unsigned int lss_busy;
-};
-
-static void lu_site_stats_get(struct cfs_hash *hs,
- struct lu_site_stats *stats, int populated)
-{
- struct cfs_hash_bd bd;
- unsigned int i;
-
- cfs_hash_for_each_bucket(hs, &bd, i) {
- struct lu_site_bkt_data *bkt = cfs_hash_bd_extra_get(hs, &bd);
- struct hlist_head *hhead;
-
- cfs_hash_bd_lock(hs, &bd, 1);
- stats->lss_busy +=
- cfs_hash_bd_count_get(&bd) - bkt->lsb_lru_len;
- stats->lss_total += cfs_hash_bd_count_get(&bd);
- stats->lss_max_search = max((int)stats->lss_max_search,
- cfs_hash_bd_depmax_get(&bd));
- if (!populated) {
- cfs_hash_bd_unlock(hs, &bd, 1);
- continue;
- }
-
- cfs_hash_bd_for_each_hlist(hs, &bd, hhead) {
- if (!hlist_empty(hhead))
- stats->lss_populated++;
- }
- cfs_hash_bd_unlock(hs, &bd, 1);
- }
-}
-
-/*
- * lu_cache_shrink_count() returns an approximate number of cached objects
- * that can be freed by shrink_slab(). A counter, which tracks the
- * number of items in the site's lru, is maintained in a percpu_counter
- * for each site. The percpu values are incremented and decremented as
- * objects are added or removed from the lru. The percpu values are summed
- * and saved whenever a percpu value exceeds a threshold. Thus the saved,
- * summed value at any given time may not accurately reflect the current
- * lru length. But this value is sufficiently accurate for the needs of
- * a shrinker.
- *
- * Using a per cpu counter is a compromise solution to concurrent access:
- * lu_object_put() can update the counter without locking the site and
- * lu_cache_shrink_count can sum the counters without locking each
- * ls_obj_hash bucket.
- */
-static unsigned long lu_cache_shrink_count(struct shrinker *sk,
- struct shrink_control *sc)
-{
- struct lu_site *s;
- struct lu_site *tmp;
- unsigned long cached = 0;
-
- if (!(sc->gfp_mask & __GFP_FS))
- return 0;
-
- down_read(&lu_sites_guard);
- list_for_each_entry_safe(s, tmp, &lu_sites, ls_linkage)
- cached += percpu_counter_read_positive(&s->ls_lru_len_counter);
- up_read(&lu_sites_guard);
-
- cached = (cached / 100) * sysctl_vfs_cache_pressure;
- CDEBUG(D_INODE, "%ld objects cached, cache pressure %d\n",
- cached, sysctl_vfs_cache_pressure);
-
- return cached;
-}
-
-static unsigned long lu_cache_shrink_scan(struct shrinker *sk,
- struct shrink_control *sc)
-{
- struct lu_site *s;
- struct lu_site *tmp;
- unsigned long remain = sc->nr_to_scan, freed = 0;
- LIST_HEAD(splice);
-
- if (!(sc->gfp_mask & __GFP_FS))
- /* We must not take the lu_sites_guard lock when
- * __GFP_FS is *not* set because of the deadlock
- * possibility detailed above. Additionally,
- * since we cannot determine the number of
- * objects in the cache without taking this
- * lock, we're in a particularly tough spot. As
- * a result, we'll just lie and say our cache is
- * empty. This _should_ be ok, as we can't
- * reclaim objects when __GFP_FS is *not* set
- * anyways.
- */
- return SHRINK_STOP;
-
- down_write(&lu_sites_guard);
- list_for_each_entry_safe(s, tmp, &lu_sites, ls_linkage) {
- freed = lu_site_purge(&lu_shrink_env, s, remain);
- remain -= freed;
- /*
- * Move just shrunk site to the tail of site list to
- * assure shrinking fairness.
- */
- list_move_tail(&s->ls_linkage, &splice);
- }
- list_splice(&splice, lu_sites.prev);
- up_write(&lu_sites_guard);
-
- return sc->nr_to_scan - remain;
-}
-
-/**
- * Debugging printer function using printk().
- */
-static struct shrinker lu_site_shrinker = {
- .count_objects = lu_cache_shrink_count,
- .scan_objects = lu_cache_shrink_scan,
- .seeks = DEFAULT_SEEKS,
-};
-
-/**
- * Initialization of global lu_* data.
- */
-int lu_global_init(void)
-{
- int result;
-
- CDEBUG(D_INFO, "Lustre LU module (%p).\n", &lu_keys);
-
- result = lu_ref_global_init();
- if (result != 0)
- return result;
-
- LU_CONTEXT_KEY_INIT(&lu_global_key);
- result = lu_context_key_register(&lu_global_key);
- if (result != 0) {
- lu_ref_global_fini();
- return result;
- }
-
- /*
- * At this level, we don't know what tags are needed, so allocate them
- * conservatively. This should not be too bad, because this
- * environment is global.
- */
- down_write(&lu_sites_guard);
- result = lu_env_init(&lu_shrink_env, LCT_SHRINKER);
- up_write(&lu_sites_guard);
- if (result != 0) {
- lu_context_key_degister(&lu_global_key);
- lu_ref_global_fini();
- return result;
- }
-
- /*
- * seeks estimation: 3 seeks to read a record from oi, one to read
- * inode, one for ea. Unfortunately setting this high value results in
- * lu_object/inode cache consuming all the memory.
- */
- result = register_shrinker(&lu_site_shrinker);
- if (result != 0) {
- /* Order explained in lu_global_fini(). */
- lu_context_key_degister(&lu_global_key);
-
- down_write(&lu_sites_guard);
- lu_env_fini(&lu_shrink_env);
- up_write(&lu_sites_guard);
-
- lu_ref_global_fini();
- return result;
- }
-
- return 0;
-}
-
-/**
- * Dual to lu_global_init().
- */
-void lu_global_fini(void)
-{
- unregister_shrinker(&lu_site_shrinker);
- lu_context_key_degister(&lu_global_key);
-
- /*
- * Tear shrinker environment down _after_ de-registering
- * lu_global_key, because the latter has a value in the former.
- */
- down_write(&lu_sites_guard);
- lu_env_fini(&lu_shrink_env);
- up_write(&lu_sites_guard);
-
- lu_ref_global_fini();
-}
-
-static __u32 ls_stats_read(struct lprocfs_stats *stats, int idx)
-{
- struct lprocfs_counter ret;
-
- lprocfs_stats_collect(stats, idx, &ret);
- return (__u32)ret.lc_count;
-}
-
-/**
- * Output site statistical counters into a buffer. Suitable for
- * lprocfs_rd_*()-style functions.
- */
-int lu_site_stats_print(const struct lu_site *s, struct seq_file *m)
-{
- struct lu_site_stats stats;
-
- memset(&stats, 0, sizeof(stats));
- lu_site_stats_get(s->ls_obj_hash, &stats, 1);
-
- seq_printf(m, "%d/%d %d/%ld %d %d %d %d %d %d %d\n",
- stats.lss_busy,
- stats.lss_total,
- stats.lss_populated,
- CFS_HASH_NHLIST(s->ls_obj_hash),
- stats.lss_max_search,
- ls_stats_read(s->ls_stats, LU_SS_CREATED),
- ls_stats_read(s->ls_stats, LU_SS_CACHE_HIT),
- ls_stats_read(s->ls_stats, LU_SS_CACHE_MISS),
- ls_stats_read(s->ls_stats, LU_SS_CACHE_RACE),
- ls_stats_read(s->ls_stats, LU_SS_CACHE_DEATH_RACE),
- ls_stats_read(s->ls_stats, LU_SS_LRU_PURGED));
- return 0;
-}
-EXPORT_SYMBOL(lu_site_stats_print);
-
-/**
- * Helper function to initialize a number of kmem slab caches at once.
- */
-int lu_kmem_init(struct lu_kmem_descr *caches)
-{
- int result;
- struct lu_kmem_descr *iter = caches;
-
- for (result = 0; iter->ckd_cache; ++iter) {
- *iter->ckd_cache = kmem_cache_create(iter->ckd_name,
- iter->ckd_size,
- 0, 0, NULL);
- if (!*iter->ckd_cache) {
- result = -ENOMEM;
- /* free all previously allocated caches */
- lu_kmem_fini(caches);
- break;
- }
- }
- return result;
-}
-EXPORT_SYMBOL(lu_kmem_init);
-
-/**
- * Helper function to finalize a number of kmem slab cached at once. Dual to
- * lu_kmem_init().
- */
-void lu_kmem_fini(struct lu_kmem_descr *caches)
-{
- for (; caches->ckd_cache; ++caches) {
- kmem_cache_destroy(*caches->ckd_cache);
- *caches->ckd_cache = NULL;
- }
-}
-EXPORT_SYMBOL(lu_kmem_fini);
diff --git a/drivers/staging/lustre/lustre/obdclass/lu_ref.c b/drivers/staging/lustre/lustre/obdclass/lu_ref.c
deleted file mode 100644
index 54fc88206534..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/lu_ref.c
+++ /dev/null
@@ -1,47 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/lu_ref.c
- *
- * Lustre reference.
- *
- * Author: Nikita Danilov <nikita.danilov@sun.com>
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/libcfs/libcfs.h>
-
-#include <obd.h>
-#include <obd_class.h>
-#include <obd_support.h>
-#include <lu_ref.h>
diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c
deleted file mode 100644
index f53b1a3c342e..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c
+++ /dev/null
@@ -1,240 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/lustre_handles.c
- *
- * Author: Phil Schwan <phil@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <obd_support.h>
-#include <lustre_handles.h>
-#include <lustre_lib.h>
-
-static __u64 handle_base;
-#define HANDLE_INCR 7
-static spinlock_t handle_base_lock;
-
-static struct handle_bucket {
- spinlock_t lock;
- struct list_head head;
-} *handle_hash;
-
-#define HANDLE_HASH_SIZE (1 << 16)
-#define HANDLE_HASH_MASK (HANDLE_HASH_SIZE - 1)
-
-/*
- * Generate a unique 64bit cookie (hash) for a handle and insert it into
- * global (per-node) hash-table.
- */
-void class_handle_hash(struct portals_handle *h,
- struct portals_handle_ops *ops)
-{
- struct handle_bucket *bucket;
-
- LASSERT(h);
- LASSERT(list_empty(&h->h_link));
-
- /*
- * This is fast, but simplistic cookie generation algorithm, it will
- * need a re-do at some point in the future for security.
- */
- spin_lock(&handle_base_lock);
- handle_base += HANDLE_INCR;
-
- if (unlikely(handle_base == 0)) {
- /*
- * Cookie of zero is "dangerous", because in many places it's
- * assumed that 0 means "unassigned" handle, not bound to any
- * object.
- */
- CWARN("The universe has been exhausted: cookie wrap-around.\n");
- handle_base += HANDLE_INCR;
- }
- h->h_cookie = handle_base;
- spin_unlock(&handle_base_lock);
-
- h->h_ops = ops;
- spin_lock_init(&h->h_lock);
-
- bucket = &handle_hash[h->h_cookie & HANDLE_HASH_MASK];
- spin_lock(&bucket->lock);
- list_add_rcu(&h->h_link, &bucket->head);
- h->h_in = 1;
- spin_unlock(&bucket->lock);
-
- CDEBUG(D_INFO, "added object %p with handle %#llx to hash\n",
- h, h->h_cookie);
-}
-EXPORT_SYMBOL(class_handle_hash);
-
-static void class_handle_unhash_nolock(struct portals_handle *h)
-{
- if (list_empty(&h->h_link)) {
- CERROR("removing an already-removed handle (%#llx)\n",
- h->h_cookie);
- return;
- }
-
- CDEBUG(D_INFO, "removing object %p with handle %#llx from hash\n",
- h, h->h_cookie);
-
- spin_lock(&h->h_lock);
- if (h->h_in == 0) {
- spin_unlock(&h->h_lock);
- return;
- }
- h->h_in = 0;
- spin_unlock(&h->h_lock);
- list_del_rcu(&h->h_link);
-}
-
-void class_handle_unhash(struct portals_handle *h)
-{
- struct handle_bucket *bucket;
-
- bucket = handle_hash + (h->h_cookie & HANDLE_HASH_MASK);
-
- spin_lock(&bucket->lock);
- class_handle_unhash_nolock(h);
- spin_unlock(&bucket->lock);
-}
-EXPORT_SYMBOL(class_handle_unhash);
-
-void *class_handle2object(__u64 cookie, const void *owner)
-{
- struct handle_bucket *bucket;
- struct portals_handle *h;
- void *retval = NULL;
-
- LASSERT(handle_hash);
-
- /* Be careful when you want to change this code. See the
- * rcu_read_lock() definition on top this file. - jxiong
- */
- bucket = handle_hash + (cookie & HANDLE_HASH_MASK);
-
- rcu_read_lock();
- list_for_each_entry_rcu(h, &bucket->head, h_link) {
- if (h->h_cookie != cookie || h->h_owner != owner)
- continue;
-
- spin_lock(&h->h_lock);
- if (likely(h->h_in != 0)) {
- h->h_ops->hop_addref(h);
- retval = h;
- }
- spin_unlock(&h->h_lock);
- break;
- }
- rcu_read_unlock();
-
- return retval;
-}
-EXPORT_SYMBOL(class_handle2object);
-
-void class_handle_free_cb(struct rcu_head *rcu)
-{
- struct portals_handle *h;
- void *ptr;
-
- h = container_of(rcu, struct portals_handle, h_rcu);
- ptr = (void *)(unsigned long)h->h_cookie;
-
- if (h->h_ops->hop_free)
- h->h_ops->hop_free(ptr, h->h_size);
- else
- kfree(ptr);
-}
-EXPORT_SYMBOL(class_handle_free_cb);
-
-int class_handle_init(void)
-{
- struct handle_bucket *bucket;
-
- LASSERT(!handle_hash);
-
- handle_hash = kvzalloc(sizeof(*bucket) * HANDLE_HASH_SIZE,
- GFP_KERNEL);
- if (!handle_hash)
- return -ENOMEM;
-
- spin_lock_init(&handle_base_lock);
- for (bucket = handle_hash + HANDLE_HASH_SIZE - 1; bucket >= handle_hash;
- bucket--) {
- INIT_LIST_HEAD(&bucket->head);
- spin_lock_init(&bucket->lock);
- }
-
- get_random_bytes(&handle_base, sizeof(handle_base));
- LASSERT(handle_base != 0ULL);
-
- return 0;
-}
-
-static int cleanup_all_handles(void)
-{
- int rc;
- int i;
-
- for (rc = i = 0; i < HANDLE_HASH_SIZE; i++) {
- struct portals_handle *h;
-
- spin_lock(&handle_hash[i].lock);
- list_for_each_entry_rcu(h, &handle_hash[i].head, h_link) {
- CERROR("force clean handle %#llx addr %p ops %p\n",
- h->h_cookie, h, h->h_ops);
-
- class_handle_unhash_nolock(h);
- rc++;
- }
- spin_unlock(&handle_hash[i].lock);
- }
-
- return rc;
-}
-
-void class_handle_cleanup(void)
-{
- int count;
-
- LASSERT(handle_hash);
-
- count = cleanup_all_handles();
-
- kvfree(handle_hash);
- handle_hash = NULL;
-
- if (count != 0)
- CERROR("handle_count at cleanup: %d\n", count);
-}
diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c
deleted file mode 100644
index e286a2665423..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c
+++ /dev/null
@@ -1,214 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <obd.h>
-#include <obd_support.h>
-#include <obd_class.h>
-#include <lustre_lib.h>
-#include <lustre_ha.h>
-#include <lustre_net.h>
-#include <lprocfs_status.h>
-
-#define NIDS_MAX 32
-
-struct uuid_nid_data {
- struct list_head un_list;
- struct obd_uuid un_uuid;
- int un_nid_count;
- lnet_nid_t un_nids[NIDS_MAX];
-};
-
-/* FIXME: This should probably become more elegant than a global linked list */
-static struct list_head g_uuid_list;
-static spinlock_t g_uuid_lock;
-
-void class_init_uuidlist(void)
-{
- INIT_LIST_HEAD(&g_uuid_list);
- spin_lock_init(&g_uuid_lock);
-}
-
-void class_exit_uuidlist(void)
-{
- /* delete all */
- class_del_uuid(NULL);
-}
-
-int lustre_uuid_to_peer(const char *uuid, lnet_nid_t *peer_nid, int index)
-{
- struct uuid_nid_data *data;
- struct obd_uuid tmp;
- int rc = -ENOENT;
-
- obd_str2uuid(&tmp, uuid);
- spin_lock(&g_uuid_lock);
- list_for_each_entry(data, &g_uuid_list, un_list) {
- if (obd_uuid_equals(&data->un_uuid, &tmp)) {
- if (index >= data->un_nid_count)
- break;
-
- rc = 0;
- *peer_nid = data->un_nids[index];
- break;
- }
- }
- spin_unlock(&g_uuid_lock);
- return rc;
-}
-EXPORT_SYMBOL(lustre_uuid_to_peer);
-
-/* Add a nid to a niduuid. Multiple nids can be added to a single uuid;
- * LNET will choose the best one.
- */
-int class_add_uuid(const char *uuid, __u64 nid)
-{
- struct uuid_nid_data *data, *entry;
- int found = 0;
-
- LASSERT(nid != 0); /* valid newconfig NID is never zero */
-
- if (strlen(uuid) > UUID_MAX - 1)
- return -EOVERFLOW;
-
- data = kzalloc(sizeof(*data), GFP_NOFS);
- if (!data)
- return -ENOMEM;
-
- obd_str2uuid(&data->un_uuid, uuid);
- data->un_nids[0] = nid;
- data->un_nid_count = 1;
-
- spin_lock(&g_uuid_lock);
- list_for_each_entry(entry, &g_uuid_list, un_list) {
- if (obd_uuid_equals(&entry->un_uuid, &data->un_uuid)) {
- int i;
-
- found = 1;
- for (i = 0; i < entry->un_nid_count; i++)
- if (nid == entry->un_nids[i])
- break;
-
- if (i == entry->un_nid_count) {
- LASSERT(entry->un_nid_count < NIDS_MAX);
- entry->un_nids[entry->un_nid_count++] = nid;
- }
- break;
- }
- }
- if (!found)
- list_add(&data->un_list, &g_uuid_list);
- spin_unlock(&g_uuid_lock);
-
- if (found) {
- CDEBUG(D_INFO, "found uuid %s %s cnt=%d\n", uuid,
- libcfs_nid2str(nid), entry->un_nid_count);
- kfree(data);
- } else {
- CDEBUG(D_INFO, "add uuid %s %s\n", uuid, libcfs_nid2str(nid));
- }
- return 0;
-}
-
-/* Delete the nids for one uuid if specified, otherwise delete all */
-int class_del_uuid(const char *uuid)
-{
- LIST_HEAD(deathrow);
- struct uuid_nid_data *data;
- struct uuid_nid_data *temp;
-
- spin_lock(&g_uuid_lock);
- if (uuid) {
- struct obd_uuid tmp;
-
- obd_str2uuid(&tmp, uuid);
- list_for_each_entry(data, &g_uuid_list, un_list) {
- if (obd_uuid_equals(&data->un_uuid, &tmp)) {
- list_move(&data->un_list, &deathrow);
- break;
- }
- }
- } else {
- list_splice_init(&g_uuid_list, &deathrow);
- }
- spin_unlock(&g_uuid_lock);
-
- if (uuid && list_empty(&deathrow)) {
- CDEBUG(D_INFO, "Try to delete a non-existent uuid %s\n", uuid);
- return -EINVAL;
- }
-
- list_for_each_entry_safe(data, temp, &deathrow, un_list) {
- list_del(&data->un_list);
-
- CDEBUG(D_INFO, "del uuid %s %s/%d\n",
- obd_uuid2str(&data->un_uuid),
- libcfs_nid2str(data->un_nids[0]),
- data->un_nid_count);
-
- kfree(data);
- }
-
- return 0;
-}
-
-/* check if @nid exists in nid list of @uuid */
-int class_check_uuid(struct obd_uuid *uuid, __u64 nid)
-{
- struct uuid_nid_data *entry;
- int found = 0;
-
- CDEBUG(D_INFO, "check if uuid %s has %s.\n",
- obd_uuid2str(uuid), libcfs_nid2str(nid));
-
- spin_lock(&g_uuid_lock);
- list_for_each_entry(entry, &g_uuid_list, un_list) {
- int i;
-
- if (!obd_uuid_equals(&entry->un_uuid, uuid))
- continue;
-
- /* found the uuid, check if it has @nid */
- for (i = 0; i < entry->un_nid_count; i++) {
- if (entry->un_nids[i] == nid) {
- found = 1;
- break;
- }
- }
- break;
- }
- spin_unlock(&g_uuid_lock);
- return found;
-}
-EXPORT_SYMBOL(class_check_uuid);
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c
deleted file mode 100644
index 277576b586db..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/obd_config.c
+++ /dev/null
@@ -1,1559 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/obd_config.c
- *
- * Config API
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/string.h>
-
-#include <uapi/linux/lustre/lustre_ioctl.h>
-#include <llog_swab.h>
-#include <lprocfs_status.h>
-#include <lustre_log.h>
-#include <uapi/linux/lustre/lustre_param.h>
-#include <obd_class.h>
-
-#include "llog_internal.h"
-
-static struct cfs_hash_ops uuid_hash_ops;
-
-/*********** string parsing utils *********/
-
-/* returns 0 if we find this key in the buffer, else 1 */
-int class_find_param(char *buf, char *key, char **valp)
-{
- char *ptr;
-
- if (!buf)
- return 1;
-
- ptr = strstr(buf, key);
- if (!ptr)
- return 1;
-
- if (valp)
- *valp = ptr + strlen(key);
-
- return 0;
-}
-EXPORT_SYMBOL(class_find_param);
-
-/* returns 0 if this is the first key in the buffer, else 1.
- * valp points to first char after key.
- */
-static int class_match_param(char *buf, const char *key, char **valp)
-{
- if (!buf)
- return 1;
-
- if (memcmp(buf, key, strlen(key)) != 0)
- return 1;
-
- if (valp)
- *valp = buf + strlen(key);
-
- return 0;
-}
-
-static int parse_nid(char *buf, void *value, int quiet)
-{
- lnet_nid_t *nid = value;
-
- *nid = libcfs_str2nid(buf);
- if (*nid != LNET_NID_ANY)
- return 0;
-
- if (!quiet)
- LCONSOLE_ERROR_MSG(0x159, "Can't parse NID '%s'\n", buf);
- return -EINVAL;
-}
-
-static int parse_net(char *buf, void *value)
-{
- __u32 *net = value;
-
- *net = libcfs_str2net(buf);
- CDEBUG(D_INFO, "Net %s\n", libcfs_net2str(*net));
- return 0;
-}
-
-enum {
- CLASS_PARSE_NID = 1,
- CLASS_PARSE_NET,
-};
-
-/* 0 is good nid,
- * 1 not found
- * < 0 error
- * endh is set to next separator
- */
-static int class_parse_value(char *buf, int opc, void *value, char **endh,
- int quiet)
-{
- char *endp;
- char tmp;
- int rc = 0;
-
- if (!buf)
- return 1;
- while (*buf == ',' || *buf == ':')
- buf++;
- if (*buf == ' ' || *buf == '/' || *buf == '\0')
- return 1;
-
- /* nid separators or end of nids */
- endp = strpbrk(buf, ",: /");
- if (!endp)
- endp = buf + strlen(buf);
-
- tmp = *endp;
- *endp = '\0';
- switch (opc) {
- default:
- LBUG();
- case CLASS_PARSE_NID:
- rc = parse_nid(buf, value, quiet);
- break;
- case CLASS_PARSE_NET:
- rc = parse_net(buf, value);
- break;
- }
- *endp = tmp;
- if (rc != 0)
- return rc;
- if (endh)
- *endh = endp;
- return 0;
-}
-
-int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh)
-{
- return class_parse_value(buf, CLASS_PARSE_NID, (void *)nid, endh, 0);
-}
-EXPORT_SYMBOL(class_parse_nid);
-
-int class_parse_nid_quiet(char *buf, lnet_nid_t *nid, char **endh)
-{
- return class_parse_value(buf, CLASS_PARSE_NID, (void *)nid, endh, 1);
-}
-EXPORT_SYMBOL(class_parse_nid_quiet);
-
-char *lustre_cfg_string(struct lustre_cfg *lcfg, u32 index)
-{
- char *s;
-
- if (!lcfg->lcfg_buflens[index])
- return NULL;
-
- s = lustre_cfg_buf(lcfg, index);
- if (!s)
- return NULL;
-
- /*
- * make sure it's NULL terminated, even if this kills a char
- * of data. Try to use the padding first though.
- */
- if (s[lcfg->lcfg_buflens[index] - 1] != '\0') {
- size_t last = ALIGN(lcfg->lcfg_buflens[index], 8) - 1;
- char lost;
-
- /* Use the smaller value */
- if (last > lcfg->lcfg_buflens[index])
- last = lcfg->lcfg_buflens[index];
-
- lost = s[last];
- s[last] = '\0';
- if (lost != '\0') {
- CWARN("Truncated buf %d to '%s' (lost '%c'...)\n",
- index, s, lost);
- }
- }
- return s;
-}
-EXPORT_SYMBOL(lustre_cfg_string);
-
-/********************** class fns **********************/
-
-/**
- * Create a new obd device and set the type, name and uuid. If successful,
- * the new device can be accessed by either name or uuid.
- */
-static int class_attach(struct lustre_cfg *lcfg)
-{
- struct obd_device *obd = NULL;
- char *typename, *name, *uuid;
- int rc, len;
-
- if (!LUSTRE_CFG_BUFLEN(lcfg, 1)) {
- CERROR("No type passed!\n");
- return -EINVAL;
- }
- typename = lustre_cfg_string(lcfg, 1);
-
- if (!LUSTRE_CFG_BUFLEN(lcfg, 0)) {
- CERROR("No name passed!\n");
- return -EINVAL;
- }
- name = lustre_cfg_string(lcfg, 0);
-
- if (!LUSTRE_CFG_BUFLEN(lcfg, 2)) {
- CERROR("No UUID passed!\n");
- return -EINVAL;
- }
- uuid = lustre_cfg_string(lcfg, 2);
-
- CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
- typename, name, uuid);
-
- obd = class_newdev(typename, name);
- if (IS_ERR(obd)) {
- /* Already exists or out of obds */
- rc = PTR_ERR(obd);
- obd = NULL;
- CERROR("Cannot create device %s of type %s : %d\n",
- name, typename, rc);
- goto out;
- }
- LASSERTF(obd, "Cannot get obd device %s of type %s\n",
- name, typename);
- LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
- "obd %p obd_magic %08X != %08X\n",
- obd, obd->obd_magic, OBD_DEVICE_MAGIC);
- LASSERTF(strncmp(obd->obd_name, name, strlen(name)) == 0,
- "%p obd_name %s != %s\n", obd, obd->obd_name, name);
-
- rwlock_init(&obd->obd_pool_lock);
- obd->obd_pool_limit = 0;
- obd->obd_pool_slv = 0;
-
- INIT_LIST_HEAD(&obd->obd_exports);
- INIT_LIST_HEAD(&obd->obd_unlinked_exports);
- INIT_LIST_HEAD(&obd->obd_delayed_exports);
- spin_lock_init(&obd->obd_nid_lock);
- spin_lock_init(&obd->obd_dev_lock);
- mutex_init(&obd->obd_dev_mutex);
- spin_lock_init(&obd->obd_osfs_lock);
- /* obd->obd_osfs_age must be set to a value in the distant
- * past to guarantee a fresh statfs is fetched on mount.
- */
- obd->obd_osfs_age = cfs_time_shift_64(-1000);
-
- /* XXX belongs in setup not attach */
- init_rwsem(&obd->obd_observer_link_sem);
- /* recovery data */
- init_waitqueue_head(&obd->obd_evict_inprogress_waitq);
-
- llog_group_init(&obd->obd_olg);
-
- obd->obd_conn_inprogress = 0;
-
- len = strlen(uuid);
- if (len >= sizeof(obd->obd_uuid)) {
- CERROR("uuid must be < %d bytes long\n",
- (int)sizeof(obd->obd_uuid));
- rc = -EINVAL;
- goto out;
- }
- memcpy(obd->obd_uuid.uuid, uuid, len);
-
- /* Detach drops this */
- spin_lock(&obd->obd_dev_lock);
- atomic_set(&obd->obd_refcount, 1);
- spin_unlock(&obd->obd_dev_lock);
- lu_ref_init(&obd->obd_reference);
- lu_ref_add(&obd->obd_reference, "attach", obd);
-
- obd->obd_attached = 1;
- CDEBUG(D_IOCTL, "OBD: dev %d attached type %s with refcount %d\n",
- obd->obd_minor, typename, atomic_read(&obd->obd_refcount));
- return 0;
- out:
- if (obd)
- class_release_dev(obd);
-
- return rc;
-}
-
-/** Create hashes, self-export, and call type-specific setup.
- * Setup is effectively the "start this obd" call.
- */
-static int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
-{
- int err = 0;
- struct obd_export *exp;
-
- LASSERT(obd);
- LASSERTF(obd == class_num2obd(obd->obd_minor),
- "obd %p != obd_devs[%d] %p\n",
- obd, obd->obd_minor, class_num2obd(obd->obd_minor));
- LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
- "obd %p obd_magic %08x != %08x\n",
- obd, obd->obd_magic, OBD_DEVICE_MAGIC);
-
- /* have we attached a type to this device? */
- if (!obd->obd_attached) {
- CERROR("Device %d not attached\n", obd->obd_minor);
- return -ENODEV;
- }
-
- if (obd->obd_set_up) {
- CERROR("Device %d already setup (type %s)\n",
- obd->obd_minor, obd->obd_type->typ_name);
- return -EEXIST;
- }
-
- /* is someone else setting us up right now? (attach inits spinlock) */
- spin_lock(&obd->obd_dev_lock);
- if (obd->obd_starting) {
- spin_unlock(&obd->obd_dev_lock);
- CERROR("Device %d setup in progress (type %s)\n",
- obd->obd_minor, obd->obd_type->typ_name);
- return -EEXIST;
- }
- /* just leave this on forever. I can't use obd_set_up here because
- * other fns check that status, and we're not actually set up yet.
- */
- obd->obd_starting = 1;
- obd->obd_uuid_hash = NULL;
- spin_unlock(&obd->obd_dev_lock);
-
- /* create an uuid-export lustre hash */
- obd->obd_uuid_hash = cfs_hash_create("UUID_HASH",
- HASH_UUID_CUR_BITS,
- HASH_UUID_MAX_BITS,
- HASH_UUID_BKT_BITS, 0,
- CFS_HASH_MIN_THETA,
- CFS_HASH_MAX_THETA,
- &uuid_hash_ops, CFS_HASH_DEFAULT);
- if (!obd->obd_uuid_hash) {
- err = -ENOMEM;
- goto err_hash;
- }
-
- exp = class_new_export(obd, &obd->obd_uuid);
- if (IS_ERR(exp)) {
- err = PTR_ERR(exp);
- goto err_hash;
- }
-
- obd->obd_self_export = exp;
- class_export_put(exp);
-
- err = obd_setup(obd, lcfg);
- if (err)
- goto err_exp;
-
- obd->obd_set_up = 1;
-
- spin_lock(&obd->obd_dev_lock);
- /* cleanup drops this */
- class_incref(obd, "setup", obd);
- spin_unlock(&obd->obd_dev_lock);
-
- CDEBUG(D_IOCTL, "finished setup of obd %s (uuid %s)\n",
- obd->obd_name, obd->obd_uuid.uuid);
-
- return 0;
-err_exp:
- if (obd->obd_self_export) {
- class_unlink_export(obd->obd_self_export);
- obd->obd_self_export = NULL;
- }
-err_hash:
- if (obd->obd_uuid_hash) {
- cfs_hash_putref(obd->obd_uuid_hash);
- obd->obd_uuid_hash = NULL;
- }
- obd->obd_starting = 0;
- CERROR("setup %s failed (%d)\n", obd->obd_name, err);
- return err;
-}
-
-/** We have finished using this obd and are ready to destroy it.
- * There can be no more references to this obd.
- */
-static int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
-{
- if (obd->obd_set_up) {
- CERROR("OBD device %d still set up\n", obd->obd_minor);
- return -EBUSY;
- }
-
- spin_lock(&obd->obd_dev_lock);
- if (!obd->obd_attached) {
- spin_unlock(&obd->obd_dev_lock);
- CERROR("OBD device %d not attached\n", obd->obd_minor);
- return -ENODEV;
- }
- obd->obd_attached = 0;
- spin_unlock(&obd->obd_dev_lock);
-
- CDEBUG(D_IOCTL, "detach on obd %s (uuid %s)\n",
- obd->obd_name, obd->obd_uuid.uuid);
-
- class_decref(obd, "attach", obd);
- return 0;
-}
-
-/** Start shutting down the obd. There may be in-progress ops when
- * this is called. We tell them to start shutting down with a call
- * to class_disconnect_exports().
- */
-static int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
-{
- int err = 0;
- char *flag;
-
- OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
-
- if (!obd->obd_set_up) {
- CERROR("Device %d not setup\n", obd->obd_minor);
- return -ENODEV;
- }
-
- spin_lock(&obd->obd_dev_lock);
- if (obd->obd_stopping) {
- spin_unlock(&obd->obd_dev_lock);
- CERROR("OBD %d already stopping\n", obd->obd_minor);
- return -ENODEV;
- }
- /* Leave this on forever */
- obd->obd_stopping = 1;
- spin_unlock(&obd->obd_dev_lock);
-
- while (obd->obd_conn_inprogress > 0)
- cond_resched();
- smp_rmb();
-
- if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
- for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
- switch (*flag) {
- case 'F':
- obd->obd_force = 1;
- break;
- case 'A':
- LCONSOLE_WARN("Failing over %s\n",
- obd->obd_name);
- obd->obd_fail = 1;
- obd->obd_no_transno = 1;
- obd->obd_no_recov = 1;
- if (OBP(obd, iocontrol)) {
- obd_iocontrol(OBD_IOC_SYNC,
- obd->obd_self_export,
- 0, NULL, NULL);
- }
- break;
- default:
- CERROR("Unrecognised flag '%c'\n", *flag);
- }
- }
-
- LASSERT(obd->obd_self_export);
-
- /* Precleanup, we must make sure all exports get destroyed. */
- err = obd_precleanup(obd);
- if (err)
- CERROR("Precleanup %s returned %d\n",
- obd->obd_name, err);
-
- /* destroy an uuid-export hash body */
- if (obd->obd_uuid_hash) {
- cfs_hash_putref(obd->obd_uuid_hash);
- obd->obd_uuid_hash = NULL;
- }
-
- class_decref(obd, "setup", obd);
- obd->obd_set_up = 0;
-
- return 0;
-}
-
-struct obd_device *class_incref(struct obd_device *obd,
- const char *scope, const void *source)
-{
- lu_ref_add_atomic(&obd->obd_reference, scope, source);
- atomic_inc(&obd->obd_refcount);
- CDEBUG(D_INFO, "incref %s (%p) now %d\n", obd->obd_name, obd,
- atomic_read(&obd->obd_refcount));
-
- return obd;
-}
-EXPORT_SYMBOL(class_incref);
-
-void class_decref(struct obd_device *obd, const char *scope, const void *source)
-{
- int err;
- int refs;
-
- spin_lock(&obd->obd_dev_lock);
- atomic_dec(&obd->obd_refcount);
- refs = atomic_read(&obd->obd_refcount);
- spin_unlock(&obd->obd_dev_lock);
- lu_ref_del(&obd->obd_reference, scope, source);
-
- CDEBUG(D_INFO, "Decref %s (%p) now %d\n", obd->obd_name, obd, refs);
-
- if ((refs == 1) && obd->obd_stopping) {
- /* All exports have been destroyed; there should
- * be no more in-progress ops by this point.
- */
-
- spin_lock(&obd->obd_self_export->exp_lock);
- obd->obd_self_export->exp_flags |= exp_flags_from_obd(obd);
- spin_unlock(&obd->obd_self_export->exp_lock);
-
- /* note that we'll recurse into class_decref again */
- class_unlink_export(obd->obd_self_export);
- return;
- }
-
- if (refs == 0) {
- CDEBUG(D_CONFIG, "finishing cleanup of obd %s (%s)\n",
- obd->obd_name, obd->obd_uuid.uuid);
- LASSERT(!obd->obd_attached);
- if (obd->obd_stopping) {
- /* If we're not stopping, we were never set up */
- err = obd_cleanup(obd);
- if (err)
- CERROR("Cleanup %s returned %d\n",
- obd->obd_name, err);
- }
- class_release_dev(obd);
- }
-}
-EXPORT_SYMBOL(class_decref);
-
-/** Add a failover nid location.
- * Client obd types contact server obd types using this nid list.
- */
-static int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
-{
- struct obd_import *imp;
- struct obd_uuid uuid;
- int rc;
-
- if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
- LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
- CERROR("invalid conn_uuid\n");
- return -EINVAL;
- }
- if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
- strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) &&
- strcmp(obd->obd_type->typ_name, LUSTRE_OSP_NAME) &&
- strcmp(obd->obd_type->typ_name, LUSTRE_LWP_NAME) &&
- strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
- CERROR("can't add connection on non-client dev\n");
- return -EINVAL;
- }
-
- imp = obd->u.cli.cl_import;
- if (!imp) {
- CERROR("try to add conn on immature client dev\n");
- return -EINVAL;
- }
-
- obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
- rc = obd_add_conn(imp, &uuid, lcfg->lcfg_num);
-
- return rc;
-}
-
-/** Remove a failover nid location.
- */
-static int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
-{
- struct obd_import *imp;
- struct obd_uuid uuid;
- int rc;
-
- if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
- LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
- CERROR("invalid conn_uuid\n");
- return -EINVAL;
- }
- if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
- strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
- CERROR("can't del connection on non-client dev\n");
- return -EINVAL;
- }
-
- imp = obd->u.cli.cl_import;
- if (!imp) {
- CERROR("try to del conn on immature client dev\n");
- return -EINVAL;
- }
-
- obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
- rc = obd_del_conn(imp, &uuid);
-
- return rc;
-}
-
-static LIST_HEAD(lustre_profile_list);
-static DEFINE_SPINLOCK(lustre_profile_list_lock);
-
-struct lustre_profile *class_get_profile(const char *prof)
-{
- struct lustre_profile *lprof;
-
- spin_lock(&lustre_profile_list_lock);
- list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
- if (!strcmp(lprof->lp_profile, prof)) {
- lprof->lp_refs++;
- spin_unlock(&lustre_profile_list_lock);
- return lprof;
- }
- }
- spin_unlock(&lustre_profile_list_lock);
- return NULL;
-}
-EXPORT_SYMBOL(class_get_profile);
-
-/** Create a named "profile".
- * This defines the mdc and osc names to use for a client.
- * This also is used to define the lov to be used by a mdt.
- */
-static int class_add_profile(int proflen, char *prof, int osclen, char *osc,
- int mdclen, char *mdc)
-{
- struct lustre_profile *lprof;
- int err = 0;
-
- CDEBUG(D_CONFIG, "Add profile %s\n", prof);
-
- lprof = kzalloc(sizeof(*lprof), GFP_NOFS);
- if (!lprof)
- return -ENOMEM;
- INIT_LIST_HEAD(&lprof->lp_list);
-
- LASSERT(proflen == (strlen(prof) + 1));
- lprof->lp_profile = kmemdup(prof, proflen, GFP_NOFS);
- if (!lprof->lp_profile) {
- err = -ENOMEM;
- goto free_lprof;
- }
-
- LASSERT(osclen == (strlen(osc) + 1));
- lprof->lp_dt = kmemdup(osc, osclen, GFP_NOFS);
- if (!lprof->lp_dt) {
- err = -ENOMEM;
- goto free_lp_profile;
- }
-
- if (mdclen > 0) {
- LASSERT(mdclen == (strlen(mdc) + 1));
- lprof->lp_md = kmemdup(mdc, mdclen, GFP_NOFS);
- if (!lprof->lp_md) {
- err = -ENOMEM;
- goto free_lp_dt;
- }
- }
-
- spin_lock(&lustre_profile_list_lock);
- lprof->lp_refs = 1;
- lprof->lp_list_deleted = false;
- list_add(&lprof->lp_list, &lustre_profile_list);
- spin_unlock(&lustre_profile_list_lock);
- return err;
-
-free_lp_dt:
- kfree(lprof->lp_dt);
-free_lp_profile:
- kfree(lprof->lp_profile);
-free_lprof:
- kfree(lprof);
- return err;
-}
-
-void class_del_profile(const char *prof)
-{
- struct lustre_profile *lprof;
-
- CDEBUG(D_CONFIG, "Del profile %s\n", prof);
-
- lprof = class_get_profile(prof);
- if (lprof) {
- spin_lock(&lustre_profile_list_lock);
- /* because get profile increments the ref counter */
- lprof->lp_refs--;
- list_del(&lprof->lp_list);
- lprof->lp_list_deleted = true;
- spin_unlock(&lustre_profile_list_lock);
-
- class_put_profile(lprof);
- }
-}
-EXPORT_SYMBOL(class_del_profile);
-
-void class_put_profile(struct lustre_profile *lprof)
-{
- spin_lock(&lustre_profile_list_lock);
- if (--lprof->lp_refs > 0) {
- LASSERT(lprof->lp_refs > 0);
- spin_unlock(&lustre_profile_list_lock);
- return;
- }
- spin_unlock(&lustre_profile_list_lock);
-
- /* confirm not a negative number */
- LASSERT(!lprof->lp_refs);
-
- /*
- * At least one class_del_profile/profiles must be called
- * on the target profile or lustre_profile_list will corrupt
- */
- LASSERT(lprof->lp_list_deleted);
- kfree(lprof->lp_profile);
- kfree(lprof->lp_dt);
- kfree(lprof->lp_md);
- kfree(lprof);
-}
-EXPORT_SYMBOL(class_put_profile);
-
-/* COMPAT_146 */
-void class_del_profiles(void)
-{
- struct lustre_profile *lprof, *n;
-
- spin_lock(&lustre_profile_list_lock);
- list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
- list_del(&lprof->lp_list);
- lprof->lp_list_deleted = true;
- spin_unlock(&lustre_profile_list_lock);
-
- class_put_profile(lprof);
-
- spin_lock(&lustre_profile_list_lock);
- }
- spin_unlock(&lustre_profile_list_lock);
-}
-EXPORT_SYMBOL(class_del_profiles);
-
-static int class_set_global(char *ptr, int val, struct lustre_cfg *lcfg)
-{
- if (class_match_param(ptr, PARAM_AT_MIN, NULL) == 0)
- at_min = val;
- else if (class_match_param(ptr, PARAM_AT_MAX, NULL) == 0)
- at_max = val;
- else if (class_match_param(ptr, PARAM_AT_EXTRA, NULL) == 0)
- at_extra = val;
- else if (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, NULL) == 0)
- at_early_margin = val;
- else if (class_match_param(ptr, PARAM_AT_HISTORY, NULL) == 0)
- at_history = val;
- else if (class_match_param(ptr, PARAM_JOBID_VAR, NULL) == 0)
- strlcpy(obd_jobid_var, lustre_cfg_string(lcfg, 2),
- JOBSTATS_JOBID_VAR_MAX_LEN + 1);
- else
- return -EINVAL;
-
- CDEBUG(D_IOCTL, "global %s = %d\n", ptr, val);
- return 0;
-}
-
-/* We can't call ll_process_config or lquota_process_config directly because
- * it lives in a module that must be loaded after this one.
- */
-static int (*client_process_config)(struct lustre_cfg *lcfg);
-static int (*quota_process_config)(struct lustre_cfg *lcfg);
-
-void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg))
-{
- client_process_config = cpc;
-}
-EXPORT_SYMBOL(lustre_register_client_process_config);
-
-static int process_param2_config(struct lustre_cfg *lcfg)
-{
- char *param = lustre_cfg_string(lcfg, 1);
- char *upcall = lustre_cfg_string(lcfg, 2);
- char *argv[] = {
- [0] = "/usr/sbin/lctl",
- [1] = "set_param",
- [2] = param,
- [3] = NULL
- };
- ktime_t start;
- ktime_t end;
- int rc;
-
- /* Add upcall processing here. Now only lctl is supported */
- if (strcmp(upcall, LCTL_UPCALL) != 0) {
- CERROR("Unsupported upcall %s\n", upcall);
- return -EINVAL;
- }
-
- start = ktime_get();
- rc = call_usermodehelper(argv[0], argv, NULL, UMH_WAIT_PROC);
- end = ktime_get();
-
- if (rc < 0) {
- CERROR(
- "lctl: error invoking upcall %s %s %s: rc = %d; time %ldus\n",
- argv[0], argv[1], argv[2], rc,
- (long)ktime_us_delta(end, start));
- } else {
- CDEBUG(D_HA, "lctl: invoked upcall %s %s %s, time %ldus\n",
- argv[0], argv[1], argv[2],
- (long)ktime_us_delta(end, start));
- rc = 0;
- }
-
- return rc;
-}
-
-/** Process configuration commands given in lustre_cfg form.
- * These may come from direct calls (e.g. class_manual_cleanup)
- * or processing the config llog, or ioctl from lctl.
- */
-int class_process_config(struct lustre_cfg *lcfg)
-{
- struct obd_device *obd;
- int err;
-
- LASSERT(lcfg && !IS_ERR(lcfg));
- CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command);
-
- /* Commands that don't need a device */
- switch (lcfg->lcfg_command) {
- case LCFG_ATTACH: {
- err = class_attach(lcfg);
- goto out;
- }
- case LCFG_ADD_UUID: {
- CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid %#llx (%s)\n",
- lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid,
- libcfs_nid2str(lcfg->lcfg_nid));
-
- err = class_add_uuid(lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid);
- goto out;
- }
- case LCFG_DEL_UUID: {
- CDEBUG(D_IOCTL, "removing mappings for uuid %s\n",
- (lcfg->lcfg_bufcount < 2 || LUSTRE_CFG_BUFLEN(lcfg, 1) == 0)
- ? "<all uuids>" : lustre_cfg_string(lcfg, 1));
-
- err = class_del_uuid(lustre_cfg_string(lcfg, 1));
- goto out;
- }
- case LCFG_MOUNTOPT: {
- CDEBUG(D_IOCTL, "mountopt: profile %s osc %s mdc %s\n",
- lustre_cfg_string(lcfg, 1),
- lustre_cfg_string(lcfg, 2),
- lustre_cfg_string(lcfg, 3));
- /* set these mount options somewhere, so ll_fill_super
- * can find them.
- */
- err = class_add_profile(LUSTRE_CFG_BUFLEN(lcfg, 1),
- lustre_cfg_string(lcfg, 1),
- LUSTRE_CFG_BUFLEN(lcfg, 2),
- lustre_cfg_string(lcfg, 2),
- LUSTRE_CFG_BUFLEN(lcfg, 3),
- lustre_cfg_string(lcfg, 3));
- goto out;
- }
- case LCFG_DEL_MOUNTOPT: {
- CDEBUG(D_IOCTL, "mountopt: profile %s\n",
- lustre_cfg_string(lcfg, 1));
- class_del_profile(lustre_cfg_string(lcfg, 1));
- err = 0;
- goto out;
- }
- case LCFG_SET_TIMEOUT: {
- CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n",
- obd_timeout, lcfg->lcfg_num);
- obd_timeout = max(lcfg->lcfg_num, 1U);
- obd_timeout_set = 1;
- err = 0;
- goto out;
- }
- case LCFG_SET_LDLM_TIMEOUT: {
- /* ldlm_timeout is not used on the client */
- err = 0;
- goto out;
- }
- case LCFG_SET_UPCALL: {
- LCONSOLE_ERROR_MSG(0x15a, "recovery upcall is deprecated\n");
- /* COMPAT_146 Don't fail on old configs */
- err = 0;
- goto out;
- }
- case LCFG_MARKER: {
- struct cfg_marker *marker;
-
- marker = lustre_cfg_buf(lcfg, 1);
- CDEBUG(D_IOCTL, "marker %d (%#x) %.16s %s\n", marker->cm_step,
- marker->cm_flags, marker->cm_tgtname, marker->cm_comment);
- err = 0;
- goto out;
- }
- case LCFG_PARAM: {
- char *tmp;
- /* llite has no obd */
- if ((class_match_param(lustre_cfg_string(lcfg, 1),
- PARAM_LLITE, NULL) == 0) &&
- client_process_config) {
- err = (*client_process_config)(lcfg);
- goto out;
- } else if ((class_match_param(lustre_cfg_string(lcfg, 1),
- PARAM_SYS, &tmp) == 0)) {
- /* Global param settings */
- err = class_set_global(tmp, lcfg->lcfg_num, lcfg);
- /*
- * Client or server should not fail to mount if
- * it hits an unknown configuration parameter.
- */
- if (err != 0)
- CWARN("Ignoring unknown param %s\n", tmp);
-
- err = 0;
- goto out;
- } else if ((class_match_param(lustre_cfg_string(lcfg, 1),
- PARAM_QUOTA, &tmp) == 0) &&
- quota_process_config) {
- err = (*quota_process_config)(lcfg);
- goto out;
- }
-
- break;
- }
- case LCFG_SET_PARAM: {
- err = process_param2_config(lcfg);
- goto out;
- }
- }
- /* Commands that require a device */
- obd = class_name2obd(lustre_cfg_string(lcfg, 0));
- if (!obd) {
- if (!LUSTRE_CFG_BUFLEN(lcfg, 0))
- CERROR("this lcfg command requires a device name\n");
- else
- CERROR("no device for: %s\n",
- lustre_cfg_string(lcfg, 0));
-
- err = -EINVAL;
- goto out;
- }
-
- switch (lcfg->lcfg_command) {
- case LCFG_SETUP: {
- err = class_setup(obd, lcfg);
- goto out;
- }
- case LCFG_DETACH: {
- err = class_detach(obd, lcfg);
- err = 0;
- goto out;
- }
- case LCFG_CLEANUP: {
- err = class_cleanup(obd, lcfg);
- err = 0;
- goto out;
- }
- case LCFG_ADD_CONN: {
- err = class_add_conn(obd, lcfg);
- err = 0;
- goto out;
- }
- case LCFG_DEL_CONN: {
- err = class_del_conn(obd, lcfg);
- err = 0;
- goto out;
- }
- case LCFG_POOL_NEW: {
- err = obd_pool_new(obd, lustre_cfg_string(lcfg, 2));
- err = 0;
- goto out;
- }
- case LCFG_POOL_ADD: {
- err = obd_pool_add(obd, lustre_cfg_string(lcfg, 2),
- lustre_cfg_string(lcfg, 3));
- err = 0;
- goto out;
- }
- case LCFG_POOL_REM: {
- err = obd_pool_rem(obd, lustre_cfg_string(lcfg, 2),
- lustre_cfg_string(lcfg, 3));
- err = 0;
- goto out;
- }
- case LCFG_POOL_DEL: {
- err = obd_pool_del(obd, lustre_cfg_string(lcfg, 2));
- err = 0;
- goto out;
- }
- default: {
- err = obd_process_config(obd, sizeof(*lcfg), lcfg);
- goto out;
- }
- }
-out:
- if ((err < 0) && !(lcfg->lcfg_command & LCFG_REQUIRED)) {
- CWARN("Ignoring error %d on optional command %#x\n", err,
- lcfg->lcfg_command);
- err = 0;
- }
- return err;
-}
-EXPORT_SYMBOL(class_process_config);
-
-int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
- struct lustre_cfg *lcfg, void *data)
-{
- struct lprocfs_vars *var;
- struct file fakefile;
- struct seq_file fake_seqfile;
- char *key, *sval;
- int i, keylen, vallen;
- int matched = 0, j = 0;
- int rc = 0;
- int skip = 0;
-
- if (lcfg->lcfg_command != LCFG_PARAM) {
- CERROR("Unknown command: %d\n", lcfg->lcfg_command);
- return -EINVAL;
- }
-
- /* fake a seq file so that var->fops->write can work... */
- fakefile.private_data = &fake_seqfile;
- fake_seqfile.private = data;
- /* e.g. tunefs.lustre --param mdt.group_upcall=foo /r/tmp/lustre-mdt
- * or lctl conf_param lustre-MDT0000.mdt.group_upcall=bar
- * or lctl conf_param lustre-OST0000.osc.max_dirty_mb=36
- */
- for (i = 1; i < lcfg->lcfg_bufcount; i++) {
- key = lustre_cfg_buf(lcfg, i);
- /* Strip off prefix */
- if (class_match_param(key, prefix, &key)) {
- /*
- * If the prefix doesn't match, return error so we
- * can pass it down the stack
- */
- return -ENOSYS;
- }
- sval = strchr(key, '=');
- if (!sval || (*(sval + 1) == 0)) {
- CERROR("Can't parse param %s (missing '=')\n", key);
- /* rc = -EINVAL; continue parsing other params */
- continue;
- }
- keylen = sval - key;
- sval++;
- vallen = strlen(sval);
- matched = 0;
- j = 0;
- /* Search proc entries */
- while (lvars[j].name) {
- var = &lvars[j];
- if (!class_match_param(key, var->name, NULL) &&
- keylen == strlen(var->name)) {
- matched++;
- rc = -EROFS;
- if (var->fops && var->fops->write) {
- mm_segment_t oldfs;
-
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- rc = var->fops->write(&fakefile,
- (const char __user *)sval,
- vallen, NULL);
- set_fs(oldfs);
- }
- break;
- }
- j++;
- }
- if (!matched) {
- CERROR("%.*s: %s unknown param %s\n",
- (int)strlen(prefix) - 1, prefix,
- (char *)lustre_cfg_string(lcfg, 0), key);
- /* rc = -EINVAL; continue parsing other params */
- skip++;
- } else if (rc < 0) {
- CERROR("%s: error writing proc entry '%s': rc = %d\n",
- prefix, var->name, rc);
- rc = 0;
- } else {
- CDEBUG(D_CONFIG, "%s.%.*s: Set parameter %.*s=%s\n",
- lustre_cfg_string(lcfg, 0),
- (int)strlen(prefix) - 1, prefix,
- (int)(sval - key - 1), key, sval);
- }
- }
-
- if (rc > 0)
- rc = 0;
- if (!rc && skip)
- rc = skip;
- return rc;
-}
-EXPORT_SYMBOL(class_process_proc_param);
-
-/** Parse a configuration llog, doing various manipulations on them
- * for various reasons, (modifications for compatibility, skip obsolete
- * records, change uuids, etc), then class_process_config() resulting
- * net records.
- */
-int class_config_llog_handler(const struct lu_env *env,
- struct llog_handle *handle,
- struct llog_rec_hdr *rec, void *data)
-{
- struct config_llog_instance *clli = data;
- int cfg_len = rec->lrh_len;
- char *cfg_buf = (char *)(rec + 1);
- int rc = 0;
-
- switch (rec->lrh_type) {
- case OBD_CFG_REC: {
- struct lustre_cfg *lcfg, *lcfg_new;
- struct lustre_cfg_bufs bufs;
- char *inst_name = NULL;
- int inst_len = 0;
- size_t lcfg_len;
- int swab = 0;
-
- lcfg = (struct lustre_cfg *)cfg_buf;
- if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
- lustre_swab_lustre_cfg(lcfg);
- swab = 1;
- }
-
- rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
- if (rc)
- goto out;
-
- /* Figure out config state info */
- if (lcfg->lcfg_command == LCFG_MARKER) {
- struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
-
- lustre_swab_cfg_marker(marker, swab,
- LUSTRE_CFG_BUFLEN(lcfg, 1));
- CDEBUG(D_CONFIG, "Marker, inst_flg=%#x mark_flg=%#x\n",
- clli->cfg_flags, marker->cm_flags);
- if (marker->cm_flags & CM_START) {
- /* all previous flags off */
- clli->cfg_flags = CFG_F_MARKER;
- if (marker->cm_flags & CM_SKIP) {
- clli->cfg_flags |= CFG_F_SKIP;
- CDEBUG(D_CONFIG, "SKIP #%d\n",
- marker->cm_step);
- } else if ((marker->cm_flags & CM_EXCLUDE) ||
- (clli->cfg_sb &&
- lustre_check_exclusion(clli->cfg_sb,
- marker->cm_tgtname))) {
- clli->cfg_flags |= CFG_F_EXCLUDE;
- CDEBUG(D_CONFIG, "EXCLUDE %d\n",
- marker->cm_step);
- }
- } else if (marker->cm_flags & CM_END) {
- clli->cfg_flags = 0;
- }
- }
- /* A config command without a start marker before it is
- * illegal (post 146)
- */
- if (!(clli->cfg_flags & CFG_F_COMPAT146) &&
- !(clli->cfg_flags & CFG_F_MARKER) &&
- (lcfg->lcfg_command != LCFG_MARKER)) {
- CWARN("Config not inside markers, ignoring! (inst: %p, uuid: %s, flags: %#x)\n",
- clli->cfg_instance,
- clli->cfg_uuid.uuid, clli->cfg_flags);
- clli->cfg_flags |= CFG_F_SKIP;
- }
- if (clli->cfg_flags & CFG_F_SKIP) {
- CDEBUG(D_CONFIG, "skipping %#x\n",
- clli->cfg_flags);
- rc = 0;
- /* No processing! */
- break;
- }
-
- /*
- * For interoperability between 1.8 and 2.0,
- * rename "mds" obd device type to "mdt".
- */
- {
- char *typename = lustre_cfg_string(lcfg, 1);
- char *index = lustre_cfg_string(lcfg, 2);
-
- if ((lcfg->lcfg_command == LCFG_ATTACH && typename &&
- strcmp(typename, "mds") == 0)) {
- CWARN("For 1.8 interoperability, rename obd type from mds to mdt\n");
- typename[2] = 't';
- }
- if ((lcfg->lcfg_command == LCFG_SETUP && index &&
- strcmp(index, "type") == 0)) {
- CDEBUG(D_INFO, "For 1.8 interoperability, set this index to '0'\n");
- index[0] = '0';
- index[1] = 0;
- }
- }
-
- if (clli->cfg_flags & CFG_F_EXCLUDE) {
- CDEBUG(D_CONFIG, "cmd: %x marked EXCLUDED\n",
- lcfg->lcfg_command);
- if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD)
- /* Add inactive instead */
- lcfg->lcfg_command = LCFG_LOV_ADD_INA;
- }
-
- lustre_cfg_bufs_init(&bufs, lcfg);
-
- if (clli && clli->cfg_instance &&
- LUSTRE_CFG_BUFLEN(lcfg, 0) > 0) {
- inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
- sizeof(clli->cfg_instance) * 2 + 4;
- inst_name = kasprintf(GFP_NOFS, "%s-%p",
- lustre_cfg_string(lcfg, 0),
- clli->cfg_instance);
- if (!inst_name) {
- rc = -ENOMEM;
- goto out;
- }
- lustre_cfg_bufs_set_string(&bufs, 0, inst_name);
- CDEBUG(D_CONFIG, "cmd %x, instance name: %s\n",
- lcfg->lcfg_command, inst_name);
- }
-
- /* we override the llog's uuid for clients, to insure they
- * are unique
- */
- if (clli && clli->cfg_instance &&
- lcfg->lcfg_command == LCFG_ATTACH) {
- lustre_cfg_bufs_set_string(&bufs, 2,
- clli->cfg_uuid.uuid);
- }
- /*
- * sptlrpc config record, we expect 2 data segments:
- * [0]: fs_name/target_name,
- * [1]: rule string
- * moving them to index [1] and [2], and insert MGC's
- * obdname at index [0].
- */
- if (clli && !clli->cfg_instance &&
- lcfg->lcfg_command == LCFG_SPTLRPC_CONF) {
- lustre_cfg_bufs_set(&bufs, 2, bufs.lcfg_buf[1],
- bufs.lcfg_buflen[1]);
- lustre_cfg_bufs_set(&bufs, 1, bufs.lcfg_buf[0],
- bufs.lcfg_buflen[0]);
- lustre_cfg_bufs_set_string(&bufs, 0,
- clli->cfg_obdname);
- }
-
- lcfg_len = lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen);
- lcfg_new = kzalloc(lcfg_len, GFP_NOFS);
- if (!lcfg_new) {
- rc = -ENOMEM;
- goto out;
- }
-
- lustre_cfg_init(lcfg_new, lcfg->lcfg_command, &bufs);
- lcfg_new->lcfg_num = lcfg->lcfg_num;
- lcfg_new->lcfg_flags = lcfg->lcfg_flags;
-
- /* XXX Hack to try to remain binary compatible with
- * pre-newconfig logs
- */
- if (lcfg->lcfg_nal != 0 && /* pre-newconfig log? */
- (lcfg->lcfg_nid >> 32) == 0) {
- __u32 addr = (__u32)(lcfg->lcfg_nid & 0xffffffff);
-
- lcfg_new->lcfg_nid =
- LNET_MKNID(LNET_MKNET(lcfg->lcfg_nal, 0), addr);
- CWARN("Converted pre-newconfig NAL %d NID %x to %s\n",
- lcfg->lcfg_nal, addr,
- libcfs_nid2str(lcfg_new->lcfg_nid));
- } else {
- lcfg_new->lcfg_nid = lcfg->lcfg_nid;
- }
-
- lcfg_new->lcfg_nal = 0; /* illegal value for obsolete field */
-
- rc = class_process_config(lcfg_new);
- kfree(lcfg_new);
- kfree(inst_name);
- break;
- }
- default:
- CERROR("Unknown llog record type %#x encountered\n",
- rec->lrh_type);
- break;
- }
-out:
- if (rc) {
- CERROR("%s: cfg command failed: rc = %d\n",
- handle->lgh_ctxt->loc_obd->obd_name, rc);
- class_config_dump_handler(NULL, handle, rec, data);
- }
- return rc;
-}
-EXPORT_SYMBOL(class_config_llog_handler);
-
-int class_config_parse_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
- char *name, struct config_llog_instance *cfg)
-{
- struct llog_process_cat_data cd = {0, 0};
- struct llog_handle *llh;
- llog_cb_t callback;
- int rc;
-
- CDEBUG(D_INFO, "looking up llog %s\n", name);
- rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
- if (rc)
- return rc;
-
- rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
- if (rc)
- goto parse_out;
-
- /* continue processing from where we last stopped to end-of-log */
- if (cfg) {
- cd.lpcd_first_idx = cfg->cfg_last_idx;
- callback = cfg->cfg_callback;
- LASSERT(callback);
- } else {
- callback = class_config_llog_handler;
- }
-
- cd.lpcd_last_idx = 0;
-
- rc = llog_process(env, llh, callback, cfg, &cd);
-
- CDEBUG(D_CONFIG, "Processed log %s gen %d-%d (rc=%d)\n", name,
- cd.lpcd_first_idx + 1, cd.lpcd_last_idx, rc);
- if (cfg)
- cfg->cfg_last_idx = cd.lpcd_last_idx;
-
-parse_out:
- llog_close(env, llh);
- return rc;
-}
-EXPORT_SYMBOL(class_config_parse_llog);
-
-/**
- * parse config record and output dump in supplied buffer.
- * This is separated from class_config_dump_handler() to use
- * for ioctl needs as well
- */
-static int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf,
- int size)
-{
- struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
- char *ptr = buf;
- char *end = buf + size;
- int rc = 0;
-
- LASSERT(rec->lrh_type == OBD_CFG_REC);
- rc = lustre_cfg_sanity_check(lcfg, rec->lrh_len);
- if (rc < 0)
- return rc;
-
- ptr += snprintf(ptr, end - ptr, "cmd=%05x ", lcfg->lcfg_command);
- if (lcfg->lcfg_flags)
- ptr += snprintf(ptr, end - ptr, "flags=%#08x ",
- lcfg->lcfg_flags);
-
- if (lcfg->lcfg_num)
- ptr += snprintf(ptr, end - ptr, "num=%#08x ", lcfg->lcfg_num);
-
- if (lcfg->lcfg_nid) {
- char nidstr[LNET_NIDSTR_SIZE];
-
- libcfs_nid2str_r(lcfg->lcfg_nid, nidstr, sizeof(nidstr));
- ptr += snprintf(ptr, end - ptr, "nid=%s(%#llx)\n ",
- nidstr, lcfg->lcfg_nid);
- }
-
- if (lcfg->lcfg_command == LCFG_MARKER) {
- struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
-
- ptr += snprintf(ptr, end - ptr, "marker=%d(%#x)%s '%s'",
- marker->cm_step, marker->cm_flags,
- marker->cm_tgtname, marker->cm_comment);
- } else {
- int i;
-
- for (i = 0; i < lcfg->lcfg_bufcount; i++) {
- ptr += snprintf(ptr, end - ptr, "%d:%s ", i,
- lustre_cfg_string(lcfg, i));
- }
- }
- ptr += snprintf(ptr, end - ptr, "\n");
- /* return consumed bytes */
- rc = ptr - buf;
- return rc;
-}
-
-int class_config_dump_handler(const struct lu_env *env,
- struct llog_handle *handle,
- struct llog_rec_hdr *rec, void *data)
-{
- char *outstr;
- int rc = 0;
-
- outstr = kzalloc(256, GFP_NOFS);
- if (!outstr)
- return -ENOMEM;
-
- if (rec->lrh_type == OBD_CFG_REC) {
- class_config_parse_rec(rec, outstr, 256);
- LCONSOLE(D_WARNING, " %s", outstr);
- } else {
- LCONSOLE(D_WARNING, "unhandled lrh_type: %#x\n", rec->lrh_type);
- rc = -EINVAL;
- }
-
- kfree(outstr);
- return rc;
-}
-
-/** Call class_cleanup and class_detach.
- * "Manual" only in the sense that we're faking lcfg commands.
- */
-int class_manual_cleanup(struct obd_device *obd)
-{
- char flags[3] = "";
- struct lustre_cfg *lcfg;
- struct lustre_cfg_bufs bufs;
- int rc;
-
- if (!obd) {
- CERROR("empty cleanup\n");
- return -EALREADY;
- }
-
- if (obd->obd_force)
- strcat(flags, "F");
- if (obd->obd_fail)
- strcat(flags, "A");
-
- CDEBUG(D_CONFIG, "Manual cleanup of %s (flags='%s')\n",
- obd->obd_name, flags);
-
- lustre_cfg_bufs_reset(&bufs, obd->obd_name);
- lustre_cfg_bufs_set_string(&bufs, 1, flags);
- lcfg = kzalloc(lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen),
- GFP_NOFS);
- if (!lcfg)
- return -ENOMEM;
- lustre_cfg_init(lcfg, LCFG_CLEANUP, &bufs);
-
- rc = class_process_config(lcfg);
- if (rc) {
- CERROR("cleanup failed %d: %s\n", rc, obd->obd_name);
- goto out;
- }
-
- /* the lcfg is almost the same for both ops */
- lcfg->lcfg_command = LCFG_DETACH;
- rc = class_process_config(lcfg);
- if (rc)
- CERROR("detach failed %d: %s\n", rc, obd->obd_name);
-out:
- kfree(lcfg);
- return rc;
-}
-EXPORT_SYMBOL(class_manual_cleanup);
-
-/*
- * uuid<->export lustre hash operations
- */
-
-static unsigned int
-uuid_hash(struct cfs_hash *hs, const void *key, unsigned int mask)
-{
- return cfs_hash_djb2_hash(((struct obd_uuid *)key)->uuid,
- sizeof(((struct obd_uuid *)key)->uuid), mask);
-}
-
-static void *
-uuid_key(struct hlist_node *hnode)
-{
- struct obd_export *exp;
-
- exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
-
- return &exp->exp_client_uuid;
-}
-
-/*
- * NOTE: It is impossible to find an export that is in failed
- * state with this function
- */
-static int
-uuid_keycmp(const void *key, struct hlist_node *hnode)
-{
- struct obd_export *exp;
-
- LASSERT(key);
- exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
-
- return obd_uuid_equals(key, &exp->exp_client_uuid) &&
- !exp->exp_failed;
-}
-
-static void *
-uuid_export_object(struct hlist_node *hnode)
-{
- return hlist_entry(hnode, struct obd_export, exp_uuid_hash);
-}
-
-static void
-uuid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
-{
- struct obd_export *exp;
-
- exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
- class_export_get(exp);
-}
-
-static void
-uuid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
-{
- struct obd_export *exp;
-
- exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
- class_export_put(exp);
-}
-
-static struct cfs_hash_ops uuid_hash_ops = {
- .hs_hash = uuid_hash,
- .hs_key = uuid_key,
- .hs_keycmp = uuid_keycmp,
- .hs_object = uuid_export_object,
- .hs_get = uuid_export_get,
- .hs_put_locked = uuid_export_put_locked,
-};
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
deleted file mode 100644
index f5e8214ac37b..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+++ /dev/null
@@ -1,1244 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/obd_mount.c
- *
- * Client mount routines
- *
- * Author: Nathan Rutman <nathan@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-#define D_MOUNT (D_SUPER | D_CONFIG/*|D_WARNING */)
-#define PRINT_CMD CDEBUG
-
-#include <obd.h>
-#include <lustre_compat.h>
-#include <obd_class.h>
-#include <uapi/linux/lustre/lustre_idl.h>
-#include <lustre_log.h>
-#include <lustre_disk.h>
-#include <uapi/linux/lustre/lustre_param.h>
-
-static DEFINE_SPINLOCK(client_lock);
-static struct module *client_mod;
-static int (*client_fill_super)(struct super_block *sb);
-static void (*kill_super_cb)(struct super_block *sb);
-
-/**************** config llog ********************/
-
-/** Get a config log from the MGS and process it.
- * This func is called for both clients and servers.
- * Continue to process new statements appended to the logs
- * (whenever the config lock is revoked) until lustre_end_log
- * is called.
- * @param sb The superblock is used by the MGC to write to the local copy of
- * the config log
- * @param logname The name of the llog to replicate from the MGS
- * @param cfg Since the same mgc may be used to follow multiple config logs
- * (e.g. ost1, ost2, client), the config_llog_instance keeps the state for
- * this log, and is added to the mgc's list of logs to follow.
- */
-int lustre_process_log(struct super_block *sb, char *logname,
- struct config_llog_instance *cfg)
-{
- struct lustre_cfg *lcfg;
- struct lustre_cfg_bufs *bufs;
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct obd_device *mgc = lsi->lsi_mgc;
- int rc;
-
- LASSERT(mgc);
- LASSERT(cfg);
-
- bufs = kzalloc(sizeof(*bufs), GFP_NOFS);
- if (!bufs)
- return -ENOMEM;
-
- /* mgc_process_config */
- lustre_cfg_bufs_reset(bufs, mgc->obd_name);
- lustre_cfg_bufs_set_string(bufs, 1, logname);
- lustre_cfg_bufs_set(bufs, 2, cfg, sizeof(*cfg));
- lustre_cfg_bufs_set(bufs, 3, &sb, sizeof(sb));
- lcfg = kzalloc(lustre_cfg_len(bufs->lcfg_bufcount, bufs->lcfg_buflen),
- GFP_NOFS);
- if (!lcfg) {
- rc = -ENOMEM;
- goto out;
- }
- lustre_cfg_init(lcfg, LCFG_LOG_START, bufs);
-
- rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
- kfree(lcfg);
-out:
- kfree(bufs);
-
- if (rc == -EINVAL)
- LCONSOLE_ERROR_MSG(0x15b, "%s: The configuration from log '%s' failed from the MGS (%d). Make sure this client and the MGS are running compatible versions of Lustre.\n",
- mgc->obd_name, logname, rc);
-
- else if (rc)
- LCONSOLE_ERROR_MSG(0x15c, "%s: The configuration from log '%s' failed (%d). This may be the result of communication errors between this node and the MGS, a bad configuration, or other errors. See the syslog for more information.\n",
- mgc->obd_name, logname,
- rc);
-
- /* class_obd_list(); */
- return rc;
-}
-EXPORT_SYMBOL(lustre_process_log);
-
-/* Stop watching this config log for updates */
-int lustre_end_log(struct super_block *sb, char *logname,
- struct config_llog_instance *cfg)
-{
- struct lustre_cfg *lcfg;
- struct lustre_cfg_bufs bufs;
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct obd_device *mgc = lsi->lsi_mgc;
- int rc;
-
- if (!mgc)
- return -ENOENT;
-
- /* mgc_process_config */
- lustre_cfg_bufs_reset(&bufs, mgc->obd_name);
- lustre_cfg_bufs_set_string(&bufs, 1, logname);
- if (cfg)
- lustre_cfg_bufs_set(&bufs, 2, cfg, sizeof(*cfg));
- lcfg = kzalloc(lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen),
- GFP_NOFS);
- if (!lcfg)
- return -ENOMEM;
- lustre_cfg_init(lcfg, LCFG_LOG_END, &bufs);
-
- rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
- kfree(lcfg);
- return rc;
-}
-EXPORT_SYMBOL(lustre_end_log);
-
-/**************** obd start *******************/
-
-/** lustre_cfg_bufs are a holdover from 1.4; we can still set these up from
- * lctl (and do for echo cli/srv.
- */
-static int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
- char *s1, char *s2, char *s3, char *s4)
-{
- struct lustre_cfg_bufs bufs;
- struct lustre_cfg *lcfg = NULL;
- int rc;
-
- CDEBUG(D_TRACE, "lcfg %s %#x %s %s %s %s\n", cfgname,
- cmd, s1, s2, s3, s4);
-
- lustre_cfg_bufs_reset(&bufs, cfgname);
- if (s1)
- lustre_cfg_bufs_set_string(&bufs, 1, s1);
- if (s2)
- lustre_cfg_bufs_set_string(&bufs, 2, s2);
- if (s3)
- lustre_cfg_bufs_set_string(&bufs, 3, s3);
- if (s4)
- lustre_cfg_bufs_set_string(&bufs, 4, s4);
-
- lcfg = kzalloc(lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen),
- GFP_NOFS);
- if (!lcfg)
- return -ENOMEM;
- lustre_cfg_init(lcfg, cmd, &bufs);
- lcfg->lcfg_nid = nid;
- rc = class_process_config(lcfg);
- kfree(lcfg);
- return rc;
-}
-
-/** Call class_attach and class_setup. These methods in turn call
- * obd type-specific methods.
- */
-static int lustre_start_simple(char *obdname, char *type, char *uuid,
- char *s1, char *s2, char *s3, char *s4)
-{
- int rc;
-
- CDEBUG(D_MOUNT, "Starting obd %s (typ=%s)\n", obdname, type);
-
- rc = do_lcfg(obdname, 0, LCFG_ATTACH, type, uuid, NULL, NULL);
- if (rc) {
- CERROR("%s attach error %d\n", obdname, rc);
- return rc;
- }
- rc = do_lcfg(obdname, 0, LCFG_SETUP, s1, s2, s3, s4);
- if (rc) {
- CERROR("%s setup error %d\n", obdname, rc);
- do_lcfg(obdname, 0, LCFG_DETACH, NULL, NULL, NULL, NULL);
- }
- return rc;
-}
-
-static DEFINE_MUTEX(mgc_start_lock);
-
-/** Set up a mgc obd to process startup logs
- *
- * \param sb [in] super block of the mgc obd
- *
- * \retval 0 success, otherwise error code
- */
-int lustre_start_mgc(struct super_block *sb)
-{
- struct obd_connect_data *data = NULL;
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct obd_device *obd;
- struct obd_export *exp;
- struct obd_uuid *uuid;
- class_uuid_t uuidc;
- lnet_nid_t nid;
- char nidstr[LNET_NIDSTR_SIZE];
- char *mgcname = NULL, *niduuid = NULL, *mgssec = NULL;
- char *ptr;
- int rc = 0, i = 0, j;
-
- LASSERT(lsi->lsi_lmd);
-
- /* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
- ptr = lsi->lsi_lmd->lmd_dev;
- if (class_parse_nid(ptr, &nid, &ptr) == 0)
- i++;
- if (i == 0) {
- CERROR("No valid MGS nids found.\n");
- return -EINVAL;
- }
-
- mutex_lock(&mgc_start_lock);
-
- libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
- mgcname = kasprintf(GFP_NOFS,
- "%s%s", LUSTRE_MGC_OBDNAME, nidstr);
- niduuid = kasprintf(GFP_NOFS, "%s_%x", mgcname, 0);
- if (!mgcname || !niduuid) {
- rc = -ENOMEM;
- goto out_free;
- }
-
- mgssec = lsi->lsi_lmd->lmd_mgssec ? lsi->lsi_lmd->lmd_mgssec : "";
-
- data = kzalloc(sizeof(*data), GFP_NOFS);
- if (!data) {
- rc = -ENOMEM;
- goto out_free;
- }
-
- obd = class_name2obd(mgcname);
- if (obd && !obd->obd_stopping) {
- int recov_bk;
-
- rc = obd_set_info_async(NULL, obd->obd_self_export,
- strlen(KEY_MGSSEC), KEY_MGSSEC,
- strlen(mgssec), mgssec, NULL);
- if (rc)
- goto out_free;
-
- /* Re-using an existing MGC */
- atomic_inc(&obd->u.cli.cl_mgc_refcount);
-
- /* IR compatibility check, only for clients */
- if (lmd_is_client(lsi->lsi_lmd)) {
- int has_ir;
- int vallen = sizeof(*data);
- __u32 *flags = &lsi->lsi_lmd->lmd_flags;
-
- rc = obd_get_info(NULL, obd->obd_self_export,
- strlen(KEY_CONN_DATA), KEY_CONN_DATA,
- &vallen, data);
- LASSERT(rc == 0);
- has_ir = OCD_HAS_FLAG(data, IMP_RECOV);
- if (has_ir ^ !(*flags & LMD_FLG_NOIR)) {
- /* LMD_FLG_NOIR is for test purpose only */
- LCONSOLE_WARN(
- "Trying to mount a client with IR setting not compatible with current mgc. Force to use current mgc setting that is IR %s.\n",
- has_ir ? "enabled" : "disabled");
- if (has_ir)
- *flags &= ~LMD_FLG_NOIR;
- else
- *flags |= LMD_FLG_NOIR;
- }
- }
-
- recov_bk = 0;
-
- /* Try all connections, but only once (again).
- * We don't want to block another target from starting
- * (using its local copy of the log), but we do want to connect
- * if at all possible.
- */
- recov_bk++;
- CDEBUG(D_MOUNT, "%s: Set MGC reconnect %d\n", mgcname,
- recov_bk);
- rc = obd_set_info_async(NULL, obd->obd_self_export,
- sizeof(KEY_INIT_RECOV_BACKUP),
- KEY_INIT_RECOV_BACKUP,
- sizeof(recov_bk), &recov_bk, NULL);
- rc = 0;
- goto out;
- }
-
- CDEBUG(D_MOUNT, "Start MGC '%s'\n", mgcname);
-
- /* Add the primary nids for the MGS */
- i = 0;
- /* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
- ptr = lsi->lsi_lmd->lmd_dev;
- while (class_parse_nid(ptr, &nid, &ptr) == 0) {
- rc = do_lcfg(mgcname, nid,
- LCFG_ADD_UUID, niduuid, NULL, NULL, NULL);
- if (!rc)
- i++;
- /* Stop at the first failover nid */
- if (*ptr == ':')
- break;
- }
- if (i == 0) {
- CERROR("No valid MGS nids found.\n");
- rc = -EINVAL;
- goto out_free;
- }
- lsi->lsi_lmd->lmd_mgs_failnodes = 1;
-
- /* Random uuid for MGC allows easier reconnects */
- uuid = kzalloc(sizeof(*uuid), GFP_NOFS);
- if (!uuid) {
- rc = -ENOMEM;
- goto out_free;
- }
-
- ll_generate_random_uuid(uuidc);
- class_uuid_unparse(uuidc, uuid);
-
- /* Start the MGC */
- rc = lustre_start_simple(mgcname, LUSTRE_MGC_NAME,
- (char *)uuid->uuid, LUSTRE_MGS_OBDNAME,
- niduuid, NULL, NULL);
- kfree(uuid);
- if (rc)
- goto out_free;
-
- /* Add any failover MGS nids */
- i = 1;
- while (ptr && ((*ptr == ':' ||
- class_find_param(ptr, PARAM_MGSNODE, &ptr) == 0))) {
- /* New failover node */
- sprintf(niduuid, "%s_%x", mgcname, i);
- j = 0;
- while (class_parse_nid_quiet(ptr, &nid, &ptr) == 0) {
- rc = do_lcfg(mgcname, nid, LCFG_ADD_UUID, niduuid,
- NULL, NULL, NULL);
- if (!rc)
- ++j;
- if (*ptr == ':')
- break;
- }
- if (j > 0) {
- rc = do_lcfg(mgcname, 0, LCFG_ADD_CONN,
- niduuid, NULL, NULL, NULL);
- if (!rc)
- i++;
- } else {
- /* at ":/fsname" */
- break;
- }
- }
- lsi->lsi_lmd->lmd_mgs_failnodes = i;
-
- obd = class_name2obd(mgcname);
- if (!obd) {
- CERROR("Can't find mgcobd %s\n", mgcname);
- rc = -ENOTCONN;
- goto out_free;
- }
-
- rc = obd_set_info_async(NULL, obd->obd_self_export,
- strlen(KEY_MGSSEC), KEY_MGSSEC,
- strlen(mgssec), mgssec, NULL);
- if (rc)
- goto out_free;
-
- /* Keep a refcount of servers/clients who started with "mount",
- * so we know when we can get rid of the mgc.
- */
- atomic_set(&obd->u.cli.cl_mgc_refcount, 1);
-
- /* We connect to the MGS at setup, and don't disconnect until cleanup */
- data->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_AT |
- OBD_CONNECT_FULL20 | OBD_CONNECT_IMP_RECOV |
- OBD_CONNECT_LVB_TYPE | OBD_CONNECT_BULK_MBITS;
-
-#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE
- data->ocd_connect_flags |= OBD_CONNECT_MNE_SWAB;
-#endif
-
- if (lmd_is_client(lsi->lsi_lmd) &&
- lsi->lsi_lmd->lmd_flags & LMD_FLG_NOIR)
- data->ocd_connect_flags &= ~OBD_CONNECT_IMP_RECOV;
- data->ocd_version = LUSTRE_VERSION_CODE;
- rc = obd_connect(NULL, &exp, obd, &obd->obd_uuid, data, NULL);
- if (rc) {
- CERROR("connect failed %d\n", rc);
- goto out;
- }
-
- obd->u.cli.cl_mgc_mgsexp = exp;
-
-out:
- /* Keep the mgc info in the sb. Note that many lsi's can point
- * to the same mgc.
- */
- lsi->lsi_mgc = obd;
-out_free:
- mutex_unlock(&mgc_start_lock);
-
- kfree(data);
- kfree(mgcname);
- kfree(niduuid);
- return rc;
-}
-
-static int lustre_stop_mgc(struct super_block *sb)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct obd_device *obd;
- char *niduuid = NULL, *ptr = NULL;
- int i, rc = 0, len = 0;
-
- if (!lsi)
- return -ENOENT;
- obd = lsi->lsi_mgc;
- if (!obd)
- return -ENOENT;
- lsi->lsi_mgc = NULL;
-
- mutex_lock(&mgc_start_lock);
- LASSERT(atomic_read(&obd->u.cli.cl_mgc_refcount) > 0);
- if (!atomic_dec_and_test(&obd->u.cli.cl_mgc_refcount)) {
- /* This is not fatal, every client that stops
- * will call in here.
- */
- CDEBUG(D_MOUNT, "mgc still has %d references.\n",
- atomic_read(&obd->u.cli.cl_mgc_refcount));
- rc = -EBUSY;
- goto out;
- }
-
- /* The MGC has no recoverable data in any case.
- * force shutdown set in umount_begin
- */
- obd->obd_no_recov = 1;
-
- if (obd->u.cli.cl_mgc_mgsexp) {
- /* An error is not fatal, if we are unable to send the
- * disconnect mgs ping evictor cleans up the export
- */
- rc = obd_disconnect(obd->u.cli.cl_mgc_mgsexp);
- if (rc)
- CDEBUG(D_MOUNT, "disconnect failed %d\n", rc);
- }
-
- /* Save the obdname for cleaning the nid uuids, which are obdname_XX */
- len = strlen(obd->obd_name) + 6;
- niduuid = kzalloc(len, GFP_NOFS);
- if (niduuid) {
- strcpy(niduuid, obd->obd_name);
- ptr = niduuid + strlen(niduuid);
- }
-
- rc = class_manual_cleanup(obd);
- if (rc)
- goto out;
-
- /* Clean the nid uuids */
- if (!niduuid) {
- rc = -ENOMEM;
- goto out;
- }
-
- for (i = 0; i < lsi->lsi_lmd->lmd_mgs_failnodes; i++) {
- sprintf(ptr, "_%x", i);
- rc = do_lcfg(LUSTRE_MGC_OBDNAME, 0, LCFG_DEL_UUID,
- niduuid, NULL, NULL, NULL);
- if (rc)
- CERROR("del MDC UUID %s failed: rc = %d\n",
- niduuid, rc);
- }
-out:
- kfree(niduuid);
-
- /* class_import_put will get rid of the additional connections */
- mutex_unlock(&mgc_start_lock);
- return rc;
-}
-
-/***************** lustre superblock **************/
-
-static struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
-{
- struct lustre_sb_info *lsi;
-
- lsi = kzalloc(sizeof(*lsi), GFP_NOFS);
- if (!lsi)
- return NULL;
- lsi->lsi_lmd = kzalloc(sizeof(*lsi->lsi_lmd), GFP_NOFS);
- if (!lsi->lsi_lmd) {
- kfree(lsi);
- return NULL;
- }
-
- lsi->lsi_lmd->lmd_exclude_count = 0;
- lsi->lsi_lmd->lmd_recovery_time_soft = 0;
- lsi->lsi_lmd->lmd_recovery_time_hard = 0;
- s2lsi_nocast(sb) = lsi;
- /* we take 1 extra ref for our setup */
- atomic_set(&lsi->lsi_mounts, 1);
-
- /* Default umount style */
- lsi->lsi_flags = LSI_UMOUNT_FAILOVER;
-
- return lsi;
-}
-
-static int lustre_free_lsi(struct super_block *sb)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
-
- CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi);
-
- /* someone didn't call server_put_mount. */
- LASSERT(atomic_read(&lsi->lsi_mounts) == 0);
-
- if (lsi->lsi_lmd) {
- kfree(lsi->lsi_lmd->lmd_dev);
- kfree(lsi->lsi_lmd->lmd_profile);
- kfree(lsi->lsi_lmd->lmd_mgssec);
- kfree(lsi->lsi_lmd->lmd_opts);
- if (lsi->lsi_lmd->lmd_exclude_count)
- kfree(lsi->lsi_lmd->lmd_exclude);
- kfree(lsi->lsi_lmd->lmd_mgs);
- kfree(lsi->lsi_lmd->lmd_osd_type);
- kfree(lsi->lsi_lmd->lmd_params);
-
- kfree(lsi->lsi_lmd);
- }
-
- LASSERT(!lsi->lsi_llsbi);
- kfree(lsi);
- s2lsi_nocast(sb) = NULL;
-
- return 0;
-}
-
-/* The lsi has one reference for every server that is using the disk -
- * e.g. MDT, MGS, and potentially MGC
- */
-static int lustre_put_lsi(struct super_block *sb)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
-
- CDEBUG(D_MOUNT, "put %p %d\n", sb, atomic_read(&lsi->lsi_mounts));
- if (atomic_dec_and_test(&lsi->lsi_mounts)) {
- lustre_free_lsi(sb);
- return 1;
- }
- return 0;
-}
-
-/*** SERVER NAME ***
- * <FSNAME><SEPARATOR><TYPE><INDEX>
- * FSNAME is between 1 and 8 characters (inclusive).
- * Excluded characters are '/' and ':'
- * SEPARATOR is either ':' or '-'
- * TYPE: "OST", "MDT", etc.
- * INDEX: Hex representation of the index
- */
-
-/** Get the fsname ("lustre") from the server name ("lustre-OST003F").
- * @param [in] svname server name including type and index
- * @param [out] fsname Buffer to copy filesystem name prefix into.
- * Must have at least 'strlen(fsname) + 1' chars.
- * @param [out] endptr if endptr isn't NULL it is set to end of fsname
- * rc < 0 on error
- */
-static int server_name2fsname(const char *svname, char *fsname,
- const char **endptr)
-{
- const char *dash;
-
- dash = svname + strnlen(svname, 8); /* max fsname length is 8 */
- for (; dash > svname && *dash != '-' && *dash != ':'; dash--)
- ;
- if (dash == svname)
- return -EINVAL;
-
- if (fsname) {
- strncpy(fsname, svname, dash - svname);
- fsname[dash - svname] = '\0';
- }
-
- if (endptr)
- *endptr = dash;
-
- return 0;
-}
-
-/* Get the index from the obd name.
- * rc = server type, or
- * rc < 0 on error
- * if endptr isn't NULL it is set to end of name
- */
-static int server_name2index(const char *svname, __u32 *idx,
- const char **endptr)
-{
- unsigned long index;
- int rc;
- const char *dash;
-
- /* We use server_name2fsname() just for parsing */
- rc = server_name2fsname(svname, NULL, &dash);
- if (rc != 0)
- return rc;
-
- dash++;
-
- if (strncmp(dash, "MDT", 3) == 0)
- rc = LDD_F_SV_TYPE_MDT;
- else if (strncmp(dash, "OST", 3) == 0)
- rc = LDD_F_SV_TYPE_OST;
- else
- return -EINVAL;
-
- dash += 3;
-
- if (strncmp(dash, "all", 3) == 0) {
- if (endptr)
- *endptr = dash + 3;
- return rc | LDD_F_SV_ALL;
- }
-
- index = simple_strtoul(dash, (char **)endptr, 16);
- if (idx)
- *idx = index;
-
- /* Account for -mdc after index that is possible when specifying mdt */
- if (endptr && strncmp(LUSTRE_MDC_NAME, *endptr + 1,
- sizeof(LUSTRE_MDC_NAME) - 1) == 0)
- *endptr += sizeof(LUSTRE_MDC_NAME);
-
- return rc;
-}
-
-/*************** mount common between server and client ***************/
-
-/* Common umount */
-int lustre_common_put_super(struct super_block *sb)
-{
- int rc;
-
- CDEBUG(D_MOUNT, "dropping sb %p\n", sb);
-
- /* Drop a ref to the MGC */
- rc = lustre_stop_mgc(sb);
- if (rc && (rc != -ENOENT)) {
- if (rc != -EBUSY) {
- CERROR("Can't stop MGC: %d\n", rc);
- return rc;
- }
- /* BUSY just means that there's some other obd that
- * needs the mgc. Let him clean it up.
- */
- CDEBUG(D_MOUNT, "MGC still in use\n");
- }
- /* Drop a ref to the mounted disk */
- lustre_put_lsi(sb);
- return rc;
-}
-EXPORT_SYMBOL(lustre_common_put_super);
-
-static void lmd_print(struct lustre_mount_data *lmd)
-{
- int i;
-
- PRINT_CMD(D_MOUNT, " mount data:\n");
- if (lmd_is_client(lmd))
- PRINT_CMD(D_MOUNT, "profile: %s\n", lmd->lmd_profile);
- PRINT_CMD(D_MOUNT, "device: %s\n", lmd->lmd_dev);
- PRINT_CMD(D_MOUNT, "flags: %x\n", lmd->lmd_flags);
-
- if (lmd->lmd_opts)
- PRINT_CMD(D_MOUNT, "options: %s\n", lmd->lmd_opts);
-
- if (lmd->lmd_recovery_time_soft)
- PRINT_CMD(D_MOUNT, "recovery time soft: %d\n",
- lmd->lmd_recovery_time_soft);
-
- if (lmd->lmd_recovery_time_hard)
- PRINT_CMD(D_MOUNT, "recovery time hard: %d\n",
- lmd->lmd_recovery_time_hard);
-
- for (i = 0; i < lmd->lmd_exclude_count; i++) {
- PRINT_CMD(D_MOUNT, "exclude %d: OST%04x\n", i,
- lmd->lmd_exclude[i]);
- }
-}
-
-/* Is this server on the exclusion list */
-int lustre_check_exclusion(struct super_block *sb, char *svname)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
- struct lustre_mount_data *lmd = lsi->lsi_lmd;
- __u32 index;
- int i, rc;
-
- rc = server_name2index(svname, &index, NULL);
- if (rc != LDD_F_SV_TYPE_OST)
- /* Only exclude OSTs */
- return 0;
-
- CDEBUG(D_MOUNT, "Check exclusion %s (%d) in %d of %s\n", svname,
- index, lmd->lmd_exclude_count, lmd->lmd_dev);
-
- for (i = 0; i < lmd->lmd_exclude_count; i++) {
- if (index == lmd->lmd_exclude[i]) {
- CWARN("Excluding %s (on exclusion list)\n", svname);
- return 1;
- }
- }
- return 0;
-}
-
-/* mount -v -o exclude=lustre-OST0001:lustre-OST0002 -t lustre ... */
-static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr)
-{
- const char *s1 = ptr, *s2;
- __u32 index = 0, *exclude_list;
- int rc = 0, devmax;
-
- /* The shortest an ost name can be is 8 chars: -OST0000.
- * We don't actually know the fsname at this time, so in fact
- * a user could specify any fsname.
- */
- devmax = strlen(ptr) / 8 + 1;
-
- /* temp storage until we figure out how many we have */
- exclude_list = kcalloc(devmax, sizeof(index), GFP_NOFS);
- if (!exclude_list)
- return -ENOMEM;
-
- /* we enter this fn pointing at the '=' */
- while (*s1 && *s1 != ' ' && *s1 != ',') {
- s1++;
- rc = server_name2index(s1, &index, &s2);
- if (rc < 0) {
- CERROR("Can't parse server name '%s': rc = %d\n",
- s1, rc);
- break;
- }
- if (rc == LDD_F_SV_TYPE_OST)
- exclude_list[lmd->lmd_exclude_count++] = index;
- else
- CDEBUG(D_MOUNT, "ignoring exclude %.*s: type = %#x\n",
- (uint)(s2 - s1), s1, rc);
- s1 = s2;
- /* now we are pointing at ':' (next exclude)
- * or ',' (end of excludes)
- */
- if (lmd->lmd_exclude_count >= devmax)
- break;
- }
- if (rc >= 0) /* non-err */
- rc = 0;
-
- if (lmd->lmd_exclude_count) {
- /* permanent, freed in lustre_free_lsi */
- lmd->lmd_exclude = kcalloc(lmd->lmd_exclude_count,
- sizeof(index), GFP_NOFS);
- if (lmd->lmd_exclude) {
- memcpy(lmd->lmd_exclude, exclude_list,
- sizeof(index) * lmd->lmd_exclude_count);
- } else {
- rc = -ENOMEM;
- lmd->lmd_exclude_count = 0;
- }
- }
- kfree(exclude_list);
- return rc;
-}
-
-static int lmd_parse_mgssec(struct lustre_mount_data *lmd, char *ptr)
-{
- char *tail;
- int length;
-
- kfree(lmd->lmd_mgssec);
- lmd->lmd_mgssec = NULL;
-
- tail = strchr(ptr, ',');
- if (!tail)
- length = strlen(ptr);
- else
- length = tail - ptr;
-
- lmd->lmd_mgssec = kzalloc(length + 1, GFP_NOFS);
- if (!lmd->lmd_mgssec)
- return -ENOMEM;
-
- memcpy(lmd->lmd_mgssec, ptr, length);
- lmd->lmd_mgssec[length] = '\0';
- return 0;
-}
-
-static int lmd_parse_string(char **handle, char *ptr)
-{
- char *tail;
- int length;
-
- if (!handle || !ptr)
- return -EINVAL;
-
- kfree(*handle);
- *handle = NULL;
-
- tail = strchr(ptr, ',');
- if (!tail)
- length = strlen(ptr);
- else
- length = tail - ptr;
-
- *handle = kzalloc(length + 1, GFP_NOFS);
- if (!*handle)
- return -ENOMEM;
-
- memcpy(*handle, ptr, length);
- (*handle)[length] = '\0';
-
- return 0;
-}
-
-/* Collect multiple values for mgsnid specifiers */
-static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr)
-{
- lnet_nid_t nid;
- char *tail = *ptr;
- char *mgsnid;
- int length;
- int oldlen = 0;
-
- /* Find end of nidlist */
- while (class_parse_nid_quiet(tail, &nid, &tail) == 0)
- ;
- length = tail - *ptr;
- if (length == 0) {
- LCONSOLE_ERROR_MSG(0x159, "Can't parse NID '%s'\n", *ptr);
- return -EINVAL;
- }
-
- if (lmd->lmd_mgs)
- oldlen = strlen(lmd->lmd_mgs) + 1;
-
- mgsnid = kzalloc(oldlen + length + 1, GFP_NOFS);
- if (!mgsnid)
- return -ENOMEM;
-
- if (lmd->lmd_mgs) {
- /* Multiple mgsnid= are taken to mean failover locations */
- memcpy(mgsnid, lmd->lmd_mgs, oldlen);
- mgsnid[oldlen - 1] = ':';
- kfree(lmd->lmd_mgs);
- }
- memcpy(mgsnid + oldlen, *ptr, length);
- mgsnid[oldlen + length] = '\0';
- lmd->lmd_mgs = mgsnid;
- *ptr = tail;
-
- return 0;
-}
-
-/** Parse mount line options
- * e.g. mount -v -t lustre -o abort_recov uml1:uml2:/lustre-client /mnt/lustre
- * dev is passed as device=uml1:/lustre by mount.lustre
- */
-static int lmd_parse(char *options, struct lustre_mount_data *lmd)
-{
- char *s1, *s2, *devname = NULL;
- struct lustre_mount_data *raw = (struct lustre_mount_data *)options;
- int rc = 0;
-
- LASSERT(lmd);
- if (!options) {
- LCONSOLE_ERROR_MSG(0x162, "Missing mount data: check that /sbin/mount.lustre is installed.\n");
- return -EINVAL;
- }
-
- /* Options should be a string - try to detect old lmd data */
- if ((raw->lmd_magic & 0xffffff00) == (LMD_MAGIC & 0xffffff00)) {
- LCONSOLE_ERROR_MSG(0x163, "You're using an old version of /sbin/mount.lustre. Please install version %s\n",
- LUSTRE_VERSION_STRING);
- return -EINVAL;
- }
- lmd->lmd_magic = LMD_MAGIC;
-
- lmd->lmd_params = kzalloc(LMD_PARAMS_MAXLEN, GFP_NOFS);
- if (!lmd->lmd_params)
- return -ENOMEM;
- lmd->lmd_params[0] = '\0';
-
- /* Set default flags here */
-
- s1 = options;
- while (*s1) {
- int clear = 0;
- int time_min = OBD_RECOVERY_TIME_MIN;
- char *s3;
-
- /* Skip whitespace and extra commas */
- while (*s1 == ' ' || *s1 == ',')
- s1++;
- s3 = s1;
-
- /* Client options are parsed in ll_options: eg. flock,
- * user_xattr, acl
- */
-
- /* Parse non-ldiskfs options here. Rather than modifying
- * ldiskfs, we just zero these out here
- */
- if (strncmp(s1, "abort_recov", 11) == 0) {
- lmd->lmd_flags |= LMD_FLG_ABORT_RECOV;
- clear++;
- } else if (strncmp(s1, "recovery_time_soft=", 19) == 0) {
- lmd->lmd_recovery_time_soft = max_t(int,
- simple_strtoul(s1 + 19, NULL, 10), time_min);
- clear++;
- } else if (strncmp(s1, "recovery_time_hard=", 19) == 0) {
- lmd->lmd_recovery_time_hard = max_t(int,
- simple_strtoul(s1 + 19, NULL, 10), time_min);
- clear++;
- } else if (strncmp(s1, "noir", 4) == 0) {
- lmd->lmd_flags |= LMD_FLG_NOIR; /* test purpose only. */
- clear++;
- } else if (strncmp(s1, "nosvc", 5) == 0) {
- lmd->lmd_flags |= LMD_FLG_NOSVC;
- clear++;
- } else if (strncmp(s1, "nomgs", 5) == 0) {
- lmd->lmd_flags |= LMD_FLG_NOMGS;
- clear++;
- } else if (strncmp(s1, "noscrub", 7) == 0) {
- lmd->lmd_flags |= LMD_FLG_NOSCRUB;
- clear++;
- } else if (strncmp(s1, PARAM_MGSNODE,
- sizeof(PARAM_MGSNODE) - 1) == 0) {
- s2 = s1 + sizeof(PARAM_MGSNODE) - 1;
- /* Assume the next mount opt is the first
- * invalid nid we get to.
- */
- rc = lmd_parse_mgs(lmd, &s2);
- if (rc)
- goto invalid;
- clear++;
- } else if (strncmp(s1, "writeconf", 9) == 0) {
- lmd->lmd_flags |= LMD_FLG_WRITECONF;
- clear++;
- } else if (strncmp(s1, "update", 6) == 0) {
- lmd->lmd_flags |= LMD_FLG_UPDATE;
- clear++;
- } else if (strncmp(s1, "virgin", 6) == 0) {
- lmd->lmd_flags |= LMD_FLG_VIRGIN;
- clear++;
- } else if (strncmp(s1, "noprimnode", 10) == 0) {
- lmd->lmd_flags |= LMD_FLG_NO_PRIMNODE;
- clear++;
- } else if (strncmp(s1, "mgssec=", 7) == 0) {
- rc = lmd_parse_mgssec(lmd, s1 + 7);
- if (rc)
- goto invalid;
- s3 = s2;
- clear++;
- /* ost exclusion list */
- } else if (strncmp(s1, "exclude=", 8) == 0) {
- rc = lmd_make_exclusion(lmd, s1 + 7);
- if (rc)
- goto invalid;
- clear++;
- } else if (strncmp(s1, "mgs", 3) == 0) {
- /* We are an MGS */
- lmd->lmd_flags |= LMD_FLG_MGS;
- clear++;
- } else if (strncmp(s1, "svname=", 7) == 0) {
- rc = lmd_parse_string(&lmd->lmd_profile, s1 + 7);
- if (rc)
- goto invalid;
- clear++;
- } else if (strncmp(s1, "param=", 6) == 0) {
- size_t length, params_length;
- char *tail = strchr(s1 + 6, ',');
-
- if (!tail) {
- length = strlen(s1);
- } else {
- lnet_nid_t nid;
- char *param_str = tail + 1;
- int supplementary = 1;
-
- while (!class_parse_nid_quiet(param_str, &nid,
- &param_str)) {
- supplementary = 0;
- }
- length = param_str - s1 - supplementary;
- }
- length -= 6;
- params_length = strlen(lmd->lmd_params);
- if (params_length + length + 1 >= LMD_PARAMS_MAXLEN)
- return -E2BIG;
- strncat(lmd->lmd_params, s1 + 6, length);
- lmd->lmd_params[params_length + length] = '\0';
- strlcat(lmd->lmd_params, " ", LMD_PARAMS_MAXLEN);
- s3 = s1 + 6 + length;
- clear++;
- } else if (strncmp(s1, "osd=", 4) == 0) {
- rc = lmd_parse_string(&lmd->lmd_osd_type, s1 + 4);
- if (rc)
- goto invalid;
- clear++;
- }
- /* Linux 2.4 doesn't pass the device, so we stuck it at the
- * end of the options.
- */
- else if (strncmp(s1, "device=", 7) == 0) {
- devname = s1 + 7;
- /* terminate options right before device. device
- * must be the last one.
- */
- *s1 = '\0';
- break;
- }
-
- /* Find next opt */
- s2 = strchr(s1, ',');
- if (!s2) {
- if (clear)
- *s1 = '\0';
- break;
- }
- s2++;
- if (clear)
- memmove(s1, s2, strlen(s2) + 1);
- else
- s1 = s2;
- }
-
- if (!devname) {
- LCONSOLE_ERROR_MSG(0x164, "Can't find the device name (need mount option 'device=...')\n");
- goto invalid;
- }
-
- s1 = strstr(devname, ":/");
- if (s1) {
- ++s1;
- lmd->lmd_flags |= LMD_FLG_CLIENT;
- /* Remove leading /s from fsname */
- while (*++s1 == '/')
- ;
- /* Freed in lustre_free_lsi */
- lmd->lmd_profile = kasprintf(GFP_NOFS, "%s-client", s1);
- if (!lmd->lmd_profile)
- return -ENOMEM;
- }
-
- /* Freed in lustre_free_lsi */
- lmd->lmd_dev = kzalloc(strlen(devname) + 1, GFP_NOFS);
- if (!lmd->lmd_dev)
- return -ENOMEM;
- strcpy(lmd->lmd_dev, devname);
-
- /* Save mount options */
- s1 = options + strlen(options) - 1;
- while (s1 >= options && (*s1 == ',' || *s1 == ' '))
- *s1-- = 0;
- if (*options != 0) {
- /* Freed in lustre_free_lsi */
- lmd->lmd_opts = kzalloc(strlen(options) + 1, GFP_NOFS);
- if (!lmd->lmd_opts)
- return -ENOMEM;
- strcpy(lmd->lmd_opts, options);
- }
-
- lmd_print(lmd);
- lmd->lmd_magic = LMD_MAGIC;
-
- return rc;
-
-invalid:
- CERROR("Bad mount options %s\n", options);
- return -EINVAL;
-}
-
-/** This is the entry point for the mount call into Lustre.
- * This is called when a server or client is mounted,
- * and this is where we start setting things up.
- * @param data Mount options (e.g. -o flock,abort_recov)
- */
-static int lustre_fill_super(struct super_block *sb, void *lmd2_data, int silent)
-{
- struct lustre_mount_data *lmd;
- struct lustre_sb_info *lsi;
- int rc;
-
- CDEBUG(D_MOUNT | D_VFSTRACE, "VFS Op: sb %p\n", sb);
-
- lsi = lustre_init_lsi(sb);
- if (!lsi)
- return -ENOMEM;
- lmd = lsi->lsi_lmd;
-
- /*
- * Disable lockdep during mount, because mount locking patterns are
- * `special'.
- */
- lockdep_off();
-
- /*
- * LU-639: the obd cleanup of last mount may not finish yet, wait here.
- */
- obd_zombie_barrier();
-
- /* Figure out the lmd from the mount options */
- if (lmd_parse(lmd2_data, lmd)) {
- lustre_put_lsi(sb);
- rc = -EINVAL;
- goto out;
- }
-
- if (lmd_is_client(lmd)) {
- bool have_client = false;
- CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
- if (!client_fill_super)
- request_module("lustre");
- spin_lock(&client_lock);
- if (client_fill_super && try_module_get(client_mod))
- have_client = true;
- spin_unlock(&client_lock);
- if (!have_client) {
- LCONSOLE_ERROR_MSG(0x165, "Nothing registered for client mount! Is the 'lustre' module loaded?\n");
- lustre_put_lsi(sb);
- rc = -ENODEV;
- } else {
- rc = lustre_start_mgc(sb);
- if (rc) {
- lustre_common_put_super(sb);
- goto out;
- }
- /* Connect and start */
- /* (should always be ll_fill_super) */
- rc = (*client_fill_super)(sb);
- /* c_f_s will call lustre_common_put_super on failure, otherwise
- * c_f_s will have taken another reference to the module */
- module_put(client_mod);
- }
- } else {
- CERROR("This is client-side-only module, cannot handle server mount.\n");
- rc = -EINVAL;
- }
-
- /* If error happens in fill_super() call, @lsi will be killed there.
- * This is why we do not put it here.
- */
- goto out;
-out:
- if (rc) {
- CERROR("Unable to mount %s (%d)\n",
- s2lsi(sb) ? lmd->lmd_dev : "", rc);
- } else {
- CDEBUG(D_SUPER, "Mount %s complete\n",
- lmd->lmd_dev);
- }
- lockdep_on();
- return rc;
-}
-
-/* We can't call ll_fill_super by name because it lives in a module that
- * must be loaded after this one.
- */
-void lustre_register_super_ops(struct module *mod,
- int (*cfs)(struct super_block *sb),
- void (*ksc)(struct super_block *sb))
-{
- spin_lock(&client_lock);
- client_mod = mod;
- client_fill_super = cfs;
- kill_super_cb = ksc;
- spin_unlock(&client_lock);
-}
-EXPORT_SYMBOL(lustre_register_super_ops);
-
-/***************** FS registration ******************/
-static struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
- const char *devname, void *data)
-{
- return mount_nodev(fs_type, flags, data, lustre_fill_super);
-}
-
-static void lustre_kill_super(struct super_block *sb)
-{
- struct lustre_sb_info *lsi = s2lsi(sb);
-
- if (kill_super_cb && lsi)
- (*kill_super_cb)(sb);
-
- kill_anon_super(sb);
-}
-
-/** Register the "lustre" fs type
- */
-static struct file_system_type lustre_fs_type = {
- .owner = THIS_MODULE,
- .name = "lustre",
- .mount = lustre_mount,
- .kill_sb = lustre_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE,
-};
-MODULE_ALIAS_FS("lustre");
-
-int lustre_register_fs(void)
-{
- return register_filesystem(&lustre_fs_type);
-}
-
-int lustre_unregister_fs(void)
-{
- return unregister_filesystem(&lustre_fs_type);
-}
diff --git a/drivers/staging/lustre/lustre/obdclass/obdo.c b/drivers/staging/lustre/lustre/obdclass/obdo.c
deleted file mode 100644
index c4503bc36591..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/obdo.c
+++ /dev/null
@@ -1,181 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/obdo.c
- *
- * Object Devices Class Driver
- * These are the only exported functions, they provide some generic
- * infrastructure for managing object devices
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <obd_class.h>
-#include <uapi/linux/lustre/lustre_idl.h>
-#include <lustre_obdo.h>
-
-void obdo_set_parent_fid(struct obdo *dst, const struct lu_fid *parent)
-{
- dst->o_parent_oid = fid_oid(parent);
- dst->o_parent_seq = fid_seq(parent);
- dst->o_parent_ver = fid_ver(parent);
- dst->o_valid |= OBD_MD_FLGENER | OBD_MD_FLFID;
-}
-EXPORT_SYMBOL(obdo_set_parent_fid);
-
-/* WARNING: the file systems must take care not to tinker with
- * attributes they don't manage (such as blocks).
- */
-void obdo_from_inode(struct obdo *dst, struct inode *src, u32 valid)
-{
- u32 newvalid = 0;
-
- if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
- CDEBUG(D_INODE, "valid %x, new time %lu/%lu\n",
- valid, LTIME_S(src->i_mtime),
- LTIME_S(src->i_ctime));
-
- if (valid & OBD_MD_FLATIME) {
- dst->o_atime = LTIME_S(src->i_atime);
- newvalid |= OBD_MD_FLATIME;
- }
- if (valid & OBD_MD_FLMTIME) {
- dst->o_mtime = LTIME_S(src->i_mtime);
- newvalid |= OBD_MD_FLMTIME;
- }
- if (valid & OBD_MD_FLCTIME) {
- dst->o_ctime = LTIME_S(src->i_ctime);
- newvalid |= OBD_MD_FLCTIME;
- }
- if (valid & OBD_MD_FLSIZE) {
- dst->o_size = i_size_read(src);
- newvalid |= OBD_MD_FLSIZE;
- }
- if (valid & OBD_MD_FLBLOCKS) { /* allocation of space (x512 bytes) */
- dst->o_blocks = src->i_blocks;
- newvalid |= OBD_MD_FLBLOCKS;
- }
- if (valid & OBD_MD_FLBLKSZ) { /* optimal block size */
- dst->o_blksize = 1 << src->i_blkbits;
- newvalid |= OBD_MD_FLBLKSZ;
- }
- if (valid & OBD_MD_FLTYPE) {
- dst->o_mode = (dst->o_mode & S_IALLUGO) |
- (src->i_mode & S_IFMT);
- newvalid |= OBD_MD_FLTYPE;
- }
- if (valid & OBD_MD_FLMODE) {
- dst->o_mode = (dst->o_mode & S_IFMT) |
- (src->i_mode & S_IALLUGO);
- newvalid |= OBD_MD_FLMODE;
- }
- if (valid & OBD_MD_FLUID) {
- dst->o_uid = from_kuid(&init_user_ns, src->i_uid);
- newvalid |= OBD_MD_FLUID;
- }
- if (valid & OBD_MD_FLGID) {
- dst->o_gid = from_kgid(&init_user_ns, src->i_gid);
- newvalid |= OBD_MD_FLGID;
- }
- if (valid & OBD_MD_FLFLAGS) {
- dst->o_flags = src->i_flags;
- newvalid |= OBD_MD_FLFLAGS;
- }
- dst->o_valid |= newvalid;
-}
-EXPORT_SYMBOL(obdo_from_inode);
-
-void obdo_to_ioobj(const struct obdo *oa, struct obd_ioobj *ioobj)
-{
- ioobj->ioo_oid = oa->o_oi;
- if (unlikely(!(oa->o_valid & OBD_MD_FLGROUP)))
- ostid_set_seq_mdt0(&ioobj->ioo_oid);
-
- /* Since 2.4 this does not contain o_mode in the low 16 bits.
- * Instead, it holds (bd_md_max_brw - 1) for multi-bulk BRW RPCs
- */
- ioobj->ioo_max_brw = 0;
-}
-EXPORT_SYMBOL(obdo_to_ioobj);
-
-/**
- * Create an obdo to send over the wire
- */
-void lustre_set_wire_obdo(const struct obd_connect_data *ocd,
- struct obdo *wobdo, const struct obdo *lobdo)
-{
- *wobdo = *lobdo;
- wobdo->o_flags &= ~OBD_FL_LOCAL_MASK;
- if (!ocd)
- return;
-
- if (unlikely(!(ocd->ocd_connect_flags & OBD_CONNECT_FID)) &&
- fid_seq_is_echo(ostid_seq(&lobdo->o_oi))) {
- /*
- * Currently OBD_FL_OSTID will only be used when 2.4 echo
- * client communicate with pre-2.4 server
- */
- wobdo->o_oi.oi.oi_id = fid_oid(&lobdo->o_oi.oi_fid);
- wobdo->o_oi.oi.oi_seq = fid_seq(&lobdo->o_oi.oi_fid);
- }
-}
-EXPORT_SYMBOL(lustre_set_wire_obdo);
-
-/**
- * Create a local obdo from a wire based odbo
- */
-void lustre_get_wire_obdo(const struct obd_connect_data *ocd,
- struct obdo *lobdo, const struct obdo *wobdo)
-{
- u32 local_flags = 0;
-
- if (lobdo->o_valid & OBD_MD_FLFLAGS)
- local_flags = lobdo->o_flags & OBD_FL_LOCAL_MASK;
-
- *lobdo = *wobdo;
- if (local_flags) {
- lobdo->o_valid |= OBD_MD_FLFLAGS;
- lobdo->o_flags &= ~OBD_FL_LOCAL_MASK;
- lobdo->o_flags |= local_flags;
- }
- if (!ocd)
- return;
-
- if (unlikely(!(ocd->ocd_connect_flags & OBD_CONNECT_FID)) &&
- fid_seq_is_echo(wobdo->o_oi.oi.oi_seq)) {
- /* see above */
- lobdo->o_oi.oi_fid.f_seq = wobdo->o_oi.oi.oi_seq;
- lobdo->o_oi.oi_fid.f_oid = wobdo->o_oi.oi.oi_id;
- lobdo->o_oi.oi_fid.f_ver = 0;
- }
-}
-EXPORT_SYMBOL(lustre_get_wire_obdo);
diff --git a/drivers/staging/lustre/lustre/obdclass/statfs_pack.c b/drivers/staging/lustre/lustre/obdclass/statfs_pack.c
deleted file mode 100644
index 355e888885f4..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/statfs_pack.c
+++ /dev/null
@@ -1,58 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/statfs_pack.c
- *
- * (Un)packing of OST/MDS requests
- *
- * Author: Andreas Dilger <adilger@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/statfs.h>
-#include <lustre_export.h>
-#include <lustre_net.h>
-#include <obd_support.h>
-#include <obd_class.h>
-
-void statfs_unpack(struct kstatfs *sfs, struct obd_statfs *osfs)
-{
- memset(sfs, 0, sizeof(*sfs));
- sfs->f_type = osfs->os_type;
- sfs->f_blocks = osfs->os_blocks;
- sfs->f_bfree = osfs->os_bfree;
- sfs->f_bavail = osfs->os_bavail;
- sfs->f_files = osfs->os_files;
- sfs->f_ffree = osfs->os_ffree;
- sfs->f_bsize = osfs->os_bsize;
- sfs->f_namelen = osfs->os_namelen;
-}
-EXPORT_SYMBOL(statfs_unpack);
diff --git a/drivers/staging/lustre/lustre/obdclass/uuid.c b/drivers/staging/lustre/lustre/obdclass/uuid.c
deleted file mode 100644
index 6cf7a03f048f..000000000000
--- a/drivers/staging/lustre/lustre/obdclass/uuid.c
+++ /dev/null
@@ -1,47 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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
- */
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lustre/obdclass/uuid.c
- *
- * Public include file for the UUID library
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/libcfs/libcfs.h>
-
-#include <obd_support.h>
-#include <obd_class.h>
-
-void class_uuid_unparse(class_uuid_t uu, struct obd_uuid *out)
-{
- sprintf(out->uuid, "%pU", uu);
-}
-EXPORT_SYMBOL(class_uuid_unparse);