Ejemplo n.º 1
0
static int osd_remove_ois(struct osd_thread_info *info, struct osd_device *osd)
{
	char name[16];
	int namelen;
	int rc;
	int i;

	for (i = 0; i < osd->od_scrub.os_file.sf_oi_count; i++) {
		namelen = snprintf(name, sizeof(name), "%s.%d",
				   OSD_OI_NAME_BASE, i);
		rc = osd_remove_oi_one(osd_sb(osd)->s_root, name, namelen);
		if (rc != 0) {
			CERROR("%.16s: fail to remove the stale OI file %s: "
			       "rc = %d\n",
			       LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name,
			       name, rc);
			return rc;
		}
	}

	namelen = snprintf(name, sizeof(name), "%s", OSD_OI_NAME_BASE);
	rc = osd_remove_oi_one(osd_sb(osd)->s_root, name, namelen);
	if (rc != 0)
		CERROR("%.16s: fail to remove the stale OI file %s: rc = %d\n",
		       LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name, name, rc);

	return rc;
}
Ejemplo n.º 2
0
int osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd,
		  const struct lu_fid *fid, struct osd_inode_id *id,
		  enum oi_check_flags flags)
{
	if (unlikely(fid_is_last_id(fid)))
		return osd_obj_spec_lookup(info, osd, fid, id);

	if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid))
		return osd_obj_map_lookup(info, osd, fid, id);


	if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE)) {
		int rc;
		if (fid_is_fs_root(fid)) {
			osd_id_gen(id, osd_sb(osd)->s_root->d_inode->i_ino,
				   osd_sb(osd)->s_root->d_inode->i_generation);
			return 0;
		}
		if (unlikely(fid_is_acct(fid)))
			return osd_acct_obj_lookup(info, osd, fid, id);

		/* For other special FIDs, try OI first, then do spec lookup */
		rc = __osd_oi_lookup(info, osd, fid, id);
		if (rc == -ENOENT)
			return osd_obj_spec_lookup(info, osd, fid, id);
		return rc;
	}

	if (!osd->od_igif_inoi && fid_is_igif(fid)) {
		osd_id_gen(id, lu_igif_ino(fid), lu_igif_gen(fid));
		return 0;
	}

	return __osd_oi_lookup(info, osd, fid, id);
}
Ejemplo n.º 3
0
int osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd,
		  const struct lu_fid *fid, struct osd_inode_id *id,
		  enum oi_check_flags flags)
{
	if (unlikely(fid_is_last_id(fid)))
		return osd_obj_spec_lookup(info, osd, fid, id);

	if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid))
		return osd_obj_map_lookup(info, osd, fid, id);

	if (fid_is_fs_root(fid)) {
		osd_id_gen(id, osd_sb(osd)->s_root->d_inode->i_ino,
			   osd_sb(osd)->s_root->d_inode->i_generation);
		return 0;
	}

	if (unlikely(fid_is_acct(fid)))
		return osd_acct_obj_lookup(info, osd, fid, id);

	if (!osd->od_igif_inoi && fid_is_igif(fid)) {
		osd_id_gen(id, lu_igif_ino(fid), lu_igif_gen(fid));
		return 0;
	}

	return __osd_oi_lookup(info, osd, fid, id);
}
Ejemplo n.º 4
0
/**
 * Open OI(Object Index) table.
 * If \a oi_count is zero, which means caller doesn't know how many OIs there
 * will be, this function can either return 0 for new filesystem, or number
 * of OIs on existed filesystem.
 *
 * If \a oi_count is non-zero, which means caller does know number of OIs on
 * filesystem, this function should return the exactly same number on
 * success, or error code in failure.
 *
 * \param     oi_count  Number of expected OI containers
 * \param     create    Create OIs if doesn't exist
 *
 * \retval    +ve       number of opened OI containers
 * \retval      0       no OI containers found
 * \retval    -ve       failure
 */
