Ejemplo n.º 1
0
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 = LLOG_CHUNK_SIZE;
	__u64				 last_offset;
	int				 rc = 0, index = 1, last_index;
	int				 saved_index = 0;
	int				 last_called_index = 0;

	LASSERT(llh);

	buf = kzalloc(LLOG_CHUNK_SIZE, GFP_NOFS);
	if (!buf) {
		lpi->lpi_rc = -ENOMEM;
		return 0;
	}

	if (cd != NULL) {
		last_called_index = cd->lpcd_first_idx;
		index = cd->lpcd_first_idx + 1;
	}
	if (cd != NULL && cd->lpcd_last_idx)
		last_index = cd->lpcd_last_idx;
	else
		last_index = LLOG_BITMAP_BYTES * 8 - 1;

	while (rc == 0) {
		struct llog_rec_hdr *rec;

		/* skip records not set in bitmap */
		while (index <= last_index &&
		       !ext2_test_bit(index, llh->llh_bitmap))
			++index;

		LASSERT(index <= last_index + 1);
		if (index == last_index + 1)
			break;
repeat:
		CDEBUG(D_OTHER, "index: %d last_index %d\n",
		       index, last_index);

		/* get the buf with our target record; avoid old garbage */
		memset(buf, 0, LLOG_CHUNK_SIZE);
		last_offset = cur_offset;
		rc = llog_next_block(lpi->lpi_env, loghandle, &saved_index,
				     index, &cur_offset, buf, LLOG_CHUNK_SIZE);
		if (rc)
			goto out;

		/* 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;
		     (char *)rec < buf + LLOG_CHUNK_SIZE;
		     rec = (struct llog_rec_hdr *)((char *)rec + rec->lrh_len)){

			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);

			if (rec->lrh_index == 0) {
				/* probably another rec just got added? */
				rc = 0;
				if (index <= loghandle->lgh_last_idx)
					goto repeat;
				goto out; /* no more records */
			}
			if (rec->lrh_len == 0 ||
			    rec->lrh_len > LLOG_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;
			}

			CDEBUG(D_OTHER,
			       "lrh_index: %d lrh_len: %d (%d remains)\n",
			       rec->lrh_index, rec->lrh_len,
			       (int)(buf + LLOG_CHUNK_SIZE - (char *)rec));

			loghandle->lgh_cur_idx = rec->lrh_index;
			loghandle->lgh_cur_offset = (char *)rec - (char *)buf +
						    last_offset;

			/* if set, process the callback on this record */
			if (ext2_test_bit(index, llh->llh_bitmap)) {
				rc = lpi->lpi_cb(lpi->lpi_env, loghandle, rec,
						 lpi->lpi_cbdata);
				last_called_index = index;
				if (rc == LLOG_PROC_BREAK) {
					goto out;
				} else if (rc == LLOG_DEL_RECORD) {
					llog_cancel_rec(lpi->lpi_env,
							loghandle,
							rec->lrh_index);
					rc = 0;
				}
				if (rc)
					goto out;
			} else {
				CDEBUG(D_OTHER, "Skipped index %d\n", index);
			}

			/* next record, still in buffer? */
			++index;
			if (index > last_index) {
				rc = 0;
				goto out;
			}
		}
	}

out:
	if (cd != NULL)
		cd->lpcd_last_idx = last_called_index;

	kfree(buf);
	lpi->lpi_rc = rc;
	return 0;
}
Ejemplo n.º 2
0
void cfs_init_completion(cfs_completion_t *c)
{
        LASSERT(c != NULL);
        c->done = 0;
        cfs_waitq_init(&c->wait);
}
Ejemplo n.º 3
0
void cfs_init_rwsem(cfs_rw_semaphore_t *s)
{
        LASSERT(s != NULL);
        (void)s;
}
Ejemplo n.º 4
0
void cfs_spin_unlock_bh(cfs_spinlock_t *lock)
{
        LASSERT(lock != NULL);
        (void)lock;
}
Ejemplo n.º 5
0
int __down_interruptible(cfs_semaphore_t *s)
{
        LASSERT(s != NULL);
        (void)s;
        return 0;
}
Ejemplo n.º 6
0
/**
 * Retrieve fldb entry from MDT0 and add to local FLDB and cache.
 **/
int fld_update_from_controller(const struct lu_env *env,
			       struct lu_server_fld *fld)
{
	struct fld_thread_info	  *info;
	struct lu_seq_range	  *range;
	struct lu_seq_range_array *lsra;
	__u32			  index;
	struct ptlrpc_request	  *req;
	int			  rc;
	int			  i;
	ENTRY;

	/* Update only happens during initalization, i.e. local FLDB
	 * does not exist yet */
	if (!fld->lsf_new)
		RETURN(0);

	rc = fld_name_to_index(fld->lsf_name, &index);
	if (rc < 0)
		RETURN(rc);

	/* No need update fldb for MDT0 */
	if (index == 0)
		RETURN(0);

	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
	LASSERT(info != NULL);
	range = &info->fti_lrange;
	memset(range, 0, sizeof(*range));
	range->lsr_index = index;
	fld_range_set_mdt(range);

	do {
		rc = fld_client_rpc(fld->lsf_control_exp, range, FLD_READ,
				    &req);
		if (rc != 0 && rc != -EAGAIN)
			GOTO(out, rc);

		LASSERT(req != NULL);
		lsra = (struct lu_seq_range_array *)req_capsule_server_get(
					  &req->rq_pill, &RMF_GENERIC_DATA);
		if (lsra == NULL)
			GOTO(out, rc = -EPROTO);

		range_array_le_to_cpu(lsra, lsra);
		for (i = 0; i < lsra->lsra_count; i++) {
			int rc1;

			if (lsra->lsra_lsr[i].lsr_flags != LU_SEQ_RANGE_MDT)
				GOTO(out, rc = -EINVAL);

			if (lsra->lsra_lsr[i].lsr_index != index)
				GOTO(out, rc = -EINVAL);

			rc1 = fld_insert_entry(env, fld, &lsra->lsra_lsr[i]);
			if (rc1 != 0)
				GOTO(out, rc = rc1);
		}
		if (rc == -EAGAIN)
			*range = lsra->lsra_lsr[lsra->lsra_count - 1];
	} while (rc == -EAGAIN);

	fld->lsf_new = 1;
out:
	if (req != NULL)
		ptlrpc_req_finished(req);

	RETURN(rc);
}
Ejemplo n.º 7
0
/**
 * Helper for osc_dlm_blocking_ast() handling discrepancies between cl_lock
 * and ldlm_lock caches.
 */
