op_data->op_attr.ia_size = i_size_read(inode);
op_data->op_attr_blocks = inode->i_blocks;
op_data->op_attr_flags = ll_inode_to_ext_flags(inode->i_flags);
- op_data->op_ioepoch = ll_i2info(inode)->lli_ioepoch;
if (fh)
op_data->op_handle = *fh;
op_data->op_capa1 = ll_mdscapa_get(inode);
}
/**
- * Closes the IO epoch and packs all the attributes into @op_data for
- * the CLOSE rpc.
+ * Packs all the attributes into @op_data for the CLOSE rpc.
*/
static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data,
struct obd_client_handle *och)
if (!(och->och_flags & FMODE_WRITE))
goto out;
- if (!exp_connect_som(ll_i2mdexp(inode)) || !S_ISREG(inode->i_mode))
- op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
- else
- ll_ioepoch_close(inode, op_data, &och, 0);
+ op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
out:
ll_pack_inode2opdata(inode, op_data, &och->och_fh);
struct md_op_data *op_data;
struct ptlrpc_request *req = NULL;
struct obd_device *obd = class_exp2obd(exp);
- int epoch_close = 1;
int rc;
ENTRY;
op_data->op_lease_handle = och->och_lease_handle;
op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
}
- epoch_close = (op_data->op_flags & MF_EPOCH_CLOSE);
+
rc = md_close(md_exp, op_data, och->och_mod, &req);
- if (rc == -EAGAIN) {
- /* This close must have the epoch closed. */
- LASSERT(epoch_close);
- /* MDS has instructed us to obtain Size-on-MDS attribute from
- * OSTs and send setattr to back to MDS. */
- rc = ll_som_update(inode, op_data);
- if (rc) {
- CERROR("%s: inode "DFID" mdc Size-on-MDS update"
- " failed: rc = %d\n",
- ll_i2mdexp(inode)->exp_obd->obd_name,
- PFID(ll_inode2fid(inode)), rc);
- rc = 0;
- }
- } else if (rc) {
+ if (rc) {
CERROR("%s: inode "DFID" mdc close failed: rc = %d\n",
ll_i2mdexp(inode)->exp_obd->obd_name,
PFID(ll_inode2fid(inode)), rc);
EXIT;
out:
- if (exp_connect_som(exp) && !epoch_close &&
- S_ISREG(inode->i_mode) && (och->och_flags & FMODE_WRITE)) {
- ll_queue_done_writing(inode, LLIF_DONE_WRITING);
- } else {
- md_clear_open_replay_data(md_exp, och);
- /* Free @och if it is not waiting for DONE_WRITING. */
- och->och_fh.cookie = DEAD_HANDLE_MAGIC;
- OBD_FREE_PTR(och);
- }
+ md_clear_open_replay_data(md_exp, och);
+ och->och_fh.cookie = DEAD_HANDLE_MAGIC;
+ OBD_FREE_PTR(och);
+
if (req) /* This is close request */
ptlrpc_req_finished(req);
return rc;
RETURN(rc);
}
-/**
- * Assign an obtained @ioepoch to client's inode. No lock is needed, MDS does
- * not believe attributes if a few ioepoch holders exist. Attributes for
- * previous ioepoch if new one is opened are also skipped by MDS.
- */
-void ll_ioepoch_open(struct ll_inode_info *lli, __u64 ioepoch)
-{
- if (ioepoch && lli->lli_ioepoch != ioepoch) {
- lli->lli_ioepoch = ioepoch;
- CDEBUG(D_INODE, "Epoch "LPU64" opened on "DFID"\n",
- ioepoch, PFID(&lli->lli_fid));
- }
-}
-
static int ll_och_fill(struct obd_export *md_exp, struct lookup_intent *it,
struct obd_client_handle *och)
{
static int ll_local_open(struct file *file, struct lookup_intent *it,
struct ll_file_data *fd, struct obd_client_handle *och)
{
- struct inode *inode = file->f_dentry->d_inode;
- struct ll_inode_info *lli = ll_i2info(inode);
- ENTRY;
+ struct inode *inode = file->f_dentry->d_inode;
+ ENTRY;
- LASSERT(!LUSTRE_FPRIVATE(file));
+ LASSERT(!LUSTRE_FPRIVATE(file));
- LASSERT(fd != NULL);
+ LASSERT(fd != NULL);
- if (och) {
- struct ptlrpc_request *req = it->d.lustre.it_data;
- struct mdt_body *body;
- int rc;
+ if (och) {
+ int rc;
rc = ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och);
if (rc != 0)
RETURN(rc);
-
- body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
- ll_ioepoch_open(lli, body->mbo_ioepoch);
}
LUSTRE_FPRIVATE(file) = fd;
/* Fills the obdo with the attributes for the lsm */
static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp,
struct obd_capa *capa, struct obdo *obdo,
- __u64 ioepoch, int dv_flags)
+ int dv_flags)
{
struct ptlrpc_request_set *set;
struct obd_info oinfo = { { { 0 } } };
oinfo.oi_oa = obdo;
oinfo.oi_oa->o_oi = lsm->lsm_oi;
oinfo.oi_oa->o_mode = S_IFREG;
- oinfo.oi_oa->o_ioepoch = ioepoch;
oinfo.oi_oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE |
OBD_MD_FLSIZE | OBD_MD_FLBLOCKS |
OBD_MD_FLBLKSZ | OBD_MD_FLATIME |
OBD_MD_FLMTIME | OBD_MD_FLCTIME |
- OBD_MD_FLGROUP | OBD_MD_FLEPOCH |
- OBD_MD_FLDATAVERSION;
+ OBD_MD_FLGROUP | OBD_MD_FLDATAVERSION;
oinfo.oi_capa = capa;
if (dv_flags & (LL_DV_WR_FLUSH | LL_DV_RD_FLUSH)) {
oinfo.oi_oa->o_valid |= OBD_MD_FLFLAGS;
RETURN(rc);
}
-/**
- * Performs the getattr on the inode and updates its fields.
- * If @sync != 0, perform the getattr under the server-side lock.
- */
-int ll_inode_getattr(struct inode *inode, struct obdo *obdo,
- __u64 ioepoch, int sync)
-{
- struct obd_capa *capa = ll_mdscapa_get(inode);
- struct lov_stripe_md *lsm;
- int rc;
- ENTRY;
-
- lsm = ccc_inode_lsm_get(inode);
- rc = ll_lsm_getattr(lsm, ll_i2dtexp(inode),
- capa, obdo, ioepoch, sync ? LL_DV_RD_FLUSH : 0);
- capa_put(capa);
- if (rc == 0) {
- struct ost_id *oi = lsm ? &lsm->lsm_oi : &obdo->o_oi;
-
- obdo_refresh_inode(inode, obdo, obdo->o_valid);
- CDEBUG(D_INODE, "objid "DOSTID" size %llu, blocks %llu,"
- " blksize %lu\n", POSTID(oi), i_size_read(inode),
- (unsigned long long)inode->i_blocks,
- 1UL << inode->i_blkbits);
- }
- ccc_inode_lsm_put(inode, lsm);
- RETURN(rc);
-}
-
int ll_merge_attr(const struct lu_env *env, struct inode *inode)
{
struct ll_inode_info *lli = ll_i2info(inode);
struct obdo obdo = { 0 };
int rc;
- rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, NULL, &obdo, 0, 0);
+ rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, NULL, &obdo, 0);
if (rc == 0) {
st->st_size = obdo.o_size;
st->st_blocks = obdo.o_blocks;
struct file *file, enum cl_io_type iot,
loff_t *ppos, size_t count)
{
- struct ll_inode_info *lli = ll_i2info(file->f_dentry->d_inode);
+ struct inode *inode = file->f_dentry->d_inode;
+ struct ll_inode_info *lli = ll_i2info(inode);
+ loff_t end;
struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
struct cl_io *io;
ssize_t result;
io = ccc_env_thread_io(env);
ll_io_init(io, file, iot == CIT_WRITE);
+ /* The maximum Lustre file size is variable, based on the
+ * OST maximum object size and number of stripes. This
+ * needs another check in addition to the VFS checks earlier. */
+ end = (io->u.ci_wr.wr_append ? i_size_read(inode) : *ppos) + count;
+ if (end > ll_file_maxbytes(inode)) {
+ result = -EFBIG;
+ CDEBUG(D_INODE, "%s: file "DFID" offset %llu > maxbytes "LPU64
+ ": rc = %zd\n", ll_get_fsname(inode->i_sb, NULL, 0),
+ PFID(&lli->lli_fid), end, ll_file_maxbytes(inode),
+ result);
+ RETURN(result);
+ }
+
if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
struct vvp_io *vio = vvp_env_io(env);
bool range_locked = false;
/**
* Get size for inode for which FIEMAP mapping is requested.
* Make the FIEMAP get_info call and returns the result.
+ * \param fiemap kernel buffer to hold extens
+ * \param num_bytes kernel buffer size
*/
-static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap,
+static int ll_do_fiemap(struct inode *inode, struct fiemap *fiemap,
size_t num_bytes)
{
- struct obd_export *exp = ll_i2dtexp(inode);
- struct lov_stripe_md *lsm = NULL;
- struct ll_fiemap_info_key fm_key = { .name = KEY_FIEMAP, };
- __u32 vallen = num_bytes;
- int rc;
- ENTRY;
-
- /* Checks for fiemap flags */
- if (fiemap->fm_flags & ~LUSTRE_FIEMAP_FLAGS_COMPAT) {
- fiemap->fm_flags &= ~LUSTRE_FIEMAP_FLAGS_COMPAT;
- return -EBADR;
- }
-
- /* Check for FIEMAP_FLAG_SYNC */
- if (fiemap->fm_flags & FIEMAP_FLAG_SYNC) {
- rc = filemap_fdatawrite(inode->i_mapping);
- if (rc)
- return rc;
- }
+ struct lu_env *env;
+ int refcheck;
+ int rc = 0;
+ struct ll_fiemap_info_key fmkey = { .name = KEY_FIEMAP, };
+ ENTRY;
- lsm = ccc_inode_lsm_get(inode);
- if (lsm == NULL)
- return -ENOENT;
+ /* Checks for fiemap flags */
+ if (fiemap->fm_flags & ~LUSTRE_FIEMAP_FLAGS_COMPAT) {
+ fiemap->fm_flags &= ~LUSTRE_FIEMAP_FLAGS_COMPAT;
+ return -EBADR;
+ }
- /* If the stripe_count > 1 and the application does not understand
- * DEVICE_ORDER flag, then it cannot interpret the extents correctly.
- */
- if (lsm->lsm_stripe_count > 1 &&
- !(fiemap->fm_flags & FIEMAP_FLAG_DEVICE_ORDER))
- GOTO(out, rc = -EOPNOTSUPP);
+ /* Check for FIEMAP_FLAG_SYNC */
+ if (fiemap->fm_flags & FIEMAP_FLAG_SYNC) {
+ rc = filemap_fdatawrite(inode->i_mapping);
+ if (rc)
+ return rc;
+ }
- fm_key.oa.o_oi = lsm->lsm_oi;
- fm_key.oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
+ env = cl_env_get(&refcheck);
+ if (IS_ERR(env))
+ RETURN(PTR_ERR(env));
if (i_size_read(inode) == 0) {
rc = ll_glimpse_size(inode);
GOTO(out, rc);
}
- obdo_from_inode(&fm_key.oa, inode, OBD_MD_FLSIZE);
- obdo_set_parent_fid(&fm_key.oa, &ll_i2info(inode)->lli_fid);
- /* If filesize is 0, then there would be no objects for mapping */
- if (fm_key.oa.o_size == 0) {
- fiemap->fm_mapped_extents = 0;
- GOTO(out, rc = 0);
- }
+ fmkey.oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
+ obdo_from_inode(&fmkey.oa, inode, OBD_MD_FLSIZE);
+ obdo_set_parent_fid(&fmkey.oa, &ll_i2info(inode)->lli_fid);
- memcpy(&fm_key.fiemap, fiemap, sizeof(*fiemap));
+ /* If filesize is 0, then there would be no objects for mapping */
+ if (fmkey.oa.o_size == 0) {
+ fiemap->fm_mapped_extents = 0;
+ GOTO(out, rc = 0);
+ }
- rc = obd_get_info(NULL, exp, sizeof(fm_key), &fm_key, &vallen,
- fiemap, lsm);
- if (rc)
- CERROR("obd_get_info failed: rc = %d\n", rc);
+ fmkey.fiemap = *fiemap;
+ rc = cl_object_fiemap(env, ll_i2info(inode)->lli_clob,
+ &fmkey, fiemap, &num_bytes);
out:
- ccc_inode_lsm_put(inode, lsm);
+ cl_env_put(env, &refcheck);
RETURN(rc);
}
RETURN(rc);
}
-static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg)
+static int ll_ioctl_fiemap(struct inode *inode, struct fiemap __user *arg)
{
- struct ll_user_fiemap *fiemap_s;
- size_t num_bytes, ret_bytes;
- unsigned int extent_count;
- int rc = 0;
+ struct fiemap *fiemap;
+ size_t num_bytes;
+ size_t ret_bytes;
+ __u32 extent_count;
+ int rc = 0;
- /* Get the extent count so we can calculate the size of
- * required fiemap buffer */
- if (get_user(extent_count,
- &((struct ll_user_fiemap __user *)arg)->fm_extent_count))
- RETURN(-EFAULT);
+ /* Get the extent count so we can calculate the size of
+ * required fiemap buffer */
+ if (get_user(extent_count, &arg->fm_extent_count))
+ RETURN(-EFAULT);
if (extent_count >=
- (SIZE_MAX - sizeof(*fiemap_s)) / sizeof(struct ll_fiemap_extent))
+ (SIZE_MAX - sizeof(*fiemap)) / sizeof(struct ll_fiemap_extent))
RETURN(-EINVAL);
- num_bytes = sizeof(*fiemap_s) + (extent_count *
- sizeof(struct ll_fiemap_extent));
+ num_bytes = sizeof(*fiemap) + (extent_count *
+ sizeof(struct ll_fiemap_extent));
- OBD_ALLOC_LARGE(fiemap_s, num_bytes);
- if (fiemap_s == NULL)
- RETURN(-ENOMEM);
+ OBD_ALLOC_LARGE(fiemap, num_bytes);
+ if (fiemap == NULL)
+ RETURN(-ENOMEM);
/* get the fiemap value */
- if (copy_from_user(fiemap_s, (struct ll_user_fiemap __user *)arg,
- sizeof(*fiemap_s)))
+ if (copy_from_user(fiemap, arg, sizeof(*fiemap)))
GOTO(error, rc = -EFAULT);
- /* If fm_extent_count is non-zero, read the first extent since
- * it is used to calculate end_offset and device from previous
- * fiemap call. */
- if (extent_count) {
- if (copy_from_user(&fiemap_s->fm_extents[0],
- (char __user *)arg + sizeof(*fiemap_s),
- sizeof(struct ll_fiemap_extent)))
- GOTO(error, rc = -EFAULT);
- }
+ /* If fm_extent_count is non-zero, read the first extent since
+ * it is used to calculate end_offset and device from previous
+ * fiemap call. */
+ if (extent_count != 0) {
+ if (copy_from_user(&fiemap->fm_extents[0],
+ (char __user *)arg + sizeof(*fiemap),
+ sizeof(struct ll_fiemap_extent)))
+ GOTO(error, rc = -EFAULT);
+ }
- rc = ll_do_fiemap(inode, fiemap_s, num_bytes);
- if (rc)
- GOTO(error, rc);
+ rc = ll_do_fiemap(inode, fiemap, num_bytes);
+ if (rc)
+ GOTO(error, rc);
- ret_bytes = sizeof(struct ll_user_fiemap);
+ ret_bytes = sizeof(struct fiemap);
- if (extent_count != 0)
- ret_bytes += (fiemap_s->fm_mapped_extents *
- sizeof(struct ll_fiemap_extent));
+ if (extent_count != 0)
+ ret_bytes += (fiemap->fm_mapped_extents *
+ sizeof(struct ll_fiemap_extent));
- if (copy_to_user((void __user *)arg, fiemap_s, ret_bytes))
+ if (copy_to_user((void __user *)arg, fiemap, ret_bytes))
rc = -EFAULT;
error:
- OBD_FREE_LARGE(fiemap_s, num_bytes);
- RETURN(rc);
+ OBD_FREE_LARGE(fiemap, num_bytes);
+ RETURN(rc);
}
/*
* This value is computed using stripe object version on OST.
* Version is computed using server side locking.
*
- * @param sync if do sync on the OST side;
+ * @param flags if do sync on the OST side;
* 0: no sync
* LL_DV_RD_FLUSH: flush dirty pages, LCK_PR on OSTs
* LL_DV_WR_FLUSH: drop all caching pages, LCK_PW on OSTs
*/
int ll_data_version(struct inode *inode, __u64 *data_version, int flags)
{
- struct lov_stripe_md *lsm = NULL;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct obdo *obdo = NULL;
- int rc;
+ struct lu_env *env;
+ int refcheck;
+ int rc;
ENTRY;
- /* If no stripe, we consider version is 0. */
- lsm = ccc_inode_lsm_get(inode);
- if (!lsm_has_objects(lsm)) {
+ /* If no file object initialized, we consider its version is 0. */
+ if (ll_i2info(inode)->lli_clob == NULL) {
*data_version = 0;
- CDEBUG(D_INODE, "No object for inode\n");
- GOTO(out, rc = 0);
+ RETURN(0);
}
- OBD_ALLOC_PTR(obdo);
- if (obdo == NULL)
- GOTO(out, rc = -ENOMEM);
-
- rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, NULL, obdo, 0, flags);
- if (rc == 0) {
- if (!(obdo->o_valid & OBD_MD_FLDATAVERSION))
- rc = -EOPNOTSUPP;
- else
- *data_version = obdo->o_data_version;
- }
+ env = cl_env_get(&refcheck);
+ if (IS_ERR(env))
+ RETURN(PTR_ERR(env));
- OBD_FREE_PTR(obdo);
- EXIT;
-out:
- ccc_inode_lsm_put(inode, lsm);
+ rc = cl_object_data_version(env, ll_i2info(inode)->lli_clob,
+ data_version, flags);
+ cl_env_put(env, &refcheck);
RETURN(rc);
}
{
struct md_op_data *op_data;
int rc;
+ ENTRY;
+
+ /* Detect out-of range masks */
+ if ((hss->hss_setmask | hss->hss_clearmask) & ~HSM_FLAGS_MASK)
+ RETURN(-EINVAL);
/* Non-root users are forbidden to set or clear flags which are
* NOT defined in HSM_USER_MASK. */
!cfs_capable(CFS_CAP_SYS_ADMIN))
RETURN(-EPERM);
+ /* Detect out-of range archive id */
+ if ((hss->hss_valid & HSS_ARCHIVE_ID) &&
+ (hss->hss_archive_id > LL_HSM_MAX_ARCHIVE))
+ RETURN(-EINVAL);
+
op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
LUSTRE_OPC_ANY, hss);
if (IS_ERR(op_data))
case LL_IOC_LOV_GETSTRIPE:
RETURN(ll_file_getstripe(inode,
(struct lov_user_md __user *)arg));
- case FSFILT_IOC_FIEMAP:
- RETURN(ll_ioctl_fiemap(inode, arg));
+ case FSFILT_IOC_FIEMAP:
+ RETURN(ll_ioctl_fiemap(inode, (struct fiemap __user *)arg));
case FSFILT_IOC_GETFLAGS:
case FSFILT_IOC_SETFLAGS:
RETURN(ll_iocontrol(inode, file, cmd, arg));
qstr.name = name;
qstr.len = namelen;
dchild = d_lookup(file->f_dentry, &qstr);
- if (dchild != NULL && dchild->d_inode != NULL) {
- op_data->op_fid3 = *ll_inode2fid(dchild->d_inode);
+ if (dchild != NULL) {
if (dchild->d_inode != NULL) {
child_inode = igrab(dchild->d_inode);
- ll_invalidate_aliases(child_inode);
+ if (child_inode != NULL) {
+ mutex_lock(&child_inode->i_mutex);
+ op_data->op_fid3 = *ll_inode2fid(child_inode);
+ ll_invalidate_aliases(child_inode);
+ }
}
dput(dchild);
} else {
out_free:
if (child_inode != NULL) {
clear_nlink(child_inode);
+ mutex_unlock(&child_inode->i_mutex);
iput(child_inode);
}