static int
osd_oi_table_open(struct osd_thread_info *info, struct osd_device *osd,
		  struct osd_oi **oi_table, unsigned oi_count, bool create)
{
	struct scrub_file *sf = &osd->od_scrub.os_file;
	int		   count = 0;
	int		   rc = 0;
	int		   i;
	ENTRY;

	/* NB: oi_count != 0 means that we have already created/known all OIs
	 * and have known exact number of OIs. */
	LASSERT(oi_count <= OSD_OI_FID_NR_MAX);

	for (i = 0; i < (oi_count != 0 ? oi_count : OSD_OI_FID_NR_MAX); i++) {
		char name[12];

		if (oi_table[i] != NULL) {
			count++;
			continue;
		}

		sprintf(name, "%s.%d", OSD_OI_NAME_BASE, i);
		rc = osd_oi_open(info, osd, name, &oi_table[i], create);
		if (rc == 0) {
			count++;
			continue;
		}

		if (rc == -ENOENT && create == false) {
			if (oi_count == 0)
				return count;

			rc = 0;
			ldiskfs_set_bit(i, sf->sf_oi_bitmap);
			continue;
		}

		CERROR("%.16s: can't open %s: rc = %d\n",
		       LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name, name, rc);
		if (oi_count > 0)
			CERROR("%.16s: expect to open total %d OI files.\n",
			       LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name,
			       oi_count);
		break;
	}

	if (rc < 0) {
		osd_oi_table_put(info, oi_table, oi_count > 0 ? oi_count : i);
		count = rc;
	}

	RETURN(count);
}
Ejemplo n.º 5
0
int osd_compat_spec_lookup(struct osd_thread_info *info,
                           struct osd_device *osd, const struct lu_fid *fid,
                           struct osd_inode_id *id)
{
        struct dentry *dentry;
        char          *name;
        int            rc = -ERESTART;

        ENTRY;

        name = oid2name(fid_oid(fid));
        if (name == NULL || strlen(name) == 0)
                return -ERESTART;

        dentry = ll_lookup_one_len(name, osd_sb(osd)->s_root, strlen(name));
        if (!IS_ERR(dentry)) {
                if (dentry->d_inode) {
                        if (is_bad_inode(dentry->d_inode)) {
                                rc = -EIO;
                        } else {
                                id->oii_ino = dentry->d_inode->i_ino;
                                id->oii_gen = dentry->d_inode->i_generation;
                                rc = 0;
                        }
                }
                dput(dentry);
        }