static int osc_dlm_blocking_ast0(const struct lu_env *env,
                                 struct ldlm_lock *dlmlock,
                                 void *data, int flag)
{
	struct cl_object	*obj = NULL;
	int			result = 0;
	int			discard;
	enum cl_lock_mode	mode = CLM_READ;
	ENTRY;

	LASSERT(flag == LDLM_CB_CANCELING);

	lock_res_and_lock(dlmlock);
	if (dlmlock->l_granted_mode != dlmlock->l_req_mode) {
		dlmlock->l_ast_data = NULL;
		unlock_res_and_lock(dlmlock);
		RETURN(0);
	}

	discard = ldlm_is_discard_data(dlmlock);
	if (dlmlock->l_granted_mode & (LCK_PW | LCK_GROUP))
		mode = CLM_WRITE;

	if (dlmlock->l_ast_data != NULL) {
		obj = osc2cl(dlmlock->l_ast_data);
		dlmlock->l_ast_data = NULL;

		cl_object_get(obj);
	}

	unlock_res_and_lock(dlmlock);

	/* if l_ast_data is NULL, the dlmlock was enqueued by AGL or
	 * the object has been destroyed. */
	if (obj != NULL) {
		struct ldlm_extent *extent = &dlmlock->l_policy_data.l_extent;
		struct cl_attr *attr = &osc_env_info(env)->oti_attr;
		__u64 old_kms;

		/* Destroy pages covered by the extent of the DLM lock */
		result = osc_lock_flush(cl2osc(obj),
					cl_index(obj, extent->start),
					cl_index(obj, extent->end),
					mode, discard);

		/* losing a lock, update kms */
		lock_res_and_lock(dlmlock);
		cl_object_attr_lock(obj);
		/* Must get the value under the lock to avoid race. */
		old_kms = cl2osc(obj)->oo_oinfo->loi_kms;
		/* Update the kms. Need to loop all granted locks.
		 * Not a problem for the client */
		attr->cat_kms = ldlm_extent_shift_kms(dlmlock, old_kms);

		cl_object_attr_update(env, obj, attr, CAT_KMS);
		cl_object_attr_unlock(obj);
		unlock_res_and_lock(dlmlock);

		cl_object_put(env, obj);
	}
	RETURN(result);
}
Ejemplo n.º 8
0
static int mdt_ck_thread_main(void *args)
{
        struct mdt_device      *mdt = args;
        struct ptlrpc_thread   *thread = &mdt->mdt_ck_thread;
        struct lustre_capa_key *bkey = &mdt->mdt_capa_keys[0],
                               *rkey = &mdt->mdt_capa_keys[1];
        struct lustre_capa_key *tmp;
        struct lu_env           env;
        struct mdt_thread_info *info;
        struct md_device       *next;
        struct l_wait_info      lwi = { 0 };
        mdsno_t                 mdsnum;
        int                     rc;
        ENTRY;

        cfs_daemonize_ctxt("mdt_ck");
        cfs_block_allsigs();

        thread_set_flags(thread, SVC_RUNNING);
        cfs_waitq_signal(&thread->t_ctl_waitq);

        rc = lu_env_init(&env, LCT_MD_THREAD|LCT_REMEMBER|LCT_NOREF);
        if (rc)
                RETURN(rc);

        thread->t_env = &env;
        env.le_ctx.lc_thread = thread;
        env.le_ctx.lc_cookie = 0x1;

        info = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
        LASSERT(info != NULL);

	tmp = &info->mti_capa_key;
	mdsnum = mdt_seq_site(mdt)->ss_node_id;
        while (1) {
                l_wait_event(thread->t_ctl_waitq,
                             thread_is_stopping(thread) ||
                             thread_is_event(thread),
                             &lwi);

                if (thread_is_stopping(thread))
                        break;
                thread_clear_flags(thread, SVC_EVENT);

                if (cfs_time_before(cfs_time_current(), mdt->mdt_ck_expiry))
                        break;

                *tmp = *rkey;
                make_capa_key(tmp, mdsnum, rkey->lk_keyid);

                next = mdt->mdt_child;
                rc = next->md_ops->mdo_update_capa_key(&env, next, tmp);
                if (!rc) {
			spin_lock(&capa_lock);
			*bkey = *rkey;
			*rkey = *tmp;
			spin_unlock(&capa_lock);

			rc = write_capa_keys(&env, mdt, mdt->mdt_capa_keys);
			if (rc) {
				spin_lock(&capa_lock);
				*rkey = *bkey;
				memset(bkey, 0, sizeof(*bkey));
				spin_unlock(&capa_lock);
                        } else {
                                set_capa_key_expiry(mdt);
                                DEBUG_CAPA_KEY(D_SEC, rkey, "new");
                        }
                }
                if (rc) {
                        DEBUG_CAPA_KEY(D_ERROR, rkey, "update failed for");
                        /* next retry is in 300 sec */
                        mdt->mdt_ck_expiry = jiffies + 300 * CFS_HZ;
                }

                cfs_timer_arm(&mdt->mdt_ck_timer, mdt->mdt_ck_expiry);
                CDEBUG(D_SEC, "mdt_ck_timer %lu\n", mdt->mdt_ck_expiry);
        }
        lu_env_fini(&env);

        thread_set_flags(thread, SVC_STOPPED);
        cfs_waitq_signal(&thread->t_ctl_waitq);
        RETURN(0);
}
Ejemplo n.º 9
0
static int ll_get_name(struct dentry *dentry, char *name,
		       struct dentry *child)
{
	struct inode *dir = d_inode(dentry);
	int rc;
	struct ll_getname_data lgd = {
		.lgd_name = name,
		.lgd_fid = ll_i2info(d_inode(child))->lli_fid,
		.ctx.actor = ll_nfs_get_name_filldir,
	};

	if (!dir || !S_ISDIR(dir->i_mode)) {
		rc = -ENOTDIR;
		goto out;
	}

	if (!dir->i_fop) {
		rc = -EINVAL;
		goto out;
	}

	mutex_lock(&dir->i_mutex);
	rc = ll_dir_read(dir, &lgd.ctx);
	mutex_unlock(&dir->i_mutex);
	if (!rc && !lgd.lgd_found)
		rc = -ENOENT;
out:
	return rc;
}

static struct dentry *ll_fh_to_dentry(struct super_block *sb, struct fid *fid,
				      int fh_len, int fh_type)
{
	struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;

	if (fh_type != LUSTRE_NFS_FID)
		return ERR_PTR(-EPROTO);

	return ll_iget_for_nfs(sb, &nfs_fid->lnf_child, &nfs_fid->lnf_parent);
}

static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid,
				      int fh_len, int fh_type)
{
	struct lustre_nfs_fid *nfs_fid = (struct lustre_nfs_fid *)fid;

	if (fh_type != LUSTRE_NFS_FID)
		return ERR_PTR(-EPROTO);

	return ll_iget_for_nfs(sb, &nfs_fid->lnf_parent, NULL);
}

static struct dentry *ll_get_parent(struct dentry *dchild)
{
	struct ptlrpc_request *req = NULL;
	struct inode	  *dir = d_inode(dchild);
	struct ll_sb_info     *sbi;
	struct dentry	 *result = NULL;
	struct mdt_body       *body;
	static char	   dotdot[] = "..";
	struct md_op_data     *op_data;
	int		   rc;
	int		      lmmsize;

	LASSERT(dir && S_ISDIR(dir->i_mode));

	sbi = ll_s2sbi(dir->i_sb);

