Ejemplo n.º 1
0
int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
		    struct inode *inode, struct cl_object *clob, int agl)
{
	const struct lu_fid  *fid   = lu_object_fid(&clob->co_lu);
	struct cl_lock *lock = vvp_env_lock(env);
	struct cl_lock_descr *descr = &lock->cll_descr;
	int result = 0;

	CDEBUG(D_DLMTRACE, "Glimpsing inode " DFID "\n", PFID(fid));

	/* NOTE: this looks like DLM lock request, but it may
	 *       not be one. Due to CEF_ASYNC flag (translated
	 *       to LDLM_FL_HAS_INTENT by osc), this is
	 *       glimpse request, that won't revoke any
	 *       conflicting DLM locks held. Instead,
	 *       ll_glimpse_callback() will be called on each
	 *       client holding a DLM lock against this file,
	 *       and resulting size will be returned for each
	 *       stripe. DLM lock on [0, EOF] is acquired only
	 *       if there were no conflicting locks. If there
	 *       were conflicting locks, enqueuing or waiting
	 *       fails with -ENAVAIL, but valid inode
	 *       attributes are returned anyway.
	 */
	*descr = whole_file;
	descr->cld_obj = clob;
	descr->cld_mode = CLM_READ;
	descr->cld_enq_flags = CEF_ASYNC | CEF_MUST;
	if (agl)
		descr->cld_enq_flags |= CEF_AGL;
	/*
	 * CEF_ASYNC is used because glimpse sub-locks cannot
	 * deadlock (because they never conflict with other
	 * locks) and, hence, can be enqueued out-of-order.
	 *
	 * CEF_MUST protects glimpse lock from conversion into
	 * a lockless mode.
	 */
	result = cl_lock_request(env, io, lock);
	if (result < 0)
		return result;

	if (!agl) {
		ll_merge_attr(env, inode);
		if (i_size_read(inode) > 0 && !inode->i_blocks) {
			/*
			 * LU-417: Add dirty pages block count
			 * lest i_blocks reports 0, some "cp" or
			 * "tar" may think it's a completely
			 * sparse file and skip it.
			 */
			inode->i_blocks = dirty_cnt(inode);
		}
	}

	cl_lock_release(env, lock);

	return result;
}
Ejemplo n.º 2
0
int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock,
                     struct ccc_grouplock *cg)
{
        struct lu_env          *env;
        struct cl_io           *io;
        struct cl_lock         *lock;
        struct cl_lock_descr   *descr;
        __u32                   enqflags;
        int                     refcheck;
        int                     rc;

        env = cl_env_get(&refcheck);
        if (IS_ERR(env))
                return PTR_ERR(env);

        io = ccc_env_thread_io(env);
        io->ci_obj = obj;
	io->ci_ignore_layout = 1;

	rc = cl_io_init(env, io, CIT_MISC, io->ci_obj);
	if (rc) {
		cl_io_fini(env, io);
		cl_env_put(env, &refcheck);
		/* Does not make sense to take GL for released layout */
		if (rc > 0)
			rc = -ENOTSUPP;
		return rc;
        }

        descr = &ccc_env_info(env)->cti_descr;
        descr->cld_obj = obj;
        descr->cld_start = 0;
        descr->cld_end = CL_PAGE_EOF;
        descr->cld_gid = gid;
        descr->cld_mode = CLM_GROUP;

	enqflags = CEF_MUST | (nonblock ? CEF_NONBLOCK : 0);
	descr->cld_enq_flags = enqflags;

	lock = cl_lock_request(env, io, descr, GROUPLOCK_SCOPE, current);
	if (IS_ERR(lock)) {
		cl_io_fini(env, io);
		cl_env_put(env, &refcheck);
		return PTR_ERR(lock);
	}

        cg->cg_env  = cl_env_get(&refcheck);
        cg->cg_io   = io;
        cg->cg_lock = lock;
        cg->cg_gid  = gid;
        LASSERT(cg->cg_env == env);

        cl_env_unplant(env, &refcheck);
        return 0;
}
Ejemplo n.º 3
0
int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock,
		     struct ll_grouplock *lg)
{
        struct lu_env          *env;
        struct cl_io           *io;
        struct cl_lock         *lock;
        struct cl_lock_descr   *descr;
        __u32                   enqflags;
	__u16                   refcheck;
        int                     rc;

        env = cl_env_get(&refcheck);
        if (IS_ERR(env))
                return PTR_ERR(env);

	io = vvp_env_thread_io(env);
        io->ci_obj = obj;

	rc = cl_io_init(env, io, CIT_MISC, io->ci_obj);
	if (rc != 0) {
		cl_io_fini(env, io);
		cl_env_put(env, &refcheck);
		/* Does not make sense to take GL for released layout */
		if (rc > 0)
			rc = -ENOTSUPP;
		return rc;
	}

	lock = vvp_env_lock(env);
	descr = &lock->cll_descr;
        descr->cld_obj = obj;
        descr->cld_start = 0;
        descr->cld_end = CL_PAGE_EOF;
        descr->cld_gid = gid;
        descr->cld_mode = CLM_GROUP;