        RETURN(rc);
}
Ejemplo n.º 6
0
int osd_compat_spec_insert(struct osd_thread_info *info,
                           struct osd_device *osd, const struct lu_fid *fid,
                           const struct osd_inode_id *id, struct thandle *th)
{
        struct osd_compat_objid *map = osd->od_ost_map;
        struct dentry           *root = osd_sb(osd)->s_root;
        char                    *name;
        int                      rc = 0;
        int                      seq;
        ENTRY;

        if (fid_oid(fid) >= OFD_GROUP0_LAST_OID &&
            fid_oid(fid) < OFD_GROUP4K_LAST_OID) {
                /* on creation of LAST_ID we create O/<group> hierarchy */
                LASSERT(map);
                seq = fid_oid(fid) - OFD_GROUP0_LAST_OID;
                LASSERT(seq < MAX_OBJID_GROUP);
                LASSERT(map->groups[seq].groot);
        } else {
                name = oid2name(fid_oid(fid));
                if (name == NULL)
                        CWARN("UNKNOWN COMPAT FID "DFID"\n", PFID(fid));
                else if (name[0])
                        rc = osd_compat_add_entry(info, osd, root, name, id,
                                                  th);
        }

        RETURN(rc);
}
Ejemplo n.º 7
0
int osd_compat_add_entry(struct osd_thread_info *info, struct osd_device *osd,
                         struct dentry *dir, char *name,
                         const struct osd_inode_id *id, struct thandle *th)
{
        struct osd_thandle *oh;
        struct dentry *child;
        struct inode *inode;
        int rc;

        ENTRY;

        oh = container_of(th, struct osd_thandle, ot_super);
        LASSERT(oh->ot_handle != NULL);
        LASSERT(oh->ot_handle->h_transaction != NULL);

        inode = &info->oti_inode;
        inode->i_sb = osd_sb(osd);
        inode->i_ino = id->oii_ino;
        inode->i_generation = id->oii_gen;

        child = &info->oti_child_dentry;
        child->d_name.hash = 0;
        child->d_name.name = name;
        child->d_name.len = strlen(name);
        child->d_parent = dir;
        child->d_inode = inode;

        LOCK_INODE_MUTEX(dir->d_inode);
        rc = osd_ldiskfs_add_entry(oh->ot_handle, child, inode, NULL);
        UNLOCK_INODE_MUTEX(dir->d_inode);

        RETURN(rc);
}
Ejemplo n.º 8
0
void osd_brw_stats_update(struct osd_device *osd, struct osd_iobuf *iobuf)
{
        struct brw_stats *s = &osd->od_brw_stats;
        unsigned long    *last_block = NULL;
        struct page     **pages = iobuf->dr_pages;
        struct page      *last_page = NULL;
        unsigned long     discont_pages = 0;
        unsigned long     discont_blocks = 0;
        unsigned long    *blocks = iobuf->dr_blocks;
        int               i, nr_pages = iobuf->dr_npages;
        int               blocks_per_page;
        int               rw = iobuf->dr_rw;

        if (unlikely(nr_pages == 0))
                return;

	blocks_per_page = PAGE_CACHE_SIZE >> osd_sb(osd)->s_blocksize_bits;

        lprocfs_oh_tally_log2(&s->hist[BRW_R_PAGES+rw], nr_pages);

        while (nr_pages-- > 0) {
                if (last_page && (*pages)->index != (last_page->index + 1))
                        discont_pages++;
                last_page = *pages;
                pages++;
                for (i = 0; i < blocks_per_page; i++) {
                        if (last_block && *blocks != (*last_block + 1))
                                discont_blocks++;
                        last_block = blocks++;
                }
        }

        lprocfs_oh_tally(&s->hist[BRW_R_DISCONT_PAGES+rw], discont_pages);
        lprocfs_oh_tally(&s->hist[BRW_R_DISCONT_BLOCKS+rw], discont_blocks);
}
Ejemplo n.º 9
0
static struct inode *osd_oi_index_open(struct osd_thread_info *info,
                                       struct osd_device *osd,
                                       const char *name,
                                       struct dt_index_features *f,
                                       bool create)
{
        struct dentry *dentry;
        struct inode  *inode;
        int            rc;

        dentry = ll_lookup_one_len(name, osd_sb(osd)->s_root, strlen(name));
        if (IS_ERR(dentry))
                return (void *) dentry;

        if (dentry->d_inode) {
                LASSERT(!is_bad_inode(dentry->d_inode));
                inode = dentry->d_inode;
                atomic_inc(&inode->i_count);
                dput(dentry);
                return inode;
        }

        /* create */
        dput(dentry);
        shrink_dcache_parent(osd_sb(osd)->s_root);
        if (!create)
                return ERR_PTR(-ENOENT);

        rc = osd_oi_index_create_one(info, osd, name, f);
        if (rc)
		return ERR_PTR(rc);

        dentry = ll_lookup_one_len(name, osd_sb(osd)->s_root, strlen(name));
        if (IS_ERR(dentry))
                return (void *) dentry;

        if (dentry->d_inode) {
                LASSERT(!is_bad_inode(dentry->d_inode));
                inode = dentry->d_inode;
                atomic_inc(&inode->i_count);
                dput(dentry);
                return inode;
        }

        return ERR_PTR(-ENOENT);
}
Ejemplo n.º 10
0
static int osd_oi_index_create_one(struct osd_thread_info *info,
				   struct osd_device *osd, const char *name,
				   struct dt_index_features *feat)
{
	const struct lu_env		*env = info->oti_env;
	struct osd_inode_id		*id  = &info->oti_id;
	struct buffer_head		*bh;
	struct inode			*inode;
	struct ldiskfs_dir_entry_2	*de;
	struct dentry			*dentry;
	struct super_block		*sb  = osd_sb(osd);
	struct inode			*dir = sb->s_root->d_inode;
	handle_t			*jh;
	int				 rc;

