-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
* GPL HEADER START
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011 Whamcloud, Inc.
- *
+ * Copyright (c) 2011, 2012, Whamcloud, Inc.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
# include <lustre_quota.h>
#endif
#include <lustre_fsfilt.h>
+#include <lustre/lustre_lfsck_user.h>
#ifdef HAVE_QUOTA_SUPPORT
/* quota stuff */
struct mdd_object *mdd_obf;
};
+extern const char lfsck_bookmark_name[];
+
+struct md_lfsck {
+ cfs_mutex_t ml_mutex;
+ cfs_spinlock_t ml_lock;
+ struct ptlrpc_thread ml_thread;
+ struct dt_object *ml_bookmark_obj;
+ struct dt_object *ml_it_obj;
+ __u32 ml_new_scanned;
+ /* Arguments for low layer iteration. */
+ __u32 ml_args;
+
+ /* Raw value for LFSCK speed limit. */
+ __u32 ml_speed_limit;
+
+ /* Schedule for every N objects. */
+ __u32 ml_sleep_rate;
+
+ /* Sleep N jiffies for each schedule. */
+ __u32 ml_sleep_jif;
+ __u16 ml_version;
+ unsigned int ml_paused:1; /* The lfsck is paused. */
+};
+
struct mdd_device {
struct md_device mdd_md_dev;
struct dt_device *mdd_child;
struct obd_device *mdd_obd_dev;
struct lu_fid mdd_root_fid;
struct dt_device_param mdd_dt_conf;
- struct dt_object *mdd_orphans;
+ struct dt_object *mdd_orphans; /* PENDING directory */
struct dt_object *mdd_capa;
struct dt_txn_callback mdd_txn_cb;
cfs_proc_dir_entry_t *mdd_proc_entry;
unsigned long mdd_atime_diff;
struct mdd_object *mdd_dot_lustre;
struct mdd_dot_lustre_objs mdd_dot_lustre_objs;
- unsigned int mdd_sync_permission;
+ struct md_lfsck mdd_lfsck;
+ unsigned int mdd_sync_permission;
};
enum mod_flags {
APPEND_OBJ = 1 << 1,
IMMUTE_OBJ = 1 << 2,
ORPHAN_OBJ = 1 << 3,
- MNLINK_OBJ = 1 << 4
};
enum mdd_object_role {
struct lu_attr mti_la_for_fix;
struct md_attr mti_ma;
struct obd_info mti_oi;
+ /* mti_orph_ent and mti_orph_key must be conjoint,
+ * then mti_orph_ent::lde_name will be mti_orph_key. */
+ struct lu_dirent mti_orph_ent;
char mti_orph_key[NAME_MAX + 1];
struct obd_trans_info mti_oti;
struct lu_buf mti_buf;
extern const struct dt_index_features orph_index_features;
+struct lov_mds_md *mdd_max_lmm_buffer(const struct lu_env *env, int size);
struct lov_mds_md *mdd_max_lmm_get(const struct lu_env *env,
struct mdd_device *mdd);
int mdd_lov_create(const struct lu_env *env, struct mdd_device *mdd,
struct mdd_object *parent, struct mdd_object *child,
struct lov_mds_md **lmm, int *lmm_size,
- const struct md_op_spec *spec, struct lu_attr *la);
+ const struct md_op_spec *spec, struct md_attr *ma);
int mdd_lov_objid_prepare(struct mdd_device *mdd, struct lov_mds_md *lmm);
int mdd_declare_lov_objid_update(const struct lu_env *, struct mdd_device *,
struct thandle *);
struct lustre_handle *lockh);
int mdd_file_unlock(const struct lu_env *env, struct md_object *obj,
struct lov_mds_md *lmm, struct lustre_handle *lockh);
+int mdd_lum_lmm_cmp(const struct lu_env *env, struct md_object *cobj,
+ const struct md_op_spec *spec, struct md_attr *ma);
int mdd_get_md(const struct lu_env *env, struct mdd_object *obj,
void *md, int *md_size, const char *name);
int mdd_get_md_locked(const struct lu_env *env, struct mdd_object *obj,
int mdd_data_get(const struct lu_env *env, struct mdd_object *obj, void **data);
int mdd_la_get(const struct lu_env *env, struct mdd_object *obj,
struct lu_attr *la, struct lustre_capa *capa);
+int mdd_attr_get(const struct lu_env *env, struct md_object *obj,
+ struct md_attr *ma);
+int mdd_attr_set(const struct lu_env *env, struct md_object *obj,
+ const struct md_attr *ma);
int mdd_attr_set_internal(const struct lu_env *env,
struct mdd_object *obj,
struct lu_attr *attr,
/* mdd_dir.c */
int mdd_is_subdir(const struct lu_env *env, struct md_object *mo,
const struct lu_fid *fid, struct lu_fid *sfid);
-void __mdd_ref_add(const struct lu_env *env, struct mdd_object *obj,
- struct thandle *handle);
-void __mdd_ref_del(const struct lu_env *env, struct mdd_object *obj,
- struct thandle *handle, int is_dot);
int mdd_may_create(const struct lu_env *env, struct mdd_object *pobj,
struct mdd_object *cobj, int check_perm, int check_nlink);
int mdd_may_unlink(const struct lu_env *env, struct mdd_object *pobj,
struct lov_mds_md *lmm, int lmm_size,
struct llog_cookie *logcookies);
+int mdd_lovobj_unlink(const struct lu_env *env, struct mdd_device *mdd,
+ struct mdd_object *obj, struct lu_attr *la,
+ struct md_attr *ma, int log_unlink);
+
struct mdd_thread_info *mdd_env_info(const struct lu_env *env);
struct lu_buf *mdd_buf_get(const struct lu_env *env, void *area, ssize_t len);
int mdd_txn_start_cb(const struct lu_env *env, struct thandle *,
void *cookie);
+/* mdd_lfsck.c */
+void mdd_lfsck_set_speed(struct md_lfsck *lfsck, __u32 limit);
+int mdd_lfsck_start(const struct lu_env *env, struct md_lfsck *lfsck,
+ struct lfsck_start *start);
+int mdd_lfsck_stop(const struct lu_env *env, struct md_lfsck *lfsck);
+int mdd_lfsck_setup(const struct lu_env *env, struct mdd_device *mdd);
+void mdd_lfsck_cleanup(const struct lu_env *env, struct mdd_device *mdd);
+
/* mdd_device.c */
struct lu_object *mdd_object_alloc(const struct lu_env *env,
const struct lu_object_header *hdr,
int mdd_changelog_llog_write(struct mdd_device *mdd,
struct llog_changelog_rec *rec,
struct thandle *handle);
-int mdd_changelog_llog_cancel(struct mdd_device *mdd, long long endrec);
+int mdd_changelog_ext_llog_write(struct mdd_device *mdd,
+ struct llog_changelog_ext_rec *rec,
+ struct thandle *handle);
+int mdd_changelog_llog_cancel(const struct lu_env *env, struct mdd_device *mdd,
+ long long endrec);
int mdd_changelog_write_header(struct mdd_device *mdd, int markerflags);
int mdd_changelog_on(struct mdd_device *mdd, int on);
return obj->mod_flags & APPEND_OBJ;
}
-static inline int mdd_is_mnlink(struct mdd_object *obj)
-{
- return obj->mod_flags & MNLINK_OBJ;
-}
-
static inline int mdd_object_exists(struct mdd_object *obj)
{
return lu_object_exists(mdd2lu_obj(obj));
if (!ci)
return BYPASS_CAPA;
for (i = 0; i < MD_CAPAINFO_MAX; i++)
- if (ci->mc_fid[i] && lu_fid_eq(ci->mc_fid[i], fid))
+ if (lu_fid_eq(&ci->mc_fid[i], fid))
return ci->mc_capa[i];
return NULL;
}
/* NB: in mdt_init0 */
if (!ci)
return;
- ci->mc_fid[offset] = fid;
+ ci->mc_fid[offset] = *fid;
ci->mc_capa[offset] = capa;
}
+static inline const char *mdd_obj_dev_name(const struct mdd_object *obj)
+{
+ return lu_dev_name(obj->mod_obj.mo_lu.lo_dev);
+}
+
#define MAX_ATIME_DIFF 60
enum {
struct lustre_capa *capa)
{
struct dt_object *next = mdd_object_child(obj);
- LASSERT(mdd_object_exists(obj));
+ if (mdd_object_exists(obj) == 0) {
+ CERROR("%s: object "DFID" not found: rc = -2\n",
+ mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)));
+ return -ENOENT;
+ }
return next->do_ops->do_attr_set(env, next, la, handle, capa);
}
struct lustre_capa *capa)
{
struct dt_object *next = mdd_object_child(obj);
- LASSERT(mdd_object_exists(obj));
+ if (mdd_object_exists(obj) == 0) {
+ CERROR("%s: object "DFID" not found: rc = -2\n",
+ mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)));
+ return -ENOENT;
+ }
return next->do_ops->do_xattr_set(env, next, buf, name, fl, handle,
capa);
}
struct lustre_capa *capa)
{
struct dt_object *next = mdd_object_child(obj);
- LASSERT(mdd_object_exists(obj));
+ if (mdd_object_exists(obj) == 0) {
+ CERROR("%s: object "DFID" not found: rc = -2\n",
+ mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)));
+ return -ENOENT;
+ }
return next->do_ops->do_xattr_del(env, next, name, handle, capa);
}
struct lu_buf *buf, struct lustre_capa *capa)
{
struct dt_object *next = mdd_object_child(obj);
- LASSERT(mdd_object_exists(obj));
+ if (mdd_object_exists(obj) == 0) {
+ CERROR("%s: object "DFID" not found: rc = -2\n",
+ mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)));
+ return -ENOENT;
+ }
return next->do_ops->do_xattr_list(env, next, buf, capa);
}
struct thandle *handle)
{
struct dt_object *next = mdd_object_child(obj);
- LASSERT(mdd_object_exists(obj));
+ if (mdd_object_exists(obj) == 0) {
+ CERROR("%s: object "DFID" not found: rc = -2\n",
+ mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)));
+ return -ENOENT;
+ }
return next->do_ops->do_ref_add(env, next, handle);
}
struct thandle *handle)
{
struct dt_object *next = mdd_object_child(obj);
- LASSERT(mdd_object_exists(obj));
+ if (mdd_object_exists(obj) == 0) {
+ CERROR("%s: object "DFID" not found: rc = -2\n",
+ mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)));
+ return -ENOENT;
+ }
return next->do_ops->do_ref_del(env, next, handle);
}
__u64 opc)
{
struct dt_object *next = mdd_object_child(obj);
- LASSERT(mdd_object_exists(obj));
+ if (mdd_object_exists(obj) == 0) {
+ CERROR("%s: object "DFID" not found: rc = -2\n",
+ mdd_obj_dev_name(obj), PFID(mdd_object_fid(obj)));
+ return ERR_PTR(-ENOENT);
+ }
return next->do_ops->do_capa_get(env, next, old, opc);
}