Example #1
0
void obdo_from_iattr(struct obdo *oa, struct iattr *attr, unsigned int ia_valid)
{
	if (ia_valid & ATTR_ATIME) {
		oa->o_atime = LTIME_S(attr->ia_atime);
		oa->o_valid |= OBD_MD_FLATIME;
	}
	if (ia_valid & ATTR_MTIME) {
		oa->o_mtime = LTIME_S(attr->ia_mtime);
		oa->o_valid |= OBD_MD_FLMTIME;
	}
	if (ia_valid & ATTR_CTIME) {
		oa->o_ctime = LTIME_S(attr->ia_ctime);
		oa->o_valid |= OBD_MD_FLCTIME;
	}
	if (ia_valid & ATTR_SIZE) {
		oa->o_size = attr->ia_size;
		oa->o_valid |= OBD_MD_FLSIZE;
	}
	if (ia_valid & ATTR_MODE) {
		oa->o_mode = attr->ia_mode;
		oa->o_valid |= OBD_MD_FLTYPE | OBD_MD_FLMODE;
		if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) &&
		    !cfs_capable(CFS_CAP_FSETID))
			oa->o_mode &= ~S_ISGID;
	}
	if (ia_valid & ATTR_UID) {
		oa->o_uid = from_kuid(&init_user_ns, attr->ia_uid);
		oa->o_valid |= OBD_MD_FLUID;
	}
	if (ia_valid & ATTR_GID) {
		oa->o_gid = from_kgid(&init_user_ns, attr->ia_gid);
		oa->o_valid |= OBD_MD_FLGID;
	}
}
Example #2
0
static void mdc_setattr_pack_rec(struct mdt_rec_setattr *rec,
				 struct md_op_data *op_data)
{
	rec->sa_opcode  = REINT_SETATTR;
	rec->sa_fsuid   = from_kuid(&init_user_ns, current_fsuid());
	rec->sa_fsgid   = from_kgid(&init_user_ns, current_fsgid());
	rec->sa_cap     = cfs_curproc_cap_pack();
	rec->sa_suppgid = -1;