	CDEBUG(D_INFO, "getting parent for (%lu,"DFID")\n",
			dir->i_ino, PFID(ll_inode2fid(dir)));

	rc = ll_get_default_mdsize(sbi, &lmmsize);
	if (rc != 0)
		return ERR_PTR(rc);

	op_data = ll_prep_md_op_data(NULL, dir, NULL, dotdot,
				     strlen(dotdot), lmmsize,
				     LUSTRE_OPC_ANY, NULL);
	if (IS_ERR(op_data))
		return (void *)op_data;

	rc = md_getattr_name(sbi->ll_md_exp, op_data, &req);
	ll_finish_md_op_data(op_data);
	if (rc) {
		CERROR("failure %d inode %lu get parent\n", rc, dir->i_ino);
		return ERR_PTR(rc);
	}
	body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
	LASSERT(body->valid & OBD_MD_FLID);

	CDEBUG(D_INFO, "parent for "DFID" is "DFID"\n",
		PFID(ll_inode2fid(dir)), PFID(&body->fid1));

	result = ll_iget_for_nfs(dir->i_sb, &body->fid1, NULL);

	ptlrpc_req_finished(req);
	return result;
}

struct export_operations lustre_export_operations = {
       .get_parent = ll_get_parent,
       .encode_fh  = ll_encode_fh,
       .get_name   = ll_get_name,
	.fh_to_dentry = ll_fh_to_dentry,
	.fh_to_parent = ll_fh_to_parent,
};
Ejemplo n.º 10
0
static int
ofd_write_attr_set(const struct lu_env *env, struct ofd_device *ofd,
                   struct ofd_object *ofd_obj, struct lu_attr *la,
                   struct filter_fid *ff)
{
    struct ofd_thread_info	*info = ofd_info(env);
    __u64			 valid = la->la_valid;
    int			 rc;
    struct thandle		*th;
    struct dt_object	*dt_obj;
    int			 ff_needed = 0;

    ENTRY;

    LASSERT(la);

    dt_obj = ofd_object_child(ofd_obj);
    LASSERT(dt_obj != NULL);

    la->la_valid &= LA_UID | LA_GID;

    rc = ofd_attr_handle_ugid(env, ofd_obj, la, 0 /* !is_setattr */);
    if (rc != 0)
        GOTO(out, rc);

    if (ff != NULL) {
        rc = ofd_object_ff_check(env, ofd_obj);
        if (rc == -ENODATA)
            ff_needed = 1;
        else if (rc < 0)
            GOTO(out, rc);
    }

    if (!la->la_valid && !ff_needed)
        /* no attributes to set */
        GOTO(out, rc = 0);

    th = ofd_trans_create(env, ofd);
    if (IS_ERR(th))
        GOTO(out, rc = PTR_ERR(th));

    if (la->la_valid) {
        rc = dt_declare_attr_set(env, dt_obj, la, th);
        if (rc)
            GOTO(out_tx, rc);
    }

    if (ff_needed) {
        info->fti_buf.lb_buf = ff;
        info->fti_buf.lb_len = sizeof(*ff);
        rc = dt_declare_xattr_set(env, dt_obj, &info->fti_buf,
                                  XATTR_NAME_FID, 0, th);
        if (rc)
            GOTO(out_tx, rc);
    }

    /* We don't need a transno for this operation which will be re-executed
     * anyway when the OST_WRITE (with a transno assigned) is replayed */
    rc = dt_trans_start_local(env, ofd->ofd_osd , th);
    if (rc)
        GOTO(out_tx, rc);

    /* set uid/gid */
    if (la->la_valid) {
        rc = dt_attr_set(env, dt_obj, la, th,
                         ofd_object_capa(env, ofd_obj));
        if (rc)
            GOTO(out_tx, rc);
    }

    /* set filter fid EA */
    if (ff_needed) {
        rc = dt_xattr_set(env, dt_obj, &info->fti_buf, XATTR_NAME_FID,
                          0, th, BYPASS_CAPA);
        if (rc)
            GOTO(out_tx, rc);
    }

    EXIT;
out_tx:
    dt_trans_stop(env, ofd->ofd_osd, th);
out:
    la->la_valid = valid;
    return rc;
}
Ejemplo n.º 11
0
int mdc_create(struct obd_export *exp, struct md_op_data *op_data,
		const void *data, size_t datalen,
		umode_t mode, uid_t uid, gid_t gid,
		cfs_cap_t cap_effective, __u64 rdev,
		struct ptlrpc_request **request)
{
        struct ptlrpc_request *req;
        int level, rc;
        int count, resends = 0;
        struct obd_import *import = exp->exp_obd->u.cli.cl_import;
        int generation = import->imp_generation;
	struct list_head cancels = LIST_HEAD_INIT(cancels);
        ENTRY;

	/* For case if upper layer did not alloc fid, do it now. */
	if (!fid_is_sane(&op_data->op_fid2)) {
		/*
		 * mdc_fid_alloc() may return errno 1 in case of switch to new
		 * sequence, handle this.
		 */
		rc = mdc_fid_alloc(NULL, exp, &op_data->op_fid2, op_data);
		if (rc < 0)
			RETURN(rc);
	}

rebuild:
        count = 0;
        if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
            (fid_is_sane(&op_data->op_fid1)))
                count = mdc_resource_get_unused(exp, &op_data->op_fid1,
                                                &cancels, LCK_EX,
                                                MDS_INODELOCK_UPDATE);

        req = ptlrpc_request_alloc(class_exp2cliimp(exp),
                                   &RQF_MDS_REINT_CREATE_RMT_ACL);
        if (req == NULL) {
                ldlm_lock_list_put(&cancels, l_bl_ast, count);
                RETURN(-ENOMEM);
        }
        mdc_set_capa_size(req, &RMF_CAPA1, op_data->op_capa1);
        req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
                             op_data->op_namelen + 1);
        req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT,
                             data && datalen ? datalen : 0);

	rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
	if (rc) {
		ptlrpc_request_free(req);
		RETURN(rc);
	}

        /*
         * mdc_create_pack() fills msg->bufs[1] with name and msg->bufs[2] with
         * tgt, for symlinks or lov MD data.
         */
        mdc_create_pack(req, op_data, data, datalen, mode, uid,
                        gid, cap_effective, rdev);

        ptlrpc_request_set_replen(req);

	/* ask ptlrpc not to resend on EINPROGRESS since we have our own retry
	 * logic here */
	req->rq_no_retry_einprogress = 1;

        if (resends) {
                req->rq_generation_set = 1;
                req->rq_import_generation = generation;
                req->rq_sent = cfs_time_current_sec() + resends;
        }
        level = LUSTRE_IMP_FULL;
 resend:
        rc = mdc_reint(req, exp->exp_obd->u.cli.cl_rpc_lock, level);

        /* Resend if we were told to. */
        if (rc == -ERESTARTSYS) {
                level = LUSTRE_IMP_RECOVER;
                goto resend;
        } else if (rc == -EINPROGRESS) {
                /* Retry create infinitely until succeed or get other
                 * error code. */
                ptlrpc_req_finished(req);
                resends++;

                CDEBUG(D_HA, "%s: resend:%d create on "DFID"/"DFID"\n",
                       exp->exp_obd->obd_name, resends,
                       PFID(&op_data->op_fid1), PFID(&op_data->op_fid2));

                if (generation == import->imp_generation) {
                        goto rebuild;
                } else {
                        CDEBUG(D_HA, "resend cross eviction\n");
                        RETURN(-EIO);
                }
        } else if (rc == 0) {
                struct mdt_body *body;
                struct lustre_capa *capa;

                body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
                LASSERT(body);
		if (body->mbo_valid & OBD_MD_FLMDSCAPA) {
                        capa = req_capsule_server_get(&req->rq_pill,
                                                      &RMF_CAPA1);
                        if (capa == NULL)
                                rc = -EPROTO;
                }
        }

        *request = req;
        RETURN(rc);
}
Ejemplo n.º 12
0
int ofd_preprw(const struct lu_env *env, int cmd, struct obd_export *exp,
               struct obdo *oa, int objcount, struct obd_ioobj *obj,
               struct niobuf_remote *rnb, int *nr_local,
               struct niobuf_local *lnb, struct obd_trans_info *oti,
               struct lustre_capa *capa)
{
    struct tgt_session_info	*tsi = tgt_ses_info(env);
    struct ofd_device	*ofd = ofd_exp(exp);
    struct ofd_thread_info	*info;
    char			*jobid;
    int			 rc = 0;

