op_data->op_xvalid |= OP_XVALID_CTIME_SET;
op_data->op_attr_blocks = inode->i_blocks;
op_data->op_attr_flags = ll_inode_to_ext_flags(inode->i_flags);
- if (ll_file_test_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT))
+ if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags))
op_data->op_attr_flags |= LUSTRE_PROJINHERIT_FL;
op_data->op_open_handle = och->och_open_handle;
if (och->och_flags & FMODE_WRITE &&
- ll_file_test_and_clear_flag(ll_i2info(inode), LLIF_DATA_MODIFIED))
+ test_and_clear_bit(LLIF_DATA_MODIFIED, &ll_i2info(inode)->lli_flags))
/* For HSM: if inode data has been modified, pack it so that
* MDT can set data dirty flag in the archive. */
op_data->op_bias |= MDS_DATA_MODIFIED;
/* Usually the lease is not released when the
* application crashed, we need to release here. */
rc = ll_lease_close(fd->fd_lease_och, inode, &lease_broken);
- CDEBUG(rc ? D_ERROR : D_INODE, "Clean up lease "DFID" %d/%d\n",
- PFID(&lli->lli_fid), rc, lease_broken);
+ CDEBUG_LIMIT(rc ? D_ERROR : D_INODE,
+ "Clean up lease "DFID" %d/%d\n",
+ PFID(&lli->lli_fid), rc, lease_broken);
fd->fd_lease_och = NULL;
}
if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd)
ll_deauthorize_statahead(inode, fd);
- if (inode->i_sb->s_root == file_dentry(file)) {
+ if (is_root_inode(inode)) {
file->private_data = NULL;
ll_file_data_put(fd);
GOTO(out, rc = 0);
libcfs_debug_dumplog();
out:
- if (!rc && inode->i_sb->s_root != file_dentry(file))
+ if (!rc && !is_root_inode(inode))
ll_stats_ops_tally(sbi, LPROC_LL_RELEASE,
ktime_us_delta(ktime_get(), kstart));
RETURN(rc);
file->private_data = fd;
ll_readahead_init(inode, &fd->fd_ras);
fd->fd_omode = it->it_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
+ /* turn off the kernel's read-ahead */
+ file->f_ra.ra_pages = 0;
/* ll_cl_context initialize */
rwlock_init(&fd->fd_lock);
if (S_ISDIR(inode->i_mode))
ll_authorize_statahead(inode, fd);
- if (inode->i_sb->s_root == file_dentry(file)) {
+ if (is_root_inode(inode)) {
file->private_data = fd;
RETURN(0);
}
mutex_unlock(&lli->lli_och_mutex);
- /* lockless for direct IO so that it can do IO in parallel */
- if (file->f_flags & O_DIRECT)
- fd->fd_flags |= LL_FILE_LOCKLESS_IO;
fd = NULL;
/* Must do this outside lli_och_mutex lock to prevent deadlock where
* POSIX. Solving this problem needs to send an RPC to MDT for each
* read, this will hurt performance.
*/
- if (ll_file_test_and_clear_flag(lli, LLIF_UPDATE_ATIME) ||
+ if (test_and_clear_bit(LLIF_UPDATE_ATIME, &lli->lli_flags) ||
inode->i_atime.tv_sec < lli->lli_atime)
inode->i_atime.tv_sec = lli->lli_atime;
struct vvp_io *vio = vvp_env_io(env);
struct inode *inode = file_inode(file);
struct ll_inode_info *lli = ll_i2info(inode);
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
struct ll_file_data *fd = file->private_data;
struct range_lock range;
struct cl_io *io;
ssize_t result = 0;
int rc = 0;
- unsigned int retried = 0, ignore_lockless = 0;
+ unsigned int retried = 0, dio_lock = 0;
bool is_aio = false;
struct cl_dio_aio *ci_aio = NULL;
+ size_t per_bytes;
+ bool partial_io = false;
+ size_t max_io_pages, max_cached_pages;
ENTRY;
file_dentry(file)->d_name.name,
iot == CIT_READ ? "read" : "write", *ppos, count);
+ max_io_pages = PTLRPC_MAX_BRW_PAGES * OBD_MAX_RIF_DEFAULT;
+ max_cached_pages = sbi->ll_cache->ccc_lru_max;
+ if (max_io_pages > (max_cached_pages >> 2))
+ max_io_pages = max_cached_pages >> 2;
+
io = vvp_env_thread_io(env);
if (file->f_flags & O_DIRECT) {
if (!is_sync_kiocb(args->u.normal.via_iocb))
}
restart:
+ /**
+ * IO block size need be aware of cached page limit, otherwise
+ * if we have small max_cached_mb but large block IO issued, io
+ * could not be finished and blocked whole client.
+ */
+ if (file->f_flags & O_DIRECT)
+ per_bytes = count;
+ else
+ per_bytes = min(max_io_pages << PAGE_SHIFT, count);
+ partial_io = per_bytes < count;
io = vvp_env_thread_io(env);
ll_io_init(io, file, iot, args);
io->ci_aio = ci_aio;
- io->ci_ignore_lockless = ignore_lockless;
+ io->ci_dio_lock = dio_lock;
io->ci_ndelay_tried = retried;
- if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
+ if (cl_io_rw_init(env, io, iot, *ppos, per_bytes) == 0) {
bool range_locked = false;
if (file->f_flags & O_APPEND)
range_lock_init(&range, 0, LUSTRE_EOF);
else
- range_lock_init(&range, *ppos, *ppos + count - 1);
+ range_lock_init(&range, *ppos, *ppos + per_bytes - 1);
vio->vui_fd = file->private_data;
vio->vui_iter = args->u.normal.via_iter;
/* prepare IO restart */
if (count > 0)
args->u.normal.via_iter = vio->vui_iter;
+
+ if (partial_io) {
+ /**
+ * Reexpand iov count because it was zero
+ * after IO finish.
+ */
+ iov_iter_reexpand(vio->vui_iter, count);
+ if (per_bytes == io->ci_nob)
+ io->ci_need_restart = 1;
+ }
}
out:
cl_io_fini(env, io);
*ppos, count, result, rc);
/* preserve the tried count for FLR */
retried = io->ci_ndelay_tried;
- ignore_lockless = io->ci_ignore_lockless;
+ dio_lock = io->ci_dio_lock;
goto restart;
}
ll_heat_add(inode, CIT_WRITE, result);
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_WRITE_BYTES,
result);
- ll_file_set_flag(ll_i2info(inode), LLIF_DATA_MODIFIED);
+ set_bit(LLIF_DATA_MODIFIED, &ll_i2info(inode)->lli_flags);
}
CDEBUG(D_VFSTRACE, "result: %zu, original count %zu\n", result, count);
struct lov_mds_md **lmmp, int *lmm_size,
struct ptlrpc_request **request)
{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct mdt_body *body;
- struct lov_mds_md *lmm = NULL;
- struct ptlrpc_request *req = NULL;
- struct md_op_data *op_data;
- int rc, lmmsize;
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ struct mdt_body *body;
+ struct lov_mds_md *lmm = NULL;
+ struct ptlrpc_request *req = NULL;
+ struct md_op_data *op_data;
+ int rc, lmmsize;
+
+ ENTRY;
rc = ll_get_default_mdsize(sbi, &lmmsize);
if (rc)
RETURN(rc);
- op_data = ll_prep_md_op_data(NULL, inode, NULL, filename,
- strlen(filename), lmmsize,
- LUSTRE_OPC_ANY, NULL);
- if (IS_ERR(op_data))
- RETURN(PTR_ERR(op_data));
+ op_data = ll_prep_md_op_data(NULL, inode, NULL, filename,
+ strlen(filename), lmmsize,
+ LUSTRE_OPC_ANY, NULL);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
- op_data->op_valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
- rc = md_getattr_name(sbi->ll_md_exp, op_data, &req);
- ll_finish_md_op_data(op_data);
- if (rc < 0) {
- CDEBUG(D_INFO, "md_getattr_name failed "
- "on %s: rc %d\n", filename, rc);
- GOTO(out, rc);
- }
+ op_data->op_valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
+ rc = md_getattr_name(sbi->ll_md_exp, op_data, &req);
+ ll_finish_md_op_data(op_data);
+ if (rc < 0) {
+ CDEBUG(D_INFO, "md_getattr_name failed "
+ "on %s: rc %d\n", filename, rc);
+ GOTO(out, rc);
+ }
- body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
- LASSERT(body != NULL); /* checked by mdc_getattr_name */
+ body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
+ LASSERT(body != NULL); /* checked by mdc_getattr_name */
lmmsize = body->mbo_eadatasize;
if (!(body->mbo_valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) ||
- lmmsize == 0) {
- GOTO(out, rc = -ENODATA);
- }
+ lmmsize == 0)
+ GOTO(out, rc = -ENODATA);
- lmm = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD, lmmsize);
- LASSERT(lmm != NULL);
+ lmm = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD, lmmsize);
+ LASSERT(lmm != NULL);
if (lmm->lmm_magic != cpu_to_le32(LOV_MAGIC_V1) &&
lmm->lmm_magic != cpu_to_le32(LOV_MAGIC_V3) &&
/*
* This is coming from the MDS, so is probably in
- * little endian. We convert it to host endian before
+ * little endian. We convert it to host endian before
* passing it to userspace.
*/
- if ((lmm->lmm_magic & __swab32(LOV_MAGIC_MAGIC)) ==
- __swab32(LOV_MAGIC_MAGIC)) {
+ if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) {
int stripe_count = 0;
if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1) ||
if (le32_to_cpu(lmm->lmm_pattern) &
LOV_PATTERN_F_RELEASED)
stripe_count = 0;
- }
-
- lustre_swab_lov_user_md((struct lov_user_md *)lmm, 0);
+ lustre_swab_lov_user_md((struct lov_user_md *)lmm, 0);
- /* if function called for directory - we should
- * avoid swab not existent lsm objects */
- if (lmm->lmm_magic == LOV_MAGIC_V1 && S_ISREG(body->mbo_mode))
- lustre_swab_lov_user_md_objects(
+ /* if function called for directory - we should
+ * avoid swab not existent lsm objects
+ */
+ if (lmm->lmm_magic == LOV_MAGIC_V1 &&
+ S_ISREG(body->mbo_mode))
+ lustre_swab_lov_user_md_objects(
((struct lov_user_md_v1 *)lmm)->lmm_objects,
stripe_count);
- else if (lmm->lmm_magic == LOV_MAGIC_V3 &&
- S_ISREG(body->mbo_mode))
- lustre_swab_lov_user_md_objects(
+ else if (lmm->lmm_magic == LOV_MAGIC_V3 &&
+ S_ISREG(body->mbo_mode))
+ lustre_swab_lov_user_md_objects(
((struct lov_user_md_v3 *)lmm)->lmm_objects,
stripe_count);
+ } else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_COMP_V1)) {
+ lustre_swab_lov_comp_md_v1(
+ (struct lov_comp_md_v1 *)lmm);
+ }
}
+ if (lmm->lmm_magic == LOV_MAGIC_COMP_V1) {
+ struct lov_comp_md_v1 *comp_v1 = NULL;
+ struct lov_comp_md_entry_v1 *ent;
+ struct lov_user_md_v1 *v1;
+ __u32 off;
+ int i = 0;
+
+ comp_v1 = (struct lov_comp_md_v1 *)lmm;
+ /* Dump the striping information */
+ for (; i < comp_v1->lcm_entry_count; i++) {
+ ent = &comp_v1->lcm_entries[i];
+ off = ent->lcme_offset;
+ v1 = (struct lov_user_md_v1 *)((char *)lmm + off);
+ CDEBUG(D_INFO,
+ "comp[%d]: stripe_count=%u, stripe_size=%u\n",
+ i, v1->lmm_stripe_count, v1->lmm_stripe_size);
+ }
+
+ /**
+ * Return valid stripe_count and stripe_size instead of 0 for
+ * DoM files to avoid divide-by-zero for older userspace that
+ * calls this ioctl, e.g. lustre ADIO driver.
+ */
+ if (lmm->lmm_stripe_count == 0)
+ lmm->lmm_stripe_count = 1;
+ if (lmm->lmm_stripe_size == 0) {
+ /* Since the first component of the file data is placed
+ * on the MDT for faster access, the stripe_size of the
+ * second one is always that applications which are
+ * doing large IOs.
+ */
+ if (lmm->lmm_pattern == LOV_PATTERN_MDT)
+ i = comp_v1->lcm_entry_count > 1 ? 1 : 0;
+ else
+ i = comp_v1->lcm_entry_count > 1 ?
+ comp_v1->lcm_entry_count - 1 : 0;
+ ent = &comp_v1->lcm_entries[i];
+ off = ent->lcme_offset;
+ v1 = (struct lov_user_md_v1 *)((char *)lmm + off);
+ lmm->lmm_stripe_size = v1->lmm_stripe_size;
+ }
+ }
out:
*lmmp = lmm;
*lmm_size = lmmsize;
*request = req;
- return rc;
+ RETURN(rc);
}
static int ll_lov_setea(struct inode *inode, struct file *file,
int rc;
ENTRY;
- if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN))
RETURN(-EPERM);
OBD_ALLOC_LARGE(lump, lum_size);
GOTO(out, rc = PTR_ERR(env));
rc = cl_object_layout_get(env, obj, &cl);
- if (!rc && cl.cl_is_composite)
+ if (rc >= 0 && cl.cl_is_composite)
rc = ll_layout_write_intent(inode, LAYOUT_INTENT_WRITE,
&ext);
cl_env_put(env, &refcheck);
- if (rc)
+ if (rc < 0)
GOTO(out, rc);
}
*/
int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it)
{
- struct inode *inode = dentry->d_inode;
- struct obd_client_handle *och;
- int rc;
- ENTRY;
+ struct inode *inode = dentry->d_inode;
+ struct obd_client_handle *och;
+ int rc;
+ ENTRY;
- LASSERT(inode);
+ LASSERT(inode);
- /* Root ? Do nothing. */
- if (dentry->d_inode->i_sb->s_root == dentry)
- RETURN(0);
+ /* Root ? Do nothing. */
+ if (is_root_inode(inode))
+ RETURN(0);
- /* No open handle to close? Move away */
- if (!it_disposition(it, DISP_OPEN_OPEN))
- RETURN(0);
+ /* No open handle to close? Move away */
+ if (!it_disposition(it, DISP_OPEN_OPEN))
+ RETURN(0);
- LASSERT(it_open_error(DISP_OPEN_OPEN, it) == 0);
+ LASSERT(it_open_error(DISP_OPEN_OPEN, it) == 0);
- OBD_ALLOC(och, sizeof(*och));
- if (!och)
- GOTO(out, rc = -ENOMEM);
+ OBD_ALLOC(och, sizeof(*och));
+ if (!och)
+ GOTO(out, rc = -ENOMEM);
rc = ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och);
if (rc)
ENTRY;
- if (!cfs_capable(CFS_CAP_DAC_READ_SEARCH) &&
+ if (!capable(CAP_DAC_READ_SEARCH) &&
!(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH))
RETURN(-EPERM);
/* Non-root users are forbidden to set or clear flags which are
* NOT defined in HSM_USER_MASK. */
if (((hss->hss_setmask | hss->hss_clearmask) & ~HSM_USER_MASK) &&
- !cfs_capable(CFS_CAP_SYS_ADMIN))
+ !capable(CAP_SYS_ADMIN))
RETURN(-EPERM);
if (!exp_connect_archive_id_array(exp)) {
RETURN(-EFAULT);
fsxattr.fsx_xflags = ll_inode_flags_to_xflags(inode->i_flags);
- if (ll_file_test_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT))
+ if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags))
fsxattr.fsx_xflags |= FS_XFLAG_PROJINHERIT;
fsxattr.fsx_projid = ll_i2info(inode)->lli_projid;
if (copy_to_user((struct fsxattr __user *)arg,
if (ll_i2info(inode)->lli_projid != fa->fsx_projid)
return -EINVAL;
- if (ll_file_test_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT)) {
+ if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags)) {
if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT))
return -EINVAL;
} else {
int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
unsigned long arg)
{
-
struct md_op_data *op_data;
struct ptlrpc_request *req = NULL;
- int rc = 0;
struct fsxattr fsxattr;
struct cl_object *obj;
- struct iattr *attr;
- int flags;
+ unsigned int inode_flags;
+ int rc = 0;
if (copy_from_user(&fsxattr,
(const struct fsxattr __user *)arg,
if (IS_ERR(op_data))
RETURN(PTR_ERR(op_data));
- flags = ll_xflags_to_inode_flags(fsxattr.fsx_xflags);
- op_data->op_attr_flags = ll_inode_to_ext_flags(flags);
+ inode_flags = ll_xflags_to_inode_flags(fsxattr.fsx_xflags);
+ op_data->op_attr_flags = ll_inode_to_ext_flags(inode_flags);
if (fsxattr.fsx_xflags & FS_XFLAG_PROJINHERIT)
op_data->op_attr_flags |= LUSTRE_PROJINHERIT_FL;
op_data->op_projid = fsxattr.fsx_projid;
op_data->op_xvalid |= OP_XVALID_PROJID | OP_XVALID_FLAGS;
- rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL,
- 0, &req);
+ rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL, 0, &req);
ptlrpc_req_finished(req);
if (rc)
GOTO(out_fsxattr, rc);
ll_update_inode_flags(inode, op_data->op_attr_flags);
- obj = ll_i2info(inode)->lli_clob;
- if (obj == NULL)
- GOTO(out_fsxattr, rc);
- /* Avoiding OST RPC if this is only project ioctl */
+ /* Avoid OST RPC if this is only ioctl setting project inherit flag */
if (fsxattr.fsx_xflags == 0 ||
fsxattr.fsx_xflags == FS_XFLAG_PROJINHERIT)
GOTO(out_fsxattr, rc);
- OBD_ALLOC_PTR(attr);
- if (attr == NULL)
- GOTO(out_fsxattr, rc = -ENOMEM);
+ obj = ll_i2info(inode)->lli_clob;
+ if (obj) {
+ struct iattr attr = { 0 };
+
+ rc = cl_setattr_ost(obj, &attr, OP_XVALID_FLAGS,
+ fsxattr.fsx_xflags);
+ }
- rc = cl_setattr_ost(obj, attr, OP_XVALID_FLAGS,
- fsxattr.fsx_xflags);
- OBD_FREE_PTR(attr);
out_fsxattr:
ll_finish_md_op_data(op_data);
RETURN(rc);
if (!layout_file)
GOTO(out_lease_close, rc = -EBADF);
+ /* if layout_file == file, it means to destroy the mirror */
sp.sp_inode = file_inode(layout_file);
sp.sp_mirror_id = (__u16)mirror_id;
data = &sp;
RETURN(0);
}
+ case OBD_IOC_GETNAME_OLD:
+ /* fall through */
case OBD_IOC_GETDTNAME:
+ /* fall through */
case OBD_IOC_GETMDNAME:
RETURN(ll_get_obd_name(inode, cmd, arg));
case LL_IOC_HSM_STATE_GET: {
return -EOPNOTSUPP;
return llcrypt_ioctl_get_key_status(file, (void __user *)arg);
#endif
+
+ case LL_IOC_UNLOCK_FOREIGN: {
+ struct dentry *dentry = file_dentry(file);
+
+ /* if not a foreign symlink do nothing */
+ if (ll_foreign_is_removable(dentry, true)) {
+ CDEBUG(D_INFO,
+ "prevent unlink of non-foreign file ("DFID")\n",
+ PFID(ll_inode2fid(inode)));
+ RETURN(-EOPNOTSUPP);
+ }
+ RETURN(0);
+ }
+
default:
RETURN(obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL,
(void __user *)arg));
}
}
+loff_t ll_lseek(struct file *file, loff_t offset, int whence)
+{
+ struct inode *inode = file_inode(file);
+ struct lu_env *env;
+ struct cl_io *io;
+ struct cl_lseek_io *lsio;
+ __u16 refcheck;
+ int rc;
+ loff_t retval;
+
+ ENTRY;
+
+ env = cl_env_get(&refcheck);
+ if (IS_ERR(env))
+ RETURN(PTR_ERR(env));
+
+ io = vvp_env_thread_io(env);
+ io->ci_obj = ll_i2info(inode)->lli_clob;
+ ll_io_set_mirror(io, file);
+
+ lsio = &io->u.ci_lseek;
+ lsio->ls_start = offset;
+ lsio->ls_whence = whence;
+ lsio->ls_result = -ENXIO;
+
+ do {
+ rc = cl_io_init(env, io, CIT_LSEEK, io->ci_obj);
+ if (!rc) {
+ struct vvp_io *vio = vvp_env_io(env);
+
+ vio->vui_fd = file->private_data;
+ rc = cl_io_loop(env, io);
+ } else {
+ rc = io->ci_result;
+ }
+ retval = rc ? : lsio->ls_result;
+ cl_io_fini(env, io);
+ } while (unlikely(io->ci_need_restart));
+
+ cl_env_put(env, &refcheck);
+
+ RETURN(retval);
+}
+
static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
{
struct inode *inode = file_inode(file);
- loff_t retval, eof = 0;
+ loff_t retval = offset, eof = 0;
ktime_t kstart = ktime_get();
ENTRY;
- retval = offset + ((origin == SEEK_END) ? i_size_read(inode) :
- (origin == SEEK_CUR) ? file->f_pos : 0);
+
CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), to=%llu=%#llx(%d)\n",
PFID(ll_inode2fid(inode)), inode, retval, retval,
origin);
- if (origin == SEEK_END || origin == SEEK_HOLE || origin == SEEK_DATA) {
+ if (origin == SEEK_END) {
retval = ll_glimpse_size(inode);
if (retval != 0)
RETURN(retval);
eof = i_size_read(inode);
}
- retval = generic_file_llseek_size(file, offset, origin,
- ll_file_maxbytes(inode), eof);
+ if (origin == SEEK_HOLE || origin == SEEK_DATA) {
+ if (offset < 0)
+ return -ENXIO;
+
+ /* flush local cache first if any */
+ cl_sync_file_range(inode, offset, OBD_OBJECT_EOF,
+ CL_FSYNC_LOCAL, 0);
+
+ retval = ll_lseek(file, offset, origin);
+ if (retval < 0)
+ return retval;
+ retval = vfs_setpos(file, retval, ll_file_maxbytes(inode));
+ } else {
+ retval = generic_file_llseek_size(file, offset, origin,
+ ll_file_maxbytes(inode), eof);
+ }
if (retval >= 0)
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LLSEEK,
ktime_us_delta(ktime_get(), kstart));
* by checking the migrate FID against the FID of the
* filesystem root.
*/
- if (child_inode == parent->i_sb->s_root->d_inode)
+ if (is_root_inode(child_inode))
GOTO(out_iput, rc = -EINVAL);
+ if (IS_ENCRYPTED(child_inode)) {
+ rc = llcrypt_get_encryption_info(child_inode);
+ if (rc)
+ GOTO(out_iput, rc);
+ if (!llcrypt_has_encryption_key(child_inode)) {
+ CDEBUG(D_SEC, "no enc key for "DFID"\n",
+ PFID(ll_inode2fid(child_inode)));
+ GOTO(out_iput, rc = -ENOKEY);
+ }
+ }
+
op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen,
child_inode->i_mode, LUSTRE_OPC_ANY, NULL);
if (IS_ERR(op_data))
};
struct ptlrpc_request *req = NULL;
struct md_op_data *op_data;
+ const char *name = NULL;
+ size_t namelen = 0;
int rc = 0;
ENTRY;
CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p),name=%s\n",
PFID(ll_inode2fid(inode)), inode, dentry->d_name.name);
- if (exp_connect_flags2(exp) & OBD_CONNECT2_GETATTR_PFID)
+ if (exp_connect_flags2(exp) & OBD_CONNECT2_GETATTR_PFID) {
parent = dentry->d_parent->d_inode;
- else
+ name = dentry->d_name.name;
+ namelen = dentry->d_name.len;
+ } else {
parent = inode;
+ }
- /* Call getattr by fid, so do not provide name at all. */
- op_data = ll_prep_md_op_data(NULL, parent, inode, NULL, 0, 0,
+ op_data = ll_prep_md_op_data(NULL, parent, inode, name, namelen, 0,
LUSTRE_OPC_ANY, NULL);
if (IS_ERR(op_data))
RETURN(PTR_ERR(op_data));
+ /* Call getattr by fid */
+ if (exp_connect_flags2(exp) & OBD_CONNECT2_GETATTR_PFID)
+ op_data->op_flags = MF_GETATTR_BY_FID;
rc = md_intent_lock(exp, op_data, &oit, &req, &ll_md_blocking_ast, 0);
ll_finish_md_op_data(op_data);
if (rc < 0) {
RETURN(0);
down_read(&lli->lli_lsm_sem);
- rc = md_merge_attr(ll_i2mdexp(inode), &lli->lli_fid, lli->lli_lsm_md,
+ rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md,
&attr, ll_md_blocking_ast);
up_read(&lli->lli_lsm_sem);
if (rc != 0)
}
int ll_getattr_dentry(struct dentry *de, struct kstat *stat, u32 request_mask,
- unsigned int flags)
+ unsigned int flags, bool foreign)
{
struct inode *inode = de->d_inode;
struct ll_sb_info *sbi = ll_i2sbi(inode);
if (rc < 0)
RETURN(rc);
- if (S_ISREG(inode->i_mode)) {
+ /* foreign file/dir are always of zero length, so don't
+ * need to validate size.
+ */
+ if (S_ISREG(inode->i_mode) && !foreign) {
bool cached;
if (!need_glimpse)
* restore the MDT holds the layout lock so the glimpse will
* block up to the end of restore (getattr will block)
*/
- if (!ll_file_test_flag(lli, LLIF_FILE_RESTORING)) {
+ if (!test_bit(LLIF_FILE_RESTORING, &lli->lli_flags)) {
rc = ll_glimpse_size(inode);
if (rc < 0)
RETURN(rc);
}
} else {
/* If object isn't regular a file then don't validate size. */
- if (ll_dir_striped(inode)) {
+ /* foreign dir is not striped dir */
+ if (ll_dir_striped(inode) && !foreign) {
rc = ll_merge_md_attr(inode);
if (rc < 0)
RETURN(rc);
stat->rdev = inode->i_rdev;
}
- stat->mode = inode->i_mode;
+ /* foreign symlink to be exposed as a real symlink */
+ if (!foreign)
+ stat->mode = inode->i_mode;
+ else
+ stat->mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
+
stat->uid = inode->i_uid;
stat->gid = inode->i_gid;
stat->atime = inode->i_atime;
int ll_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags)
{
- return ll_getattr_dentry(path->dentry, stat, request_mask, flags);
+ return ll_getattr_dentry(path->dentry, stat, request_mask, flags,
+ false);
}
#else
int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat)
{
return ll_getattr_dentry(de, stat, STATX_BASIC_STATS,
- AT_STATX_SYNC_AS_STAT);
+ AT_STATX_SYNC_AS_STAT, false);
}
#endif
rc = -EFBIG;
goto out;
}
- io->u.ci_setattr.sa_attr.lvb_size = sa_falloc_end;
- if (!(mode & FALLOC_FL_KEEP_SIZE))
- io->u.ci_setattr.sa_avalid |= ATTR_SIZE;
- } else {
- io->u.ci_setattr.sa_attr.lvb_size = size;
}
again:
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FALLOCATE, 1);
rc = cl_falloc(inode, mode, offset, len);
+ /*
+ * ENOTSUPP (524) is an NFSv3 specific error code erroneously
+ * used by Lustre in several places. Retuning it here would
+ * confuse applications that explicity test for EOPNOTSUPP
+ * (95) and fall back to ftruncate().
+ */
+ if (rc == -ENOTSUPP)
+ rc = -EOPNOTSUPP;
RETURN(rc);
}
rc = ll_do_fiemap(inode, fiemap, num_bytes);
+ if (IS_ENCRYPTED(inode)) {
+ int i;
+
+ for (i = 0; i < fiemap->fm_mapped_extents; i++)
+ fiemap->fm_extents[i].fe_flags |=
+ FIEMAP_EXTENT_DATA_ENCRYPTED |
+ FIEMAP_EXTENT_ENCODED;
+ }
+
fieinfo->fi_flags = fiemap->fm_flags;
fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents;
if (extent_count > 0 &&
return rc;
}
-struct posix_acl *ll_get_acl(struct inode *inode, int type)
-{
- struct ll_inode_info *lli = ll_i2info(inode);
- struct posix_acl *acl = NULL;
- ENTRY;
-
- spin_lock(&lli->lli_lock);
- /* VFS' acl_permission_check->check_acl will release the refcount */
- acl = posix_acl_dup(lli->lli_posix_acl);
- spin_unlock(&lli->lli_lock);
-
- RETURN(acl);
-}
-
-#ifdef HAVE_IOP_SET_ACL
-#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
-int ll_set_acl(struct inode *inode, struct posix_acl *acl, int type)
-{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ptlrpc_request *req = NULL;
- const char *name = NULL;
- char *value = NULL;
- size_t value_size = 0;
- int rc = 0;
- ENTRY;
-
- switch (type) {
- case ACL_TYPE_ACCESS:
- name = XATTR_NAME_POSIX_ACL_ACCESS;
- if (acl)
- rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
- break;
-
- case ACL_TYPE_DEFAULT:
- name = XATTR_NAME_POSIX_ACL_DEFAULT;
- if (!S_ISDIR(inode->i_mode))
- rc = acl ? -EACCES : 0;
- break;
-
- default:
- rc = -EINVAL;
- break;
- }
- if (rc)
- return rc;
-
- if (acl) {
- value_size = posix_acl_xattr_size(acl->a_count);
- value = kmalloc(value_size, GFP_NOFS);
- if (value == NULL)
- GOTO(out, rc = -ENOMEM);
-
- rc = posix_acl_to_xattr(&init_user_ns, acl, value, value_size);
- if (rc < 0)
- GOTO(out_value, rc);
- }
-
- rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode),
- value ? OBD_MD_FLXATTR : OBD_MD_FLXATTRRM,
- name, value, value_size, 0, 0, &req);
-
- ptlrpc_req_finished(req);
-out_value:
- kfree(value);
-out:
- if (rc)
- forget_cached_acl(inode, type);
- else
- set_cached_acl(inode, type, acl);
- RETURN(rc);
-}
-#endif /* CONFIG_LUSTRE_FS_POSIX_ACL */
-#endif /* HAVE_IOP_SET_ACL */
-
int ll_inode_permission(struct inode *inode, int mask)
{
int rc = 0;
struct root_squash_info *squash;
struct cred *cred = NULL;
const struct cred *old_cred = NULL;
- cfs_cap_t cap;
bool squash_id = false;
ktime_t kstart = ktime_get();
* need to do it before permission check.
*/
- if (inode == inode->i_sb->s_root->d_inode) {
+ if (is_root_inode(inode)) {
rc = ll_inode_revalidate(inode->i_sb->s_root, IT_LOOKUP);
if (rc)
RETURN(rc);
cred->fsuid = make_kuid(&init_user_ns, squash->rsi_uid);
cred->fsgid = make_kgid(&init_user_ns, squash->rsi_gid);
- for (cap = 0; cap < sizeof(cfs_cap_t) * 8; cap++) {
- if (BIT(cap) & CFS_CAP_FS_MASK)
- cap_lower(cred->cap_effective, cap);
- }
+ cred->cap_effective = cap_drop_nfsd_set(cred->cap_effective);
+ cred->cap_effective = cap_drop_fs_set(cred->cap_effective);
+
old_cred = override_creds(cred);
}
}
/* -o localflock - only provides locally consistent flock locks */
-struct file_operations ll_file_operations = {
+static const struct file_operations ll_file_operations = {
#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
# ifdef HAVE_SYNC_READ_WRITE
.read = new_sync_read,
.fallocate = ll_fallocate,
};
-struct file_operations ll_file_operations_flock = {
+static const struct file_operations ll_file_operations_flock = {
#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
# ifdef HAVE_SYNC_READ_WRITE
.read = new_sync_read,
};
/* These are for -o noflock - to return ENOSYS on flock calls */
-struct file_operations ll_file_operations_noflock = {
+static const struct file_operations ll_file_operations_noflock = {
#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
# ifdef HAVE_SYNC_READ_WRITE
.read = new_sync_read,
.fallocate = ll_fallocate,
};
-struct inode_operations ll_file_inode_operations = {
+const struct inode_operations ll_file_inode_operations = {
.setattr = ll_setattr,
.getattr = ll_getattr,
.permission = ll_inode_permission,
#endif
};
+const struct file_operations *ll_select_file_operations(struct ll_sb_info *sbi)
+{
+ const struct file_operations *fops = &ll_file_operations_noflock;
+
+ if (sbi->ll_flags & LL_SBI_FLOCK)
+ fops = &ll_file_operations_flock;
+ else if (sbi->ll_flags & LL_SBI_LOCALFLOCK)
+ fops = &ll_file_operations;
+
+ return fops;
+}
+
int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf)
{
struct ll_inode_info *lli = ll_i2info(inode);
out:
cl_env_put(env, &refcheck);
- RETURN(rc);
+ RETURN(rc < 0 ? rc : 0);
}
/* Fetch layout from MDT with getxattr request, if it's not ready yet */