	rec->sa_fid    = op_data->op_fid1;
	rec->sa_valid  = attr_pack(op_data->op_attr.ia_valid);
	rec->sa_mode   = op_data->op_attr.ia_mode;
	rec->sa_uid    = from_kuid(&init_user_ns, op_data->op_attr.ia_uid);
	rec->sa_gid    = from_kgid(&init_user_ns, op_data->op_attr.ia_gid);
	rec->sa_size   = op_data->op_attr.ia_size;
	rec->sa_blocks = op_data->op_attr_blocks;
	rec->sa_atime  = LTIME_S(op_data->op_attr.ia_atime);
	rec->sa_mtime  = LTIME_S(op_data->op_attr.ia_mtime);
	rec->sa_ctime  = LTIME_S(op_data->op_attr.ia_ctime);
	rec->sa_attr_flags = ((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags;
	if ((op_data->op_attr.ia_valid & ATTR_GID) &&
	    in_group_p(op_data->op_attr.ia_gid))
		rec->sa_suppgid =
			from_kgid(&init_user_ns, op_data->op_attr.ia_gid);
	else
		rec->sa_suppgid = op_data->op_suppgids[0];

	rec->sa_bias = op_data->op_bias;
}
Example #3
0
/* WARNING: the file systems must take care not to tinker with
 * attributes they don't manage (such as blocks).
 */
void obdo_from_inode(struct obdo *dst, struct inode *src, u32 valid)
{
	u32 newvalid = 0;

	if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
		CDEBUG(D_INODE, "valid %x, new time %lu/%lu\n",
		       valid, LTIME_S(src->i_mtime),
		       LTIME_S(src->i_ctime));

	if (valid & OBD_MD_FLATIME) {
		dst->o_atime = LTIME_S(src->i_atime);
		newvalid |= OBD_MD_FLATIME;
	}
	if (valid & OBD_MD_FLMTIME) {
		dst->o_mtime = LTIME_S(src->i_mtime);
		newvalid |= OBD_MD_FLMTIME;
	}
	if (valid & OBD_MD_FLCTIME) {
		dst->o_ctime = LTIME_S(src->i_ctime);
		newvalid |= OBD_MD_FLCTIME;
	}
	if (valid & OBD_MD_FLSIZE) {
		dst->o_size = i_size_read(src);
		newvalid |= OBD_MD_FLSIZE;
	}
	if (valid & OBD_MD_FLBLOCKS) {  /* allocation of space (x512 bytes) */
		dst->o_blocks = src->i_blocks;
		newvalid |= OBD_MD_FLBLOCKS;
	}
	if (valid & OBD_MD_FLBLKSZ) {   /* optimal block size */
		dst->o_blksize = 1 << src->i_blkbits;
		newvalid |= OBD_MD_FLBLKSZ;
	}
	if (valid & OBD_MD_FLTYPE) {
		dst->o_mode = (dst->o_mode & S_IALLUGO) |
			      (src->i_mode & S_IFMT);
		newvalid |= OBD_MD_FLTYPE;
	}
	if (valid & OBD_MD_FLMODE) {
		dst->o_mode = (dst->o_mode & S_IFMT) |
			      (src->i_mode & S_IALLUGO);
		newvalid |= OBD_MD_FLMODE;
	}
	if (valid & OBD_MD_FLUID) {
		dst->o_uid = from_kuid(&init_user_ns, src->i_uid);
		newvalid |= OBD_MD_FLUID;
	}
	if (valid & OBD_MD_FLGID) {
		dst->o_gid = from_kgid(&init_user_ns, src->i_gid);
		newvalid |= OBD_MD_FLGID;
	}
	if (valid & OBD_MD_FLFLAGS) {
		dst->o_flags = src->i_flags;
		newvalid |= OBD_MD_FLFLAGS;
	}
	dst->o_valid |= newvalid;
}
Example #4
0
int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
		void *ea, size_t ealen, struct ptlrpc_request **request)
{
	struct list_head cancels = LIST_HEAD_INIT(cancels);
        struct ptlrpc_request *req;
        struct mdc_rpc_lock *rpc_lock;
        struct obd_device *obd = exp->exp_obd;
        int count = 0, rc;
        __u64 bits;
        ENTRY;

        LASSERT(op_data != NULL);

        bits = MDS_INODELOCK_UPDATE;
        if (op_data->op_attr.ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID))
                bits |= MDS_INODELOCK_LOOKUP;
	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, bits);
        req = ptlrpc_request_alloc(class_exp2cliimp(exp),
                                   &RQF_MDS_REINT_SETATTR);
        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_MDT_EPOCH, RCL_CLIENT, 0);
	req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, ealen);
	req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_CLIENT, 0);

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

        rpc_lock = obd->u.cli.cl_rpc_lock;

        if (op_data->op_attr.ia_valid & (ATTR_MTIME | ATTR_CTIME))
                CDEBUG(D_INODE, "setting mtime "CFS_TIME_T
                       ", ctime "CFS_TIME_T"\n",
                       LTIME_S(op_data->op_attr.ia_mtime),
                       LTIME_S(op_data->op_attr.ia_ctime));
	mdc_setattr_pack(req, op_data, ea, ealen);

        ptlrpc_request_set_replen(req);

        rc = mdc_reint(req, rpc_lock, LUSTRE_IMP_FULL);
	if (rc == -ERESTARTSYS)
                rc = 0;

        *request = req;

	RETURN(rc);
}
Example #5
0
void obdo_refresh_inode(struct inode *dst, struct obdo *src, obd_flag valid)
{
	valid &= src->o_valid;

	if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
		CDEBUG(D_INODE,
		       "valid %#llx, cur time %lu/%lu, new %llu/%llu\n",
		       src->o_valid, LTIME_S(dst->i_mtime),
		       LTIME_S(dst->i_ctime), src->o_mtime, src->o_ctime);

	if (valid & OBD_MD_FLATIME && src->o_atime > LTIME_S(dst->i_atime))
		LTIME_S(dst->i_atime) = src->o_atime;
	if (valid & OBD_MD_FLMTIME && src->o_mtime > LTIME_S(dst->i_mtime))
		LTIME_S(dst->i_mtime) = src->o_mtime;
	if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(dst->i_ctime))
		LTIME_S(dst->i_ctime) = src->o_ctime;
	if (valid & OBD_MD_FLSIZE)
		i_size_write(dst, src->o_size);
	/* optimum IO size */
	if (valid & OBD_MD_FLBLKSZ && src->o_blksize > (1 << dst->i_blkbits))
		dst->i_blkbits = ffs(src->o_blksize) - 1;

	if (dst->i_blkbits < PAGE_CACHE_SHIFT)
		dst->i_blkbits = PAGE_CACHE_SHIFT;

	/* allocation of space */
	if (valid & OBD_MD_FLBLOCKS && src->o_blocks > dst->i_blocks)
		/*
		 * XXX shouldn't overflow be checked here like in
		 * obdo_to_inode().
		 */
		dst->i_blocks = src->o_blocks;
}
Example #6
0
File: file.c Project: DCteam/lustre
void obdo_refresh_inode(struct inode *dst,
                        struct obdo *src,
                        obd_flag valid)
{
        struct intnl_stat *st = llu_i2stat(dst);
        valid &= src->o_valid;

        if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
                CDEBUG(D_INODE,"valid "LPX64", cur time "CFS_TIME_T"/"CFS_TIME_T
		       ", new %lu/%lu\n",
                       src->o_valid, LTIME_S(st->st_mtime),
                       LTIME_S(st->st_ctime),
                       (long)src->o_mtime, (long)src->o_ctime);

        if (valid & OBD_MD_FLATIME && src->o_atime > LTIME_S(st->st_atime))
                LTIME_S(st->st_atime) = src->o_atime;
        if (valid & OBD_MD_FLMTIME && src->o_mtime > LTIME_S(st->st_mtime))
                LTIME_S(st->st_mtime) = src->o_mtime;
        if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(st->st_ctime))
                LTIME_S(st->st_ctime) = src->o_ctime;
        if (valid & OBD_MD_FLSIZE && src->o_size > st->st_size)
                st->st_size = src->o_size;
        /* optimum IO size */
        if (valid & OBD_MD_FLBLKSZ)
                st->st_blksize = src->o_blksize;
        /* allocation of space */
        if (valid & OBD_MD_FLBLOCKS && src->o_blocks > st->st_blocks)
                st->st_blocks = src->o_blocks;
}
Example #7
0
int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
		void *ea, size_t ealen, struct ptlrpc_request **request)
{
	LIST_HEAD(cancels);
	struct ptlrpc_request *req;
	int count = 0, rc;
	__u64 bits;

	bits = MDS_INODELOCK_UPDATE;
	if (op_data->op_attr.ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
		bits |= MDS_INODELOCK_LOOKUP;
	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, bits);
	req = ptlrpc_request_alloc(class_exp2cliimp(exp),
				   &RQF_MDS_REINT_SETATTR);
	if (!req) {
		ldlm_lock_list_put(&cancels, l_bl_ast, count);
		return -ENOMEM;
	}
	req_capsule_set_size(&req->rq_pill, &RMF_MDT_EPOCH, RCL_CLIENT, 0);
	req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, ealen);
	req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_CLIENT, 0);

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

	if (op_data->op_attr.ia_valid & (ATTR_MTIME | ATTR_CTIME))
		CDEBUG(D_INODE, "setting mtime %ld, ctime %ld\n",
		       LTIME_S(op_data->op_attr.ia_mtime),
		       LTIME_S(op_data->op_attr.ia_ctime));
	mdc_setattr_pack(req, op_data, ea, ealen);

	ptlrpc_request_set_replen(req);

	rc = mdc_reint(req, LUSTRE_IMP_FULL);

	if (rc == -ERESTARTSYS)
		rc = 0;

	*request = req;

	return rc;
}
Example #8
0
void iattr_from_obdo(struct iattr *attr, struct obdo *oa, obd_flag valid)
{
	valid &= oa->o_valid;

	if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
		CDEBUG(D_INODE, "valid "LPX64", new time "LPU64"/"LPU64"\n",
		       oa->o_valid, oa->o_mtime, oa->o_ctime);

	attr->ia_valid = 0;
	if (valid & OBD_MD_FLATIME) {
		LTIME_S(attr->ia_atime) = oa->o_atime;
		attr->ia_valid |= ATTR_ATIME;
	}
	if (valid & OBD_MD_FLMTIME) {
		LTIME_S(attr->ia_mtime) = oa->o_mtime;
		attr->ia_valid |= ATTR_MTIME;
	}
	if (valid & OBD_MD_FLCTIME) {
		LTIME_S(attr->ia_ctime) = oa->o_ctime;
		attr->ia_valid |= ATTR_CTIME;
	}
	if (valid & OBD_MD_FLSIZE) {
		attr->ia_size = oa->o_size;
		attr->ia_valid |= ATTR_SIZE;
	}
#if 0   /* you shouldn't be able to change a file's type with setattr */
	if (valid & OBD_MD_FLTYPE) {
		attr->ia_mode = (attr->ia_mode & ~S_IFMT)|(oa->o_mode & S_IFMT);
		attr->ia_valid |= ATTR_MODE;
	}
#endif
	if (valid & OBD_MD_FLMODE) {
		attr->ia_mode = (attr->ia_mode & S_IFMT)|(oa->o_mode & ~S_IFMT);
		attr->ia_valid |= ATTR_MODE;
		if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) &&
		    !cfs_capable(CFS_CAP_FSETID))
			attr->ia_mode &= ~S_ISGID;
	}
	if (valid & OBD_MD_FLUID) {
		attr->ia_uid = make_kuid(&init_user_ns, oa->o_uid);
		attr->ia_valid |= ATTR_UID;
	}
	if (valid & OBD_MD_FLGID) {
		attr->ia_gid = make_kgid(&init_user_ns, oa->o_gid);
		attr->ia_valid |= ATTR_GID;
	}
}
Example #9
0
static int vvp_object_glimpse(const struct lu_env *env,
			      const struct cl_object *obj, struct ost_lvb *lvb)
{
	struct inode *inode = vvp_object_inode(obj);

	lvb->lvb_mtime = LTIME_S(inode->i_mtime);
	lvb->lvb_atime = LTIME_S(inode->i_atime);
	lvb->lvb_ctime = LTIME_S(inode->i_ctime);
	/*
	 * LU-417: Add dirty pages block count lest i_blocks reports 0, some
	 * "cp" or "tar" on remote node may think it's a completely sparse file
	 * and skip it.
	 */
	if (lvb->lvb_size > 0 && lvb->lvb_blocks == 0)
		lvb->lvb_blocks = dirty_cnt(inode);
	return 0;
}
Example #10
0
static int vvp_io_fault_iter_init(const struct lu_env *env,
                                  const struct cl_io_slice *ios)
{
        struct vvp_io *vio   = cl2vvp_io(env, ios);
        struct inode  *inode = ccc_object_inode(ios->cis_obj);

        LASSERT(inode ==
                cl2ccc_io(env, ios)->cui_fd->fd_file->f_dentry->d_inode);
        vio->u.fault.ft_mtime = LTIME_S(inode->i_mtime);
        return 0;
}
Example #11
0
static int vvp_attr_get(const struct lu_env *env, struct cl_object *obj,
                        struct cl_attr *attr)
{
	struct inode *inode = vvp_object_inode(obj);