    if (*nr_local > PTLRPC_MAX_BRW_PAGES) {
        CERROR("%s: bulk has too many pages %d, which exceeds the"
               "maximum pages per RPC of %d\n",
               exp->exp_obd->obd_name, *nr_local, PTLRPC_MAX_BRW_PAGES);
        RETURN(-EPROTO);
    }

    if (tgt_ses_req(tsi) == NULL) { /* echo client case */
        LASSERT(oti != NULL);
        lu_env_refill((struct lu_env *)env);
        info = ofd_info_init(env, exp);
        ofd_oti2info(info, oti);
        jobid = oti->oti_jobid;
    } else {
        info = tsi2ofd_info(tsi);
        jobid = tsi->tsi_jobid;
    }

    LASSERT(oa != NULL);

    if (OBD_FAIL_CHECK(OBD_FAIL_OST_ENOENT)) {
        struct ofd_seq		*oseq;

        oseq = ofd_seq_load(env, ofd, ostid_seq(&oa->o_oi));
        if (IS_ERR(oseq)) {
            CERROR("%s: Can not find seq for "DOSTID
                   ": rc = %ld\n", ofd_name(ofd), POSTID(&oa->o_oi),
                   PTR_ERR(oseq));
            RETURN(-EINVAL);
        }

        if (oseq->os_destroys_in_progress == 0) {
            /* don't fail lookups for orphan recovery, it causes
             * later LBUGs when objects still exist during
             * precreate */
            ofd_seq_put(env, oseq);
            RETURN(-ENOENT);
        }
        ofd_seq_put(env, oseq);
    }

    LASSERT(objcount == 1);
    LASSERT(obj->ioo_bufcnt > 0);

    rc = ostid_to_fid(&info->fti_fid, &oa->o_oi, 0);
    if (unlikely(rc != 0))
        RETURN(rc);

    if (cmd == OBD_BRW_WRITE) {
        rc = ofd_auth_capa(exp, &info->fti_fid, ostid_seq(&oa->o_oi),
                           capa, CAPA_OPC_OSS_WRITE);
        if (rc == 0) {
            la_from_obdo(&info->fti_attr, oa, OBD_MD_FLGETATTR);
            rc = ofd_preprw_write(env, exp, ofd, &info->fti_fid,
                                  &info->fti_attr, oa, objcount,
                                  obj, rnb, nr_local, lnb, jobid);
        }
    } else if (cmd == OBD_BRW_READ) {
        rc = ofd_auth_capa(exp, &info->fti_fid, ostid_seq(&oa->o_oi),
                           capa, CAPA_OPC_OSS_READ);
        if (rc == 0) {
            ofd_grant_prepare_read(env, exp, oa);
            rc = ofd_preprw_read(env, exp, ofd, &info->fti_fid,
                                 &info->fti_attr, obj->ioo_bufcnt,
                                 rnb, nr_local, lnb, jobid);
            obdo_from_la(oa, &info->fti_attr, LA_ATIME);
        }
    } else {
        CERROR("%s: wrong cmd %d received!\n",
               exp->exp_obd->obd_name, cmd);
        rc = -EPROTO;
    }
    RETURN(rc);
}
Ejemplo n.º 13
0
static int ofd_preprw_write(const struct lu_env *env, struct obd_export *exp,
                            struct ofd_device *ofd, struct lu_fid *fid,
                            struct lu_attr *la, struct obdo *oa,
                            int objcount, struct obd_ioobj *obj,
                            struct niobuf_remote *rnb, int *nr_local,
                            struct niobuf_local *lnb, char *jobid)
{
    struct ofd_object	*fo;
    int			 i, j, k, rc = 0, tot_bytes = 0;

    ENTRY;
    LASSERT(env != NULL);
    LASSERT(objcount == 1);

    if (unlikely(exp->exp_obd->obd_recovering)) {
        struct ofd_thread_info *info = ofd_info(env);

        /* copied from ofd_precreate_object */
        /* XXX this should be consolidated to use the same code
         *     instead of a copy, due to the ongoing risk of bugs. */
        memset(&info->fti_attr, 0, sizeof(info->fti_attr));
        info->fti_attr.la_valid = LA_TYPE | LA_MODE;
        info->fti_attr.la_mode = S_IFREG | S_ISUID | S_ISGID | 0666;
        info->fti_attr.la_valid |= LA_ATIME | LA_MTIME | LA_CTIME;
        /* Initialize a/c/m time so any client timestamp will always
         * be newer and update the inode. ctime = 0 is also handled
         * specially in osd_inode_setattr().  See LU-221, LU-1042 */
        info->fti_attr.la_atime = 0;
        info->fti_attr.la_mtime = 0;
        info->fti_attr.la_ctime = 0;

        fo = ofd_object_find_or_create(env, ofd, fid, &info->fti_attr);
    } else {
        fo = ofd_object_find(env, ofd, fid);
    }

    if (IS_ERR(fo))
        GOTO(out, rc = PTR_ERR(fo));
    LASSERT(fo != NULL);

    ofd_read_lock(env, fo);
    if (!ofd_object_exists(fo)) {
        CERROR("%s: BRW to missing obj "DOSTID"\n",
               exp->exp_obd->obd_name, POSTID(&obj->ioo_oid));
        ofd_read_unlock(env, fo);
        ofd_object_put(env, fo);
        GOTO(out, rc = -ENOENT);
    }

    /* Process incoming grant info, set OBD_BRW_GRANTED flag and grant some
     * space back if possible */
    ofd_grant_prepare_write(env, exp, oa, rnb, obj->ioo_bufcnt);

