#include <obd_support.h>
#include <obd_class.h>
#include <uapi/linux/lustre/lustre_ioctl.h>
+#include <uapi/linux/llcrypt.h>
#include <lustre_lib.h>
#include <lustre_dlm.h>
#include <lustre_fid.h>
put_page(page);
}
-/**
- * return IF_* type for given lu_dirent entry.
- * IF_* flag shld be converted to particular OS file type in
- * platform llite module.
- */
-static u16 ll_dirent_type_get(struct lu_dirent *ent)
-{
- u16 type = 0;
- struct luda_type *lt;
- int len = 0;
-
- if (le32_to_cpu(ent->lde_attrs) & LUDA_TYPE) {
- const unsigned align = sizeof(struct luda_type) - 1;
-
- len = le16_to_cpu(ent->lde_namelen);
- len = (len + align) & ~align;
- lt = (void *)ent->lde_name + len;
- type = IFTODT(le16_to_cpu(lt->lt_type));
- }
-
- return type;
-}
-
#ifdef HAVE_DIR_CONTEXT
int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data,
struct dir_context *ctx)
lhash = hash;
fid_le_to_cpu(&fid, &ent->lde_fid);
ino = cl_fid_build_ino(&fid, is_api32);
- type = ll_dirent_type_get(ent);
+ type = IFTODT(lu_dirent_type_get(ent));
/* For ll_nfs_get_name_filldir(), it will try to access
* 'ent' through 'lde_name', so the parameter 'name'
* for 'filldir()' must be part of the 'ent'. */
#endif
{
struct inode *inode = file_inode(filp);
- struct ll_file_data *lfd = LUSTRE_FPRIVATE(filp);
+ struct ll_file_data *lfd = filp->private_data;
struct ll_sb_info *sbi = ll_i2sbi(inode);
int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH;
int api32 = ll_need_32bit_api(sbi);
else
pos = 0;
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) pos/size"
- "%lu/%llu 32bit_api %d\n", PFID(ll_inode2fid(inode)),
+ CDEBUG(D_VFSTRACE,
+ "VFS Op:inode="DFID"(%p) pos/size%lu/%llu 32bit_api %d\n",
+ PFID(ll_inode2fid(inode)),
inode, (unsigned long)pos, i_size_read(inode), api32);
if (pos == MDS_DIR_END_OFF)
RETURN(rc);
}
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 13, 53, 0)
-static int ll_send_mgc_param(struct obd_export *mgc, char *string)
-{
- struct mgs_send_param *msp;
- int rc = 0;
-
- OBD_ALLOC_PTR(msp);
- if (!msp)
- return -ENOMEM;
-
- strlcpy(msp->mgs_param, string, sizeof(msp->mgs_param));
- rc = obd_set_info_async(NULL, mgc, sizeof(KEY_SET_INFO), KEY_SET_INFO,
- sizeof(struct mgs_send_param), msp, NULL);
- if (rc)
- CERROR("Failed to set parameter: %d\n", rc);
- OBD_FREE_PTR(msp);
-
- return rc;
-}
-#endif
-
/**
* Create striped directory with specified stripe(@lump)
*
strlen(dirname)),
},
};
+ bool encrypt = false;
int err;
ENTRY;
- if (unlikely(!lmv_magic_supported(lump->lum_magic)))
+ if (unlikely(!lmv_user_magic_supported(lump->lum_magic)))
RETURN(-EINVAL);
if (lump->lum_magic != LMV_MAGIC_FOREIGN) {
!OBD_FAIL_CHECK(OBD_FAIL_LLITE_NO_CHECK_DEAD))
RETURN(-ENOENT);
- if (unlikely(!lmv_magic_supported(cpu_to_le32(lump->lum_magic))))
+ if (!(exp_connect_flags2(sbi->ll_md_exp) & OBD_CONNECT2_CRUSH)) {
+ if ((lump->lum_hash_type & LMV_HASH_TYPE_MASK) ==
+ LMV_HASH_TYPE_CRUSH) {
+ /* if server doesn't support 'crush' hash type,
+ * switch to fnv_1a_64.
+ */
+ lump->lum_hash_type &= ~LMV_HASH_TYPE_MASK;
+ lump->lum_hash_type |= LMV_HASH_TYPE_FNV_1A_64;
+ } else if ((lump->lum_hash_type & LMV_HASH_TYPE_MASK) ==
+ LMV_HASH_TYPE_UNKNOWN) {
+ /* from 2.14 MDT will choose default hash type if client
+ * doesn't set a valid one, while old server doesn't
+ * handle it.
+ */
+ lump->lum_hash_type &= ~LMV_HASH_TYPE_MASK;
+ lump->lum_hash_type |= LMV_HASH_TYPE_DEFAULT;
+ }
+ }
+
+ if (unlikely(!lmv_user_magic_supported(cpu_to_le32(lump->lum_magic))))
lustre_swab_lmv_user_md(lump);
if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent)))
if (IS_ERR(op_data))
RETURN(PTR_ERR(op_data));
+ if (IS_ENCRYPTED(parent) ||
+ unlikely(llcrypt_dummy_context_enabled(parent))) {
+ err = llcrypt_get_encryption_info(parent);
+ if (err)
+ GOTO(out_op_data, err);
+ if (!llcrypt_has_encryption_key(parent))
+ GOTO(out_op_data, err = -ENOKEY);
+ encrypt = true;
+ }
+
if (sbi->ll_flags & LL_SBI_FILE_SECCTX) {
/* selinux_dentry_init_security() uses dentry->d_parent and name
* to determine the security context for the file. So our fake
if (err)
GOTO(out_inode, err);
+ if (encrypt) {
+ err = llcrypt_inherit_context(parent, inode, NULL, false);
+ if (err)
+ GOTO(out_inode, err);
+ }
+
out_inode:
if (inode != NULL)
iput(inode);
struct md_op_data *op_data;
struct ptlrpc_request *req = NULL;
int rc = 0;
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 13, 53, 0)
- struct lustre_sb_info *lsi = s2lsi(inode->i_sb);
- struct obd_device *mgc = lsi->lsi_mgc;
-#endif
int lum_size;
ENTRY;
if (rc)
RETURN(rc);
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 13, 53, 0)
- /*
- * 2.9 server has stored filesystem default stripe in ROOT xattr,
- * and it's stored into system config for backward compatibility.
- *
- * In the following we use the fact that LOV_USER_MAGIC_V1 and
- * LOV_USER_MAGIC_V3 have the same initial fields so we do not
- * need the make the distiction between the 2 versions
- */
- if (set_default && mgc->u.cli.cl_mgc_mgsexp &&
- (lump == NULL ||
- le32_to_cpu(lump->lmm_magic) == LOV_USER_MAGIC_V1 ||
- le32_to_cpu(lump->lmm_magic) == LOV_USER_MAGIC_V3)) {
- char *param = NULL;
- char *buf;
-
- OBD_ALLOC(param, MGS_PARAM_MAXLEN);
- if (param == NULL)
- GOTO(end, rc = -ENOMEM);
-
- buf = param;
- /* Get fsname and assume devname to be -MDT0000. */
- snprintf(buf, MGS_PARAM_MAXLEN, "%s-MDT0000.lov",
- sbi->ll_fsname);
- buf += strlen(buf);
-
- /* Set root stripesize */
- snprintf(buf, MGS_PARAM_MAXLEN, ".stripesize=%u",
- lump ? le32_to_cpu(lump->lmm_stripe_size) : 0);
- rc = ll_send_mgc_param(mgc->u.cli.cl_mgc_mgsexp, param);
- if (rc)
- GOTO(end, rc);
-
- /* Set root stripecount */
- snprintf(buf, MGS_PARAM_MAXLEN, ".stripecount=%hd",
- lump ? le16_to_cpu(lump->lmm_stripe_count) : 0);
- rc = ll_send_mgc_param(mgc->u.cli.cl_mgc_mgsexp, param);
- if (rc)
- GOTO(end, rc);
-
- /* Set root stripeoffset */
- snprintf(buf, MGS_PARAM_MAXLEN, ".stripeoffset=%hd",
- lump ? le16_to_cpu(lump->lmm_stripe_offset) :
- (typeof(lump->lmm_stripe_offset))(-1));
- rc = ll_send_mgc_param(mgc->u.cli.cl_mgc_mgsexp, param);
-
-end:
- if (param != NULL)
- OBD_FREE(param, MGS_PARAM_MAXLEN);
- }
-#endif
RETURN(rc);
}
count = 0;
for (i = 0; i < sizeof(archive_mask) * 8; i++) {
- if ((1 << i) & archive_mask) {
+ if (BIT(i) & archive_mask) {
lk->lk_data[count] = i + 1;
count++;
}
case Q_SETQUOTA:
case Q_SETINFO:
case LUSTRE_Q_SETDEFAULT:
+ case LUSTRE_Q_SETQUOTAPOOL:
+ case LUSTRE_Q_SETINFOPOOL:
if (!cfs_capable(CFS_CAP_SYS_ADMIN))
RETURN(-EPERM);
break;
case Q_GETQUOTA:
case LUSTRE_Q_GETDEFAULT:
+ case LUSTRE_Q_GETQUOTAPOOL:
if (check_owner(type, id) &&
(!cfs_capable(CFS_CAP_SYS_ADMIN)))
RETURN(-EPERM);
break;
case Q_GETINFO:
+ case LUSTRE_Q_GETINFOPOOL:
break;
default:
CERROR("unsupported quotactl op: %#x\n", cmd);
RETURN(-ENOTSUPP);
}
- if (valid != QC_GENERAL) {
- if (cmd == Q_GETINFO)
- qctl->qc_cmd = Q_GETOINFO;
- else if (cmd == Q_GETQUOTA)
- qctl->qc_cmd = Q_GETOQUOTA;
- else
- RETURN(-EINVAL);
+ if (valid != QC_GENERAL) {
+ if (cmd == Q_GETINFO)
+ qctl->qc_cmd = Q_GETOINFO;
+ else if (cmd == Q_GETQUOTA ||
+ cmd == LUSTRE_Q_GETQUOTAPOOL)
+ qctl->qc_cmd = Q_GETOQUOTA;
+ else
+ RETURN(-EINVAL);
switch (valid) {
case QC_MDTIDX:
qctl->qc_cmd = cmd;
} else {
struct obd_quotactl *oqctl;
+ int oqctl_len = sizeof(*oqctl);
- OBD_ALLOC_PTR(oqctl);
- if (oqctl == NULL)
- RETURN(-ENOMEM);
+ if (LUSTRE_Q_CMD_IS_POOL(cmd))
+ oqctl_len += LOV_MAXPOOLNAME + 1;
- QCTL_COPY(oqctl, qctl);
- rc = obd_quotactl(sbi->ll_md_exp, oqctl);
- if (rc) {
- OBD_FREE_PTR(oqctl);
- RETURN(rc);
- }
+ OBD_ALLOC(oqctl, oqctl_len);
+ if (oqctl == NULL)
+ RETURN(-ENOMEM);
+
+ QCTL_COPY(oqctl, qctl);
+ rc = obd_quotactl(sbi->ll_md_exp, oqctl);
+ if (rc) {
+ OBD_FREE(oqctl, oqctl_len);
+ RETURN(rc);
+ }
/* If QIF_SPACE is not set, client should collect the
* space usage from OSSs by itself */
- if (cmd == Q_GETQUOTA &&
- !(oqctl->qc_dqblk.dqb_valid & QIF_SPACE) &&
- !oqctl->qc_dqblk.dqb_curspace) {
+ if ((cmd == Q_GETQUOTA || cmd == LUSTRE_Q_GETQUOTAPOOL) &&
+ !(oqctl->qc_dqblk.dqb_valid & QIF_SPACE) &&
+ !oqctl->qc_dqblk.dqb_curspace) {
struct obd_quotactl *oqctl_tmp;
OBD_ALLOC_PTR(oqctl_tmp);
OBD_FREE_PTR(oqctl_tmp);
}
out:
- QCTL_COPY(qctl, oqctl);
- OBD_FREE_PTR(oqctl);
- }
+ QCTL_COPY(qctl, oqctl);
+ OBD_FREE(oqctl, oqctl_len);
+ }
- RETURN(rc);
+ RETURN(rc);
}
int ll_rmfid(struct file *file, void __user *arg)
OBD_ALLOC(lfa, size);
if (!lfa)
RETURN(-ENOMEM);
- OBD_ALLOC(rcs, sizeof(int) * nr);
+ OBD_ALLOC_PTR_ARRAY(rcs, nr);
if (!rcs)
GOTO(free_lfa, rc = -ENOMEM);
}
free_rcs:
- OBD_FREE(rcs, sizeof(int) * nr);
+ OBD_FREE_PTR_ARRAY(rcs, nr);
free_lfa:
OBD_FREE(lfa, size);
lum = (struct lmv_user_md *)data->ioc_inlbuf2;
lumlen = data->ioc_inllen2;
- if (!lmv_magic_supported(lum->lum_magic)) {
+ if (!lmv_user_magic_supported(lum->lum_magic)) {
CERROR("%s: wrong lum magic %x : rc = %d\n", filename,
lum->lum_magic, -EINVAL);
GOTO(lmv_out_free, rc = -EINVAL);
GOTO(lmv_out_free, rc = -EINVAL);
}
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 50, 0)
- mode = data->ioc_type != 0 ? data->ioc_type : S_IRWXUGO;
-#else
mode = data->ioc_type;
-#endif
rc = ll_dir_setdirstripe(dentry, lum, lumlen, filename, mode);
lmv_out_free:
OBD_FREE_LARGE(buf, len);
stx.stx_atime.tv_sec = body->mbo_atime;
stx.stx_ctime.tv_sec = body->mbo_ctime;
stx.stx_mtime.tv_sec = body->mbo_mtime;
+ stx.stx_btime.tv_sec = body->mbo_btime;
stx.stx_rdev_major = MAJOR(body->mbo_rdev);
stx.stx_rdev_minor = MINOR(body->mbo_rdev);
stx.stx_dev_major = MAJOR(inode->i_sb->s_dev);
stx.stx_dev_minor = MINOR(inode->i_sb->s_dev);
- stx.stx_mask |= STATX_BASIC_STATS;
+ stx.stx_mask |= STATX_BASIC_STATS | STATX_BTIME;
/*
* For a striped directory, the size and blocks returned
return rc;
}
case OBD_IOC_QUOTACTL: {
- struct if_quotactl *qctl;
+ struct if_quotactl *qctl;
+ int qctl_len = sizeof(*qctl) + LOV_MAXPOOLNAME + 1;
- OBD_ALLOC_PTR(qctl);
- if (!qctl)
- RETURN(-ENOMEM);
+ OBD_ALLOC(qctl, qctl_len);
+ if (!qctl)
+ RETURN(-ENOMEM);
if (copy_from_user(qctl, (void __user *)arg, sizeof(*qctl)))
- GOTO(out_quotactl, rc = -EFAULT);
-
- rc = quotactl_ioctl(sbi, qctl);
+ GOTO(out_quotactl, rc = -EFAULT);
+
+ if (LUSTRE_Q_CMD_IS_POOL(qctl->qc_cmd)) {
+ char __user *from = (char __user *)arg +
+ offsetof(typeof(*qctl), qc_poolname);
+ if (copy_from_user(qctl->qc_poolname, from,
+ LOV_MAXPOOLNAME + 1))
+ GOTO(out_quotactl, rc = -EFAULT);
+ }
+ rc = quotactl_ioctl(sbi, qctl);
if (rc == 0 &&
copy_to_user((void __user *)arg, qctl, sizeof(*qctl)))
rc = -EFAULT;
- out_quotactl:
- OBD_FREE_PTR(qctl);
- RETURN(rc);
+out_quotactl:
+ OBD_FREE(qctl, qctl_len);
+ RETURN(rc);
}
case OBD_IOC_GETDTNAME:
case OBD_IOC_GETMDNAME:
RETURN(rc);
}
- 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 LL_IOC_PCC_DETACH_BY_FID: {
struct lu_pcc_detach_fid *detach;
OBD_FREE_PTR(detach);
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, sbi->ll_dt_exp, 0, NULL,
(void __user *)arg));
static loff_t ll_dir_seek(struct file *file, loff_t offset, int origin)
{
- struct inode *inode = file->f_mapping->host;
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- int api32 = ll_need_32bit_api(sbi);
- loff_t ret = -EINVAL;
- ENTRY;
+ struct inode *inode = file->f_mapping->host;
+ struct ll_file_data *fd = file->private_data;
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ int api32 = ll_need_32bit_api(sbi);
+ loff_t ret = -EINVAL;
+ ENTRY;
inode_lock(inode);
- switch (origin) {
- case SEEK_SET:
- break;
- case SEEK_CUR:
- offset += file->f_pos;
- break;
- case SEEK_END:
- if (offset > 0)
- GOTO(out, ret);
- if (api32)
- offset += LL_DIR_END_OFF_32BIT;
- else
- offset += LL_DIR_END_OFF;
- break;
- default:
- GOTO(out, ret);
- }
+ switch (origin) {
+ case SEEK_SET:
+ break;
+ case SEEK_CUR:
+ offset += file->f_pos;
+ break;
+ case SEEK_END:
+ if (offset > 0)
+ GOTO(out, ret);
+ if (api32)
+ offset += LL_DIR_END_OFF_32BIT;
+ else
+ offset += LL_DIR_END_OFF;
+ break;
+ default:
+ GOTO(out, ret);
+ }
- if (offset >= 0 &&
- ((api32 && offset <= LL_DIR_END_OFF_32BIT) ||
- (!api32 && offset <= LL_DIR_END_OFF))) {
- if (offset != file->f_pos) {
- if ((api32 && offset == LL_DIR_END_OFF_32BIT) ||
- (!api32 && offset == LL_DIR_END_OFF))
+ if (offset >= 0 &&
+ ((api32 && offset <= LL_DIR_END_OFF_32BIT) ||
+ (!api32 && offset <= LL_DIR_END_OFF))) {
+ if (offset != file->f_pos) {
+ if ((api32 && offset == LL_DIR_END_OFF_32BIT) ||
+ (!api32 && offset == LL_DIR_END_OFF))
fd->lfd_pos = MDS_DIR_END_OFF;
- else if (api32 && sbi->ll_flags & LL_SBI_64BIT_HASH)
+ else if (api32 && sbi->ll_flags & LL_SBI_64BIT_HASH)
fd->lfd_pos = offset << 32;
- else
+ else
fd->lfd_pos = offset;
- file->f_pos = offset;
- file->f_version = 0;
- }
- ret = offset;
- }
- GOTO(out, ret);
+ file->f_pos = offset;
+ file->f_version = 0;
+ }
+ ret = offset;
+ }
+ GOTO(out, ret);
out:
inode_unlock(inode);
- return ret;
+ return ret;
}
static int ll_dir_open(struct inode *inode, struct file *file)