	/*
	 * lov overwrites most of these fields in
	 * lov_attr_get()->...lov_merge_lvb_kms(), except when inode
	 * attributes are newer.
	 */

	attr->cat_size = i_size_read(inode);
	attr->cat_mtime = LTIME_S(inode->i_mtime);
	attr->cat_atime = LTIME_S(inode->i_atime);
	attr->cat_ctime = LTIME_S(inode->i_ctime);
	attr->cat_blocks = inode->i_blocks;
	attr->cat_uid = from_kuid(&init_user_ns, inode->i_uid);
	attr->cat_gid = from_kgid(&init_user_ns, inode->i_gid);
	/* KMS is not known by this layer */
	return 0; /* layers below have to fill in the rest */
}
Example #12
0
static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj,
                        const struct cl_attr *attr, unsigned valid)
{
        struct inode *inode = ccc_object_inode(obj);

        if (valid & CAT_UID)
                inode->i_uid = attr->cat_uid;
        if (valid & CAT_GID)
                inode->i_gid = attr->cat_gid;
        if (valid & CAT_ATIME)
                LTIME_S(inode->i_atime) = attr->cat_atime;
        if (valid & CAT_MTIME)
                LTIME_S(inode->i_mtime) = attr->cat_mtime;
        if (valid & CAT_CTIME)
                LTIME_S(inode->i_ctime) = attr->cat_ctime;
        if (0 && valid & CAT_SIZE)
                cl_isize_write_nolock(inode, attr->cat_size);
        /* not currently necessary */
        if (0 && valid & (CAT_UID|CAT_GID|CAT_SIZE))
                mark_inode_dirty(inode);
        return 0;
}
Example #13
0
static int vvp_attr_update(const struct lu_env *env, struct cl_object *obj,
			   const struct cl_attr *attr, unsigned valid)
{
	struct inode *inode = vvp_object_inode(obj);

	if (valid & CAT_UID)
		inode->i_uid = make_kuid(&init_user_ns, attr->cat_uid);
	if (valid & CAT_GID)
		inode->i_gid = make_kgid(&init_user_ns, attr->cat_gid);
	if (valid & CAT_ATIME)
		LTIME_S(inode->i_atime) = attr->cat_atime;
	if (valid & CAT_MTIME)
		LTIME_S(inode->i_mtime) = attr->cat_mtime;
	if (valid & CAT_CTIME)
		LTIME_S(inode->i_ctime) = attr->cat_ctime;
	if (0 && valid & CAT_SIZE)
		i_size_write(inode, attr->cat_size);
	/* not currently necessary */
	if (0 && valid & (CAT_UID|CAT_GID|CAT_SIZE))
		mark_inode_dirty(inode);
	return 0;
}
Example #14
0
static int osc_io_read_start(const struct lu_env *env,
			     const struct cl_io_slice *slice)
{
	struct cl_object *obj   = slice->cis_obj;
	struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
	int rc = 0;

	if (!slice->cis_io->ci_noatime) {
		cl_object_attr_lock(obj);
		attr->cat_atime = LTIME_S(CURRENT_TIME);
		rc = cl_object_attr_set(env, obj, attr, CAT_ATIME);
		cl_object_attr_unlock(obj);
	}
	return rc;
}
Example #15
0
static int osc_io_write_start(const struct lu_env *env,
			      const struct cl_io_slice *slice)
{
	struct cl_object *obj   = slice->cis_obj;
	struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
	int rc = 0;

	OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_DELAY_SETTIME, 1);
	cl_object_attr_lock(obj);
	attr->cat_mtime = attr->cat_ctime = LTIME_S(CURRENT_TIME);
	rc = cl_object_attr_set(env, obj, attr, CAT_MTIME | CAT_CTIME);
	cl_object_attr_unlock(obj);

	return rc;
}
Example #16
0
static int osc_io_read_start(const struct lu_env *env,
                             const struct cl_io_slice *slice)
{
	struct osc_io	 *oio  = cl2osc_io(env, slice);
	struct cl_object *obj  = slice->cis_obj;
	struct cl_attr	 *attr = &osc_env_info(env)->oti_attr;
	int rc = 0;
	ENTRY;

	if (oio->oi_lockless == 0 && !slice->cis_io->ci_noatime) {
		cl_object_attr_lock(obj);
		attr->cat_atime = LTIME_S(CFS_CURRENT_TIME);
		rc = cl_object_attr_set(env, obj, attr, CAT_ATIME);
		cl_object_attr_unlock(obj);
	}

	RETURN(rc);
}
Example #17
0
static int osc_io_write_start(const struct lu_env *env,
                              const struct cl_io_slice *slice)
{
        struct osc_io    *oio   = cl2osc_io(env, slice);
        struct cl_object *obj   = slice->cis_obj;
        struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
        int              result = 0;
        ENTRY;

        if (oio->oi_lockless == 0) {
		OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_DELAY_SETTIME, 1);
                cl_object_attr_lock(obj);
                result = cl_object_attr_get(env, obj, attr);
                if (result == 0) {
                        attr->cat_mtime = attr->cat_ctime =
                                LTIME_S(CFS_CURRENT_TIME);
                        result = cl_object_attr_set(env, obj, attr,
                                                    CAT_MTIME | CAT_CTIME);
                }
                cl_object_attr_unlock(obj);
        }
        RETURN(result);
}
Example #18
0
/**
 * This is called when a page is accessed within file in a way that creates
 * new page, if one were missing (i.e., if there were a hole at that place in
 * the file, or accessed page is beyond the current file size).
 *
 * Expand stripe KMS if necessary.
 */