    /* parse remote buffers to local buffers and prepare the latter */
    *nr_local = 0;
    for (i = 0, j = 0; i < obj->ioo_bufcnt; i++) {
        rc = dt_bufs_get(env, ofd_object_child(fo),
                         rnb + i, lnb + j, 1,
                         ofd_object_capa(env, fo));
        if (unlikely(rc < 0))
            GOTO(err, rc);
        LASSERT(rc <= PTLRPC_MAX_BRW_PAGES);
        /* correct index for local buffers to continue with */
        for (k = 0; k < rc; k++) {
            lnb[j+k].lnb_flags = rnb[i].rnb_flags;
            if (!(rnb[i].rnb_flags & OBD_BRW_GRANTED))
                lnb[j+k].lnb_rc = -ENOSPC;

            /* remote client can't break through quota */
            if (exp_connect_rmtclient(exp))
                lnb[j+k].lnb_flags &= ~OBD_BRW_NOQUOTA;
        }
        j += rc;
        *nr_local += rc;
        LASSERT(j <= PTLRPC_MAX_BRW_PAGES);
        tot_bytes += rnb[i].rnb_len;
    }
    LASSERT(*nr_local > 0 && *nr_local <= PTLRPC_MAX_BRW_PAGES);

    rc = dt_write_prep(env, ofd_object_child(fo), lnb, *nr_local);
    if (unlikely(rc != 0))
        GOTO(err, rc);

    ofd_counter_incr(exp, LPROC_OFD_STATS_WRITE, jobid, tot_bytes);
    RETURN(0);
err:
    dt_bufs_put(env, ofd_object_child(fo), lnb, *nr_local);
    ofd_read_unlock(env, fo);
    /* ofd_grant_prepare_write() was called, so we must commit */
    ofd_grant_commit(env, exp, rc);
out:
    /* let's still process incoming grant information packed in the oa,
     * but without enforcing grant since we won't proceed with the write.
     * Just like a read request actually. */
    ofd_grant_prepare_read(env, exp, oa);
    return rc;
}
Ejemplo n.º 14
0
int llog_reverse_process(const struct lu_env *env,
			 struct llog_handle *loghandle, llog_cb_t cb,
			 void *data, void *catdata)
{
	struct llog_log_hdr *llh = loghandle->lgh_hdr;
	struct llog_process_cat_data *cd = catdata;
	void *buf;
	int rc = 0, first_index = 1, index, idx;

	buf = kzalloc(LLOG_CHUNK_SIZE, GFP_NOFS);
	if (!buf)
		return -ENOMEM;

	if (cd != NULL)
		first_index = cd->lpcd_first_idx + 1;
	if (cd != NULL && cd->lpcd_last_idx)
		index = cd->lpcd_last_idx;
	else
		index = LLOG_BITMAP_BYTES * 8 - 1;

	while (rc == 0) {
		struct llog_rec_hdr *rec;
		struct llog_rec_tail *tail;

		/* skip records not set in bitmap */
		while (index >= first_index &&
		       !ext2_test_bit(index, llh->llh_bitmap))
			--index;

		LASSERT(index >= first_index - 1);
		if (index == first_index - 1)
			break;

		/* get the buf with our target record; avoid old garbage */
		memset(buf, 0, LLOG_CHUNK_SIZE);
		rc = llog_prev_block(env, loghandle, index, buf,
				     LLOG_CHUNK_SIZE);
		if (rc)
			goto out;

		rec = buf;
		idx = rec->lrh_index;
		CDEBUG(D_RPCTRACE, "index %u : idx %u\n", index, idx);
		while (idx < index) {
			rec = (void *)rec + rec->lrh_len;
			if (LLOG_REC_HDR_NEEDS_SWABBING(rec))
				lustre_swab_llog_rec(rec);
			idx ++;
		}
		LASSERT(idx == index);
		tail = (void *)rec + rec->lrh_len - sizeof(*tail);

		/* process records in buffer, starting where we found one */
		while ((void *)tail > buf) {
			if (tail->lrt_index == 0) {
				/* no more records */
				rc = 0;
				goto out;
			}

			/* if set, process the callback on this record */
			if (ext2_test_bit(index, llh->llh_bitmap)) {
				rec = (void *)tail - tail->lrt_len +
				      sizeof(*tail);

				rc = cb(env, loghandle, rec, data);
				if (rc == LLOG_PROC_BREAK) {
					goto out;
				} else if (rc == LLOG_DEL_RECORD) {
					llog_cancel_rec(env, loghandle,
							tail->lrt_index);
					rc = 0;
				}
				if (rc)
					goto out;
			}

			/* previous record, still in buffer? */
			--index;
			if (index < first_index) {
				rc = 0;
				goto out;
			}
			tail = (void *)tail - tail->lrt_len;
		}
	}

out:
	kfree(buf);
	return rc;
}
Ejemplo n.º 15
0
void cfs_waitlink_init(struct cfs_waitlink *link)
{
        LASSERT(link != NULL);
        (void)link;
}
Ejemplo n.º 16
0
/* Allocate new fid on passed client @seq and save it to @fid. */
int seq_client_alloc_fid(const struct lu_env *env,
			 struct lu_client_seq *seq, struct lu_fid *fid)
{
	wait_queue_t link;
	int rc;
	ENTRY;

	LASSERT(seq != NULL);
	LASSERT(fid != NULL);

	init_waitqueue_entry_current(&link);
	mutex_lock(&seq->lcs_mutex);

	if (OBD_FAIL_CHECK(OBD_FAIL_SEQ_EXHAUST))
		seq->lcs_fid.f_oid = seq->lcs_width;

        while (1) {
                seqno_t seqnr;

                if (!fid_is_zero(&seq->lcs_fid) &&
                    fid_oid(&seq->lcs_fid) < seq->lcs_width) {
                        /* Just bump last allocated fid and return to caller. */
                        seq->lcs_fid.f_oid += 1;
                        rc = 0;
                        break;
                }

                rc = seq_fid_alloc_prep(seq, &link);
                if (rc)
                        continue;

                rc = seq_client_alloc_seq(env, seq, &seqnr);
                if (rc) {
                        CERROR("%s: Can't allocate new sequence, "
                               "rc %d\n", seq->lcs_name, rc);
                        seq_fid_alloc_fini(seq);
			mutex_unlock(&seq->lcs_mutex);
                        RETURN(rc);
                }

                CDEBUG(D_INFO, "%s: Switch to sequence "
                       "[0x%16.16"LPF64"x]\n", seq->lcs_name, seqnr);

                seq->lcs_fid.f_oid = LUSTRE_FID_INIT_OID;
                seq->lcs_fid.f_seq = seqnr;
                seq->lcs_fid.f_ver = 0;

                /*
                 * Inform caller that sequence switch is performed to allow it
                 * to setup FLD for it.
                 */
                rc = 1;

                seq_fid_alloc_fini(seq);
                break;
        }

        *fid = seq->lcs_fid;
	mutex_unlock(&seq->lcs_mutex);