	dentry = osd_child_dentry_by_inode(env, dir, name, strlen(name));
	bh = osd_ldiskfs_find_entry(dir, &dentry->d_name, &de, NULL, NULL);
	if (bh) {
		osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN);
		brelse(bh);
		inode = osd_iget(info, osd, id);
		if (!IS_ERR(inode)) {
			iput(inode);
			inode = ERR_PTR(-EEXIST);
		}
		return PTR_ERR(inode);
	}

	jh = osd_journal_start_sb(sb, LDISKFS_HT_MISC, 100);
	if (IS_ERR(jh))
		return PTR_ERR(jh);

	inode = ldiskfs_create_inode(jh, dir, (S_IFREG | S_IRUGO | S_IWUSR));
	if (IS_ERR(inode)) {
		ldiskfs_journal_stop(jh);
		return PTR_ERR(inode);
	}

	ldiskfs_set_inode_state(inode, LDISKFS_STATE_LUSTRE_NOSCRUB);
	unlock_new_inode(inode);

	if (feat->dif_flags & DT_IND_VARKEY)
		rc = iam_lvar_create(inode, feat->dif_keysize_max,
				     feat->dif_ptrsize, feat->dif_recsize_max,
				     jh);
	else
		rc = iam_lfix_create(inode, feat->dif_keysize_max,
				     feat->dif_ptrsize, feat->dif_recsize_max,
				     jh);
	dentry = osd_child_dentry_by_inode(env, dir, name, strlen(name));
	rc = osd_ldiskfs_add_entry(info, jh, dentry, inode, NULL);
	ldiskfs_journal_stop(jh);
	iput(inode);
	return rc;
}
Ejemplo n.º 11
0
/*
 * directory structure on legacy OST:
 *
 * O/<seq>/d0-31/<objid>
 * O/<seq>/LAST_ID
 * last_rcvd
 * LAST_GROUP
 * CONFIGS
 *
 */
