X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Ffile.c;h=f411a7113207647b95d31977cf860c46f420043b;hp=86c5fc468dfa0388ab2cdaa328192910f1d9f25d;hb=a71586d4ee8d6f039a413e2a0fd791db847a3c19;hpb=48457868a02ae5a0407f304c9028f7e80e7fb574;ds=sidebyside diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 86c5fc4..f411a71 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -46,6 +46,7 @@ #include #include +#include #include #include "cl_object.h" @@ -422,6 +423,9 @@ static inline int ll_dom_readpage(void *data, struct page *page) { struct niobuf_local *lnb = data; void *kaddr; + int rc = 0; + + struct inode *inode = page2inode(page); kaddr = kmap_atomic(page); memcpy(kaddr, lnb->lnb_data, lnb->lnb_len); @@ -431,9 +435,22 @@ static inline int ll_dom_readpage(void *data, struct page *page) flush_dcache_page(page); SetPageUptodate(page); kunmap_atomic(kaddr); + + if (inode && IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) { + if (!llcrypt_has_encryption_key(inode)) + CDEBUG(D_SEC, "no enc key for "DFID"\n", + PFID(ll_inode2fid(inode))); + /* decrypt only if page is not empty */ + else if (memcmp(page_address(page), + page_address(ZERO_PAGE(0)), + PAGE_SIZE) != 0) + rc = llcrypt_decrypt_pagecache_blocks(page, + PAGE_SIZE, + 0); + } unlock_page(page); - return 0; + return rc; } void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req, @@ -474,7 +491,8 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req, * buffer, in both cases total size should be equal to the file size. */ body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - if (rnb->rnb_offset + rnb->rnb_len != body->mbo_dom_size) { + if (rnb->rnb_offset + rnb->rnb_len != body->mbo_dom_size && + !(inode && IS_ENCRYPTED(inode))) { CERROR("%s: server returns off/len %llu/%u but size %llu\n", ll_i2sbi(inode)->ll_fsname, rnb->rnb_offset, rnb->rnb_len, body->mbo_dom_size); @@ -706,6 +724,12 @@ int ll_file_open(struct inode *inode, struct file *file) 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); @@ -1471,16 +1495,16 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, struct file *file, enum cl_io_type iot, loff_t *ppos, size_t count) { - 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 = file->private_data; - struct range_lock range; - struct cl_io *io; - ssize_t result = 0; - int rc = 0; - unsigned retried = 0; - unsigned ignore_lockless = 0; + 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 = 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; + bool is_aio = false; ENTRY; @@ -1509,6 +1533,13 @@ restart: case IO_NORMAL: vio->vui_iter = args->u.normal.via_iter; vio->vui_iocb = args->u.normal.via_iocb; + if (file->f_flags & O_DIRECT) { + if (!is_sync_kiocb(vio->vui_iocb)) + is_aio = true; + io->ci_aio = cl_aio_alloc(vio->vui_iocb); + if (!io->ci_aio) + GOTO(out, rc = -ENOMEM); + } /* Direct IO reads must also take range lock, * or multiple reads will try to work on the same pages * See LU-6227 for details. */ @@ -1547,7 +1578,14 @@ restart: rc = io->ci_result; } - if (io->ci_nob > 0) { + /* + * In order to move forward AIO, ci_nob was increased, + * but that doesn't mean io have been finished, it just + * means io have been submited, we will always return + * EIOCBQUEUED to the caller, So we could only return + * number of bytes in non-AIO case. + */ + if (io->ci_nob > 0 && !is_aio) { result += io->ci_nob; count -= io->ci_nob; *ppos = io->u.ci_wr.wr.crw_pos; /* for splice */ @@ -1557,6 +1595,19 @@ restart: args->u.normal.via_iter = vio->vui_iter; } out: + if (io->ci_aio) { + /** + * Drop one extra reference so that end_io() could be + * called for this IO context, we could call it after + * we make sure all AIO requests have been proceed. + */ + cl_sync_io_note(env, &io->ci_aio->cda_sync, + rc == -EIOCBQUEUED ? 0 : rc); + if (!is_aio) { + cl_aio_free(io->ci_aio); + io->ci_aio = NULL; + } + } cl_io_fini(env, io); CDEBUG(D_VFSTRACE, @@ -2249,6 +2300,13 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file, 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); @@ -2960,9 +3018,9 @@ int ll_file_lock_ahead(struct file *file, struct llapi_lu_ladvise *ladvise) 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); @@ -3899,9 +3957,9 @@ out_ladvise: 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)); @@ -3982,6 +4040,33 @@ out_state: 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)); @@ -4543,24 +4628,24 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits, enum ldlm_mode l_req_mode) 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); } @@ -4624,8 +4709,8 @@ static int ll_inode_revalidate(struct dentry *dentry, enum ldlm_intent_flags op) PFID(ll_inode2fid(inode)), inode, dentry->d_name.name); /* Call getattr by fid, so do not provide name at all. */ - op_data = ll_prep_md_op_data(NULL, inode, inode, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); + op_data = ll_prep_md_op_data(NULL, dentry->d_parent->d_inode, inode, + NULL, 0, 0, LUSTRE_OPC_ANY, NULL); if (IS_ERR(op_data)) RETURN(PTR_ERR(op_data)); @@ -4671,7 +4756,7 @@ static int ll_merge_md_attr(struct inode *inode) RETURN(0); down_read(&lli->lli_lsm_sem); - rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, + rc = md_merge_attr(ll_i2mdexp(inode), &lli->lli_fid, lli->lli_lsm_md, &attr, ll_md_blocking_ast); up_read(&lli->lli_lsm_sem); if (rc != 0) @@ -4688,14 +4773,29 @@ static int ll_merge_md_attr(struct inode *inode) 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); @@ -4703,10 +4803,36 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat) 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. @@ -4714,7 +4840,7 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat) * 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); @@ -4727,11 +4853,15 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat) 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)) { @@ -4763,6 +4893,26 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat) 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)); @@ -4773,13 +4923,15 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat) 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) { -#endif - return ll_getattr_dentry(de, stat); + return ll_getattr_dentry(de, stat, STATX_BASIC_STATS, + AT_STATX_SYNC_AS_STAT); } +#endif int cl_falloc(struct inode *inode, int mode, loff_t offset, loff_t len) { @@ -5023,7 +5175,7 @@ int ll_inode_permission(struct inode *inode, int 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);