	enqflags = CEF_MUST | (nonblock ? CEF_NONBLOCK : 0);
	descr->cld_enq_flags = enqflags;

	rc = cl_lock_request(env, io, lock);
	if (rc < 0) {
		cl_io_fini(env, io);
		cl_env_put(env, &refcheck);
		return rc;
	}

	lg->lg_env = env;
	lg->lg_io = io;
	lg->lg_lock = lock;
	lg->lg_gid = gid;

	return 0;
}
Ejemplo n.º 4
0
int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock,
                     struct ccc_grouplock *cg)
{
        struct lu_env          *env;
        struct cl_io           *io;
        struct cl_lock         *lock;
        struct cl_lock_descr   *descr;
        __u32                   enqflags;
        int                     refcheck;
        int                     rc;

        env = cl_env_get(&refcheck);
        if (IS_ERR(env))
                return PTR_ERR(env);

        io = &ccc_env_info(env)->cti_io;
        io->ci_obj = obj;

        rc = cl_io_init(env, io, CIT_MISC, io->ci_obj);
        if (rc) {
                LASSERT(rc < 0);
                cl_env_put(env, &refcheck);
                return rc;
        }

        descr = &ccc_env_info(env)->cti_descr;
        descr->cld_obj = obj;
        descr->cld_start = 0;
        descr->cld_end = CL_PAGE_EOF;
        descr->cld_gid = gid;
        descr->cld_mode = CLM_GROUP;

        enqflags = CEF_MUST | (nonblock ? CEF_NONBLOCK : 0);
        descr->cld_enq_flags = enqflags;

        lock = cl_lock_request(env, io, descr, GROUPLOCK_SCOPE, cfs_current());
        if (IS_ERR(lock)) {
                cl_io_fini(env, io);
                cl_env_put(env, &refcheck);
                return PTR_ERR(lock);
        }

        cg->cg_env = cl_env_get(&refcheck);
        cg->cg_lock = lock;
        cg->cg_gid = gid;
        LASSERT(cg->cg_env == env);

        cl_env_unplant(env, &refcheck);
        return 0;
}
Ejemplo n.º 5
0
int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
		    struct inode *inode, struct cl_object *clob, int agl)
{
	struct cl_lock_descr *descr = &ccc_env_info(env)->cti_descr;
	struct cl_inode_info *lli   = cl_i2info(inode);
	const struct lu_fid  *fid   = lu_object_fid(&clob->co_lu);
	struct ccc_io	*cio   = ccc_env_io(env);
	struct cl_lock       *lock;
	int result;

	ENTRY;
	result = 0;
	if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) {
		CDEBUG(D_DLMTRACE, "Glimpsing inode "DFID"\n", PFID(fid));
		if (lli->lli_has_smd) {
			/* NOTE: this looks like DLM lock request, but it may
			 *       not be one. Due to CEF_ASYNC flag (translated
			 *       to LDLM_FL_HAS_INTENT by osc), this is
			 *       glimpse request, that won't revoke any
			 *       conflicting DLM locks held. Instead,
			 *       ll_glimpse_callback() will be called on each
			 *       client holding a DLM lock against this file,
			 *       and resulting size will be returned for each
			 *       stripe. DLM lock on [0, EOF] is acquired only
			 *       if there were no conflicting locks. If there
			 *       were conflicting locks, enqueuing or waiting
			 *       fails with -ENAVAIL, but valid inode
			 *       attributes are returned anyway. */
			*descr = whole_file;
			descr->cld_obj   = clob;
			descr->cld_mode  = CLM_PHANTOM;
			descr->cld_enq_flags = CEF_ASYNC | CEF_MUST;
			if (agl)
				descr->cld_enq_flags |= CEF_AGL;
			cio->cui_glimpse = 1;
			/*
			 * CEF_ASYNC is used because glimpse sub-locks cannot
			 * deadlock (because they never conflict with other
			 * locks) and, hence, can be enqueued out-of-order.
			 *
			 * CEF_MUST protects glimpse lock from conversion into
			 * a lockless mode.
			 */
			lock = cl_lock_request(env, io, descr, "glimpse",
					       current);
			cio->cui_glimpse = 0;

			if (lock == NULL)
				RETURN(0);

			if (IS_ERR(lock))
				RETURN(PTR_ERR(lock));

			LASSERT(agl == 0);
			result = cl_wait(env, lock);
			if (result == 0) {
				cl_merge_lvb(env, inode);
				if (cl_isize_read(inode) > 0 &&
				    inode->i_blocks == 0) {
					/*
					 * LU-417: Add dirty pages block count
					 * lest i_blocks reports 0, some "cp" or
					 * "tar" may think it's a completely
					 * sparse file and skip it.
					 */
					inode->i_blocks = dirty_cnt(inode);
				}
				cl_unuse(env, lock);
			}
			cl_lock_release(env, lock, "glimpse", current);
		} else {
			CDEBUG(D_DLMTRACE, "No objects for inode\n");
			cl_merge_lvb(env, inode);
		}
	}

	RETURN(result);
}