*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * 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, 2013, Intel Corporation.
+ * Copyright (c) 2011, 2017, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#define DEBUG_SUBSYSTEM S_CLASS
-#include <obd.h>
+#include <linux/list.h>
+#include <obd_class.h>
#include <dt_object.h>
-#include <libcfs/list.h>
/* fid_be_to_cpu() */
#include <lustre_fid.h>
-
+#include <lustre_nodemap.h>
#include <lustre_quota.h>
+#include <lustre_lfsck.h>
/* context key constructor/destructor: dt_global_key_init, dt_global_key_fini */
LU_KEY_INIT(dt_global, struct dt_thread_info);
LU_KEY_FINI(dt_global, struct dt_thread_info);
struct lu_context_key dt_key = {
- .lct_tags = LCT_MD_THREAD | LCT_DT_THREAD | LCT_MG_THREAD | LCT_LOCAL,
- .lct_init = dt_global_key_init,
- .lct_fini = dt_global_key_fini
+ .lct_tags = LCT_MD_THREAD | LCT_DT_THREAD | LCT_MG_THREAD | LCT_LOCAL,
+ .lct_init = dt_global_key_init,
+ .lct_fini = dt_global_key_fini
};
-EXPORT_SYMBOL(dt_key);
-/* no lock is necessary to protect the list, because call-backs
+/*
+ * no lock is necessary to protect the list, because call-backs
* are added during system startup. Please refer to "struct dt_device".
*/
void dt_txn_callback_add(struct dt_device *dev, struct dt_txn_callback *cb)
EXPORT_SYMBOL(dt_txn_callback_del);
int dt_txn_hook_start(const struct lu_env *env,
- struct dt_device *dev, struct thandle *th)
+ struct dt_device *dev, struct thandle *th)
{
- int rc = 0;
- struct dt_txn_callback *cb;
+ int rc = 0;
+ struct dt_txn_callback *cb;
- if (th->th_local)
- return 0;
+ if (th->th_local)
+ return 0;
list_for_each_entry(cb, &dev->dd_txn_callbacks, dtc_linkage) {
- if (cb->dtc_txn_start == NULL ||
- !(cb->dtc_tag & env->le_ctx.lc_tags))
- continue;
- rc = cb->dtc_txn_start(env, th, cb->dtc_cookie);
- if (rc < 0)
- break;
- }
- return rc;
+ struct thandle *dtc_th = th;
+
+ if (cb->dtc_txn_start == NULL ||
+ !(cb->dtc_tag & env->le_ctx.lc_tags))
+ continue;
+
+ /*
+ * Usually dt_txn_hook_start is called from bottom device,
+ * and if the thandle has th_top, then we need use top
+ * thandle for the callback in the top thandle layer
+ */
+ if (th->th_top != NULL)
+ dtc_th = th->th_top;
+
+ rc = cb->dtc_txn_start(env, dtc_th, cb->dtc_cookie);
+ if (rc < 0)
+ break;
+ }
+ return rc;
}
EXPORT_SYMBOL(dt_txn_hook_start);
-int dt_txn_hook_stop(const struct lu_env *env, struct thandle *txn)
+int dt_txn_hook_stop(const struct lu_env *env, struct thandle *th)
{
- struct dt_device *dev = txn->th_dev;
- struct dt_txn_callback *cb;
- int rc = 0;
+ struct dt_device *dev = th->th_dev;
+ struct dt_txn_callback *cb;
+ int rc = 0;
+
+ if (th->th_local)
+ return 0;
- if (txn->th_local)
- return 0;
+ if (OBD_FAIL_CHECK(OBD_FAIL_DT_TXN_STOP))
+ return -EIO;
list_for_each_entry(cb, &dev->dd_txn_callbacks, dtc_linkage) {
- if (cb->dtc_txn_stop == NULL ||
- !(cb->dtc_tag & env->le_ctx.lc_tags))
- continue;
- rc = cb->dtc_txn_stop(env, txn, cb->dtc_cookie);
- if (rc < 0)
- break;
- }
- return rc;
+ struct thandle *dtc_th = th;
+
+ if (cb->dtc_txn_stop == NULL ||
+ !(cb->dtc_tag & env->le_ctx.lc_tags))
+ continue;
+
+ /*
+ * Usually dt_txn_hook_stop is called from bottom device,
+ * and if the thandle has th_top, then we need use top
+ * thandle for the callback in the top thandle layer
+ */
+ if (th->th_top != NULL)
+ dtc_th = th->th_top;
+
+ rc = cb->dtc_txn_stop(env, dtc_th, cb->dtc_cookie);
+ if (rc < 0)
+ break;
+ }
+ return rc;
}
EXPORT_SYMBOL(dt_txn_hook_stop);
-void dt_txn_hook_commit(struct thandle *txn)
+void dt_txn_hook_commit(struct thandle *th)
{
struct dt_txn_callback *cb;
- if (txn->th_local)
+ if (th->th_local)
return;
- list_for_each_entry(cb, &txn->th_dev->dd_txn_callbacks,
+ list_for_each_entry(cb, &th->th_dev->dd_txn_callbacks,
dtc_linkage) {
+ /*
+ * Right now, the bottom device (OSD) will use this hook
+ * commit to notify OSP, so we do not check and replace
+ * the thandle to top thandle now
+ */
if (cb->dtc_txn_commit)
- cb->dtc_txn_commit(txn, cb->dtc_cookie);
+ cb->dtc_txn_commit(th, cb->dtc_cookie);
}
}
EXPORT_SYMBOL(dt_txn_hook_commit);
void dt_device_fini(struct dt_device *dev)
{
- lu_device_fini(&dev->dd_lu_dev);
+ lu_device_fini(&dev->dd_lu_dev);
}
EXPORT_SYMBOL(dt_device_fini);
int dt_object_init(struct dt_object *obj,
- struct lu_object_header *h, struct lu_device *d)
+ struct lu_object_header *h, struct lu_device *d)
{
- return lu_object_init(&obj->do_lu, h, d);
+ return lu_object_init(&obj->do_lu, h, d);
}
EXPORT_SYMBOL(dt_object_init);
void dt_object_fini(struct dt_object *obj)
{
- lu_object_fini(&obj->do_lu);
+ lu_object_fini(&obj->do_lu);
}
EXPORT_SYMBOL(dt_object_fini);
int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj)
{
- if (obj->do_index_ops == NULL)
- obj->do_ops->do_index_try(env, obj, &dt_directory_features);
- return obj->do_index_ops != NULL;
+ if (obj->do_index_ops == NULL)
+ obj->do_ops->do_index_try(env, obj, &dt_directory_features);
+ return obj->do_index_ops != NULL;
}
EXPORT_SYMBOL(dt_try_as_dir);
enum dt_format_type dt_mode_to_dft(__u32 mode)
{
- enum dt_format_type result;
-
- switch (mode & S_IFMT) {
- case S_IFDIR:
- result = DFT_DIR;
- break;
- case S_IFREG:
- result = DFT_REGULAR;
- break;
- case S_IFLNK:
- result = DFT_SYM;
- break;
- case S_IFCHR:
- case S_IFBLK:
- case S_IFIFO:
- case S_IFSOCK:
- result = DFT_NODE;
- break;
- default:
- LBUG();
- break;
- }
- return result;
+ enum dt_format_type result;
+
+ switch (mode & S_IFMT) {
+ case S_IFDIR:
+ result = DFT_DIR;
+ break;
+ case S_IFREG:
+ result = DFT_REGULAR;
+ break;
+ case S_IFLNK:
+ result = DFT_SYM;
+ break;
+ case S_IFCHR:
+ case S_IFBLK:
+ case S_IFIFO:
+ case S_IFSOCK:
+ result = DFT_NODE;
+ break;
+ default:
+ LASSERTF(0, "invalid mode %o\n", mode);
+ result = 0; /* Just for satisfying compiler. */
+ break;
+ }
+ return result;
}
EXPORT_SYMBOL(dt_mode_to_dft);
int dt_lookup_dir(const struct lu_env *env, struct dt_object *dir,
const char *name, struct lu_fid *fid)
{
- if (dt_try_as_dir(env, dir))
- return dt_lookup(env, dir, (struct dt_rec *)fid,
- (const struct dt_key *)name, BYPASS_CAPA);
- return -ENOTDIR;
+ if (dt_try_as_dir(env, dir))
+ return dt_lookup(env, dir, (struct dt_rec *)fid,
+ (const struct dt_key *)name);
+ return -ENOTDIR;
}
EXPORT_SYMBOL(dt_lookup_dir);
-/* this differs from dt_locate by top_dev as parameter
- * but not one from lu_site */
+/*
+ * this differs from dt_locate by top_dev as parameter
+ * but not one from lu_site
+ */
struct dt_object *dt_locate_at(const struct lu_env *env,
struct dt_device *dev,
const struct lu_fid *fid,
return container_of0(n, struct dt_object, do_lu);
}
+ lu_object_put(env, lo);
return ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL(dt_locate_at);
/**
- * find a object named \a entry in given \a dfh->dfh_o directory.
+ * find an object named \a entry in given \a dfh->dfh_o directory.
*/
-static int dt_find_entry(const struct lu_env *env, const char *entry, void *data)
+static int dt_find_entry(const struct lu_env *env, const char *entry,
+ void *data)
{
- struct dt_find_hint *dfh = data;
- struct dt_device *dt = dfh->dfh_dt;
- struct lu_fid *fid = dfh->dfh_fid;
- struct dt_object *obj = dfh->dfh_o;
- int result;
-
- result = dt_lookup_dir(env, obj, entry, fid);
- lu_object_put(env, &obj->do_lu);
- if (result == 0) {
- obj = dt_locate(env, dt, fid);
- if (IS_ERR(obj))
- result = PTR_ERR(obj);
- }
- dfh->dfh_o = obj;
- return result;
+ struct dt_find_hint *dfh = data;
+ struct dt_device *dt = dfh->dfh_dt;
+ struct lu_fid *fid = dfh->dfh_fid;
+ struct dt_object *obj = dfh->dfh_o;
+ int rc;
+
+ rc = dt_lookup_dir(env, obj, entry, fid);
+ dt_object_put(env, obj);
+ if (rc == 0) {
+ obj = dt_locate(env, dt, fid);
+ if (IS_ERR(obj))
+ rc = PTR_ERR(obj);
+ }
+ dfh->dfh_o = obj;
+
+ return rc;
}
/**
* path component to \a entry_func.
*/
int dt_path_parser(const struct lu_env *env,
- char *path, dt_entry_func_t entry_func,
- void *data)
+ char *path, dt_entry_func_t entry_func,
+ void *data)
{
- char *e;
- int rc = 0;
-
- while (1) {
- e = strsep(&path, "/");
- if (e == NULL)
- break;
-
- if (e[0] == 0) {
- if (!path || path[0] == '\0')
- break;
- continue;
- }
- rc = entry_func(env, e, data);
- if (rc)
- break;
- }
-
- return rc;
+ char *e;
+ int rc = 0;
+
+ while (1) {
+ e = strsep(&path, "/");
+ if (e == NULL)
+ break;
+
+ if (e[0] == 0) {
+ if (!path || path[0] == '\0')
+ break;
+ continue;
+ }
+ rc = entry_func(env, e, data);
+ if (rc)
+ break;
+ }
+
+ return rc;
}
struct dt_object *
const char *path, struct lu_fid *fid)
{
struct dt_thread_info *info = dt_info(env);
- struct dt_find_hint *dfh = &info->dti_dfh;
- struct dt_object *obj;
- int result;
+ struct dt_find_hint *dfh = &info->dti_dfh;
+ struct dt_object *obj;
+ int result;
- dfh->dfh_dt = dt;
- dfh->dfh_fid = fid;
+ dfh->dfh_dt = dt;
+ dfh->dfh_fid = fid;
strlcpy(info->dti_buf, path, sizeof(info->dti_buf));
- result = dt->dd_ops->dt_root_get(env, dt, fid);
- if (result == 0) {
- obj = dt_locate(env, dt, fid);
- if (!IS_ERR(obj)) {
- dfh->dfh_o = obj;
+ result = dt->dd_ops->dt_root_get(env, dt, fid);
+ if (result == 0) {
+ obj = dt_locate(env, dt, fid);
+ if (!IS_ERR(obj)) {
+ dfh->dfh_o = obj;
result = dt_path_parser(env, info->dti_buf,
dt_find_entry, dfh);
- if (result != 0)
- obj = ERR_PTR(result);
- else
- obj = dfh->dfh_o;
- }
- } else {
- obj = ERR_PTR(result);
- }
- return obj;
+ if (result != 0)
+ obj = ERR_PTR(result);
+ else
+ obj = dfh->dfh_o;
+ }
+ } else {
+ obj = ERR_PTR(result);
+ }
+ return obj;
}
-EXPORT_SYMBOL(dt_store_resolve);
static struct dt_object *dt_reg_open(const struct lu_env *env,
- struct dt_device *dt,
- struct dt_object *p,
- const char *name,
- struct lu_fid *fid)
+ struct dt_device *dt,
+ struct dt_object *p,
+ const char *name,
+ struct lu_fid *fid)
{
- struct dt_object *o;
- int result;
+ struct dt_object *o;
+ int result;
- result = dt_lookup_dir(env, p, name, fid);
- if (result == 0){
- o = dt_locate(env, dt, fid);
- }
- else
- o = ERR_PTR(result);
+ result = dt_lookup_dir(env, p, name, fid);
+ if (result == 0)
+ o = dt_locate(env, dt, fid);
+ else
+ o = ERR_PTR(result);
- return o;
+ return o;
}
/**
* \param dt dt device
* \param fid on success, object fid is stored in *fid
*/
-struct dt_object *dt_store_open(const struct lu_env *env,
- struct dt_device *dt,
- const char *dirname,
- const char *filename,
- struct lu_fid *fid)
+struct dt_object *dt_store_open(const struct lu_env *env, struct dt_device *dt,
+ const char *dirname, const char *filename,
+ struct lu_fid *fid)
{
- struct dt_object *file;
- struct dt_object *dir;
-
- dir = dt_store_resolve(env, dt, dirname, fid);
- if (!IS_ERR(dir)) {
- file = dt_reg_open(env, dt, dir,
- filename, fid);
- lu_object_put(env, &dir->do_lu);
- } else {
- file = dir;
- }
- return file;
+ struct dt_object *file;
+ struct dt_object *dir;
+
+ dir = dt_store_resolve(env, dt, dirname, fid);
+ if (!IS_ERR(dir)) {
+ file = dt_reg_open(env, dt, dir, filename, fid);
+ dt_object_put(env, dir);
+ } else {
+ file = dir;
+ }
+
+ return file;
}
-EXPORT_SYMBOL(dt_store_open);
struct dt_object *dt_find_or_create(const struct lu_env *env,
- struct dt_device *dt,
- const struct lu_fid *fid,
- struct dt_object_format *dof,
- struct lu_attr *at)
+ struct dt_device *dt,
+ const struct lu_fid *fid,
+ struct dt_object_format *dof,
+ struct lu_attr *at)
{
- struct dt_object *dto;
- struct thandle *th;
- int rc;
+ struct dt_object *dto;
+ struct thandle *th;
+ int rc;
- ENTRY;
+ ENTRY;
- dto = dt_locate(env, dt, fid);
- if (IS_ERR(dto))
- RETURN(dto);
+ dto = dt_locate(env, dt, fid);
+ if (IS_ERR(dto))
+ RETURN(dto);
- LASSERT(dto != NULL);
- if (dt_object_exists(dto))
- RETURN(dto);
+ LASSERT(dto != NULL);
+ if (dt_object_exists(dto))
+ RETURN(dto);
- th = dt_trans_create(env, dt);
- if (IS_ERR(th))
- GOTO(out, rc = PTR_ERR(th));
+ th = dt_trans_create(env, dt);
+ if (IS_ERR(th))
+ GOTO(out, rc = PTR_ERR(th));
- rc = dt_declare_create(env, dto, at, NULL, dof, th);
- if (rc)
- GOTO(trans_stop, rc);
+ rc = dt_declare_create(env, dto, at, NULL, dof, th);
+ if (rc)
+ GOTO(trans_stop, rc);
- rc = dt_trans_start_local(env, dt, th);
- if (rc)
- GOTO(trans_stop, rc);
+ rc = dt_trans_start_local(env, dt, th);
+ if (rc)
+ GOTO(trans_stop, rc);
- dt_write_lock(env, dto, 0);
- if (dt_object_exists(dto))
- GOTO(unlock, rc = 0);
+ dt_write_lock(env, dto, 0);
+ if (dt_object_exists(dto))
+ GOTO(unlock, rc = 0);
- CDEBUG(D_OTHER, "create new object "DFID"\n", PFID(fid));
+ CDEBUG(D_OTHER, "create new object "DFID"\n", PFID(fid));
- rc = dt_create(env, dto, at, NULL, dof, th);
- if (rc)
+ rc = dt_create(env, dto, at, NULL, dof, th);
+ if (rc)
GOTO(unlock, rc);
- LASSERT(dt_object_exists(dto));
+ LASSERT(dt_object_exists(dto));
unlock:
- dt_write_unlock(env, dto);
+ dt_write_unlock(env, dto);
trans_stop:
- dt_trans_stop(env, dt, th);
+ dt_trans_stop(env, dt, th);
out:
- if (rc) {
- lu_object_put(env, &dto->do_lu);
- RETURN(ERR_PTR(rc));
- }
- RETURN(dto);
+ if (rc) {
+ dt_object_put(env, dto);
+ dto = ERR_PTR(rc);
+ }
+
+ RETURN(dto);
}
EXPORT_SYMBOL(dt_find_or_create);
/* dt class init function. */
int dt_global_init(void)
{
- int result;
+ int result;
- LU_CONTEXT_KEY_INIT(&dt_key);
- result = lu_context_key_register(&dt_key);
- return result;
+ LU_CONTEXT_KEY_INIT(&dt_key);
+ result = lu_context_key_register(&dt_key);
+ return result;
}
void dt_global_fini(void)
{
- lu_context_key_degister(&dt_key);
+ lu_context_key_degister(&dt_key);
}
/**
* \retval -ve errno on failure
*/
int dt_read(const struct lu_env *env, struct dt_object *dt,
- struct lu_buf *buf, loff_t *pos)
+ struct lu_buf *buf, loff_t *pos)
{
- LASSERTF(dt != NULL, "dt is NULL when we want to read record\n");
- return dt->do_body_ops->dbo_read(env, dt, buf, pos, BYPASS_CAPA);
+ LASSERTF(dt != NULL, "dt is NULL when we want to read record\n");
+ return dt->do_body_ops->dbo_read(env, dt, buf, pos);
}
EXPORT_SYMBOL(dt_read);
int dt_record_read(const struct lu_env *env, struct dt_object *dt,
struct lu_buf *buf, loff_t *pos)
{
- int rc;
-
- LASSERTF(dt != NULL, "dt is NULL when we want to read record\n");
+ ssize_t size;
- rc = dt->do_body_ops->dbo_read(env, dt, buf, pos, BYPASS_CAPA);
+ LASSERTF(dt != NULL, "dt is NULL when we want to read record\n");
- if (rc == buf->lb_len)
- rc = 0;
- else if (rc >= 0)
- rc = -EFAULT;
- return rc;
+ size = dt->do_body_ops->dbo_read(env, dt, buf, pos);
+ if (size < 0)
+ return size;
+ return (size == (ssize_t)buf->lb_len) ? 0 : -EFAULT;
}
EXPORT_SYMBOL(dt_record_read);
int dt_record_write(const struct lu_env *env, struct dt_object *dt,
- const struct lu_buf *buf, loff_t *pos, struct thandle *th)
+ const struct lu_buf *buf, loff_t *pos, struct thandle *th)
{
- int rc;
-
- LASSERTF(dt != NULL, "dt is NULL when we want to write record\n");
- LASSERT(th != NULL);
- LASSERT(dt->do_body_ops);
- LASSERT(dt->do_body_ops->dbo_write);
- rc = dt->do_body_ops->dbo_write(env, dt, buf, pos, th, BYPASS_CAPA, 1);
- if (rc == buf->lb_len)
- rc = 0;
- else if (rc >= 0)
- rc = -EFAULT;
- return rc;
+ ssize_t size;
+
+ LASSERTF(dt != NULL, "dt is NULL when we want to write record\n");
+ LASSERT(th != NULL);
+ LASSERT(dt->do_body_ops);
+ LASSERT(dt->do_body_ops->dbo_write);
+
+ size = dt->do_body_ops->dbo_write(env, dt, buf, pos, th);
+ if (size < 0)
+ return size;
+ return (size == (ssize_t)buf->lb_len) ? 0 : -EFAULT;
}
EXPORT_SYMBOL(dt_record_write);
int dt_declare_version_set(const struct lu_env *env, struct dt_object *o,
- struct thandle *th)
+ struct thandle *th)
{
- struct lu_buf vbuf;
- char *xname = XATTR_NAME_VERSION;
+ struct lu_buf vbuf;
+ char *xname = XATTR_NAME_VERSION;
- LASSERT(o);
- vbuf.lb_buf = NULL;
- vbuf.lb_len = sizeof(dt_obj_version_t);
- return dt_declare_xattr_set(env, o, &vbuf, xname, 0, th);
+ LASSERT(o);
+ vbuf.lb_buf = NULL;
+ vbuf.lb_len = sizeof(dt_obj_version_t);
+ return dt_declare_xattr_set(env, o, &vbuf, xname, 0, th);
}
EXPORT_SYMBOL(dt_declare_version_set);
void dt_version_set(const struct lu_env *env, struct dt_object *o,
- dt_obj_version_t version, struct thandle *th)
+ dt_obj_version_t version, struct thandle *th)
{
- struct lu_buf vbuf;
- char *xname = XATTR_NAME_VERSION;
- int rc;
-
- LASSERT(o);
- vbuf.lb_buf = &version;
- vbuf.lb_len = sizeof(version);
-
- rc = dt_xattr_set(env, o, &vbuf, xname, 0, th, BYPASS_CAPA);
- if (rc < 0)
- CDEBUG(D_INODE, "Can't set version, rc %d\n", rc);
- return;
+ struct lu_buf vbuf;
+ char *xname = XATTR_NAME_VERSION;
+ int rc;
+
+ LASSERT(o);
+ vbuf.lb_buf = &version;
+ vbuf.lb_len = sizeof(version);
+
+ rc = dt_xattr_set(env, o, &vbuf, xname, 0, th);
+ if (rc < 0)
+ CDEBUG(D_INODE, "Can't set version, rc %d\n", rc);
+ return;
}
EXPORT_SYMBOL(dt_version_set);
dt_obj_version_t dt_version_get(const struct lu_env *env, struct dt_object *o)
{
- struct lu_buf vbuf;
- char *xname = XATTR_NAME_VERSION;
- dt_obj_version_t version;
- int rc;
-
- LASSERT(o);
- vbuf.lb_buf = &version;
- vbuf.lb_len = sizeof(version);
- rc = dt_xattr_get(env, o, &vbuf, xname, BYPASS_CAPA);
- if (rc != sizeof(version)) {
- CDEBUG(D_INODE, "Can't get version, rc %d\n", rc);
- version = 0;
- }
- return version;
+ struct lu_buf vbuf;
+ char *xname = XATTR_NAME_VERSION;
+ dt_obj_version_t version;
+ int rc;
+
+ LASSERT(o);
+ vbuf.lb_buf = &version;
+ vbuf.lb_len = sizeof(version);
+ rc = dt_xattr_get(env, o, &vbuf, xname);
+ if (rc != sizeof(version)) {
+ CDEBUG(D_INODE, "Can't get version, rc %d\n", rc);
+ version = 0;
+ }
+ return version;
}
EXPORT_SYMBOL(dt_version_get);
const struct dt_index_features dt_otable_features;
EXPORT_SYMBOL(dt_otable_features);
-/* lfsck orphan */
-const struct dt_index_features dt_lfsck_orphan_features = {
+/* lfsck layout orphan */
+const struct dt_index_features dt_lfsck_layout_orphan_features = {
.dif_flags = 0,
.dif_keysize_min = sizeof(struct lu_fid),
.dif_keysize_max = sizeof(struct lu_fid),
- .dif_recsize_min = sizeof(struct lu_orphan_rec),
- .dif_recsize_max = sizeof(struct lu_orphan_rec),
+ .dif_recsize_min = sizeof(struct lu_orphan_rec_v3),
+ .dif_recsize_max = sizeof(struct lu_orphan_rec_v3),
+ .dif_ptrsize = 4
+};
+EXPORT_SYMBOL(dt_lfsck_layout_orphan_features);
+
+/* lfsck layout dangling */
+const struct dt_index_features dt_lfsck_layout_dangling_features = {
+ .dif_flags = DT_IND_UPDATE,
+ .dif_keysize_min = sizeof(struct lfsck_layout_dangling_key),
+ .dif_keysize_max = sizeof(struct lfsck_layout_dangling_key),
+ .dif_recsize_min = sizeof(struct lu_fid),
+ .dif_recsize_max = sizeof(struct lu_fid),
.dif_ptrsize = 4
};
-EXPORT_SYMBOL(dt_lfsck_orphan_features);
+EXPORT_SYMBOL(dt_lfsck_layout_dangling_features);
-/* lfsck */
-const struct dt_index_features dt_lfsck_features = {
+/* lfsck namespace */
+const struct dt_index_features dt_lfsck_namespace_features = {
.dif_flags = DT_IND_UPDATE,
.dif_keysize_min = sizeof(struct lu_fid),
.dif_keysize_max = sizeof(struct lu_fid),
.dif_recsize_max = sizeof(__u8),
.dif_ptrsize = 4
};
-EXPORT_SYMBOL(dt_lfsck_features);
+EXPORT_SYMBOL(dt_lfsck_namespace_features);
/* accounting indexes */
const struct dt_index_features dt_acct_features = {
};
EXPORT_SYMBOL(dt_quota_slv_features);
-/* helper function returning what dt_index_features structure should be used
- * based on the FID sequence. This is used by OBD_IDX_READ RPC */
+/* nodemap files, nodemap_rec size asserted in nodemap_storage.c */
+const struct dt_index_features dt_nodemap_features = {
+ .dif_flags = DT_IND_UPDATE,
+ .dif_keysize_min = sizeof(__u64), /* 64-bit nodemap/record id */
+ .dif_keysize_max = sizeof(__u64), /* 64-bit nodemap/record id */
+ .dif_recsize_min = sizeof(union nodemap_rec), /* 32 bytes */
+ .dif_recsize_max = sizeof(union nodemap_rec), /* 32 bytes */
+ .dif_ptrsize = 4
+};
+EXPORT_SYMBOL(dt_nodemap_features);
+
+/*
+ * helper function returning what dt_index_features structure should be used
+ * based on the FID sequence. This is used by OBD_IDX_READ RPC
+ */
static inline const struct dt_index_features *dt_index_feat_select(__u64 seq,
__u32 mode)
{
return ERR_PTR(-ENOENT);
return &dt_quota_slv_features;
} else if (seq == FID_SEQ_LAYOUT_RBTREE){
- return &dt_lfsck_orphan_features;
+ return &dt_lfsck_layout_orphan_features;
} else if (seq >= FID_SEQ_NORMAL) {
/* object is part of the namespace, verify that it is a
* directory */
* \param arg - is a pointer to the idx_info structure
*/
static int dt_index_page_build(const struct lu_env *env, union lu_page *lp,
- int nob, const struct dt_it_ops *iops,
+ size_t nob, const struct dt_it_ops *iops,
struct dt_it *it, __u32 attr, void *arg)
{
- struct idx_info *ii = (struct idx_info *)arg;
- struct lu_idxpage *lip = &lp->lp_idx;
- char *entry;
- int rc, size;
+ struct idx_info *ii = (struct idx_info *)arg;
+ struct lu_idxpage *lip = &lp->lp_idx;
+ char *entry;
+ size_t size;
+ int rc;
ENTRY;
+ if (nob < LIP_HDR_SIZE)
+ return -EINVAL;
+
/* initialize the header of the new container */
memset(lip, 0, LIP_HDR_SIZE);
lip->lip_magic = LIP_MAGIC;
entry = lip->lip_entries;
do {
- char *tmp_entry = entry;
- struct dt_key *key;
- __u64 hash;
- __u16 keysize;
- __u16 recsize;
+ char *tmp_entry = entry;
+ struct dt_key *key;
+ __u64 hash;
+ __u16 keysize;
+ __u16 recsize;
/* fetch 64-bit hash value */
hash = iops->store(env, it);
}
if (!(ii->ii_flags & II_FL_NOHASH)) {
- /* client wants to the 64-bit hash value associated with
- * each record */
+ /*
+ * client wants to the 64-bit hash value associated
+ * with each record
+ */
memcpy(tmp_entry, &hash, sizeof(hash));
tmp_entry += sizeof(hash);
}
* \param obj - is the index object to parse
* \param rdpg - is the lu_rdpg descriptor associated with the transfer
* \param filler - is the callback function responsible for filling a lu_page
- * with key/record pairs in the format wanted by the caller
+ * with key/record pairs in the format wanted by the caller.
+ * If NULL, uses dt_index_page_build
* \param arg - is an opaq argument passed to the filler function
*
* \retval sum (in bytes) of all filled lu_pages
const struct lu_rdpg *rdpg, dt_index_page_build_t filler,
void *arg)
{
- struct dt_it *it;
- const struct dt_it_ops *iops;
- unsigned int pageidx, nob, nlupgs = 0;
- int rc;
+ struct dt_it *it;
+ const struct dt_it_ops *iops;
+ size_t pageidx, nob, nlupgs = 0;
+ int rc;
ENTRY;
LASSERT(rdpg->rp_pages != NULL);
LASSERT(obj->do_index_ops != NULL);
+ if (filler == NULL)
+ filler = dt_index_page_build;
+
nob = rdpg->rp_count;
- if (nob <= 0)
+ if (nob == 0)
RETURN(-EFAULT);
/* Iterate through index and fill containers from @rdpg */
iops = &obj->do_index_ops->dio_it;
LASSERT(iops != NULL);
- it = iops->init(env, obj, rdpg->rp_attrs, BYPASS_CAPA);
+ it = iops->init(env, obj, rdpg->rp_attrs);
if (IS_ERR(it))
RETURN(PTR_ERR(it));
GOTO(out, rc);
}
- /* Fill containers one after the other. There might be multiple
+ /*
+ * Fill containers one after the other. There might be multiple
* containers per physical page.
*
* At this point and across for-loop:
* rc == 0 -> ok, proceed.
* rc > 0 -> end of index.
- * rc < 0 -> error. */
+ * rc < 0 -> error.
+ */
for (pageidx = 0; rc == 0 && nob > 0; pageidx++) {
union lu_page *lp;
int i;
/* fill lu pages */
for (i = 0; i < LU_PAGE_COUNT; i++, lp++, nob -= LU_PAGE_SIZE) {
- rc = filler(env, lp, min_t(int, nob, LU_PAGE_SIZE),
+ rc = filler(env, lp, min_t(size_t, nob, LU_PAGE_SIZE),
iops, it, rdpg->rp_attrs, arg);
if (rc < 0)
break;
iops->fini(env, it);
if (rc >= 0)
- rc = min_t(unsigned int, nlupgs * LU_PAGE_SIZE, rdpg->rp_count);
+ rc = min_t(size_t, nlupgs * LU_PAGE_SIZE, rdpg->rp_count);
RETURN(rc);
}
int rc;
ENTRY;
- /* rp_count shouldn't be null and should be a multiple of the container
- * size */
+ /*
+ * rp_count shouldn't be null and should be a multiple of the container
+ * size
+ */
if (rdpg->rp_count == 0 || (rdpg->rp_count & (LU_PAGE_SIZE - 1)) != 0)
RETURN(-EFAULT);
if (!(feat->dif_flags & DT_IND_VARREC))
ii->ii_recsize = feat->dif_recsize_max;
- if (!(feat->dif_flags & DT_IND_NONUNQ))
+ if (feat->dif_flags & DT_IND_NONUNQ)
/* key isn't necessarily unique */
ii->ii_flags |= II_FL_NONUNQ;
GOTO(out, rc);
out:
- lu_object_put(env, &obj->do_lu);
+ dt_object_put(env, obj);
return rc;
}
EXPORT_SYMBOL(dt_index_read);
-#ifdef LPROCFS
+#ifdef CONFIG_PROC_FS
int lprocfs_dt_blksize_seq_show(struct seq_file *m, void *v)
{
struct dt_device *dt = m->private;
while (blk_size >>= 1)
result <<= 1;
- seq_printf(m, LPU64"\n", result);
+ seq_printf(m, "%llu\n", result);
}
return rc;
}
while (blk_size >>= 1)
result <<= 1;
- seq_printf(m, LPU64"\n", result);
+ seq_printf(m, "%llu\n", result);
}
return rc;
}
while (blk_size >>= 1)
result <<= 1;
- seq_printf(m, LPU64"\n", result);
+ seq_printf(m, "%llu\n", result);
}
return rc;
}
int rc = dt_statfs(NULL, dt, &osfs);
if (rc == 0)
- seq_printf(m, LPU64"\n", osfs.os_files);
+ seq_printf(m, "%llu\n", osfs.os_files);
return rc;
}
EXPORT_SYMBOL(lprocfs_dt_filestotal_seq_show);
int rc = dt_statfs(NULL, dt, &osfs);
if (rc == 0)
- seq_printf(m, LPU64"\n", osfs.os_ffree);
+ seq_printf(m, "%llu\n", osfs.os_ffree);
return rc;
}
EXPORT_SYMBOL(lprocfs_dt_filesfree_seq_show);
-#endif /* LPROCFS */
+#endif /* CONFIG_PROC_FS */
+
+static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct dt_device *dt = container_of(kobj, struct dt_device,
+ dd_kobj);
+ struct lu_device *lu = dt2lu_dev(dt);
+
+ if (!lu->ld_obd)
+ return -ENODEV;
+
+ return sprintf(buf, "%s\n", lu->ld_obd->obd_uuid.uuid);
+}
+LUSTRE_RO_ATTR(uuid);
+
+static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct dt_device *dt = container_of(kobj, struct dt_device,
+ dd_kobj);
+ struct obd_statfs osfs;
+ int rc;
+
+ rc = dt_statfs(NULL, dt, &osfs);
+ if (rc)
+ return rc;
+
+ return sprintf(buf, "%u\n", (unsigned) osfs.os_bsize);
+}
+LUSTRE_RO_ATTR(blocksize);
+
+static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct dt_device *dt = container_of(kobj, struct dt_device,
+ dd_kobj);
+ struct obd_statfs osfs;
+ u32 blk_size;
+ u64 result;
+ int rc;
+
+ rc = dt_statfs(NULL, dt, &osfs);
+ if (rc)
+ return rc;
+
+ blk_size = osfs.os_bsize >> 10;
+ result = osfs.os_blocks;
+
+ while (blk_size >>= 1)
+ result <<= 1;
+
+ return sprintf(buf, "%llu\n", result);
+}
+LUSTRE_RO_ATTR(kbytestotal);
+
+static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct dt_device *dt = container_of(kobj, struct dt_device,
+ dd_kobj);
+ struct obd_statfs osfs;
+ u32 blk_size;
+ u64 result;
+ int rc;
+
+ rc = dt_statfs(NULL, dt, &osfs);
+ if (rc)
+ return rc;
+
+ blk_size = osfs.os_bsize >> 10;
+ result = osfs.os_bfree;
+
+ while (blk_size >>= 1)
+ result <<= 1;
+
+ return sprintf(buf, "%llu\n", result);
+}
+LUSTRE_RO_ATTR(kbytesfree);
+
+static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct dt_device *dt = container_of(kobj, struct dt_device,
+ dd_kobj);
+ struct obd_statfs osfs;
+ u32 blk_size;
+ u64 result;
+ int rc;
+
+ rc = dt_statfs(NULL, dt, &osfs);
+ if (rc)
+ return rc;
+
+ blk_size = osfs.os_bsize >> 10;
+ result = osfs.os_bavail;
+
+ while (blk_size >>= 1)
+ result <<= 1;
+
+ return sprintf(buf, "%llu\n", result);
+}
+LUSTRE_RO_ATTR(kbytesavail);
+
+static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct dt_device *dt = container_of(kobj, struct dt_device,
+ dd_kobj);
+ struct obd_statfs osfs;
+ int rc;
+
+ rc = dt_statfs(NULL, dt, &osfs);
+ if (rc)
+ return rc;
+
+ return sprintf(buf, "%llu\n", osfs.os_files);
+}
+LUSTRE_RO_ATTR(filestotal);
+
+static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct dt_device *dt = container_of(kobj, struct dt_device,
+ dd_kobj);
+ struct obd_statfs osfs;
+ int rc;
+
+ rc = dt_statfs(NULL, dt, &osfs);
+ if (rc)
+ return rc;
+
+ return sprintf(buf, "%llu\n", osfs.os_ffree);
+}
+LUSTRE_RO_ATTR(filesfree);
+
+static const struct attribute *dt_def_attrs[] = {
+ &lustre_attr_uuid.attr,
+ &lustre_attr_blocksize.attr,
+ &lustre_attr_kbytestotal.attr,
+ &lustre_attr_kbytesfree.attr,
+ &lustre_attr_kbytesavail.attr,
+ &lustre_attr_filestotal.attr,
+ &lustre_attr_filesfree.attr,
+ NULL,
+};
+
+static void dt_sysfs_release(struct kobject *kobj)
+{
+ struct dt_device *dt = container_of(kobj, struct dt_device,
+ dd_kobj);
+
+ complete(&dt->dd_kobj_unregister);
+}
+
+int dt_tunables_fini(struct dt_device *dt)
+{
+ if (!dt)
+ return -EINVAL;
+
+ if (!IS_ERR_OR_NULL(dt->dd_debugfs_entry))
+ ldebugfs_remove(&dt->dd_debugfs_entry);
+
+ if (dt->dd_def_attrs)
+ sysfs_remove_files(&dt->dd_kobj, dt->dd_def_attrs);
+
+ kobject_put(&dt->dd_kobj);
+ wait_for_completion(&dt->dd_kobj_unregister);
+
+ return 0;
+}
+EXPORT_SYMBOL(dt_tunables_fini);
+
+int dt_tunables_init(struct dt_device *dt, struct obd_type *type,
+ const char *name, struct lprocfs_vars *list)
+{
+ int rc;
+
+ dt->dd_ktype.sysfs_ops = &lustre_sysfs_ops;
+ dt->dd_ktype.release = dt_sysfs_release;
+
+ init_completion(&dt->dd_kobj_unregister);
+ rc = kobject_init_and_add(&dt->dd_kobj, &dt->dd_ktype, type->typ_kobj,
+ "%s", name);
+ if (rc)
+ return rc;
+
+ dt->dd_def_attrs = dt_def_attrs;
+
+ rc = sysfs_create_files(&dt->dd_kobj, dt->dd_def_attrs);
+ if (rc) {
+ kobject_put(&dt->dd_kobj);
+ return rc;
+ }
+
+ /*
+ * No need to register debugfs if no enteries. This allows us to
+ * choose between using dt_device or obd_device for debugfs.
+ */
+ if (!list)
+ return rc;
+
+ dt->dd_debugfs_entry = ldebugfs_register(name,
+ type->typ_debugfs_entry,
+ list, dt);
+ if (IS_ERR_OR_NULL(dt->dd_debugfs_entry)) {
+ rc = dt->dd_debugfs_entry ? PTR_ERR(dt->dd_debugfs_entry)
+ : -ENOMEM;
+ CERROR("%s: error %d setting up debugfs\n",
+ name, rc);
+ dt->dd_debugfs_entry = NULL;
+ sysfs_remove_files(&dt->dd_kobj, dt->dd_def_attrs);
+ kobject_put(&dt->dd_kobj);
+ return rc;
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL(dt_tunables_init);