static void osc_page_touch_at(const struct lu_env *env,
			      struct cl_object *obj, pgoff_t idx, size_t to)
{
        struct lov_oinfo  *loi  = cl2osc(obj)->oo_oinfo;
        struct cl_attr    *attr = &osc_env_info(env)->oti_attr;
        int valid;
        __u64 kms;

        /* offset within stripe */
        kms = cl_offset(obj, idx) + to;

        cl_object_attr_lock(obj);
        /*
         * XXX old code used
         *
         *         ll_inode_size_lock(inode, 0); lov_stripe_lock(lsm);
         *
         * here
         */
        CDEBUG(D_INODE, "stripe KMS %sincreasing "LPU64"->"LPU64" "LPU64"\n",
               kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms,
               loi->loi_lvb.lvb_size);

	attr->cat_mtime = attr->cat_ctime = LTIME_S(CFS_CURRENT_TIME);
	valid = CAT_MTIME | CAT_CTIME;
	if (kms > loi->loi_kms) {
		attr->cat_kms = kms;
		valid |= CAT_KMS;
	}
	if (kms > loi->loi_lvb.lvb_size) {
		attr->cat_size = kms;
		valid |= CAT_SIZE;
	}
	cl_object_attr_update(env, obj, attr, valid);
	cl_object_attr_unlock(obj);
}
Example #19
0
void obdo_to_inode(struct inode *dst, struct obdo *src, obd_flag valid)
{
	valid &= src->o_valid;

	LASSERTF(!(valid & (OBD_MD_FLTYPE | OBD_MD_FLGENER | OBD_MD_FLFID |
			    OBD_MD_FLID | OBD_MD_FLGROUP)),
		 "object "DOSTID", valid %x\n", POSTID(&src->o_oi), valid);

	if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
		CDEBUG(D_INODE,
		       "valid %#llx, cur time %lu/%lu, new %llu/%llu\n",
		       src->o_valid, LTIME_S(dst->i_mtime),
		       LTIME_S(dst->i_ctime), src->o_mtime, src->o_ctime);

	if (valid & OBD_MD_FLATIME)
		LTIME_S(dst->i_atime) = src->o_atime;
	if (valid & OBD_MD_FLMTIME)
		LTIME_S(dst->i_mtime) = src->o_mtime;
	if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(dst->i_ctime))
		LTIME_S(dst->i_ctime) = src->o_ctime;
	if (valid & OBD_MD_FLSIZE)
		i_size_write(dst, src->o_size);
	if (valid & OBD_MD_FLBLOCKS) { /* allocation of space */
		dst->i_blocks = src->o_blocks;
		if (dst->i_blocks < src->o_blocks) /* overflow */
			dst->i_blocks = -1;

	}
	if (valid & OBD_MD_FLBLKSZ)
		dst->i_blkbits = ffs(src->o_blksize)-1;
	if (valid & OBD_MD_FLMODE)
		dst->i_mode = (dst->i_mode & S_IFMT) | (src->o_mode & ~S_IFMT);
	if (valid & OBD_MD_FLUID)
		dst->i_uid = make_kuid(&init_user_ns, src->o_uid);
	if (valid & OBD_MD_FLGID)
		dst->i_gid = make_kgid(&init_user_ns, src->o_gid);
	if (valid & OBD_MD_FLFLAGS)
		dst->i_flags = src->o_flags;
}
Example #20
0
static int vvp_io_fault_start(const struct lu_env *env,
                              const struct cl_io_slice *ios)
{
	struct vvp_io       *vio     = cl2vvp_io(env, ios);
	struct cl_io        *io      = ios->cis_io;
	struct cl_object    *obj     = io->ci_obj;
	struct inode        *inode   = ccc_object_inode(obj);
	struct cl_fault_io  *fio     = &io->u.ci_fault;
	struct vvp_fault_io *cfio    = &vio->u.fault;
	loff_t               offset;
	int                  result  = 0;
	struct page          *vmpage  = NULL;
	struct cl_page      *page;
	loff_t               size;
	pgoff_t              last; /* last page in a file data region */

        if (fio->ft_executable &&
            LTIME_S(inode->i_mtime) != vio->u.fault.ft_mtime)
                CWARN("binary "DFID
                      " changed while waiting for the page fault lock\n",
                      PFID(lu_object_fid(&obj->co_lu)));

        /* offset of the last byte on the page */
        offset = cl_offset(obj, fio->ft_index + 1) - 1;
        LASSERT(cl_index(obj, offset) == fio->ft_index);
        result = ccc_prep_size(env, obj, io, 0, offset + 1, NULL);
        if (result != 0)
                return result;

	/* must return locked page */
	if (fio->ft_mkwrite) {
		LASSERT(cfio->ft_vmpage != NULL);
		lock_page(cfio->ft_vmpage);
	} else {
		result = vvp_io_kernel_fault(cfio);
		if (result != 0)
			return result;
	}

	vmpage = cfio->ft_vmpage;
	LASSERT(PageLocked(vmpage));

	if (OBD_FAIL_CHECK(OBD_FAIL_LLITE_FAULT_TRUNC_RACE))
		ll_invalidate_page(vmpage);

	size = i_size_read(inode);
        /* Though we have already held a cl_lock upon this page, but
         * it still can be truncated locally. */
	if (unlikely((vmpage->mapping != inode->i_mapping) ||
		     (page_offset(vmpage) > size))) {
                CDEBUG(D_PAGE, "llite: fault and truncate race happened!\n");

                /* return +1 to stop cl_io_loop() and ll_fault() will catch
                 * and retry. */
                GOTO(out, result = +1);
        }


	if (fio->ft_mkwrite ) {
		pgoff_t last_index;
		/*
		 * Capture the size while holding the lli_trunc_sem from above
		 * we want to make sure that we complete the mkwrite action
		 * while holding this lock. We need to make sure that we are
		 * not past the end of the file.
		 */
		last_index = cl_index(obj, size - 1);
		if (last_index < fio->ft_index) {
			CDEBUG(D_PAGE,
				"llite: mkwrite and truncate race happened: "
				"%p: 0x%lx 0x%lx\n",
				vmpage->mapping,fio->ft_index,last_index);
			/*
			 * We need to return if we are
			 * passed the end of the file. This will propagate
			 * up the call stack to ll_page_mkwrite where
			 * we will return VM_FAULT_NOPAGE. Any non-negative
			 * value returned here will be silently
			 * converted to 0. If the vmpage->mapping is null
			 * the error code would be converted back to ENODATA
			 * in ll_page_mkwrite0. Thus we return -ENODATA
			 * to handle both cases
			 */
			GOTO(out, result = -ENODATA);
		}
	}

        page = cl_page_find(env, obj, fio->ft_index, vmpage, CPT_CACHEABLE);
        if (IS_ERR(page))
                GOTO(out, result = PTR_ERR(page));

        /* if page is going to be written, we should add this page into cache
         * earlier. */
        if (fio->ft_mkwrite) {
                wait_on_page_writeback(vmpage);
                if (set_page_dirty(vmpage)) {
                        struct ccc_page *cp;

                        /* vvp_page_assume() calls wait_on_page_writeback(). */
                        cl_page_assume(env, io, page);

                        cp = cl2ccc_page(cl_page_at(page, &vvp_device_type));
                        vvp_write_pending(cl2ccc(obj), cp);

                        /* Do not set Dirty bit here so that in case IO is
                         * started before the page is really made dirty, we
                         * still have chance to detect it. */
                        result = cl_page_cache_add(env, io, page, CRT_WRITE);
			LASSERT(cl_page_is_owned(page, io));

			vmpage = NULL;
			if (result < 0) {
				cl_page_unmap(env, io, page);
				cl_page_discard(env, io, page);
				cl_page_disown(env, io, page);

				cl_page_put(env, page);

				/* we're in big trouble, what can we do now? */
				if (result == -EDQUOT)
					result = -ENOSPC;
				GOTO(out, result);
			} else
				cl_page_disown(env, io, page);
		}
	}

	last = cl_index(obj, size - 1);
	/*
	 * The ft_index is only used in the case of
	 * a mkwrite action. We need to check
	 * our assertions are correct, since
	 * we should have caught this above
	 */
	LASSERT(!fio->ft_mkwrite || fio->ft_index <= last);
        if (fio->ft_index == last)
                /*
                 * Last page is mapped partially.
                 */
                fio->ft_nob = size - cl_offset(obj, fio->ft_index);
        else
                fio->ft_nob = cl_page_size(obj);

        lu_ref_add(&page->cp_reference, "fault", io);
        fio->ft_page = page;
        EXIT;

out:
	/* return unlocked vmpage to avoid deadlocking */
	if (vmpage != NULL)
		unlock_page(vmpage);
	cfio->fault.ft_flags &= ~VM_FAULT_LOCKED;
	return result;
}
Example #21
0
int lmv_revalidate_slaves(struct obd_export *exp,
			  const struct lmv_stripe_md *lsm,
			  ldlm_blocking_callback cb_blocking,
			  int extra_lock_flags)
{
	struct obd_device      *obd = exp->exp_obd;
	struct lmv_obd         *lmv = &obd->u.lmv;
	struct ptlrpc_request	*req = NULL;
	struct mdt_body		*body;
	struct md_op_data      *op_data;
	int                     i;
	int                     rc = 0;

	ENTRY;

	/**
	 * revalidate slaves has some problems, temporarily return,
	 * we may not need that
	 */
	OBD_ALLOC_PTR(op_data);
	if (op_data == NULL)
		RETURN(-ENOMEM);

	/**
	 * Loop over the stripe information, check validity and update them
	 * from MDS if needed.
	 */
	for (i = 0; i < lsm->lsm_md_stripe_count; i++) {
		struct lu_fid		fid;
		struct lookup_intent	it = { .it_op = IT_GETATTR };
		struct lustre_handle	*lockh = NULL;
		struct lmv_tgt_desc	*tgt = NULL;
		struct inode		*inode;

		fid = lsm->lsm_md_oinfo[i].lmo_fid;
		inode = lsm->lsm_md_oinfo[i].lmo_root;

		/*
		 * Prepare op_data for revalidating. Note that @fid2 shluld be
		 * defined otherwise it will go to server and take new lock
		 * which is not needed here.
		 */
		memset(op_data, 0, sizeof(*op_data));
		op_data->op_fid1 = fid;
		op_data->op_fid2 = fid;

		tgt = lmv_locate_mds(lmv, op_data, &fid);
		if (IS_ERR(tgt))
			GOTO(cleanup, rc = PTR_ERR(tgt));

		CDEBUG(D_INODE, "Revalidate slave "DFID" -> mds #%u\n",
		       PFID(&fid), tgt->ltd_idx);

		if (req != NULL) {
			ptlrpc_req_finished(req);
			req = NULL;
		}

		rc = md_intent_lock(tgt->ltd_exp, op_data, &it, &req,
				    cb_blocking, extra_lock_flags);
		if (rc < 0)
			GOTO(cleanup, rc);

		lockh = (struct lustre_handle *)&it.d.lustre.it_lock_handle;
		if (rc > 0 && req == NULL) {
			/* slave inode is still valid */
			CDEBUG(D_INODE, "slave "DFID" is still valid.\n",
			       PFID(&fid));
			rc = 0;
		} else {
			/* refresh slave from server */
			body = req_capsule_server_get(&req->rq_pill,
						      &RMF_MDT_BODY);
			if (body == NULL) {
				if (it.d.lustre.it_lock_mode && lockh) {
					ldlm_lock_decref(lockh,
						 it.d.lustre.it_lock_mode);
					it.d.lustre.it_lock_mode = 0;
				}
				GOTO(cleanup, rc = -ENOENT);
			}

			i_size_write(inode, body->mbo_size);
			inode->i_blocks = body->mbo_blocks;
			set_nlink(inode, body->mbo_nlink);
			LTIME_S(inode->i_atime) = body->mbo_atime;
			LTIME_S(inode->i_ctime) = body->mbo_ctime;
			LTIME_S(inode->i_mtime) = body->mbo_mtime;
		}

		md_set_lock_data(tgt->ltd_exp, &lockh->cookie, inode, NULL);
		if (it.d.lustre.it_lock_mode != 0 && lockh != NULL) {
			ldlm_lock_decref(lockh, it.d.lustre.it_lock_mode);
			it.d.lustre.it_lock_mode = 0;
		}
	}

cleanup:
	if (req != NULL)
		ptlrpc_req_finished(req);

	OBD_FREE_PTR(op_data);
	RETURN(rc);
}
Example #22
0
/* If mdc_setattr is called with an 'iattr', then it is a normal RPC that
 * should take the normal semaphore and go to the normal portal.
 *
 * If it is called with iattr->ia_valid & ATTR_FROM_OPEN, then it is a
 * magic open-path setattr that should take the setattr semaphore and
 * go to the setattr portal. */
