* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2012, 2015, Intel Corporation.
+ * Copyright (c) 2012, 2016, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
dt_txn_hook_commit(th);
/* call per-transaction callbacks if any */
- list_for_each_entry_safe(dcb, tmp, &oh->ot_dcb_list, dcb_linkage)
+ list_for_each_entry_safe(dcb, tmp, &oh->ot_dcb_list, dcb_linkage) {
+ LASSERTF(dcb->dcb_magic == TRANS_COMMIT_CB_MAGIC,
+ "commit callback entry: magic=%x name='%s'\n",
+ dcb->dcb_magic, dcb->dcb_name);
+ list_del_init(&dcb->dcb_linkage);
dcb->dcb_func(NULL, th, dcb, error);
+ }
/* Unlike ldiskfs, zfs updates space accounting at commit time.
* As a consequence, op_end is called only now to inform the quota slave
while (!list_empty(list)) {
obj = list_entry(list->next,
struct osd_object, oo_unlinked_linkage);
- LASSERT(obj->oo_db != NULL);
- oid = obj->oo_db->db_object;
+ LASSERT(obj->oo_dn != NULL);
+ oid = obj->oo_dn->dn_object;
list_del_init(&obj->oo_unlinked_linkage);
if (free)
oh = container_of0(th, struct osd_thandle, ot_super);
INIT_LIST_HEAD(&unlinked);
list_splice_init(&oh->ot_unlinked_list, &unlinked);
+ /* reset OI cache for safety */
+ osd_oti_get(env)->oti_ins_cache_used = 0;
if (oh->ot_assigned == 0) {
LASSERT(oh->ot_tx);
RETURN(0);
}
- /* When doing our own inode accounting, the ZAPs storing per-uid/gid
- * usage are updated at operation execution time, so we should call
- * qsd_op_end() straight away. Otherwise (for blk accounting maintained
- * by ZFS and when #inode is estimated from #blks) accounting is updated
- * at commit time and the call to qsd_op_end() must be delayed */
- if (oh->ot_quota_trans.lqt_id_cnt > 0 &&
- !oh->ot_quota_trans.lqt_ids[0].lqi_is_blk &&
- !osd->od_quota_iused_est)
- qsd_op_end(env, osd->od_quota_slave, &oh->ot_quota_trans);
-
rc = dt_txn_hook_stop(env, th);
if (rc != 0)
CDEBUG(D_OTHER, "%s: transaction hook failed: rc = %d\n",
dmu_tx_t *tx;
ENTRY;
+ if (dt->dd_rdonly) {
+ CERROR("%s: someone try to start transaction under "
+ "readonly mode, should be disabled.\n",
+ osd_name(osd_dt_dev(dt)));
+ dump_stack();
+ RETURN(ERR_PTR(-EROFS));
+ }
+
tx = dmu_tx_create(osd->od_os);
if (tx == NULL)
RETURN(ERR_PTR(-ENOMEM));
CLASSERT(OSD_DNODE_MIN_BLKSHIFT > 0);
CLASSERT(OSD_DNODE_EST_BLKSHIFT > 0);
- est_usedblocks = (usedbytes >> est_maxblockshift) +
- (OSD_DNODE_EST_COUNT >> OSD_DNODE_EST_BLKSHIFT);
- est_usedobjs = usedobjs + OSD_DNODE_EST_COUNT;
+ est_usedblocks = ((OSD_DNODE_EST_COUNT << OSD_DNODE_EST_BLKSHIFT) +
+ usedbytes) >> est_maxblockshift;
+ est_usedobjs = OSD_DNODE_EST_COUNT + usedobjs;
if (est_usedobjs <= est_usedblocks) {
/*
osfs->os_bavail = osfs->os_bfree; /* no extra root reservation */
/* Take replication (i.e. number of copies) into account */
- osfs->os_bavail /= os->os_copies;
+ if (os->os_copies != 0)
+ osfs->os_bavail /= os->os_copies;
/*
* Reserve some space so we don't run into ENOSPC due to grants not
*/
static int osd_sync(const struct lu_env *env, struct dt_device *d)
{
- struct osd_device *osd = osd_dt_dev(d);
- CDEBUG(D_CACHE, "syncing OSD %s\n", LUSTRE_OSD_ZFS_NAME);
- txg_wait_synced(dmu_objset_pool(osd->od_os), 0ULL);
- CDEBUG(D_CACHE, "synced OSD %s\n", LUSTRE_OSD_ZFS_NAME);
+ if (!d->dd_rdonly) {
+ struct osd_device *osd = osd_dt_dev(d);
+
+ CDEBUG(D_CACHE, "syncing OSD %s\n", LUSTRE_OSD_ZFS_NAME);
+ txg_wait_synced(dmu_objset_pool(osd->od_os), 0ULL);
+ CDEBUG(D_CACHE, "synced OSD %s\n", LUSTRE_OSD_ZFS_NAME);
+ }
+
return 0;
}
struct lu_context_key *key, void *data)
{
struct osd_thread_info *info = data;
+ struct osd_idmap_cache *idc = info->oti_ins_cache;
+ if (idc != NULL) {
+ LASSERT(info->oti_ins_cache_size > 0);
+ OBD_FREE(idc, sizeof(*idc) * info->oti_ins_cache_size);
+ info->oti_ins_cache = NULL;
+ info->oti_ins_cache_size = 0;
+ }
OBD_FREE_PTR(info);
}
static void osd_key_exit(const struct lu_context *ctx,
struct lu_context_key *key, void *data)
{
- struct osd_thread_info *info = data;
-
- memset(info, 0, sizeof(*info));
}
struct lu_context_key osd_key = {
int rc;
ENTRY;
- rc = -dmu_objset_own(o->od_mntdev, DMU_OST_ZFS, B_FALSE, o, &o->od_os);
+ rc = -dmu_objset_own(o->od_mntdev, DMU_OST_ZFS,
+ o->od_dt_dev.dd_rdonly ? B_TRUE : B_FALSE,
+ o, &o->od_os);
if (rc) {
CERROR("%s: can't open %s\n", o->od_svname, o->od_mntdev);
o->od_os = NULL;
- goto out;
+
+ GOTO(out, rc);
}
/* Check ZFS version */
int rc;
dmu_tx_t *tx;
+ if (osd->od_dt_dev.dd_rdonly) {
+ CERROR("%s: someone try to free objects under "
+ "readonly mode, should be disabled.\n", osd_name(osd));
+ dump_stack();
+
+ return -EROFS;
+ }
+
rc = -dmu_free_long_range(osd->od_os, oid, 0, DMU_OBJECT_END);
if (rc != 0) {
CWARN("%s: Cannot truncate %llu: rc = %d\n",
struct osd_device *o, struct lustre_cfg *cfg)
{
char *mntdev = lustre_cfg_string(cfg, 1);
+ char *str = lustre_cfg_string(cfg, 2);
char *svname = lustre_cfg_string(cfg, 4);
- dmu_buf_t *rootdb;
+ dnode_t *rootdn;
const char *opts;
int rc;
ENTRY;
if (rc >= sizeof(o->od_svname))
RETURN(-E2BIG);
+ str = strstr(str, ":");
+ if (str) {
+ unsigned long flags;
+
+ rc = kstrtoul(str + 1, 10, &flags);
+ if (rc)
+ RETURN(-EINVAL);
+
+ if (flags & LMD_FLG_DEV_RDONLY) {
+ o->od_dt_dev.dd_rdonly = 1;
+ LCONSOLE_WARN("%s: set dev_rdonly on this device\n",
+ svname);
+ }
+ }
+
if (server_name_is_ost(o->od_svname))
o->od_is_ost = 1;
if (rc)
GOTO(err, rc);
- rc = __osd_obj2dbuf(env, o->od_os, o->od_rootid, &rootdb);
+ rc = __osd_obj2dnode(env, o->od_os, o->od_rootid, &rootdn);
if (rc)
GOTO(err, rc);
- o->od_root = rootdb->db_object;
- sa_buf_rele(rootdb, osd_obj_tag);
+ o->od_root = rootdn->dn_object;
+ osd_dnode_rele(rootdn);
/* 1. initialize oi before any file create or file open */
rc = osd_oi_init(env, o);
if (rc)
GOTO(err, rc);
- /* Use our own ZAP for inode accounting by default, this can be changed
- * via procfs to estimate the inode usage from the block usage */
- o->od_quota_iused_est = 0;
-
rc = osd_procfs_init(o, o->od_svname);
if (rc)
GOTO(err, rc);
osd_unlinked_drain(env, o);
err:
- if (rc) {
+ if (rc && o->od_os) {
dmu_objset_disown(o->od_os, o);
o->od_os = NULL;
}
atomic_read(&o->od_zerocopy_pin));
if (o->od_os != NULL) {
- /* force a txg sync to get all commit callbacks */
- txg_wait_synced(dmu_objset_pool(o->od_os), 0ULL);
+ if (!o->od_dt_dev.dd_rdonly)
+ /* force a txg sync to get all commit callbacks */
+ txg_wait_synced(dmu_objset_pool(o->od_os), 0ULL);
/* close the object set */
dmu_objset_disown(o->od_os, o);
if (o->od_os) {
osd_objset_unregister_callbacks(o);
- osd_sync(env, lu2dt_dev(d));
- txg_wait_callbacks(spa_get_dsl(dmu_objset_spa(o->od_os)));
+ if (!o->od_dt_dev.dd_rdonly) {
+ osd_sync(env, lu2dt_dev(d));
+ txg_wait_callbacks(
+ spa_get_dsl(dmu_objset_spa(o->od_os)));
+ }
}
rc = osd_procfs_fini(o);