X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fdir.c;h=73444a7c3b0a6888d5b20e812d90561437886c97;hb=77f5bb4dace53e0040dea4ce5c72156e901e6819;hp=b2227aff6f59688025a8bef027ad4e87415a0c29;hpb=43d5806ffe6d6017aea0892de78dc27e54861de1;p=fs%2Flustre-release.git diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index b2227af..73444a7 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -40,9 +40,7 @@ #include #include #include -#ifdef HAVE_UIDGID_HEADER -# include -#endif +#include #include #include // for wait_on_buffer #include @@ -52,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -104,16 +103,18 @@ * returned page, page hash collision has to be handled. Pages in the * hash chain, except first one, are termed "overflow pages". * - * Solution to index uniqueness problem is to not cache overflow - * pages. Instead, when page hash collision is detected, all overflow pages - * from emerging chain are immediately requested from the server and placed in - * a special data structure (struct ll_dir_chain). This data structure is used - * by ll_readdir() to process entries from overflow pages. When readdir - * invocation finishes, overflow pages are discarded. If page hash collision - * chain weren't completely processed, next call to readdir will again detect - * page hash collision, again read overflow pages in, process next portion of - * entries and again discard the pages. This is not as wasteful as it looks, - * because, given reasonable hash, page hash collisions are extremely rare. + * Proposed (unimplimented) solution to index uniqueness problem is to + * not cache overflow pages. Instead, when page hash collision is + * detected, all overflow pages from emerging chain should be + * immediately requested from the server and placed in a special data + * structure. This data structure can be used by ll_readdir() to + * process entries from overflow pages. When readdir invocation + * finishes, overflow pages are discarded. If page hash collision chain + * weren't completely processed, next call to readdir will again detect + * page hash collision, again read overflow pages in, process next + * portion of entries and again discard the pages. This is not as + * wasteful as it looks, because, given reasonable hash, page hash + * collisions are extremely rare. * * 1. directory positioning * @@ -142,7 +143,7 @@ * */ struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data, - __u64 offset, struct ll_dir_chain *chain) + __u64 offset) { struct md_callback cb_op; struct page *page; @@ -177,29 +178,6 @@ void ll_release_page(struct inode *inode, struct page *page, 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) @@ -214,14 +192,11 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, bool is_api32 = ll_need_32bit_api(sbi); bool is_hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; struct page *page; - struct ll_dir_chain chain; bool done = false; int rc = 0; ENTRY; - ll_dir_chain_init(&chain); - - page = ll_get_dir_page(inode, op_data, pos, &chain); + page = ll_get_dir_page(inode, op_data, pos); while (rc == 0 && !done) { struct lu_dirpage *dp; @@ -258,7 +233,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, 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 = S_DT(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'. */ @@ -295,8 +270,7 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE); next = pos; - page = ll_get_dir_page(inode, op_data, pos, - &chain); + page = ll_get_dir_page(inode, op_data, pos); } } #ifdef HAVE_DIR_CONTEXT @@ -304,7 +278,6 @@ int ll_dir_read(struct inode *inode, __u64 *ppos, struct md_op_data *op_data, #else *ppos = pos; #endif - ll_dir_chain_fini(&chain); RETURN(rc); } @@ -314,15 +287,16 @@ static int ll_iterate(struct file *filp, struct dir_context *ctx) static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) #endif { - struct inode *inode = file_inode(filp); - struct ll_file_data *lfd = LUSTRE_FPRIVATE(filp); - struct ll_sb_info *sbi = ll_i2sbi(inode); - int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; - int api32 = ll_need_32bit_api(sbi); - struct md_op_data *op_data; - struct lu_fid pfid = { 0 }; - __u64 pos; - int rc; + struct inode *inode = file_inode(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); + struct md_op_data *op_data; + struct lu_fid pfid = { 0 }; + ktime_t kstart = ktime_get(); + __u64 pos; + int rc; ENTRY; if (lfd != NULL) @@ -330,8 +304,9 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) 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) @@ -406,32 +381,12 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) out: if (!rc) - ll_stats_ops_tally(sbi, LPROC_LL_READDIR, 1); + ll_stats_ops_tally(sbi, LPROC_LL_READDIR, + ktime_us_delta(ktime_get(), kstart)); 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) * @@ -460,10 +415,11 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *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) { @@ -488,7 +444,26 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump, !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))) @@ -500,6 +475,17 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump, if (IS_ERR(op_data)) RETURN(PTR_ERR(op_data)); + if (ll_sbi_has_encrypt(sbi) && + (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 @@ -512,6 +498,12 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump, GOTO(out_op_data, err); } + if (encrypt) { + err = llcrypt_inherit_context(parent, NULL, op_data, false); + if (err) + GOTO(out_op_data, err); + } + op_data->op_cli_flags |= CLI_SET_MEA; err = md_create(sbi->ll_md_exp, op_data, lump, len, mode, from_kuid(&init_user_ns, current_fsuid()), @@ -529,20 +521,28 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump, dentry.d_inode = inode; if (sbi->ll_flags & LL_SBI_FILE_SECCTX) { - inode_lock(inode); + /* no need to protect selinux_inode_setsecurity() by + * inode_lock. Taking it would lead to a client deadlock + * LU-13617 + */ err = security_inode_notifysecctx(inode, op_data->op_file_secctx, op_data->op_file_secctx_size); - inode_unlock(inode); } else { err = ll_inode_init_security(&dentry, inode, parent); } if (err) GOTO(out_inode, err); + if (encrypt) { + err = ll_set_encflags(inode, op_data->op_file_encctx, + op_data->op_file_encctx_size, false); + if (err) + GOTO(out_inode, err); + } + out_inode: - if (inode != NULL) - iput(inode); + iput(inode); out_request: ptlrpc_req_finished(request); out_op_data: @@ -554,84 +554,63 @@ out_op_data: int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, int set_default) { - struct ll_sb_info *sbi = ll_i2sbi(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; + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct md_op_data *op_data; + struct ptlrpc_request *req = NULL; + int rc = 0; + int lum_size; ENTRY; - if (lump != NULL) { - /* - * This is coming from userspace, so should be in - * local endian. But the MDS would like it in little - * endian, so we swab it before we send it. - */ - switch (lump->lmm_magic) { - case LOV_USER_MAGIC_V1: { - if (lump->lmm_magic != cpu_to_le32(LOV_USER_MAGIC_V1)) - lustre_swab_lov_user_md_v1(lump); - lum_size = sizeof(struct lov_user_md_v1); - break; - } - case LOV_USER_MAGIC_V3: { - if (lump->lmm_magic != cpu_to_le32(LOV_USER_MAGIC_V3)) - lustre_swab_lov_user_md_v3( - (struct lov_user_md_v3 *)lump); - lum_size = sizeof(struct lov_user_md_v3); - break; - } - case LOV_USER_MAGIC_COMP_V1: { - if (lump->lmm_magic != - cpu_to_le32(LOV_USER_MAGIC_COMP_V1)) - lustre_swab_lov_comp_md_v1( - (struct lov_comp_md_v1 *)lump); - lum_size = le32_to_cpu( - ((struct lov_comp_md_v1 *)lump)->lcm_size); + if (lump != NULL) { + switch (lump->lmm_magic) { + case LOV_USER_MAGIC_V1: + lum_size = sizeof(struct lov_user_md_v1); break; - } - case LMV_USER_MAGIC: { + case LOV_USER_MAGIC_V3: + lum_size = sizeof(struct lov_user_md_v3); + break; + case LOV_USER_MAGIC_COMP_V1: + lum_size = ((struct lov_comp_md_v1 *)lump)->lcm_size; + break; + case LMV_USER_MAGIC: if (lump->lmm_magic != cpu_to_le32(LMV_USER_MAGIC)) lustre_swab_lmv_user_md( (struct lmv_user_md *)lump); lum_size = sizeof(struct lmv_user_md); break; - } case LOV_USER_MAGIC_SPECIFIC: { struct lov_user_md_v3 *v3 = - (struct lov_user_md_v3 *)lump; + (struct lov_user_md_v3 *)lump; if (v3->lmm_stripe_count > LOV_MAX_STRIPE_COUNT) RETURN(-EINVAL); - if (lump->lmm_magic != - cpu_to_le32(LOV_USER_MAGIC_SPECIFIC)) { - lustre_swab_lov_user_md_v3(v3); - lustre_swab_lov_user_md_objects(v3->lmm_objects, - v3->lmm_stripe_count); - } lum_size = lov_user_md_size(v3->lmm_stripe_count, LOV_USER_MAGIC_SPECIFIC); break; } - default: { + default: CDEBUG(D_IOCTL, "bad userland LOV MAGIC:" " %#08x != %#08x nor %#08x\n", lump->lmm_magic, LOV_USER_MAGIC_V1, LOV_USER_MAGIC_V3); RETURN(-EINVAL); } - } - } else { - lum_size = sizeof(struct lov_user_md_v1); - } - op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) - RETURN(PTR_ERR(op_data)); + /* + * This is coming from userspace, so should be in + * local endian. But the MDS would like it in little + * endian, so we swab it before we send it. + */ + if ((__swab32(lump->lmm_magic) & le32_to_cpu(LOV_MAGIC_MASK)) == + le32_to_cpu(LOV_MAGIC_MAGIC)) + lustre_swab_lov_user_md(lump, 0); + } else { + lum_size = sizeof(struct lov_user_md_v1); + } + + op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, + LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + RETURN(PTR_ERR(op_data)); /* swabbing is done in lov_setstripe() on server side */ rc = md_setattr(sbi->ll_md_exp, op_data, lump, lum_size, &req); @@ -640,70 +619,13 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, 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); } -/** - * This function will be used to get default LOV/LMV/Default LMV - * @valid will be used to indicate which stripe it will retrieve - * OBD_MD_MEA LMV stripe EA - * OBD_MD_DEFAULT_MEA Default LMV stripe EA - * otherwise Default LOV EA. - * Each time, it can only retrieve 1 stripe EA - **/ -int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, - struct ptlrpc_request **request, u64 valid) +static int ll_dir_get_default_layout(struct inode *inode, void **plmm, + int *plmm_size, + struct ptlrpc_request **request, u64 valid, + enum get_default_layout_type type) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct mdt_body *body; @@ -711,6 +633,7 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, struct ptlrpc_request *req = NULL; int rc, lmm_size; struct md_op_data *op_data; + struct lu_fid fid; ENTRY; rc = ll_get_default_mdsize(sbi, &lmm_size); @@ -724,11 +647,19 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, RETURN(PTR_ERR(op_data)); op_data->op_valid = valid | OBD_MD_FLEASIZE | OBD_MD_FLDIREA; + + if (type == GET_DEFAULT_LAYOUT_ROOT) { + lu_root_fid(&op_data->op_fid1); + fid = op_data->op_fid1; + } else { + fid = *ll_inode2fid(inode); + } + rc = md_getattr(sbi->ll_md_exp, op_data, &req); ll_finish_md_op_data(op_data); if (rc < 0) { - CDEBUG(D_INFO, "md_getattr failed on inode " - DFID": rc %d\n", PFID(ll_inode2fid(inode)), rc); + CDEBUG(D_INFO, "md_getattr failed on inode "DFID": rc %d\n", + PFID(&fid), rc); GOTO(out, rc); } @@ -754,17 +685,11 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, /* We don't swab objects for directories */ switch (le32_to_cpu(lmm->lmm_magic)) { case LOV_MAGIC_V1: - if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) - lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lmm); - break; case LOV_MAGIC_V3: - if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) - lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); - break; case LOV_MAGIC_COMP_V1: + case LOV_USER_MAGIC_SPECIFIC: if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) - lustre_swab_lov_comp_md_v1( - (struct lov_comp_md_v1 *)lmm); + lustre_swab_lov_user_md((struct lov_user_md *)lmm, 0); break; case LMV_MAGIC_V1: if (LMV_MAGIC != cpu_to_le32(LMV_MAGIC)) @@ -774,16 +699,6 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, if (LMV_USER_MAGIC != cpu_to_le32(LMV_USER_MAGIC)) lustre_swab_lmv_user_md((struct lmv_user_md *)lmm); break; - case LOV_USER_MAGIC_SPECIFIC: { - struct lov_user_md_v3 *v3 = (struct lov_user_md_v3 *)lmm; - - if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) { - lustre_swab_lov_user_md_v3(v3); - lustre_swab_lov_user_md_objects(v3->lmm_objects, - v3->lmm_stripe_count); - } - } - break; case LMV_MAGIC_FOREIGN: { struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)lmm; @@ -806,6 +721,75 @@ out: return rc; } +/** + * This function will be used to get default LOV/LMV/Default LMV + * @valid will be used to indicate which stripe it will retrieve. + * If the directory does not have its own default layout, then the + * function will request the default layout from root FID. + * OBD_MD_MEA LMV stripe EA + * OBD_MD_DEFAULT_MEA Default LMV stripe EA + * otherwise Default LOV EA. + * Each time, it can only retrieve 1 stripe EA + **/ +int ll_dir_getstripe_default(struct inode *inode, void **plmm, int *plmm_size, + struct ptlrpc_request **request, + struct ptlrpc_request **root_request, + u64 valid) +{ + struct ptlrpc_request *req = NULL; + struct ptlrpc_request *root_req = NULL; + struct lov_mds_md *lmm = NULL; + int lmm_size = 0; + int rc = 0; + ENTRY; + + rc = ll_dir_get_default_layout(inode, (void **)&lmm, &lmm_size, + &req, valid, 0); + if (rc == -ENODATA && !fid_is_root(ll_inode2fid(inode)) && + !(valid & (OBD_MD_MEA|OBD_MD_DEFAULT_MEA)) && root_request != NULL){ + int rc2 = ll_dir_get_default_layout(inode, (void **)&lmm, + &lmm_size, &root_req, valid, + GET_DEFAULT_LAYOUT_ROOT); + if (rc2 == 0) + rc = 0; + } + + *plmm = lmm; + *plmm_size = lmm_size; + *request = req; + if (root_request != NULL) + *root_request = root_req; + + RETURN(rc); +} + +/** + * This function will be used to get default LOV/LMV/Default LMV + * @valid will be used to indicate which stripe it will retrieve + * OBD_MD_MEA LMV stripe EA + * OBD_MD_DEFAULT_MEA Default LMV stripe EA + * otherwise Default LOV EA. + * Each time, it can only retrieve 1 stripe EA + **/ +int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size, + struct ptlrpc_request **request, u64 valid) +{ + struct ptlrpc_request *req = NULL; + struct lov_mds_md *lmm = NULL; + int lmm_size = 0; + int rc = 0; + ENTRY; + + rc = ll_dir_get_default_layout(inode, (void **)&lmm, &lmm_size, + &req, valid, 0); + + *plmm = lmm; + *plmm_size = lmm_size; + *request = req; + + RETURN(rc); +} + int ll_get_mdt_idx_by_fid(struct ll_sb_info *sbi, const struct lu_fid *fid) { struct md_op_data *op_data; @@ -1063,7 +1047,7 @@ static int copy_and_ct_start(int cmd, struct obd_export *exp, 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++; } @@ -1138,42 +1122,48 @@ static int check_owner(int type, int id) return 0; } -static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) +int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) { - int cmd = qctl->qc_cmd; - int type = qctl->qc_type; - int id = qctl->qc_id; - int valid = qctl->qc_valid; - int rc = 0; - ENTRY; + int cmd = qctl->qc_cmd; + int type = qctl->qc_type; + int id = qctl->qc_id; + int valid = qctl->qc_valid; + int rc = 0; + + ENTRY; switch (cmd) { case Q_SETQUOTA: case Q_SETINFO: case LUSTRE_Q_SETDEFAULT: - if (!cfs_capable(CFS_CAP_SYS_ADMIN)) + case LUSTRE_Q_SETQUOTAPOOL: + case LUSTRE_Q_SETINFOPOOL: + if (!capable(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))) + (!capable(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: @@ -1203,29 +1193,41 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) 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) { - struct obd_quotactl *oqctl_tmp; - - OBD_ALLOC_PTR(oqctl_tmp); - if (oqctl_tmp == NULL) - GOTO(out, rc = -ENOMEM); - - oqctl_tmp->qc_cmd = Q_GETOQUOTA; + 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; + int qctl_len = sizeof(*oqctl_tmp) + LOV_MAXPOOLNAME + 1; + + OBD_ALLOC(oqctl_tmp, qctl_len); + if (oqctl_tmp == NULL) + GOTO(out, rc = -ENOMEM); + + if (cmd == LUSTRE_Q_GETQUOTAPOOL) { + oqctl_tmp->qc_cmd = LUSTRE_Q_GETQUOTAPOOL; + memcpy(oqctl_tmp->qc_poolname, + qctl->qc_poolname, + LOV_MAXPOOLNAME + 1); + } else { + oqctl_tmp->qc_cmd = Q_GETOQUOTA; + } oqctl_tmp->qc_id = oqctl->qc_id; oqctl_tmp->qc_type = oqctl->qc_type; @@ -1238,28 +1240,77 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) oqctl->qc_dqblk.dqb_valid |= QIF_SPACE; } - /* collect space & inode usage from MDTs */ - oqctl_tmp->qc_dqblk.dqb_curspace = 0; - oqctl_tmp->qc_dqblk.dqb_curinodes = 0; - rc = obd_quotactl(sbi->ll_md_exp, oqctl_tmp); - if (!rc || rc == -EREMOTEIO) { - oqctl->qc_dqblk.dqb_curspace += - oqctl_tmp->qc_dqblk.dqb_curspace; - oqctl->qc_dqblk.dqb_curinodes = - oqctl_tmp->qc_dqblk.dqb_curinodes; - oqctl->qc_dqblk.dqb_valid |= QIF_INODES; - } else { - oqctl->qc_dqblk.dqb_valid &= ~QIF_SPACE; - } + /* collect space & inode usage from MDTs */ + oqctl_tmp->qc_cmd = Q_GETOQUOTA; + oqctl_tmp->qc_dqblk.dqb_curspace = 0; + oqctl_tmp->qc_dqblk.dqb_curinodes = 0; + rc = obd_quotactl(sbi->ll_md_exp, oqctl_tmp); + if (!rc || rc == -EREMOTEIO) { + oqctl->qc_dqblk.dqb_curspace += + oqctl_tmp->qc_dqblk.dqb_curspace; + oqctl->qc_dqblk.dqb_curinodes = + oqctl_tmp->qc_dqblk.dqb_curinodes; + oqctl->qc_dqblk.dqb_valid |= QIF_INODES; + } else { + oqctl->qc_dqblk.dqb_valid &= ~QIF_SPACE; + } - OBD_FREE_PTR(oqctl_tmp); + OBD_FREE(oqctl_tmp, qctl_len); } out: - QCTL_COPY(qctl, oqctl); - OBD_FREE_PTR(oqctl); - } + QCTL_COPY(qctl, oqctl); + OBD_FREE(oqctl, oqctl_len); + } + + RETURN(rc); +} + +int ll_rmfid(struct file *file, void __user *arg) +{ + const struct fid_array __user *ufa = arg; + struct fid_array *lfa = NULL; + size_t size; + unsigned nr; + int i, rc, *rcs = NULL; + ENTRY; + + if (!capable(CAP_DAC_READ_SEARCH) && + !(ll_i2sbi(file_inode(file))->ll_flags & LL_SBI_USER_FID2PATH)) + RETURN(-EPERM); + /* Only need to get the buflen */ + if (get_user(nr, &ufa->fa_nr)) + RETURN(-EFAULT); + /* DoS protection */ + if (nr > OBD_MAX_FIDS_IN_ARRAY) + RETURN(-E2BIG); + + size = offsetof(struct fid_array, fa_fids[nr]); + OBD_ALLOC(lfa, size); + if (!lfa) + RETURN(-ENOMEM); + OBD_ALLOC_PTR_ARRAY(rcs, nr); + if (!rcs) + GOTO(free_lfa, rc = -ENOMEM); + + if (copy_from_user(lfa, arg, size)) + GOTO(free_rcs, rc = -EFAULT); + + /* Call mdc_iocontrol */ + rc = md_rmfid(ll_i2mdexp(file_inode(file)), lfa, rcs, NULL); + if (!rc) { + for (i = 0; i < nr; i++) + if (rcs[i]) + lfa->fa_fids[i].f_ver = rcs[i]; + if (copy_to_user(arg, lfa, size)) + rc = -EFAULT; + } + +free_rcs: + OBD_FREE_PTR_ARRAY(rcs, nr); +free_lfa: + OBD_FREE(lfa, size); - RETURN(rc); + RETURN(rc); } /* This function tries to get a single name component, @@ -1295,7 +1346,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct dentry *dentry = file_dentry(file); struct inode *inode = file_inode(file); struct ll_sb_info *sbi = ll_i2sbi(inode); - struct obd_ioctl_data *data; + struct obd_ioctl_data *data = NULL; int rc = 0; ENTRY; @@ -1333,14 +1384,12 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } case IOC_MDC_LOOKUP: { - int namelen, len = 0; - char *buf = NULL; + int namelen, len = 0; char *filename; - rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); + rc = obd_ioctl_getdata(&data, &len, (void __user *)arg); if (rc != 0) RETURN(rc); - data = (void *)buf; filename = data->ioc_inlbuf1; namelen = strlen(filename); @@ -1356,12 +1405,11 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) GOTO(out_free, rc); } out_free: - OBD_FREE_LARGE(buf, len); - return rc; - } + OBD_FREE_LARGE(data, len); + return rc; + } case LL_IOC_LMV_SETSTRIPE: { struct lmv_user_md *lum; - char *buf = NULL; char *filename; int namelen = 0; int lumlen = 0; @@ -1369,11 +1417,10 @@ out_free: int len; int rc; - rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); + rc = obd_ioctl_getdata(&data, &len, (void __user *)arg); if (rc) RETURN(rc); - data = (void *)buf; if (data->ioc_inlbuf1 == NULL || data->ioc_inlbuf2 == NULL || data->ioc_inllen1 == 0 || data->ioc_inllen2 == 0) GOTO(lmv_out_free, rc = -EINVAL); @@ -1388,7 +1435,7 @@ out_free: 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); @@ -1409,14 +1456,10 @@ out_free: 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); + OBD_FREE_LARGE(data, len); RETURN(rc); } @@ -1449,14 +1492,14 @@ lmv_out_free: int set_default = 0; - CLASSERT(sizeof(struct lov_user_md_v3) > - sizeof(struct lov_comp_md_v1)); - CLASSERT(sizeof(*lumv3) == sizeof(*lumv3p)); + BUILD_BUG_ON(sizeof(struct lov_user_md_v3) <= + sizeof(struct lov_comp_md_v1)); + BUILD_BUG_ON(sizeof(*lumv3) != sizeof(*lumv3p)); /* first try with v1 which is smaller than v3 */ if (copy_from_user(&lumv1, lumv1p, sizeof(lumv1))) RETURN(-EFAULT); - if (inode->i_sb->s_root == file_dentry(file)) + if (is_root_inode(inode)) set_default = 1; switch (lumv1.lmm_magic) { @@ -1490,6 +1533,7 @@ out: (struct lmv_user_md __user *)arg; struct lmv_user_md lum; struct ptlrpc_request *request = NULL; + struct ptlrpc_request *root_request = NULL; union lmv_mds_md *lmm = NULL; int lmmsize; u64 valid = 0; @@ -1515,8 +1559,8 @@ out: else RETURN(-EINVAL); - rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, &request, - valid); + rc = ll_dir_getstripe_default(inode, (void **)&lmm, &lmmsize, + &request, &root_request, valid); if (rc != 0) GOTO(finish_req, rc); @@ -1606,9 +1650,20 @@ out_tmp: OBD_FREE(tmp, lum_size); finish_req: ptlrpc_req_finished(request); + ptlrpc_req_finished(root_request); return rc; } + case LL_IOC_UNLOCK_FOREIGN: + /* if not a foreign symlink do nothing */ + if (ll_foreign_is_removable(dentry, true)) { + CDEBUG(D_INFO, + "prevent rmdir of non-foreign dir ("DFID")\n", + PFID(ll_inode2fid(inode))); + RETURN(-EOPNOTSUPP); + } + RETURN(0); + case LL_IOC_REMOVE_ENTRY: { char *filename = NULL; int namelen = 0; @@ -1636,45 +1691,59 @@ out_rmdir: ll_putname(filename); RETURN(rc); } + case LL_IOC_RMFID: + RETURN(ll_rmfid(file, (void __user *)arg)); case LL_IOC_LOV_SWAP_LAYOUTS: RETURN(-EPERM); case IOC_OBD_STATFS: RETURN(ll_obd_statfs(inode, (void __user *)arg)); case LL_IOC_LOV_GETSTRIPE: case LL_IOC_LOV_GETSTRIPE_NEW: - case LL_IOC_MDC_GETINFO: - case IOC_MDC_GETFILEINFO: + case LL_IOC_MDC_GETINFO_V1: + case LL_IOC_MDC_GETINFO_V2: + case IOC_MDC_GETFILEINFO_V1: + case IOC_MDC_GETFILEINFO_V2: case IOC_MDC_GETFILESTRIPE: { struct ptlrpc_request *request = NULL; + struct ptlrpc_request *root_request = NULL; struct lov_user_md __user *lump; - struct lov_mds_md *lmm = NULL; - struct mdt_body *body; - char *filename = NULL; - int lmmsize; - - if (cmd == IOC_MDC_GETFILEINFO || - cmd == IOC_MDC_GETFILESTRIPE) { + struct lov_mds_md *lmm = NULL; + struct mdt_body *body; + char *filename = NULL; + lstat_t __user *statp = NULL; + lstatx_t __user *stxp = NULL; + __u64 __user *flagsp = NULL; + __u32 __user *lmmsizep = NULL; + struct lu_fid __user *fidp = NULL; + int lmmsize; + + if (cmd == IOC_MDC_GETFILEINFO_V1 || + cmd == IOC_MDC_GETFILEINFO_V2 || + cmd == IOC_MDC_GETFILESTRIPE) { filename = ll_getname((const char __user *)arg); - if (IS_ERR(filename)) - RETURN(PTR_ERR(filename)); + if (IS_ERR(filename)) + RETURN(PTR_ERR(filename)); - rc = ll_lov_getstripe_ea_info(inode, filename, &lmm, - &lmmsize, &request); + rc = ll_lov_getstripe_ea_info(inode, filename, &lmm, + &lmmsize, &request); } else { - rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize, - &request, 0); + rc = ll_dir_getstripe_default(inode, (void **)&lmm, + &lmmsize, &request, + &root_request, 0); } - if (request) { - body = req_capsule_server_get(&request->rq_pill, - &RMF_MDT_BODY); - LASSERT(body != NULL); - } else { - GOTO(out_req, rc); - } + if (request) { + body = req_capsule_server_get(&request->rq_pill, + &RMF_MDT_BODY); + LASSERT(body != NULL); + } else { + GOTO(out_req, rc); + } - if (rc == -ENODATA && (cmd == IOC_MDC_GETFILEINFO || - cmd == LL_IOC_MDC_GETINFO)) { + if (rc == -ENODATA && (cmd == IOC_MDC_GETFILEINFO_V1 || + cmd == LL_IOC_MDC_GETINFO_V1 || + cmd == IOC_MDC_GETFILEINFO_V2 || + cmd == LL_IOC_MDC_GETINFO_V2)) { lmmsize = 0; rc = 0; } @@ -1686,11 +1755,23 @@ out_rmdir: cmd == LL_IOC_LOV_GETSTRIPE || cmd == LL_IOC_LOV_GETSTRIPE_NEW) { lump = (struct lov_user_md __user *)arg; - } else { + } else if (cmd == IOC_MDC_GETFILEINFO_V1 || + cmd == LL_IOC_MDC_GETINFO_V1){ + struct lov_user_mds_data_v1 __user *lmdp; + + lmdp = (struct lov_user_mds_data_v1 __user *)arg; + statp = &lmdp->lmd_st; + lump = &lmdp->lmd_lmm; + } else { struct lov_user_mds_data __user *lmdp; + lmdp = (struct lov_user_mds_data __user *)arg; - lump = &lmdp->lmd_lmm; - } + fidp = &lmdp->lmd_fid; + stxp = &lmdp->lmd_stx; + flagsp = &lmdp->lmd_flags; + lmmsizep = &lmdp->lmd_lmmsize; + lump = &lmdp->lmd_lmm; + } if (lmmsize == 0) { /* If the file has no striping then zero out *lump so @@ -1703,9 +1784,9 @@ out_rmdir: rc = -EOVERFLOW; } - if (cmd == IOC_MDC_GETFILEINFO || cmd == LL_IOC_MDC_GETINFO) { - struct lov_user_mds_data __user *lmdp; - lstat_t st = { 0 }; + if (cmd == IOC_MDC_GETFILEINFO_V1 || + cmd == LL_IOC_MDC_GETINFO_V1) { + lstat_t st = { 0 }; st.st_dev = inode->i_sb->s_dev; st.st_mode = body->mbo_mode; @@ -1723,37 +1804,103 @@ out_rmdir: sbi->ll_flags & LL_SBI_32BIT_API); - lmdp = (struct lov_user_mds_data __user *)arg; - if (copy_to_user(&lmdp->lmd_st, &st, sizeof(st))) - GOTO(out_req, rc = -EFAULT); - } + if (copy_to_user(statp, &st, sizeof(st))) + GOTO(out_req, rc = -EFAULT); + } else if (cmd == IOC_MDC_GETFILEINFO_V2 || + cmd == LL_IOC_MDC_GETINFO_V2) { + lstatx_t stx = { 0 }; + __u64 valid = body->mbo_valid; + + stx.stx_blksize = PAGE_SIZE; + stx.stx_nlink = body->mbo_nlink; + stx.stx_uid = body->mbo_uid; + stx.stx_gid = body->mbo_gid; + stx.stx_mode = body->mbo_mode; + stx.stx_ino = cl_fid_build_ino(&body->mbo_fid1, + sbi->ll_flags & + LL_SBI_32BIT_API); + stx.stx_size = body->mbo_size; + stx.stx_blocks = body->mbo_blocks; + 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 | STATX_BTIME; - EXIT; - out_req: - ptlrpc_req_finished(request); - if (filename) - ll_putname(filename); - return rc; - } + /* + * For a striped directory, the size and blocks returned + * from MDT is not correct. + * The size and blocks are aggregated by client across + * all stripes. + * Thus for a striped directory, do not return the valid + * FLSIZE and FLBLOCKS flags to the caller. + * However, this whould be better decided by the MDS + * instead of the client. + */ + if (cmd == LL_IOC_MDC_GETINFO_V2 && + ll_i2info(inode)->lli_lsm_md != NULL) + valid &= ~(OBD_MD_FLSIZE | OBD_MD_FLBLOCKS); + + if (flagsp && copy_to_user(flagsp, &valid, + sizeof(*flagsp))) + GOTO(out_req, rc = -EFAULT); + + if (fidp && copy_to_user(fidp, &body->mbo_fid1, + sizeof(*fidp))) + GOTO(out_req, rc = -EFAULT); + + if (!(valid & OBD_MD_FLSIZE)) + stx.stx_mask &= ~STATX_SIZE; + if (!(valid & OBD_MD_FLBLOCKS)) + stx.stx_mask &= ~STATX_BLOCKS; + + if (stxp && copy_to_user(stxp, &stx, sizeof(stx))) + GOTO(out_req, rc = -EFAULT); + + if (lmmsizep && copy_to_user(lmmsizep, &lmmsize, + sizeof(*lmmsizep))) + GOTO(out_req, rc = -EFAULT); + } + + EXIT; +out_req: + ptlrpc_req_finished(request); + ptlrpc_req_finished(root_request); + if (filename) + ll_putname(filename); + 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: @@ -1893,7 +2040,7 @@ out_hur: RETURN(rc); } case LL_IOC_HSM_CT_START: - if (!cfs_capable(CFS_CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN)) RETURN(-EPERM); rc = copy_and_ct_start(cmd, sbi->ll_md_exp, @@ -1940,17 +2087,15 @@ out_hur: } case LL_IOC_MIGRATE: { struct lmv_user_md *lum; - char *buf = NULL; int len; char *filename; int namelen = 0; int rc; - rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); + rc = obd_ioctl_getdata(&data, &len, (void __user *)arg); if (rc) RETURN(rc); - data = (struct obd_ioctl_data *)buf; if (data->ioc_inlbuf1 == NULL || data->ioc_inlbuf2 == NULL || data->ioc_inllen1 == 0 || data->ioc_inllen2 == 0) GOTO(migrate_free, rc = -EINVAL); @@ -1974,13 +2119,13 @@ out_hur: rc = ll_migrate(inode, file, lum, filename); migrate_free: - OBD_FREE_LARGE(buf, len); + OBD_FREE_LARGE(data, len); 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; @@ -2019,6 +2164,33 @@ out_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)); @@ -2027,53 +2199,53 @@ out_detach: 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) @@ -2094,7 +2266,7 @@ const struct file_operations ll_dir_operations = { .release = ll_dir_release, .read = generic_read_dir, #ifdef HAVE_DIR_CONTEXT - .iterate = ll_iterate, + .iterate_shared = ll_iterate, #else .readdir = ll_readdir, #endif