int osd_compat_init(struct osd_device *dev)
{
        struct lvfs_run_ctxt  new;
        struct lvfs_run_ctxt  save;
        struct dentry        *rootd = osd_sb(dev)->s_root;
        struct dentry        *d;
        int                   rc;
        int                   i;

        ENTRY;

        /* to get subdir count from last_rcvd */
        rc = osd_last_rcvd_subdir_count(dev);
        if (rc <= 0)
                RETURN(rc);

        dev->od_ost_map->subdir_count = rc;
        rc = 0;

        OBD_ALLOC_PTR(dev->od_ost_map);
        if (dev->od_ost_map == NULL)
                RETURN(-ENOMEM);

        LASSERT(dev->od_fsops);
        osd_push_ctxt(dev, &new, &save);

        d = simple_mkdir(rootd, dev->od_mnt, "O", 0755, 1);
        pop_ctxt(&save, &new, NULL);
        if (IS_ERR(d)) {
                OBD_FREE_PTR(dev->od_ost_map);
                RETURN(PTR_ERR(d));
        }

        dev->od_ost_map->root = d;

        /* Initialize all groups */
        for (i = 0; i < MAX_OBJID_GROUP; i++) {
                cfs_sema_init(&dev->od_ost_map->groups[i].dir_init_sem, 1);
                rc = osd_compat_seq_init(dev, i);
                if (rc) {
                        osd_compat_fini(dev);
                        break;
                }
        }

        RETURN(rc);
}
Ejemplo n.º 12
0
int osd_last_rcvd_subdir_count(struct osd_device *osd)
{
        struct lr_server_data lsd;
        struct dentry        *dlast;
        loff_t                off;
        int                   rc = 0;
        int                   count = 0;

        ENTRY;

        dlast = ll_lookup_one_len(LAST_RCVD, osd_sb(osd)->s_root,
                                  strlen(LAST_RCVD));
        if (IS_ERR(dlast))
                return PTR_ERR(dlast);
        else if (dlast->d_inode == NULL)
                goto out;

        off = 0;
        rc = osd_ldiskfs_read(dlast->d_inode, &lsd, sizeof(lsd), &off);
        if (rc == sizeof(lsd)) {
                CDEBUG(D_INFO, "read last_rcvd header, uuid = %s, "
                       "subdir count = %d\n", lsd.lsd_uuid,
                       lsd.lsd_subdir_count);
                count = le16_to_cpu(lsd.lsd_subdir_count);
        } else if (rc != 0) {
                CERROR("Can't read last_rcvd file, rc = %d\n", rc);
                if (rc > 0)
                        rc = -EFAULT;
                goto out;
        } else {
                count = FILTER_SUBDIR_COUNT;
        }

        rc = count;
out:
        dput(dlast);
        return rc;
}
Ejemplo n.º 13
0
int osd_oi_insert(struct osd_thread_info *info, struct osd_device *osd,
		  const struct lu_fid *fid, const struct osd_inode_id *id,
		  handle_t *th, enum oi_check_flags flags)
{
	struct lu_fid	    *oi_fid = &info->oti_fid2;
	struct osd_inode_id *oi_id  = &info->oti_id2;
	int		     rc     = 0;

	if (unlikely(fid_is_last_id(fid)))
		return osd_obj_spec_insert(info, osd, fid, id, th);

	if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid))
		return osd_obj_map_insert(info, osd, fid, id, th);

	fid_cpu_to_be(oi_fid, fid);
	osd_id_pack(oi_id, id);
	rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid),
			       (const struct dt_rec *)oi_id,
			       (const struct dt_key *)oi_fid, th, true);
	if (rc != 0) {
		struct inode *inode;
		struct lustre_mdt_attrs *lma = &info->oti_mdt_attrs;

		if (rc != -EEXIST)
			return rc;

		rc = osd_oi_lookup(info, osd, fid, oi_id, 0);
		if (rc != 0)
			return rc;

		if (unlikely(osd_id_eq(id, oi_id)))
			return 1;

		/* Check whether the mapping for oi_id is valid or not. */
		inode = osd_iget(info, osd, oi_id);
		if (IS_ERR(inode)) {
			rc = PTR_ERR(inode);
			if (rc == -ENOENT || rc == -ESTALE)
				goto update;
			return rc;
		}

		/* The EA inode should NOT be in OI, old OI scrub may added
		 * such OI mapping by wrong, replace it. */
		if (unlikely(osd_is_ea_inode(inode))) {
			iput(inode);
			goto update;
		}

		rc = osd_get_lma(info, inode, &info->oti_obj_dentry, lma);
		iput(inode);
		if (rc == -ENODATA)
			goto update;

		if (rc != 0)
			return rc;

		if (!(lma->lma_compat & LMAC_NOT_IN_OI) &&
		    lu_fid_eq(fid, &lma->lma_self_fid)) {
			CERROR("%.16s: the FID "DFID" is used by two objects: "
			       "%u/%u %u/%u\n",
			       LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name,
			       PFID(fid), oi_id->oii_ino, oi_id->oii_gen,
			       id->oii_ino, id->oii_gen);
			return -EEXIST;
		}

update:
		osd_id_pack(oi_id, id);
		rc = osd_oi_iam_refresh(info, osd_fid2oi(osd, fid),
					(const struct dt_rec *)oi_id,
					(const struct dt_key *)oi_fid, th, false);
		if (rc != 0)
			return rc;
	}

	if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE))
		rc = osd_obj_spec_insert(info, osd, fid, id, th);
	return rc;
}
Ejemplo n.º 14
0
int osd_oi_init(struct osd_thread_info *info, struct osd_device *osd,
		bool restored)
{
	struct osd_scrub  *scrub = &osd->od_scrub;
	struct scrub_file *sf = &scrub->os_file;
	struct osd_oi    **oi;
	int		   rc;
	ENTRY;

	if (restored) {
		rc = osd_remove_ois(info, osd);
		if (rc != 0)
			return rc;
	}

	OBD_ALLOC(oi, sizeof(*oi) * OSD_OI_FID_NR_MAX);
	if (oi == NULL)
		RETURN(-ENOMEM);

	mutex_lock(&oi_init_lock);
	/* try to open existing multiple OIs first */
	rc = osd_oi_table_open(info, osd, oi, sf->sf_oi_count, false);
	if (rc < 0)
		GOTO(out, rc);

	if (rc > 0) {
		if (rc == sf->sf_oi_count || sf->sf_oi_count == 0)
			GOTO(out, rc);

		osd_scrub_file_reset(scrub,
				     LDISKFS_SB(osd_sb(osd))->s_es->s_uuid,
				     SF_RECREATED);
		osd_oi_count = sf->sf_oi_count;
		goto create;
	}

	/* if previous failed then try found single OI from old filesystem */
	rc = osd_oi_open(info, osd, OSD_OI_NAME_BASE, &oi[0], false);
	if (rc == 0) { /* found single OI from old filesystem */
		ldiskfs_clear_bit(0, sf->sf_oi_bitmap);
		if (sf->sf_success_count == 0)
			/* XXX: There is one corner case that if the OI_scrub
			 *	file crashed or lost and we regard it upgrade,
			 *	then we allow IGIF lookup to bypass OI files.
			 *
			 *	The risk is that osd_fid_lookup() may found
			 *	a wrong inode with the given IGIF especially
			 *	when the MDT has performed file-level backup
			 *	and restored after former upgrading from 1.8
			 *	to 2.x. Fortunately, the osd_fid_lookup()can
			 *	verify the inode to decrease the risk. */
			osd_scrub_file_reset(scrub,
					LDISKFS_SB(osd_sb(osd))->s_es->s_uuid,
					SF_UPGRADE);
		GOTO(out, rc = 1);
	} else if (rc != -ENOENT) {
		CERROR("%.16s: can't open %s: rc = %d\n",
		       LDISKFS_SB(osd_sb(osd))->s_es->s_volume_name,
		       OSD_OI_NAME_BASE, rc);
		GOTO(out, rc);
	}

	if (sf->sf_oi_count > 0) {
		int i;

		memset(sf->sf_oi_bitmap, 0, SCRUB_OI_BITMAP_SIZE);
		for (i = 0; i < osd_oi_count; i++)
			ldiskfs_set_bit(i, sf->sf_oi_bitmap);
		osd_scrub_file_reset(scrub,
				     LDISKFS_SB(osd_sb(osd))->s_es->s_uuid,
				     SF_RECREATED);
	}
	sf->sf_oi_count = osd_oi_count;

create:
	rc = osd_scrub_file_store(scrub);
	if (rc < 0) {
		osd_oi_table_put(info, oi, sf->sf_oi_count);
		GOTO(out, rc);
	}

	/* No OIs exist, new filesystem, create OI objects */
	rc = osd_oi_table_open(info, osd, oi, osd_oi_count, true);
	LASSERT(ergo(rc >= 0, rc == osd_oi_count));

	GOTO(out, rc);

out:
	if (rc < 0) {
		OBD_FREE(oi, sizeof(*oi) * OSD_OI_FID_NR_MAX);
	} else {
		LASSERT((rc & (rc - 1)) == 0);
		osd->od_oi_table = oi;
		osd->od_oi_count = rc;
		if (sf->sf_oi_count != rc) {
			sf->sf_oi_count = rc;
			rc = osd_scrub_file_store(scrub);
			if (rc < 0) {
				osd_oi_table_put(info, oi, sf->sf_oi_count);
				OBD_FREE(oi, sizeof(*oi) * OSD_OI_FID_NR_MAX);
			}
		} else {
			rc = 0;
		}
	}

	mutex_unlock(&oi_init_lock);
	return rc;
}