int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data,
                void *ea, int ealen, void *ea2, int ea2len,
                struct ptlrpc_request **request, struct md_open_data **mod)
{
        CFS_LIST_HEAD(cancels);
        struct ptlrpc_request *req;
        struct mdc_rpc_lock *rpc_lock;
        struct obd_device *obd = exp->exp_obd;
        int count = 0, rc;
        __u64 bits;
        ENTRY;

        LASSERT(op_data != NULL);

        bits = MDS_INODELOCK_UPDATE;
        if (op_data->op_attr.ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID))
                bits |= MDS_INODELOCK_LOOKUP;
        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, bits);
        req = ptlrpc_request_alloc(class_exp2cliimp(exp),
                                   &RQF_MDS_REINT_SETATTR);
        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);
        if ((op_data->op_flags & (MF_SOM_CHANGE | MF_EPOCH_OPEN)) == 0)
                req_capsule_set_size(&req->rq_pill, &RMF_MDT_EPOCH, RCL_CLIENT,
                                     0);
        req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT, ealen);
        req_capsule_set_size(&req->rq_pill, &RMF_LOGCOOKIES, RCL_CLIENT,
                             ea2len);

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

        if (op_data->op_attr.ia_valid & ATTR_FROM_OPEN) {
                req->rq_request_portal = MDS_SETATTR_PORTAL;
                ptlrpc_at_set_req_timeout(req);
                rpc_lock = obd->u.cli.cl_setattr_lock;
        } else {
                rpc_lock = obd->u.cli.cl_rpc_lock;
        }

        if (op_data->op_attr.ia_valid & (ATTR_MTIME | ATTR_CTIME))
                CDEBUG(D_INODE, "setting mtime "CFS_TIME_T
                       ", ctime "CFS_TIME_T"\n",
                       LTIME_S(op_data->op_attr.ia_mtime),
                       LTIME_S(op_data->op_attr.ia_ctime));
        mdc_setattr_pack(req, op_data, ea, ealen, ea2, ea2len);

        ptlrpc_request_set_replen(req);
        if (mod && (op_data->op_flags & MF_EPOCH_OPEN) &&
            req->rq_import->imp_replayable)
        {
                LASSERT(*mod == NULL);

                *mod = obd_mod_alloc();
                if (*mod == NULL) {
                        DEBUG_REQ(D_ERROR, req, "Can't allocate "
                                  "md_open_data");
                } else {
                        req->rq_replay = 1;
                        req->rq_cb_data = *mod;
                        (*mod)->mod_open_req = req;
                        req->rq_commit_cb = mdc_commit_open;
                        /**
                         * Take an extra reference on \var mod, it protects \var
                         * mod from being freed on eviction (commit callback is
                         * called despite rq_replay flag).
                         * Will be put on mdc_done_writing().
                         */
                        obd_mod_get(*mod);
                }
        }

        rc = mdc_reint(req, rpc_lock, LUSTRE_IMP_FULL);

        /* Save the obtained info in the original RPC for the replay case. */
        if (rc == 0 && (op_data->op_flags & MF_EPOCH_OPEN)) {
                struct mdt_ioepoch *epoch;
                struct mdt_body  *body;

                epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH);
                body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
                LASSERT(epoch != NULL);
                LASSERT(body != NULL);
                epoch->handle = body->handle;
                epoch->ioepoch = body->ioepoch;
                req->rq_replay_cb = mdc_replay_open;
        /** bug 3633, open may be committed and estale answer is not error */
        } else if (rc == -ESTALE && (op_data->op_flags & MF_SOM_CHANGE)) {
                rc = 0;
        } else if (rc == -ERESTARTSYS) {
                rc = 0;
        }
        *request = req;
        if (rc && req->rq_commit_cb) {
                /* Put an extra reference on \var mod on error case. */
                obd_mod_put(*mod);
                req->rq_commit_cb(req);
        }
        RETURN(rc);
}
Example #23
0
int lmv_revalidate_slaves(struct obd_export *exp, struct mdt_body *mbody,
			  struct lmv_stripe_md *lsm,
			  ldlm_blocking_callback cb_blocking,
			  int extra_lock_flags)
{
	struct obd_device      *obd = exp->exp_obd;
	struct lmv_obd         *lmv = &obd->u.lmv;
	struct mdt_body		*body;
	struct md_op_data      *op_data;
	unsigned long           size = 0;
	unsigned long           nlink = 0;
	obd_time		atime = 0;
	obd_time		ctime = 0;
	obd_time		mtime = 0;
	int                     i;
	int                     rc = 0;

	ENTRY;

	/**
	 * revalidate slaves has some problems, temporarily return,
	 * we may not need that
	 */
	if (lsm->lsm_md_stripe_count <= 1)
		RETURN(0);

	OBD_ALLOC_PTR(op_data);
	if (op_data == NULL)
		RETURN(-ENOMEM);

	/**
	 * Loop over the stripe information, check validity and update them
	 * from MDS if needed.
	 */
	for (i = 0; i < lsm->lsm_md_stripe_count; i++) {
		struct lu_fid		fid;
		struct lookup_intent	it = { .it_op = IT_GETATTR };
		struct ptlrpc_request	*req = NULL;
		struct lustre_handle	*lockh = NULL;
		struct lmv_tgt_desc	*tgt = NULL;
		struct inode		*inode;

		fid = lsm->lsm_md_oinfo[i].lmo_fid;
		inode = lsm->lsm_md_oinfo[i].lmo_root;
		if (i == 0) {
			if (mbody != NULL) {
				body = mbody;
				goto update;
			} else {
				goto release_lock;
			}
		}

		/*
		 * Prepare op_data for revalidating. Note that @fid2 shluld be
		 * defined otherwise it will go to server and take new lock
		 * which is not needed here.
		 */
		memset(op_data, 0, sizeof(*op_data));
		op_data->op_fid1 = fid;
		op_data->op_fid2 = fid;

		tgt = lmv_locate_mds(lmv, op_data, &fid);
		if (IS_ERR(tgt))
			GOTO(cleanup, rc = PTR_ERR(tgt));

		CDEBUG(D_INODE, "Revalidate slave "DFID" -> mds #%d\n",
		       PFID(&fid), tgt->ltd_idx);

		rc = md_intent_lock(tgt->ltd_exp, op_data, NULL, 0, &it, 0,
				    &req, cb_blocking, extra_lock_flags);
		if (rc < 0)
			GOTO(cleanup, rc);

		lockh = (struct lustre_handle *)&it.d.lustre.it_lock_handle;
		if (rc > 0 && req == NULL) {
			/* slave inode is still valid */
			CDEBUG(D_INODE, "slave "DFID" is still valid.\n",
			       PFID(&fid));
			rc = 0;
		} else {
			/* refresh slave from server */
			body = req_capsule_server_get(&req->rq_pill,
						      &RMF_MDT_BODY);
			LASSERT(body != NULL);
update:
			if (unlikely(body->nlink < 2)) {
				CERROR("%s: nlink %d < 2 corrupt stripe %d "DFID
				       ":" DFID"\n", obd->obd_name, body->nlink,
				       i, PFID(&lsm->lsm_md_oinfo[i].lmo_fid),
				       PFID(&lsm->lsm_md_oinfo[0].lmo_fid));

				if (req != NULL)
					ptlrpc_req_finished(req);

				if (it.d.lustre.it_lock_mode && lockh) {
					ldlm_lock_decref(lockh,
						 it.d.lustre.it_lock_mode);
					it.d.lustre.it_lock_mode = 0;
				}

				GOTO(cleanup, rc = -EIO);
			}

			if (i != 0)
				md_set_lock_data(tgt->ltd_exp, &lockh->cookie,
						 inode, NULL);

			i_size_write(inode, body->size);
			set_nlink(inode, body->nlink);
			LTIME_S(inode->i_atime) = body->atime;
			LTIME_S(inode->i_ctime) = body->ctime;
			LTIME_S(inode->i_mtime) = body->mtime;

			if (req != NULL)
				ptlrpc_req_finished(req);
		}
release_lock:
		size += i_size_read(inode);

		if (i != 0)
			nlink += inode->i_nlink - 2;
		else
			nlink += inode->i_nlink;

		atime = LTIME_S(inode->i_atime) > atime ?
				LTIME_S(inode->i_atime) : atime;
		ctime = LTIME_S(inode->i_ctime) > ctime ?
				LTIME_S(inode->i_ctime) : ctime;
		mtime = LTIME_S(inode->i_mtime) > mtime ?
				LTIME_S(inode->i_mtime) : mtime;

		if (it.d.lustre.it_lock_mode != 0 && lockh != NULL) {
			ldlm_lock_decref(lockh, it.d.lustre.it_lock_mode);
			it.d.lustre.it_lock_mode = 0;
		}

		CDEBUG(D_INODE, "i %d "DFID" size %llu, nlink %u, atime "
		       "%lu, mtime %lu, ctime %lu.\n", i, PFID(&fid),
		       i_size_read(inode), inode->i_nlink,
		       LTIME_S(inode->i_atime), LTIME_S(inode->i_mtime),
		       LTIME_S(inode->i_ctime));
	}

	/*
	 * update attr of master request.
	 */
	CDEBUG(D_INODE, "Return refreshed attrs: size = %lu nlink %lu atime "
	       LPU64 "ctime "LPU64" mtime "LPU64" for " DFID"\n", size, nlink,
	       atime, ctime, mtime, PFID(&lsm->lsm_md_oinfo[0].lmo_fid));

	if (mbody != NULL) {
		mbody->atime = atime;
		mbody->ctime = ctime;
		mbody->mtime = mtime;
	}
cleanup:
	OBD_FREE_PTR(op_data);
	RETURN(rc);
}