        CDEBUG(D_INFO, "%s: Allocated FID "DFID"\n", seq->lcs_name,  PFID(fid));
        RETURN(rc);
}
Ejemplo n.º 17
0
int cfs_waitq_active(struct cfs_waitq *waitq)
{
        LASSERT(waitq != NULL);
        (void)waitq;
        return 0;
}
Ejemplo n.º 18
0
static int seq_client_rpc(struct lu_client_seq *seq,
                          struct lu_seq_range *output, __u32 opc,
                          const char *opcname)
{
	struct obd_export     *exp = seq->lcs_exp;
	struct ptlrpc_request *req;
	struct lu_seq_range   *out, *in;
	__u32                 *op;
	unsigned int           debug_mask;
	int                    rc;
	ENTRY;

	LASSERT(exp != NULL && !IS_ERR(exp));
	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_SEQ_QUERY,
					LUSTRE_MDS_VERSION, SEQ_QUERY);
	if (req == NULL)
		RETURN(-ENOMEM);

	/* Init operation code */
	op = req_capsule_client_get(&req->rq_pill, &RMF_SEQ_OPC);
	*op = opc;

	/* Zero out input range, this is not recovery yet. */
	in = req_capsule_client_get(&req->rq_pill, &RMF_SEQ_RANGE);
	range_init(in);

	ptlrpc_request_set_replen(req);

	in->lsr_index = seq->lcs_space.lsr_index;
	if (seq->lcs_type == LUSTRE_SEQ_METADATA)
		fld_range_set_mdt(in);
	else
		fld_range_set_ost(in);

	if (opc == SEQ_ALLOC_SUPER) {
		req->rq_request_portal = SEQ_CONTROLLER_PORTAL;
		req->rq_reply_portal = MDC_REPLY_PORTAL;
		/* During allocating super sequence for data object,
		 * the current thread might hold the export of MDT0(MDT0
		 * precreating objects on this OST), and it will send the
		 * request to MDT0 here, so we can not keep resending the
		 * request here, otherwise if MDT0 is failed(umounted),
		 * it can not release the export of MDT0 */
		if (seq->lcs_type == LUSTRE_SEQ_DATA)
			req->rq_no_delay = req->rq_no_resend = 1;
		debug_mask = D_CONSOLE;
	} else {
		if (seq->lcs_type == LUSTRE_SEQ_METADATA)
			req->rq_request_portal = SEQ_METADATA_PORTAL;
		else
			req->rq_request_portal = SEQ_DATA_PORTAL;
		debug_mask = D_INFO;
	}

	ptlrpc_at_set_req_timeout(req);

	if (opc != SEQ_ALLOC_SUPER && seq->lcs_type == LUSTRE_SEQ_METADATA)
		mdc_get_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);

	rc = ptlrpc_queue_wait(req);

	if (opc != SEQ_ALLOC_SUPER && seq->lcs_type == LUSTRE_SEQ_METADATA)
		mdc_put_rpc_lock(exp->exp_obd->u.cli.cl_rpc_lock, NULL);
	if (rc)
		GOTO(out_req, rc);

	out = req_capsule_server_get(&req->rq_pill, &RMF_SEQ_RANGE);
	*output = *out;

	if (!range_is_sane(output)) {
		CERROR("%s: Invalid range received from server: "
		       DRANGE"\n", seq->lcs_name, PRANGE(output));
		GOTO(out_req, rc = -EINVAL);
	}

	if (range_is_exhausted(output)) {
		CERROR("%s: Range received from server is exhausted: "
		       DRANGE"]\n", seq->lcs_name, PRANGE(output));
		GOTO(out_req, rc = -EINVAL);
	}

	CDEBUG_LIMIT(debug_mask, "%s: Allocated %s-sequence "DRANGE"]\n",
		     seq->lcs_name, opcname, PRANGE(output));

	EXIT;
out_req:
	ptlrpc_req_finished(req);
	return rc;
}
Ejemplo n.º 19
0
/**
 * Create a memory descriptor and attach it to a ME
 *
 * \param meh A handle for a ME to associate the new MD with.
 * \param umd Provides initial values for the user-visible parts of a MD.
 * Other than its use for initialization, there is no linkage between this
 * structure and the MD maintained by the LNet.
 * \param unlink A flag to indicate whether the MD is automatically unlinked
 * when it becomes inactive, either because the operation threshold drops to
 * zero or because the available memory becomes less than \a umd.max_size.
 * (Note that the check for unlinking a MD only occurs after the completion
 * of a successful operation on the MD.) The value LNET_UNLINK enables auto
 * unlinking; the value LNET_RETAIN disables it.
 * \param handle On successful returns, a handle to the newly created MD is
 * saved here. This handle can be used later in LNetMDUnlink().
 *
 * \retval 0       On success.
 * \retval -EINVAL If \a umd is not valid.
 * \retval -ENOMEM If new MD cannot be allocated.
 * \retval -ENOENT Either \a meh or \a umd.eq_handle does not point to a
 * valid object. Note that it's OK to supply a NULL \a umd.eq_handle by
 * calling LNetInvalidateHandle() on it.
 * \retval -EBUSY  If the ME pointed to by \a meh is already associated with
 * a MD.
 */
int
LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd,
	     lnet_unlink_t unlink, lnet_handle_md_t *handle)
{
	CFS_LIST_HEAD		(matches);
	CFS_LIST_HEAD		(drops);
	struct lnet_me		*me;
	struct lnet_libmd	*md;
	int			cpt;
	int			rc;

        LASSERT (the_lnet.ln_init);
        LASSERT (the_lnet.ln_refcount > 0);

        if (lnet_md_validate(&umd) != 0)
                return -EINVAL;

        if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT)) == 0) {
                CERROR("Invalid option: no MD_OP set\n");
                return -EINVAL;
        }

        md = lnet_md_alloc(&umd);
        if (md == NULL)
                return -ENOMEM;

	rc = lnet_md_build(md, &umd, unlink);
	cpt = lnet_cpt_of_cookie(meh.cookie);

	lnet_res_lock(cpt);
	if (rc != 0)
		goto failed;

	me = lnet_handle2me(&meh);
	if (me == NULL)
		rc = -ENOENT;
	else if (me->me_md != NULL)
		rc = -EBUSY;
	else
		rc = lnet_md_link(md, umd.eq_handle, cpt);

	if (rc != 0)
		goto failed;

	/* attach this MD to portal of ME and check if it matches any
	 * blocked msgs on this portal */
	lnet_ptl_attach_md(me, md, &matches, &drops);

	lnet_md2handle(handle, md);

	lnet_res_unlock(cpt);

	lnet_drop_delayed_msg_list(&drops, "Bad match");
	lnet_recv_delayed_msg_list(&matches);

	return 0;

 failed:
	lnet_md_free_locked(md);

	lnet_res_unlock(cpt);
	return rc;
}
Ejemplo n.º 20
0
void cfs_waitq_signal(struct cfs_waitq *waitq)
{
        LASSERT(waitq != NULL);
        (void)waitq;
}
Ejemplo n.º 21
0
Archivo: dcache.c Proyecto: LLNL/lustre
int ll_revalidate_it(struct dentry *de, int lookup_flags,
                     struct lookup_intent *it)
{
        struct md_op_data *op_data;
        struct ptlrpc_request *req = NULL;
        struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
        struct obd_export *exp;
        struct inode *parent = de->d_parent->d_inode;
        int rc;

