#include <linux/file.h>
#include <linux/sched.h>
#include <linux/user_namespace.h>
-#ifdef HAVE_UIDGID_HEADER
-# include <linux/uidgid.h>
-#endif
+#include <linux/uidgid.h>
+#include <linux/falloc.h>
#include <uapi/linux/lustre/lustre_ioctl.h>
+#include <uapi/linux/llcrypt.h>
#include <lustre_swab.h>
#include "cl_object.h"
.l_inodebits = { MDS_INODELOCK_OPEN },
};
__u64 flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK;
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
struct ll_inode_info *lli = ll_i2info(inode);
struct lustre_handle lockh;
enum ldlm_mode lockmode;
rc = ll_md_real_close(inode, fd->fd_omode);
out:
- LUSTRE_FPRIVATE(file) = NULL;
+ file->private_data = NULL;
ll_file_data_put(fd);
RETURN(rc);
CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
PFID(ll_inode2fid(inode)), inode);
- fd = LUSTRE_FPRIVATE(file);
+ fd = file->private_data;
LASSERT(fd != NULL);
/* The last ref on @file, maybe not the the owner pid of statahead,
ll_deauthorize_statahead(inode, fd);
if (inode->i_sb->s_root == file_dentry(file)) {
- LUSTRE_FPRIVATE(file) = NULL;
+ file->private_data = NULL;
ll_file_data_put(fd);
GOTO(out, rc = 0);
}
struct niobuf_local *lnb = data;
void *kaddr;
- kaddr = ll_kmap_atomic(page, KM_USER0);
+ kaddr = kmap_atomic(page);
memcpy(kaddr, lnb->lnb_data, lnb->lnb_len);
if (lnb->lnb_len < PAGE_SIZE)
memset(kaddr + lnb->lnb_len, 0,
PAGE_SIZE - lnb->lnb_len);
flush_dcache_page(page);
SetPageUptodate(page);
- ll_kunmap_atomic(kaddr, KM_USER0);
+ kunmap_atomic(kaddr);
unlock_page(page);
return 0;
if (obj == NULL)
RETURN_EXIT;
- if (!req_capsule_has_field(&req->rq_pill, &RMF_NIOBUF_INLINE,
- RCL_SERVER))
+ if (!req_capsule_field_present(&req->rq_pill, &RMF_NIOBUF_INLINE,
+ RCL_SERVER))
RETURN_EXIT;
rnb = req_capsule_server_get(&req->rq_pill, &RMF_NIOBUF_INLINE);
* client PAGE_SIZE to be used on that client, if server's PAGE_SIZE is
* smaller then offset may be not aligned and that data is just ignored.
*/
- if (rnb->rnb_offset % PAGE_SIZE)
+ if (rnb->rnb_offset & ~PAGE_MASK)
RETURN_EXIT;
/* Server returns whole file or just file tail if it fills in reply
data = (char *)rnb + sizeof(*rnb);
lnb.lnb_file_offset = rnb->rnb_offset;
- start = lnb.lnb_file_offset / PAGE_SIZE;
+ start = lnb.lnb_file_offset >> PAGE_SHIFT;
index = 0;
- LASSERT(lnb.lnb_file_offset % PAGE_SIZE == 0);
+ LASSERT((lnb.lnb_file_offset & ~PAGE_MASK) == 0);
lnb.lnb_page_offset = 0;
do {
lnb.lnb_data = data + (index << PAGE_SHIFT);
struct inode *inode = file_inode(file);
ENTRY;
- LASSERT(!LUSTRE_FPRIVATE(file));
+ LASSERT(!file->private_data);
LASSERT(fd != NULL);
RETURN(rc);
}
- LUSTRE_FPRIVATE(file) = fd;
+ file->private_data = fd;
ll_readahead_init(inode, &fd->fd_ras);
fd->fd_omode = it->it_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
it = file->private_data; /* XXX: compat macro */
file->private_data = NULL; /* prevent ll_local_open assertion */
+ if (S_ISREG(inode->i_mode)) {
+ rc = llcrypt_file_open(inode, file);
+ if (rc)
+ GOTO(out_nofiledata, rc);
+ }
+
fd = ll_file_data_get();
if (fd == NULL)
GOTO(out_nofiledata, rc = -ENOMEM);
ll_authorize_statahead(inode, fd);
if (inode->i_sb->s_root == file_dentry(file)) {
- LUSTRE_FPRIVATE(file) = fd;
- RETURN(0);
- }
+ file->private_data = fd;
+ RETURN(0);
+ }
if (!it || !it->it_disposition) {
- /* Convert f_flags into access mode. We cannot use file->f_mode,
- * because everything but O_ACCMODE mask was stripped from
- * there */
- if ((oit.it_flags + 1) & O_ACCMODE)
- oit.it_flags++;
- if (file->f_flags & O_TRUNC)
- oit.it_flags |= FMODE_WRITE;
+ /* Convert f_flags into access mode. We cannot use file->f_mode,
+ * because everything but O_ACCMODE mask was stripped from
+ * there */
+ if ((oit.it_flags + 1) & O_ACCMODE)
+ oit.it_flags++;
+ if (file->f_flags & O_TRUNC)
+ oit.it_flags |= FMODE_WRITE;
/* kernel only call f_op->open in dentry_open. filp_open calls
* dentry_open after call to open_namei that checks permissions.
if (oit.it_flags & (FMODE_WRITE | FMODE_READ))
oit.it_flags |= MDS_OPEN_OWNEROVERRIDE;
- /* We do not want O_EXCL here, presumably we opened the file
- * already? XXX - NFS implications? */
- oit.it_flags &= ~O_EXCL;
+ /* We do not want O_EXCL here, presumably we opened the file
+ * already? XXX - NFS implications? */
+ oit.it_flags &= ~O_EXCL;
- /* bug20584, if "it_flags" contains O_CREAT, the file will be
- * created if necessary, then "IT_CREAT" should be set to keep
- * consistent with it */
- if (oit.it_flags & O_CREAT)
- oit.it_op |= IT_CREAT;
+ /* bug20584, if "it_flags" contains O_CREAT, the file will be
+ * created if necessary, then "IT_CREAT" should be set to keep
+ * consistent with it */
+ if (oit.it_flags & O_CREAT)
+ oit.it_op |= IT_CREAT;
- it = &oit;
- }
+ it = &oit;
+ }
restart:
- /* Let's see if we have file open on MDS already. */
- if (it->it_flags & FMODE_WRITE) {
- och_p = &lli->lli_mds_write_och;
- och_usecount = &lli->lli_open_fd_write_count;
- } else if (it->it_flags & FMODE_EXEC) {
- och_p = &lli->lli_mds_exec_och;
- och_usecount = &lli->lli_open_fd_exec_count;
- } else {
- och_p = &lli->lli_mds_read_och;
- och_usecount = &lli->lli_open_fd_read_count;
- }
+ /* Let's see if we have file open on MDS already. */
+ if (it->it_flags & FMODE_WRITE) {
+ och_p = &lli->lli_mds_write_och;
+ och_usecount = &lli->lli_open_fd_write_count;
+ } else if (it->it_flags & FMODE_EXEC) {
+ och_p = &lli->lli_mds_exec_och;
+ och_usecount = &lli->lli_open_fd_exec_count;
+ } else {
+ och_p = &lli->lli_mds_read_och;
+ och_usecount = &lli->lli_open_fd_read_count;
+ }
mutex_lock(&lli->lli_och_mutex);
- if (*och_p) { /* Open handle is present */
- if (it_disposition(it, DISP_OPEN_OPEN)) {
- /* Well, there's extra open request that we do not need,
- let's close it somehow. This will decref request. */
- rc = it_open_error(DISP_OPEN_OPEN, it);
- if (rc) {
+ if (*och_p) { /* Open handle is present */
+ if (it_disposition(it, DISP_OPEN_OPEN)) {
+ /* Well, there's extra open request that we do not need,
+ * let's close it somehow. This will decref request. */
+ rc = it_open_error(DISP_OPEN_OPEN, it);
+ if (rc) {
mutex_unlock(&lli->lli_och_mutex);
- GOTO(out_openerr, rc);
- }
+ GOTO(out_openerr, rc);
+ }
ll_release_openhandle(file_dentry(file), it);
- }
- (*och_usecount)++;
+ }
+ (*och_usecount)++;
- rc = ll_local_open(file, it, fd, NULL);
- if (rc) {
- (*och_usecount)--;
+ rc = ll_local_open(file, it, fd, NULL);
+ if (rc) {
+ (*och_usecount)--;
mutex_unlock(&lli->lli_och_mutex);
- GOTO(out_openerr, rc);
- }
- } else {
- LASSERT(*och_usecount == 0);
+ GOTO(out_openerr, rc);
+ }
+ } else {
+ LASSERT(*och_usecount == 0);
if (!it->it_disposition) {
- struct ll_dentry_data *ldd = ll_d2d(file->f_path.dentry);
- /* We cannot just request lock handle now, new ELC code
- means that one of other OPEN locks for this file
- could be cancelled, and since blocking ast handler
- would attempt to grab och_mutex as well, that would
- result in a deadlock */
+ struct dentry *dentry = file_dentry(file);
+ struct ll_dentry_data *ldd;
+
+ /* We cannot just request lock handle now, new ELC code
+ * means that one of other OPEN locks for this file
+ * could be cancelled, and since blocking ast handler
+ * would attempt to grab och_mutex as well, that would
+ * result in a deadlock
+ */
mutex_unlock(&lli->lli_och_mutex);
/*
* Normally called under two situations:
* lookup path only, since ll_iget_for_nfs always calls
* ll_d_init().
*/
+ ldd = ll_d2d(dentry);
if (ldd && ldd->lld_nfs_dentry) {
ldd->lld_nfs_dentry = 0;
- it->it_flags |= MDS_OPEN_LOCK;
+ if (!filename_is_volatile(dentry->d_name.name,
+ dentry->d_name.len,
+ NULL))
+ it->it_flags |= MDS_OPEN_LOCK;
}
- /*
+ /*
* Always specify MDS_OPEN_BY_FID because we don't want
* to get file with different fid.
*/
it->it_flags |= MDS_OPEN_BY_FID;
- rc = ll_intent_file_open(file_dentry(file), NULL, 0,
- it);
- if (rc)
- GOTO(out_openerr, rc);
+ rc = ll_intent_file_open(dentry, NULL, 0, it);
+ if (rc)
+ GOTO(out_openerr, rc);
- goto restart;
- }
- OBD_ALLOC(*och_p, sizeof (struct obd_client_handle));
- if (!*och_p)
- GOTO(out_och_free, rc = -ENOMEM);
+ goto restart;
+ }
+ OBD_ALLOC(*och_p, sizeof(struct obd_client_handle));
+ if (!*och_p)
+ GOTO(out_och_free, rc = -ENOMEM);
- (*och_usecount)++;
+ (*och_usecount)++;
- /* md_intent_lock() didn't get a request ref if there was an
- * open error, so don't do cleanup on the request here
- * (bug 3430) */
- /* XXX (green): Should not we bail out on any error here, not
- * just open error? */
+ /* md_intent_lock() didn't get a request ref if there was an
+ * open error, so don't do cleanup on the request here
+ * (bug 3430) */
+ /* XXX (green): Should not we bail out on any error here, not
+ * just open error? */
rc = it_open_error(DISP_OPEN_OPEN, it);
if (rc != 0)
GOTO(out_och_free, rc);
GOTO(out_och_free, rc);
mutex_unlock(&lli->lli_och_mutex);
- fd = NULL;
- /* Must do this outside lli_och_mutex lock to prevent deadlock where
- different kind of OPEN lock for this same inode gets cancelled
- by ldlm_cancel_lru */
- if (!S_ISREG(inode->i_mode))
- GOTO(out_och_free, rc);
+ /* 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
+ different kind of OPEN lock for this same inode gets cancelled
+ by ldlm_cancel_lru */
+ if (!S_ISREG(inode->i_mode))
+ GOTO(out_och_free, rc);
cl_lov_delay_create_clear(&file->f_flags);
GOTO(out_och_free, rc);
out_och_free:
- if (rc) {
- if (och_p && *och_p) {
- OBD_FREE(*och_p, sizeof (struct obd_client_handle));
- *och_p = NULL; /* OBD_FREE writes some magic there */
- (*och_usecount)--;
- }
+ if (rc) {
+ if (och_p && *och_p) {
+ OBD_FREE(*och_p, sizeof(struct obd_client_handle));
+ *och_p = NULL; /* OBD_FREE writes some magic there */
+ (*och_usecount)--;
+ }
mutex_unlock(&lli->lli_och_mutex);
out_openerr:
struct lustre_handle *old_open_handle)
{
struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
struct obd_client_handle **och_p;
__u64 *och_usecount;
int rc = 0;
static int ll_lease_och_release(struct inode *inode, struct file *file)
{
struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
struct obd_client_handle **och_p;
struct obd_client_handle *old_och = NULL;
__u64 *och_usecount;
* POSIX. Solving this problem needs to send an RPC to MDT for each
* read, this will hurt performance.
*/
- if (inode->i_atime.tv_sec < lli->lli_atime ||
- lli->lli_update_atime) {
+ if (ll_file_test_and_clear_flag(lli, LLIF_UPDATE_ATIME) ||
+ inode->i_atime.tv_sec < lli->lli_atime)
inode->i_atime.tv_sec = lli->lli_atime;
- lli->lli_update_atime = 0;
- }
+
inode->i_mtime.tv_sec = lli->lli_mtime;
inode->i_ctime.tv_sec = lli->lli_ctime;
*/
void ll_io_set_mirror(struct cl_io *io, const struct file *file)
{
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
/* clear layout version for generic(non-resync) I/O in case it carries
* stale layout version due to I/O restart */
struct vvp_io_args *args)
{
struct inode *inode = file_inode(file);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
io->u.ci_rw.crw_nonblock = file->f_flags & O_NONBLOCK;
io->ci_lock_no_expand = fd->ll_lock_no_expand;
struct vvp_io *vio = vvp_env_io(env);
struct inode *inode = file_inode(file);
struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
struct range_lock range;
struct cl_io *io;
ssize_t result = 0;
int rc = 0;
unsigned retried = 0;
- bool restarted = false;
+ unsigned ignore_lockless = 0;
ENTRY;
restart:
io = vvp_env_thread_io(env);
ll_io_init(io, file, iot, args);
+ io->ci_ignore_lockless = ignore_lockless;
io->ci_ndelay_tried = retried;
if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
else
range_lock_init(&range, *ppos, *ppos + count - 1);
- vio->vui_fd = LUSTRE_FPRIVATE(file);
+ vio->vui_fd = file->private_data;
vio->vui_io_subtype = args->via_io_subtype;
switch (vio->vui_io_subtype) {
file->f_path.dentry->d_name.name,
iot, rc, result, io->ci_need_restart);
- if ((rc == 0 || rc == -ENODATA) && count > 0 && io->ci_need_restart) {
+ if ((rc == 0 || rc == -ENODATA || rc == -ENOLCK) &&
+ count > 0 && io->ci_need_restart) {
CDEBUG(D_VFSTRACE,
"%s: restart %s from %lld, count: %zu, ret: %zd, rc: %d\n",
file_dentry(file)->d_name.name,
*ppos, count, result, rc);
/* preserve the tried count for FLR */
retried = io->ci_ndelay_tried;
- restarted = true;
+ ignore_lockless = io->ci_ignore_lockless;
goto restart;
}
if (cached)
GOTO(out, result);
- ll_ras_enter(file);
+ ll_ras_enter(file, iocb->ki_pos, iov_iter_count(to));
result = ll_do_fast_read(iocb, to);
if (result < 0 || iov_iter_count(to) == 0)
out:
if (result > 0) {
ll_rw_stats_tally(ll_i2sbi(file_inode(file)), current->pid,
- LUSTRE_FPRIVATE(file), iocb->ki_pos, result,
+ file->private_data, iocb->ki_pos, result,
READ);
ll_stats_ops_tally(ll_i2sbi(file_inode(file)), LPROC_LL_READ,
ktime_us_delta(ktime_get(), kstart));
out:
if (rc_normal > 0) {
ll_rw_stats_tally(ll_i2sbi(file_inode(file)), current->pid,
- LUSTRE_FPRIVATE(file), iocb->ki_pos,
+ file->private_data, iocb->ki_pos,
rc_normal, WRITE);
ll_stats_ops_tally(ll_i2sbi(file_inode(file)), LPROC_LL_WRITE,
ktime_us_delta(ktime_get(), kstart));
* XXX: exact copy from kernel code (__generic_file_aio_write_nolock)
*/
static int ll_file_get_iov_count(const struct iovec *iov,
- unsigned long *nr_segs, size_t *count)
+ unsigned long *nr_segs, size_t *count,
+ int access_flags)
{
size_t cnt = 0;
unsigned long seg;
cnt += iv->iov_len;
if (unlikely((ssize_t)(cnt|iv->iov_len) < 0))
return -EINVAL;
- if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
+ if (access_ok(access_flags, iv->iov_base, iv->iov_len))
continue;
if (seg == 0)
return -EFAULT;
ssize_t result;
ENTRY;
- result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
+ result = ll_file_get_iov_count(iov, &nr_segs, &iov_count, VERIFY_READ);
if (result)
RETURN(result);
ssize_t result;
ENTRY;
- result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
+ result = ll_file_get_iov_count(iov, &nr_segs, &iov_count, VERIFY_WRITE);
if (result)
RETURN(result);
__u16 refcheck;
bool cached;
- ENTRY;
+ ENTRY;
result = pcc_file_splice_read(in_file, ppos, pipe,
count, flags, &cached);
if (cached)
RETURN(result);
- ll_ras_enter(in_file);
+ ll_ras_enter(in_file, *ppos, count);
env = cl_env_get(&refcheck);
- if (IS_ERR(env))
- RETURN(PTR_ERR(env));
+ if (IS_ERR(env))
+ RETURN(PTR_ERR(env));
args = ll_env_args(env, IO_SPLICE);
- args->u.splice.via_pipe = pipe;
- args->u.splice.via_flags = flags;
+ args->u.splice.via_pipe = pipe;
+ args->u.splice.via_flags = flags;
- result = ll_file_io_generic(env, args, in_file, CIT_READ, ppos, count);
- cl_env_put(env, &refcheck);
+ result = ll_file_io_generic(env, args, in_file, CIT_READ, ppos, count);
+ cl_env_put(env, &refcheck);
if (result > 0)
ll_rw_stats_tally(ll_i2sbi(file_inode(in_file)), current->pid,
- LUSTRE_FPRIVATE(in_file), *ppos, result,
+ in_file->private_data, *ppos, result,
READ);
- RETURN(result);
+ RETURN(result);
}
int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry,
GOTO(out, rc);
rc = ll_file_getstripe(inode, arg, lum_size);
+ if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode) &&
+ ll_i2info(inode)->lli_clob) {
+ struct iattr attr = { 0 };
+
+ rc = cl_setattr_ost(ll_i2info(inode)->lli_clob, &attr,
+ OP_XVALID_FLAGS, LUSTRE_ENCRYPT_FL);
+ }
}
cl_lov_delay_create_clear(&file->f_flags);
{
struct ll_inode_info *lli = ll_i2info(inode);
struct cl_object *obj = lli->lli_clob;
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
struct ll_grouplock grouplock;
int rc;
ENTRY;
unsigned long arg)
{
struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
struct ll_grouplock grouplock;
int rc;
ENTRY;
ENTRY;
- CDEBUG(D_VFSTRACE, "Lock request: file=%.*s, inode=%p, mode=%s "
- "start=%llu, end=%llu\n", dentry->d_name.len,
- dentry->d_name.name, dentry->d_inode,
+ CDEBUG(D_VFSTRACE,
+ "Lock request: file=%pd, inode=%p, mode=%s start=%llu, end=%llu\n",
+ dentry, dentry->d_inode,
user_lockname[ladvise->lla_lockahead_mode], (__u64) start,
(__u64) end);
if (advice > LU_LADVISE_MAX || advice == LU_LADVISE_INVALID) {
rc = -EINVAL;
- CDEBUG(D_VFSTRACE, "%s: advice with value '%d' not recognized,"
- "last supported advice is %s (value '%d'): rc = %d\n",
+ CDEBUG(D_VFSTRACE,
+ "%s: advice with value '%d' not recognized, last supported advice is %s (value '%d'): rc = %d\n",
sbi->ll_fsname, advice,
ladvise_names[LU_LADVISE_MAX-1], LU_LADVISE_MAX-1, rc);
GOTO(out, rc);
static int ll_lock_noexpand(struct file *file, int flags)
{
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
fd->ll_lock_no_expand = !(flags & LF_UNSET);
if (obj == NULL)
GOTO(out_fsxattr, rc);
+ /* Avoiding OST RPC if this is only project ioctl */
+ 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);
unsigned long arg)
{
struct inode *inode = file_inode(file);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
struct ll_inode_info *lli = ll_i2info(inode);
struct obd_client_handle *och = NULL;
struct split_param sp;
{
struct inode *inode = file_inode(file);
struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
struct obd_client_handle *och = NULL;
__u64 open_flags = 0;
bool lease_broken;
ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct inode *inode = file_inode(file);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
int flags, rc;
ENTRY;
fd->fd_designated_mirror = (__u32)arg;
RETURN(0);
}
- case LL_IOC_FSGETXATTR:
+ case FS_IOC_FSGETXATTR:
RETURN(ll_ioctl_fsgetxattr(inode, cmd, arg));
- case LL_IOC_FSSETXATTR:
+ case FS_IOC_FSSETXATTR:
RETURN(ll_ioctl_fssetxattr(inode, cmd, arg));
case BLKSSZGET:
RETURN(put_user(PAGE_SIZE, (int __user *)arg));
OBD_FREE_PTR(state);
RETURN(rc);
}
+#ifdef HAVE_LUSTRE_CRYPTO
+ case LL_IOC_SET_ENCRYPTION_POLICY:
+ if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+ return -EOPNOTSUPP;
+ return llcrypt_ioctl_set_policy(file, (const void __user *)arg);
+ case LL_IOC_GET_ENCRYPTION_POLICY_EX:
+ if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+ return -EOPNOTSUPP;
+ return llcrypt_ioctl_get_policy_ex(file, (void __user *)arg);
+ case LL_IOC_ADD_ENCRYPTION_KEY:
+ if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+ return -EOPNOTSUPP;
+ return llcrypt_ioctl_add_key(file, (void __user *)arg);
+ case LL_IOC_REMOVE_ENCRYPTION_KEY:
+ if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+ return -EOPNOTSUPP;
+ return llcrypt_ioctl_remove_key(file, (void __user *)arg);
+ case LL_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
+ if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+ return -EOPNOTSUPP;
+ return llcrypt_ioctl_remove_key_all_users(file,
+ (void __user *)arg);
+ case LL_IOC_GET_ENCRYPTION_KEY_STATUS:
+ if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+ return -EOPNOTSUPP;
+ return llcrypt_ioctl_get_key_status(file, (void __user *)arg);
+#endif
default:
RETURN(obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL,
(void __user *)arg));
}
}
-#ifndef HAVE_FILE_LLSEEK_SIZE
-static inline loff_t
-llseek_execute(struct file *file, loff_t offset, loff_t maxsize)
-{
- if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
- return -EINVAL;
- if (offset > maxsize)
- return -EINVAL;
-
- if (offset != file->f_pos) {
- file->f_pos = offset;
- file->f_version = 0;
- }
- return offset;
-}
-
-static loff_t
-generic_file_llseek_size(struct file *file, loff_t offset, int origin,
- loff_t maxsize, loff_t eof)
-{
- struct inode *inode = file_inode(file);
-
- switch (origin) {
- case SEEK_END:
- offset += eof;
- break;
- case SEEK_CUR:
- /*
- * Here we special-case the lseek(fd, 0, SEEK_CUR)
- * position-querying operation. Avoid rewriting the "same"
- * f_pos value back to the file because a concurrent read(),
- * write() or lseek() might have altered it
- */
- if (offset == 0)
- return file->f_pos;
- /*
- * f_lock protects against read/modify/write race with other
- * SEEK_CURs. Note that parallel writes and reads behave
- * like SEEK_SET.
- */
- inode_lock(inode);
- offset = llseek_execute(file, file->f_pos + offset, maxsize);
- inode_unlock(inode);
- return offset;
- case SEEK_DATA:
- /*
- * In the generic case the entire file is data, so as long as
- * offset isn't at the end of the file then the offset is data.
- */
- if (offset >= eof)
- return -ENXIO;
- break;
- case SEEK_HOLE:
- /*
- * There is a virtual hole at the end of the file, so as long as
- * offset isn't i_size or larger, return i_size.
- */
- if (offset >= eof)
- return -ENXIO;
- offset = eof;
- break;
- }
-
- return llseek_execute(file, offset, maxsize);
-}
-#endif
-
static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
{
struct inode *inode = file_inode(file);
eof = i_size_read(inode);
}
- retval = ll_generic_file_llseek_size(file, offset, origin,
- ll_file_maxbytes(inode), eof);
+ 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));
{
struct inode *inode = file_inode(file);
struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
int rc, err;
LASSERT(!S_ISDIR(inode->i_mode));
ENTRY;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), start %lld, end %lld,"
- "datasync %d\n",
+ CDEBUG(D_VFSTRACE,
+ "VFS Op:inode="DFID"(%p), start %lld, end %lld, datasync %d\n",
PFID(ll_inode2fid(inode)), inode, start, end, datasync);
/* fsync's caller has already called _fdata{sync,write}, we want
ptlrpc_req_finished(req);
if (S_ISREG(inode->i_mode)) {
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
bool cached;
/* Sync metadata on MDT first, and then sync the cached data
static int
ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock)
{
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ struct ll_file_data *fd = file->private_data;
ENTRY;
/*
flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK;
for (i = 0; i < MDS_INODELOCK_NUMBITS && *bits != 0; i++) {
- policy.l_inodebits.bits = *bits & (1 << i);
+ policy.l_inodebits.bits = *bits & BIT(i);
if (policy.l_inodebits.bits == 0)
continue;
- if (md_lock_match(ll_i2mdexp(inode), flags, fid, LDLM_IBITS,
- &policy, mode, &lockh)) {
- struct ldlm_lock *lock;
-
- lock = ldlm_handle2lock(&lockh);
- if (lock) {
- *bits &=
- ~(lock->l_policy_data.l_inodebits.bits);
- LDLM_LOCK_PUT(lock);
- } else {
- *bits &= ~policy.l_inodebits.bits;
- }
- }
- }
+ if (md_lock_match(ll_i2mdexp(inode), flags, fid, LDLM_IBITS,
+ &policy, mode, &lockh)) {
+ struct ldlm_lock *lock;
+
+ lock = ldlm_handle2lock(&lockh);
+ if (lock) {
+ *bits &=
+ ~(lock->l_policy_data.l_inodebits.bits);
+ LDLM_LOCK_PUT(lock);
+ } else {
+ *bits &= ~policy.l_inodebits.bits;
+ }
+ }
+ }
RETURN(*bits == 0);
}
RETURN(0);
}
-int ll_getattr_dentry(struct dentry *de, struct kstat *stat)
+int ll_getattr_dentry(struct dentry *de, struct kstat *stat, u32 request_mask,
+ unsigned int flags)
{
struct inode *inode = de->d_inode;
struct ll_sb_info *sbi = ll_i2sbi(inode);
struct ll_inode_info *lli = ll_i2info(inode);
+ struct inode *dir = de->d_parent->d_inode;
+ bool need_glimpse = true;
ktime_t kstart = ktime_get();
int rc;
+ /* The OST object(s) determine the file size, blocks and mtime. */
+ if (!(request_mask & STATX_SIZE || request_mask & STATX_BLOCKS ||
+ request_mask & STATX_MTIME))
+ need_glimpse = false;
+
+ if (dentry_may_statahead(dir, de))
+ ll_start_statahead(dir, de, need_glimpse &&
+ !(flags & AT_STATX_DONT_SYNC));
+
+ if (flags & AT_STATX_DONT_SYNC)
+ GOTO(fill_attr, rc = 0);
+
rc = ll_inode_revalidate(de, IT_GETATTR);
if (rc < 0)
RETURN(rc);
if (S_ISREG(inode->i_mode)) {
bool cached;
- rc = pcc_inode_getattr(inode, &cached);
+ if (!need_glimpse)
+ GOTO(fill_attr, rc);
+
+ rc = pcc_inode_getattr(inode, request_mask, flags, &cached);
if (cached && rc < 0)
RETURN(rc);
+ if (cached)
+ GOTO(fill_attr, rc);
+
+ /*
+ * If the returned attr is masked with OBD_MD_FLSIZE &
+ * OBD_MD_FLBLOCKS & OBD_MD_FLMTIME, it means that the file size
+ * or blocks obtained from MDT is strictly correct, and the file
+ * is usually not being modified by clients, and the [a|m|c]time
+ * got from MDT is also strictly correct.
+ * Under this circumstance, it does not need to send glimpse
+ * RPCs to OSTs for file attributes such as the size and blocks.
+ */
+ if (lli->lli_attr_valid & OBD_MD_FLSIZE &&
+ lli->lli_attr_valid & OBD_MD_FLBLOCKS &&
+ lli->lli_attr_valid & OBD_MD_FLMTIME) {
+ inode->i_mtime.tv_sec = lli->lli_mtime;
+ if (lli->lli_attr_valid & OBD_MD_FLATIME)
+ inode->i_atime.tv_sec = lli->lli_atime;
+ if (lli->lli_attr_valid & OBD_MD_FLCTIME)
+ inode->i_ctime.tv_sec = lli->lli_ctime;
+ GOTO(fill_attr, rc);
+ }
+
/* In case of restore, the MDT has the right size and has
* already send it back without granting the layout lock,
* inode is up-to-date so glimpse is useless.
* restore the MDT holds the layout lock so the glimpse will
* block up to the end of restore (getattr will block)
*/
- if (!cached && !ll_file_test_flag(lli, LLIF_FILE_RESTORING)) {
+ if (!ll_file_test_flag(lli, LLIF_FILE_RESTORING)) {
rc = ll_glimpse_size(inode);
if (rc < 0)
RETURN(rc);
RETURN(rc);
}
- inode->i_atime.tv_sec = lli->lli_atime;
- inode->i_mtime.tv_sec = lli->lli_mtime;
- inode->i_ctime.tv_sec = lli->lli_ctime;
+ if (lli->lli_attr_valid & OBD_MD_FLATIME)
+ inode->i_atime.tv_sec = lli->lli_atime;
+ if (lli->lli_attr_valid & OBD_MD_FLMTIME)
+ inode->i_mtime.tv_sec = lli->lli_mtime;
+ if (lli->lli_attr_valid & OBD_MD_FLCTIME)
+ inode->i_ctime.tv_sec = lli->lli_ctime;
}
+fill_attr:
OBD_FAIL_TIMEOUT(OBD_FAIL_GETATTR_DELAY, 30);
if (ll_need_32bit_api(sbi)) {
stat->atime = inode->i_atime;
stat->mtime = inode->i_mtime;
stat->ctime = inode->i_ctime;
- stat->blksize = sbi->ll_stat_blksize ?: 1 << inode->i_blkbits;
+ /* stat->blksize is used to tell about preferred IO size */
+ if (sbi->ll_stat_blksize)
+ stat->blksize = sbi->ll_stat_blksize;
+ else if (S_ISREG(inode->i_mode))
+ stat->blksize = 1 << min(PTLRPC_MAX_BRW_BITS + 1,
+ LL_MAX_BLKSIZE_BITS);
+ else
+ stat->blksize = 1 << inode->i_sb->s_blocksize_bits;
stat->nlink = inode->i_nlink;
stat->size = i_size_read(inode);
stat->blocks = inode->i_blocks;
+#ifdef HAVE_INODEOPS_ENHANCED_GETATTR
+ if (flags & AT_STATX_DONT_SYNC) {
+ if (stat->size == 0 &&
+ lli->lli_attr_valid & OBD_MD_FLLAZYSIZE)
+ stat->size = lli->lli_lazysize;
+ if (stat->blocks == 0 &&
+ lli->lli_attr_valid & OBD_MD_FLLAZYBLOCKS)
+ stat->blocks = lli->lli_lazyblocks;
+ }
+
+ if (lli->lli_attr_valid & OBD_MD_FLBTIME) {
+ stat->result_mask |= STATX_BTIME;
+ stat->btime.tv_sec = lli->lli_btime;
+ }
+
+ stat->attributes_mask = STATX_ATTR_IMMUTABLE | STATX_ATTR_APPEND;
+ stat->attributes |= ll_inode_to_ext_flags(inode->i_flags);
+ stat->result_mask &= request_mask;
+#endif
+
ll_stats_ops_tally(sbi, LPROC_LL_GETATTR,
ktime_us_delta(ktime_get(), kstart));
int ll_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags)
{
- struct dentry *de = path->dentry;
+ return ll_getattr_dentry(path->dentry, stat, request_mask, flags);
+}
#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);
+}
#endif
- return ll_getattr_dentry(de, stat);
+
+int cl_falloc(struct inode *inode, int mode, loff_t offset, loff_t len)
+{
+ struct lu_env *env;
+ struct cl_io *io;
+ __u16 refcheck;
+ int rc; loff_t sa_falloc_end;
+ loff_t size = i_size_read(inode);
+
+ 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;
+ io->ci_verify_layout = 1;
+ io->u.ci_setattr.sa_parent_fid = lu_object_fid(&io->ci_obj->co_lu);
+ io->u.ci_setattr.sa_falloc_mode = mode;
+ io->u.ci_setattr.sa_falloc_offset = offset;
+ io->u.ci_setattr.sa_falloc_len = len;
+ io->u.ci_setattr.sa_falloc_end = io->u.ci_setattr.sa_falloc_offset +
+ io->u.ci_setattr.sa_falloc_len;
+ io->u.ci_setattr.sa_subtype = CL_SETATTR_FALLOCATE;
+ sa_falloc_end = io->u.ci_setattr.sa_falloc_end;
+ if (sa_falloc_end > size) {
+ /* Check new size against VFS/VM file size limit and rlimit */
+ rc = inode_newsize_ok(inode, sa_falloc_end);
+ if (rc)
+ goto out;
+ if (sa_falloc_end > ll_file_maxbytes(inode)) {
+ CDEBUG(D_INODE, "file size too large %llu > %llu\n",
+ (unsigned long long)(sa_falloc_end),
+ ll_file_maxbytes(inode));
+ 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:
+ if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0)
+ rc = cl_io_loop(env, io);
+ else
+ rc = io->ci_result;
+
+ cl_io_fini(env, io);
+ if (unlikely(io->ci_need_restart))
+ goto again;
+
+out:
+ cl_env_put(env, &refcheck);
+ RETURN(rc);
+}
+
+long ll_fallocate(struct file *filp, int mode, loff_t offset, loff_t len)
+{
+ struct inode *inode = filp->f_path.dentry->d_inode;
+ int rc;
+
+ /*
+ * Only mode == 0 (which is standard prealloc) is supported now.
+ * Punch is not supported yet.
+ */
+ if (mode & ~FALLOC_FL_KEEP_SIZE)
+ RETURN(-EOPNOTSUPP);
+
+ ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FALLOCATE, 1);
+
+ rc = cl_falloc(inode, mode, offset, len);
+
+ RETURN(rc);
}
static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
cfs_cap_t cap;
bool squash_id = false;
ktime_t kstart = ktime_get();
+
ENTRY;
if (mask & MAY_NOT_BLOCK)
return -ECHILD;
- /* as root inode are NOT getting validated in lookup operation,
- * need to do it before permission check. */
+ /*
+ * as root inode are NOT getting validated in lookup operation,
+ * need to do it before permission check.
+ */
- if (inode == inode->i_sb->s_root->d_inode) {
+ if (inode == inode->i_sb->s_root->d_inode) {
rc = ll_inode_revalidate(inode->i_sb->s_root, IT_LOOKUP);
- if (rc)
- RETURN(rc);
- }
+ if (rc)
+ RETURN(rc);
+ }
CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), inode mode %x mask %o\n",
PFID(ll_inode2fid(inode)), inode, inode->i_mode, mask);
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 ((1 << cap) & CFS_CAP_FS_MASK)
+ if (BIT(cap) & CFS_CAP_FS_MASK)
cap_lower(cred->cap_effective, cap);
}
old_cred = override_creds(cred);
.llseek = ll_file_seek,
.splice_read = ll_file_splice_read,
.fsync = ll_fsync,
- .flush = ll_flush
+ .flush = ll_flush,
+ .fallocate = ll_fallocate,
};
struct file_operations ll_file_operations_flock = {
.fsync = ll_fsync,
.flush = ll_flush,
.flock = ll_file_flock,
- .lock = ll_file_flock
+ .lock = ll_file_flock,
+ .fallocate = ll_fallocate,
};
/* These are for -o noflock - to return ENOSYS on flock calls */
.fsync = ll_fsync,
.flush = ll_flush,
.flock = ll_file_noflock,
- .lock = ll_file_noflock
+ .lock = ll_file_noflock,
+ .fallocate = ll_fallocate,
};
struct inode_operations ll_file_inode_operations = {
#endif
.listxattr = ll_listxattr,
.fiemap = ll_fiemap,
-#ifdef HAVE_IOP_GET_ACL
.get_acl = ll_get_acl,
-#endif
#ifdef HAVE_IOP_SET_ACL
.set_acl = ll_set_acl,
#endif