#include <linux/ktime.h>
#include <uapi/linux/lustre/lustre_ioctl.h>
-#include <uapi/linux/llcrypt.h>
#include <lustre_swab.h>
#include "cl_object.h"
op_data->op_attr.ia_atime = inode->i_atime;
op_data->op_attr.ia_mtime = inode->i_mtime;
op_data->op_attr.ia_ctime = inode->i_ctime;
- op_data->op_attr.ia_size = i_size_read(inode);
+ /* In case of encrypted file without the key, visible size was rounded
+ * up to next LUSTRE_ENCRYPTION_UNIT_SIZE, and clear text size was
+ * stored into lli_lazysize in ll_merge_attr(), so set proper file size
+ * now that we are closing.
+ */
+ if (llcrypt_require_key(inode) == -ENOKEY &&
+ ll_i2info(inode)->lli_attr_valid & OBD_MD_FLLAZYSIZE)
+ op_data->op_attr.ia_size = ll_i2info(inode)->lli_lazysize;
+ else
+ op_data->op_attr.ia_size = i_size_read(inode);
op_data->op_attr.ia_valid |= (ATTR_MODE | ATTR_ATIME | ATTR_ATIME_SET |
ATTR_MTIME | ATTR_MTIME_SET |
ATTR_CTIME);
op_data->op_attr_blocks += ((struct inode *)data)->i_blocks;
op_data->op_attr.ia_valid |= ATTR_SIZE;
op_data->op_xvalid |= OP_XVALID_BLOCKS;
- /* fallthrough */
+ fallthrough;
case MDS_CLOSE_LAYOUT_SPLIT:
case MDS_CLOSE_LAYOUT_SWAP: {
struct split_param *sp = data;
static inline int ll_dom_readpage(void *data, struct page *page)
{
+ /* since ll_dom_readpage is a page cache helper, it is safe to assume
+ * mapping and host pointers are set here
+ */
+ struct inode *inode;
struct niobuf_local *lnb = data;
void *kaddr;
int rc = 0;
- struct inode *inode = page2inode(page);
+ inode = page2inode(page);
kaddr = kmap_atomic(page);
memcpy(kaddr, lnb->lnb_data, lnb->lnb_len);
put_page(vmpage);
break;
}
- cl_page_export(env, page, 1);
+ SetPageUptodate(vmpage);
cl_page_put(env, page);
unlock_page(vmpage);
put_page(vmpage);
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);
- INIT_LIST_HEAD(&fd->fd_lccs);
RETURN(0);
}
file->private_data = NULL; /* prevent ll_local_open assertion */
if (S_ISREG(inode->i_mode)) {
- rc = llcrypt_file_open(inode, file);
- if (rc)
+ rc = ll_file_open_encrypt(inode, file);
+ if (rc) {
+ if (it && it->it_disposition)
+ ll_release_openhandle(file_dentry(file), it);
GOTO(out_nofiledata, rc);
+ }
}
fd = ll_file_data_get();
if (!S_ISREG(inode1->i_mode) || !S_ISREG(inode2->i_mode))
return -EINVAL;
- if (inode_permission(inode1, MAY_WRITE) ||
- inode_permission(inode2, MAY_WRITE))
+ if (inode_permission(&init_user_ns, inode1, MAY_WRITE) ||
+ inode_permission(&init_user_ns, inode2, MAY_WRITE))
return -EPERM;
if (inode1->i_sb != inode2->i_sb)
CDEBUG(D_VFSTRACE, DFID" updating i_size %llu\n",
PFID(&lli->lli_fid), attr->cat_size);
+ if (llcrypt_require_key(inode) == -ENOKEY) {
+ /* Without the key, round up encrypted file size to next
+ * LUSTRE_ENCRYPTION_UNIT_SIZE. Clear text size is put in
+ * lli_lazysize for proper file size setting at close time.
+ */
+ lli->lli_attr_valid |= OBD_MD_FLLAZYSIZE;
+ lli->lli_lazysize = attr->cat_size;
+ attr->cat_size = round_up(attr->cat_size,
+ LUSTRE_ENCRYPTION_UNIT_SIZE);
+ }
i_size_write(inode, attr->cat_size);
inode->i_blocks = attr->cat_blocks;
#endif
}
+#ifdef IOCB_NOWAIT
+ io->ci_iocb_nowait = !!(args &&
+ (args->u.normal.via_iocb->ki_flags &
+ IOCB_NOWAIT));
+#endif
+
io->ci_obj = ll_i2info(inode)->lli_clob;
io->ci_lockreq = CILR_MAYBE;
if (ll_file_nolock(file)) {
io = vvp_env_thread_io(env);
if (file->f_flags & O_DIRECT) {
+ if (file->f_flags & O_APPEND)
+ dio_lock = 1;
if (!is_sync_kiocb(args->u.normal.via_iocb))
is_aio = true;
is_parallel_dio = false;
ci_aio = cl_aio_alloc(args->u.normal.via_iocb,
- ll_i2info(inode)->lli_clob);
+ ll_i2info(inode)->lli_clob, NULL);
if (!ci_aio)
GOTO(out, rc = -ENOMEM);
}
range_locked = true;
}
- ll_cl_add(file, env, io, LCC_RW);
+ ll_cl_add(inode, env, io, LCC_RW);
rc = cl_io_loop(env, io);
- ll_cl_remove(file, env);
+ ll_cl_remove(inode, env);
if (range_locked && !is_parallel_dio) {
CDEBUG(D_VFSTRACE, "Range unlock "RL_FMT"\n",
ktime_t kstart = ktime_get();
bool cached;
+ ENTRY;
+
+ CDEBUG(D_VFSTRACE|D_IOTRACE, "file %s:"DFID", ppos: %lld, count: %zu\n",
+ file_dentry(file)->d_name.name,
+ PFID(ll_inode2fid(file_inode(file))), iocb->ki_pos,
+ iov_iter_count(to));
+
if (!iov_iter_count(to))
- return 0;
+ RETURN(0);
/**
* Currently when PCC read failed, we do not fall back to the
env = cl_env_get(&refcheck);
if (IS_ERR(env))
- return PTR_ERR(env);
+ RETURN(PTR_ERR(env));
args = ll_env_args(env);
args->u.normal.via_iter = to;
ktime_us_delta(ktime_get(), kstart));
}
- return result;
+ CDEBUG(D_IOTRACE,
+ "COMPLETED: file %s:"DFID", ppos: %lld, count: %zu\n",
+ file_dentry(file)->d_name.name,
+ PFID(ll_inode2fid(file_inode(file))), iocb->ki_pos,
+ iov_iter_count(to));
+
+ RETURN(result);
}
/**
if (result > 0) {
ll_heat_add(inode, CIT_WRITE, result);
- ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_WRITE_BYTES,
- result);
set_bit(LLIF_DATA_MODIFIED, &ll_i2info(inode)->lli_flags);
}
ENTRY;
+ CDEBUG(D_VFSTRACE|D_IOTRACE, "file %s:"DFID", ppos: %lld, count: %zu\n",
+ file_dentry(file)->d_name.name,
+ PFID(ll_inode2fid(file_inode(file))), iocb->ki_pos,
+ iov_iter_count(from));
+
if (!iov_iter_count(from))
GOTO(out, rc_normal = 0);
env = cl_env_get(&refcheck);
if (IS_ERR(env))
- return PTR_ERR(env);
+ RETURN(PTR_ERR(env));
args = ll_env_args(env);
args->u.normal.via_iter = from;
ktime_us_delta(ktime_get(), kstart));
}
+ CDEBUG(D_IOTRACE,
+ "COMPLETED: file %s:"DFID", ppos: %lld, count: %zu\n",
+ file_dentry(file)->d_name.name,
+ PFID(ll_inode2fid(file_inode(file))), iocb->ki_pos,
+ iov_iter_count(from));
+
RETURN(rc_normal);
}
GOTO(out, rc);
}
- fmkey.lfik_oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
+ fmkey.lfik_oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLPROJID;
obdo_from_inode(&fmkey.lfik_oa, inode, OBD_MD_FLSIZE);
obdo_set_parent_fid(&fmkey.lfik_oa, &ll_i2info(inode)->lli_fid);
ENTRY;
if (!capable(CAP_DAC_READ_SEARCH) &&
- !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH))
+ !test_bit(LL_SBI_USER_FID2PATH, ll_i2sbi(inode)->ll_flags))
RETURN(-EPERM);
/* Only need to get the buflen */
struct lu_env *env;
struct obd_client_handle *och = NULL;
__u64 data_version = 0;
- int rc;
__u16 refcheck;
+ int rc;
+
ENTRY;
CDEBUG(D_INODE, "%s: Releasing file "DFID".\n",
GOTO(out, rc = PTR_ERR(och));
/* Grab latest data_version and [am]time values */
- rc = ll_data_version(inode, &data_version, LL_DV_WR_FLUSH);
+ rc = ll_data_version(inode, &data_version,
+ LL_DV_WR_FLUSH | LL_DV_SZ_UPDATE);
if (rc != 0)
GOTO(out, rc);
ladvise_names[advice], rc);
GOTO(out, rc);
}
- /* fallthrough */
+ fallthrough;
case LU_LADVISE_WILLREAD:
case LU_LADVISE_DONTNEED:
default:
static int ll_set_project(struct inode *inode, __u32 xflags, __u32 projid)
{
- struct md_op_data *op_data;
struct ptlrpc_request *req = NULL;
+ struct md_op_data *op_data;
struct cl_object *obj;
unsigned int inode_flags;
int rc = 0;
+ CDEBUG(D_QUOTA, DFID" xflags=%x projid=%u\n",
+ PFID(ll_inode2fid(inode)), xflags, projid);
rc = ll_ioctl_check_project(inode, xflags, projid);
if (rc)
RETURN(rc);
op_data->op_attr_flags = ll_inode_to_ext_flags(inode_flags);
if (xflags & FS_XFLAG_PROJINHERIT)
op_data->op_attr_flags |= LUSTRE_PROJINHERIT_FL;
+
+ /* pass projid to md_op_data */
op_data->op_projid = 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);
ptlrpc_req_finished(req);
if (ioc->lil_count != 1)
RETURN(-EINVAL);
+ if (IS_ENCRYPTED(inode))
+ RETURN(-EOPNOTSUPP);
+
arg += sizeof(*ioc);
if (copy_from_user(¶m.pa_archive_id, (void __user *)arg,
sizeof(__u32)))
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: {
if (!S_ISREG(inode->i_mode))
GOTO(out_detach_free, rc = -EINVAL);
- if (!inode_owner_or_capable(inode))
+ if (!inode_owner_or_capable(&init_user_ns, inode))
GOTO(out_detach_free, rc = -EPERM);
rc = pcc_ioctl_detach(inode, detach->pccd_opt);
cl_env_put(env, &refcheck);
+ /* Without the key, SEEK_HOLE return value has to be
+ * rounded up to next LUSTRE_ENCRYPTION_UNIT_SIZE.
+ */
+ if (llcrypt_require_key(inode) == -ENOKEY && whence == SEEK_HOLE)
+ retval = round_up(retval, LUSTRE_ENCRYPTION_UNIT_SIZE);
+
RETURN(retval);
}
}
int ll_migrate(struct inode *parent, struct file *file, struct lmv_user_md *lum,
- const char *name)
+ const char *name, __u32 flags)
{
struct dentry *dchild = NULL;
struct inode *child_inode = NULL;
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);
- }
- if (unlikely(!llcrypt_policy_has_filename_enc(child_inode))) {
- CDEBUG(D_SEC,
- "cannot migrate old format encrypted "DFID", please move to new enc dir first\n",
- PFID(ll_inode2fid(child_inode)));
- GOTO(out_iput, rc = -EUCLEAN);
- }
- }
-
op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen,
- child_inode->i_mode, LUSTRE_OPC_MIGR,
- NULL);
+ child_inode->i_mode, LUSTRE_OPC_ANY, NULL);
if (IS_ERR(op_data))
GOTO(out_iput, rc = PTR_ERR(op_data));
op_data->op_data = lum;
op_data->op_data_size = lumlen;
+ /* migrate dirent only for subdirs if MDS_MIGRATE_NSONLY set */
+ if (S_ISDIR(child_inode->i_mode) && (flags & MDS_MIGRATE_NSONLY) &&
+ lmv_dir_layout_changing(ll_i2info(parent)->lli_lsm_md))
+ op_data->op_bias |= MDS_MIGRATE_NSONLY;
+
again:
if (S_ISREG(child_inode->i_mode)) {
och = ll_lease_open(child_inode, NULL, FMODE_WRITE, 0);
*/
if (!(fd->fd_flags & LL_FILE_FLOCK_WARNING)) {
fd->fd_flags |= LL_FILE_FLOCK_WARNING;
- CDEBUG_LIMIT(D_TTY | D_CONSOLE,
+ CDEBUG_LIMIT(D_CONSOLE,
"flock disabled, mount with '-o [local]flock' to enable\r\n");
}
RETURN(-ENOSYS);
struct cl_attr attr = { 0 };
int rc;
- LASSERT(lli->lli_lsm_md != NULL);
-
- if (!lmv_dir_striped(lli->lli_lsm_md))
+ if (!lli->lli_lsm_md)
RETURN(0);
down_read(&lli->lli_lsm_sem);
+ if (!lmv_dir_striped(lli->lli_lsm_md)) {
+ up_read(&lli->lli_lsm_sem);
+ RETURN(0);
+ }
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)
RETURN(rc);
+ spin_lock(&inode->i_lock);
set_nlink(inode, attr.cat_nlink);
+ spin_unlock(&inode->i_lock);
+
inode->i_blocks = attr.cat_blocks;
i_size_write(inode, attr.cat_size);
stat->size = i_size_read(inode);
stat->blocks = inode->i_blocks;
-#ifdef HAVE_INODEOPS_ENHANCED_GETATTR
+#if defined(HAVE_USER_NAMESPACE_ARG) || defined(HAVE_INODEOPS_ENHANCED_GETATTR)
if (flags & AT_STATX_DONT_SYNC) {
if (stat->size == 0 &&
lli->lli_attr_valid & OBD_MD_FLLAZYSIZE)
return 0;
}
-#ifdef HAVE_INODEOPS_ENHANCED_GETATTR
-int ll_getattr(const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags)
+#if defined(HAVE_USER_NAMESPACE_ARG) || defined(HAVE_INODEOPS_ENHANCED_GETATTR)
+int ll_getattr(struct user_namespace *mnt_userns, const struct path *path,
+ struct kstat *stat, u32 request_mask, unsigned int flags)
{
return ll_getattr_dentry(path->dentry, stat, request_mask, flags,
false);
int cl_falloc(struct file *file, struct inode *inode, int mode, loff_t offset,
loff_t len)
{
+ loff_t size = i_size_read(inode);
struct lu_env *env;
struct cl_io *io;
__u16 refcheck;
int rc;
- loff_t size = i_size_read(inode);
ENTRY;
io->u.ci_setattr.sa_falloc_offset = offset;
io->u.ci_setattr.sa_falloc_end = offset + len;
io->u.ci_setattr.sa_subtype = CL_SETATTR_FALLOCATE;
+
+ CDEBUG(D_INODE, "UID %u GID %u PRJID %u\n",
+ from_kuid(&init_user_ns, inode->i_uid),
+ from_kgid(&init_user_ns, inode->i_gid),
+ ll_i2info(inode)->lli_projid);
+
+ io->u.ci_setattr.sa_falloc_uid = from_kuid(&init_user_ns, inode->i_uid);
+ io->u.ci_setattr.sa_falloc_gid = from_kgid(&init_user_ns, inode->i_gid);
+ io->u.ci_setattr.sa_falloc_projid = ll_i2info(inode)->lli_projid;
+
if (io->u.ci_setattr.sa_falloc_end > size) {
loff_t newsize = io->u.ci_setattr.sa_falloc_end;
return rc;
}
-int ll_inode_permission(struct inode *inode, int mask)
+int ll_inode_permission(struct user_namespace *mnt_userns, struct inode *inode,
+ int mask)
{
int rc = 0;
struct ll_sb_info *sbi;
squash = &sbi->ll_squash;
if (unlikely(squash->rsi_uid != 0 &&
uid_eq(current_fsuid(), GLOBAL_ROOT_UID) &&
- !(sbi->ll_flags & LL_SBI_NOROOTSQUASH))) {
+ !test_bit(LL_SBI_NOROOTSQUASH, sbi->ll_flags))) {
squash_id = true;
}
if (squash_id) {
old_cred = override_creds(cred);
}
- rc = generic_permission(inode, mask);
+ rc = generic_permission(mnt_userns, inode, mask);
/* restore current process's credentials and FS capability */
if (squash_id) {
revert_creds(old_cred);
{
const struct file_operations *fops = &ll_file_operations_noflock;
- if (sbi->ll_flags & LL_SBI_FLOCK)
+ if (test_bit(LL_SBI_FLOCK, sbi->ll_flags))
fops = &ll_file_operations_flock;
- else if (sbi->ll_flags & LL_SBI_LOCALFLOCK)
+ else if (test_bit(LL_SBI_LOCALFLOCK, sbi->ll_flags))
fops = &ll_file_operations;
return fops;
ENTRY;
*gen = ll_layout_version_get(lli);
- if (!(sbi->ll_flags & LL_SBI_LAYOUT_LOCK) || *gen != CL_LAYOUT_GEN_NONE)
+ if (!test_bit(LL_SBI_LAYOUT_LOCK, sbi->ll_flags) ||
+ *gen != CL_LAYOUT_GEN_NONE)
RETURN(0);
/* sanity checks */