        ENTRY;
        CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name,
               LL_IT2STR(it));

        if (de->d_inode == NULL) {
                __u64 ibits;

                /* We can only use negative dentries if this is stat or lookup,
                   for opens and stuff we do need to query server. */
                /* If there is IT_CREAT in intent op set, then we must throw
                   away this negative dentry and actually do the request to
                   kernel to create whatever needs to be created (if possible)*/
                if (it && (it->it_op & IT_CREAT))
                        RETURN(0);

                if (de->d_flags & DCACHE_LUSTRE_INVALID)
                        RETURN(0);

                ibits = MDS_INODELOCK_UPDATE;
                rc = ll_have_md_lock(parent, &ibits, LCK_MINMODE);
                GOTO(out_sa, rc);
        }

        /* Never execute intents for mount points.
         * Attributes will be fixed up in ll_inode_revalidate_it */
        if (d_mountpoint(de))
                GOTO(out_sa, rc = 1);

        /* need to get attributes in case root got changed from other client */
        if (de == de->d_sb->s_root) {
                rc = __ll_inode_revalidate_it(de, it, MDS_INODELOCK_LOOKUP);
                if (rc == 0)
                        rc = 1;
                GOTO(out_sa, rc);
        }

        exp = ll_i2mdexp(de->d_inode);

        OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
        ll_frob_intent(&it, &lookup_it);
        LASSERT(it);

        if (it->it_op == IT_LOOKUP && !(de->d_flags & DCACHE_LUSTRE_INVALID))
                RETURN(1);

        if ((it->it_op == IT_OPEN) && de->d_inode) {
                struct inode *inode = de->d_inode;
                struct ll_inode_info *lli = ll_i2info(inode);
                struct obd_client_handle **och_p;
                __u64 *och_usecount;
                __u64 ibits;

                /*
                 * We used to check for MDS_INODELOCK_OPEN here, but in fact
                 * just having LOOKUP lock is enough to justify inode is the
                 * same. And if inode is the same and we have suitable
                 * openhandle, then there is no point in doing another OPEN RPC
                 * just to throw away newly received openhandle.  There are no
                 * security implications too, if file owner or access mode is
                 * change, LOOKUP lock is revoked.
                 */


                if (it->it_flags & FMODE_WRITE) {
                        och_p = &lli->lli_mds_write_och;
                        och_usecount = &lli->lli_open_fd_write_count;
                } else if (it->it_flags & FMODE_EXEC) {
                        och_p = &lli->lli_mds_exec_och;
                        och_usecount = &lli->lli_open_fd_exec_count;
                } else {
                        och_p = &lli->lli_mds_read_och;
                        och_usecount = &lli->lli_open_fd_read_count;
                }
                /* Check for the proper lock. */
                ibits = MDS_INODELOCK_LOOKUP;
                if (!ll_have_md_lock(inode, &ibits, LCK_MINMODE))
                        goto do_lock;
                cfs_mutex_lock(&lli->lli_och_mutex);
                if (*och_p) { /* Everything is open already, do nothing */
                        /*(*och_usecount)++;  Do not let them steal our open
                          handle from under us */
                        SET_BUT_UNUSED(och_usecount);
                        /* XXX The code above was my original idea, but in case
                           we have the handle, but we cannot use it due to later
                           checks (e.g. O_CREAT|O_EXCL flags set), nobody
                           would decrement counter increased here. So we just
                           hope the lock won't be invalidated in between. But
                           if it would be, we'll reopen the open request to
                           MDS later during file open path */
                        cfs_mutex_unlock(&lli->lli_och_mutex);
                        RETURN(1);
                } else {
                        cfs_mutex_unlock(&lli->lli_och_mutex);
                }
        }

        if (it->it_op == IT_GETATTR) {
                rc = ll_statahead_enter(parent, &de, 0);
                if (rc == 1)
                        goto mark;
        }

do_lock:
        op_data = ll_prep_md_op_data(NULL, parent, de->d_inode,
                                     de->d_name.name, de->d_name.len,
                                     0, LUSTRE_OPC_ANY, NULL);
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));

        it->it_create_mode &= ~cfs_curproc_umask();
        it->it_create_mode |= M_CHECK_STALE;
        rc = md_intent_lock(exp, op_data, NULL, 0, it,
                            lookup_flags,
                            &req, ll_md_blocking_ast, 0);
        it->it_create_mode &= ~M_CHECK_STALE;
        ll_finish_md_op_data(op_data);

        /* If req is NULL, then md_intent_lock only tried to do a lock match;
         * if all was well, it will return 1 if it found locks, 0 otherwise. */
        if (req == NULL && rc >= 0) {
                if (!rc)
                        goto do_lookup;
                GOTO(out, rc);
        }

        if (rc < 0) {
                if (rc != -ESTALE) {
                        CDEBUG(D_INFO, "ll_intent_lock: rc %d : it->it_status "
                               "%d\n", rc, it->d.lustre.it_status);
                }
                GOTO(out, rc = 0);
        }

revalidate_finish:
        rc = ll_revalidate_it_finish(req, it, de);
        if (rc != 0) {
                if (rc != -ESTALE && rc != -ENOENT)
                        ll_intent_release(it);
                GOTO(out, rc = 0);
        }

        if ((it->it_op & IT_OPEN) && de->d_inode &&
            !S_ISREG(de->d_inode->i_mode) &&
            !S_ISDIR(de->d_inode->i_mode)) {
                ll_release_openhandle(de, it);
        }
        rc = 1;

        /* unfortunately ll_intent_lock may cause a callback and revoke our
         * dentry */
        ll_dentry_rehash(de, 0);

out:
        /* We do not free request as it may be reused during following lookup
         * (see comment in mdc/mdc_locks.c::mdc_intent_lock()), request will
         * be freed in ll_lookup_it or in ll_intent_release. But if
         * request was not completed, we need to free it. (bug 5154, 9903) */
        if (req != NULL && !it_disposition(it, DISP_ENQ_COMPLETE))
                ptlrpc_req_finished(req);
        if (rc == 0) {
                ll_unhash_aliases(de->d_inode);
                /* done in ll_unhash_aliases()
                   dentry->d_flags |= DCACHE_LUSTRE_INVALID; */
        } else {
                __u64 bits = 0;

                CDEBUG(D_DENTRY, "revalidated dentry %.*s (%p) parent %p "
                       "inode %p refc %d\n", de->d_name.len,
                       de->d_name.name, de, de->d_parent, de->d_inode,
                       atomic_read(&de->d_count));
                ll_set_lock_data(exp, de->d_inode, it, &bits);
                ll_dentry_reset_flags(de, bits);
                ll_lookup_finish_locks(it, de);
        }

mark:
        if (it != NULL && it->it_op == IT_GETATTR && rc > 0)
                ll_statahead_mark(parent, de);
        RETURN(rc);

        /*
         * This part is here to combat evil-evil race in real_lookup on 2.6
         * kernels.  The race details are: We enter do_lookup() looking for some
         * name, there is nothing in dcache for this name yet and d_lookup()
         * returns NULL.  We proceed to real_lookup(), and while we do this,
         * another process does open on the same file we looking up (most simple
         * reproducer), open succeeds and the dentry is added. Now back to
         * us. In real_lookup() we do d_lookup() again and suddenly find the
         * dentry, so we call d_revalidate on it, but there is no lock, so
         * without this code we would return 0, but unpatched real_lookup just
         * returns -ENOENT in such a case instead of retrying the lookup. Once
         * this is dealt with in real_lookup(), all of this ugly mess can go and
         * we can just check locks in ->d_revalidate without doing any RPCs
         * ever.
         */
do_lookup:
        if (it != &lookup_it) {
                /* MDS_INODELOCK_UPDATE needed for IT_GETATTR case. */
                if (it->it_op == IT_GETATTR)
                        lookup_it.it_op = IT_GETATTR;
                ll_lookup_finish_locks(it, de);
                it = &lookup_it;
        }

        /* Do real lookup here. */
        op_data = ll_prep_md_op_data(NULL, parent, NULL, de->d_name.name,
                                     de->d_name.len, 0, (it->it_op & IT_CREAT ?
                                                         LUSTRE_OPC_CREATE :
                                                         LUSTRE_OPC_ANY), NULL);
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));

        rc = md_intent_lock(exp, op_data, NULL, 0,  it, 0, &req,
                            ll_md_blocking_ast, 0);
        if (rc >= 0) {
                struct mdt_body *mdt_body;
                struct lu_fid fid = {.f_seq = 0, .f_oid = 0, .f_ver = 0};
                mdt_body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);

                if (de->d_inode)
                        fid = *ll_inode2fid(de->d_inode);

                /* see if we got same inode, if not - return error */
                if (lu_fid_eq(&fid, &mdt_body->fid1)) {
                        ll_finish_md_op_data(op_data);
                        op_data = NULL;
                        goto revalidate_finish;
                }
                ll_intent_release(it);
        }
        ll_finish_md_op_data(op_data);
        GOTO(out, rc = 0);

out_sa:
        /*
         * For rc == 1 case, should not return directly to prevent losing
         * statahead windows; for rc == 0 case, the "lookup" will be done later.
         */
        if (it != NULL && it->it_op == IT_GETATTR && rc == 1)
                ll_statahead_enter(parent, &de, 1);
        goto mark;
}

int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
{
        int rc;
        ENTRY;

        if (nd && !(nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))) {
                struct lookup_intent *it;

                it = ll_convert_intent(&nd->intent.open, nd->flags);
                if (IS_ERR(it))
                        RETURN(0);

                if (it->it_op == (IT_OPEN|IT_CREAT) &&
                    nd->intent.open.flags & O_EXCL) {
                        CDEBUG(D_VFSTRACE, "create O_EXCL, returning 0\n");
                        rc = 0;
                        goto out_it;
                }

                rc = ll_revalidate_it(dentry, nd->flags, it);

                if (rc && (nd->flags & LOOKUP_OPEN) &&
                    it_disposition(it, DISP_OPEN_OPEN)) {/*Open*/
// XXX Code duplication with ll_lookup_nd
                        if (S_ISFIFO(dentry->d_inode->i_mode)) {
                                // We cannot call open here as it would
                                // deadlock.
                                ptlrpc_req_finished(
                                               (struct ptlrpc_request *)
                                                  it->d.lustre.it_data);
                        } else {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
/* 2.6.1[456] have a bug in open_namei() that forgets to check
 * nd->intent.open.file for error, so we need to return it as lookup's result
 * instead */
                                struct file *filp;

                                nd->intent.open.file->private_data = it;
                                filp = lookup_instantiate_filp(nd, dentry,NULL);
                                if (IS_ERR(filp)) {
                                        rc = PTR_ERR(filp);
                                }
#else
                                nd->intent.open.file->private_data = it;
                                (void)lookup_instantiate_filp(nd, dentry,NULL);
#endif
                        }
                }
                if (!rc && (nd->flags & LOOKUP_CREATE) &&
                    it_disposition(it, DISP_OPEN_CREATE)) {
                        /* We created something but we may only return
                         * negative dentry here, so save request in dentry,
                         * if lookup will be called later on, it will
                         * pick the request, otherwise it would be freed
                         * with dentry */
                        ll_d2d(dentry)->lld_it = it;
                        it = NULL; /* avoid freeing */
                }

out_it:
                if (it) {
                        ll_intent_release(it);
                        OBD_FREE(it, sizeof(*it));
                }
        } else {
                rc = ll_revalidate_it(dentry, 0, NULL);
        }

        RETURN(rc);
}
Ejemplo n.º 22
0
void cfs_waitq_signal_nr(struct cfs_waitq *waitq, int nr)
{
        LASSERT(waitq != NULL);
        (void)waitq;
}
Ejemplo n.º 23
0
void cfs_sema_init(cfs_semaphore_t *s, int val)
{
        LASSERT(s != NULL);
        (void)s;
        (void)val;
}
Ejemplo n.º 24
0
void cfs_waitq_broadcast(struct cfs_waitq *waitq)
{
        LASSERT(waitq != NULL);
        (void)waitq;
}
Ejemplo n.º 25
0
void __up(cfs_semaphore_t *s)
{
        LASSERT(s != NULL);
        (void)s;
}
Ejemplo n.º 26
0
void cfs_restore_sigs(cfs_sigset_t old)
{
        int   rc = sigprocmask(SIG_SETMASK, &old, NULL);

        LASSERT (rc == 0);
}
Ejemplo n.º 27
0
void cfs_complete(cfs_completion_t *c)
{
        LASSERT(c != NULL);
        c->done  = 1;
        cfs_waitq_signal(&c->wait);
}
Ejemplo n.º 28
0
void cfs_waitq_init(struct cfs_waitq *waitq)
{
        LASSERT(waitq != NULL);
        (void)waitq;
}
Ejemplo n.º 29
0
void cfs_down_read(cfs_rw_semaphore_t *s)
{
        LASSERT(s != NULL);
        (void)s;
}
Ejemplo n.º 30
0
int llog_init_handle(const struct lu_env *env, struct llog_handle *handle,
		     int flags, struct obd_uuid *uuid)
{
	struct llog_log_hdr	*llh;
	int			 rc;

	LASSERT(handle->lgh_hdr == NULL);

	llh = kzalloc(sizeof(*llh), GFP_NOFS);
	if (llh == NULL)
		return -ENOMEM;
	handle->lgh_hdr = llh;
	/* 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);
	} 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;
	}
out:
	if (rc) {
		kfree(llh);
		handle->lgh_hdr = NULL;
	}
	return rc;
}