X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lustre%2Fllite%2Fxattr_cache.c;h=c0ef7df204170672b310a13aad8a314ba06594fd;hb=14b37c763c5751faf18d00287c16bdcbe0f8d542;hp=3489f0bf23277fd257390d3e77927e8a0a269db0;hpb=40d91eafe257fb407d27c54cd2f7ae9961672f60;p=fs%2Flustre-release.git diff --git a/lustre/llite/xattr_cache.c b/lustre/llite/xattr_cache.c index 3489f0b..c0ef7df 100644 --- a/lustre/llite/xattr_cache.c +++ b/lustre/llite/xattr_cache.c @@ -85,7 +85,7 @@ static void ll_xattr_cache_init(struct ll_inode_info *lli) LASSERT(lli != NULL); INIT_LIST_HEAD(&lli->lli_xattrs); - ll_file_set_flag(lli, LLIF_XATTR_CACHE); + set_bit(LLIF_XATTR_CACHE, &lli->lli_flags); } /** @@ -139,6 +139,12 @@ static int ll_xattr_cache_add(struct list_head *cache, ENTRY; if (ll_xattr_cache_find(cache, xattr_name, &xattr) == 0) { + if (!strcmp(xattr_name, LL_XATTR_NAME_ENCRYPTION_CONTEXT)) + /* it means enc ctx was already in cache, + * ignore error as it cannot be modified + */ + RETURN(0); + CDEBUG(D_CACHE, "duplicate xattr: [%s]\n", xattr_name); RETURN(-EPROTO); } @@ -250,14 +256,25 @@ static int ll_xattr_cache_list(struct list_head *cache, } /** - * Check if the xattr cache is initialized (filled). + * Check if the xattr cache is initialized. * * \retval 0 @cache is not initialized * \retval 1 @cache is initialized */ static int ll_xattr_cache_valid(struct ll_inode_info *lli) { - return ll_file_test_flag(lli, LLIF_XATTR_CACHE); + return test_bit(LLIF_XATTR_CACHE, &lli->lli_flags); +} + +/** + * Check if the xattr cache is filled. + * + * \retval 0 @cache is not filled + * \retval 1 @cache is filled + */ +static int ll_xattr_cache_filled(struct ll_inode_info *lli) +{ + return test_bit(LLIF_XATTR_CACHE_FILLED, &lli->lli_flags); } /** @@ -277,7 +294,8 @@ static int ll_xattr_cache_destroy_locked(struct ll_inode_info *lli) while (ll_xattr_cache_del(&lli->lli_xattrs, NULL) == 0) /* empty loop */ ; - ll_file_clear_flag(lli, LLIF_XATTR_CACHE); + clear_bit(LLIF_XATTR_CACHE_FILLED, &lli->lli_flags); + clear_bit(LLIF_XATTR_CACHE, &lli->lli_flags); RETURN(0); } @@ -297,12 +315,49 @@ int ll_xattr_cache_destroy(struct inode *inode) } /** + * ll_xattr_cache_empty - empty xattr cache for @ino + * + * Similar to ll_xattr_cache_destroy(), but preserves encryption context. + * So only LLIF_XATTR_CACHE_FILLED flag is cleared, but not LLIF_XATTR_CACHE. + */ +int ll_xattr_cache_empty(struct inode *inode) +{ + struct ll_inode_info *lli = ll_i2info(inode); + struct ll_xattr_entry *entry, *n; + + ENTRY; + + down_write(&lli->lli_xattrs_list_rwsem); + if (!ll_xattr_cache_valid(lli) || + !ll_xattr_cache_filled(lli)) + GOTO(out_empty, 0); + + list_for_each_entry_safe(entry, n, &lli->lli_xattrs, xe_list) { + if (strcmp(entry->xe_name, + LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) + continue; + + CDEBUG(D_CACHE, "delete: %s\n", entry->xe_name); + list_del(&entry->xe_list); + OBD_FREE(entry->xe_name, entry->xe_namelen); + OBD_FREE(entry->xe_value, entry->xe_vallen); + OBD_SLAB_FREE_PTR(entry, xattr_kmem); + } + clear_bit(LLIF_XATTR_CACHE_FILLED, &lli->lli_flags); + +out_empty: + up_write(&lli->lli_xattrs_list_rwsem); + RETURN(0); +} + +/** * Match or enqueue a PR lock. * * Find or request an LDLM lock with xattr data. * Since LDLM does not provide API for atomic match_or_enqueue, * the function handles it with a separate enq lock. - * If successful, the function exits with the list lock held. + * If successful, the function exits with a write lock held + * on lli_xattrs_list_rwsem. * * \retval 0 no error occured * \retval -ENOMEM not enough memory @@ -324,7 +379,7 @@ static int ll_xattr_find_get_lock(struct inode *inode, mutex_lock(&lli->lli_xattrs_enq_lock); /* inode may have been shrunk and recreated, so data is gone, match lock * only when data exists. */ - if (ll_xattr_cache_valid(lli)) { + if (ll_xattr_cache_filled(lli)) { /* Try matching first. */ mode = ll_take_md_lock(inode, MDS_INODELOCK_XATTR, &lockh, 0, LCK_PR); @@ -367,7 +422,9 @@ out: /** * Refill the xattr cache. * - * Fetch and cache the whole of xattrs for @inode, acquiring a read lock. + * Fetch and cache the whole of xattrs for @inode, thanks to the write lock + * on lli_xattrs_list_rwsem obtained from ll_xattr_find_get_lock(). + * If successful, this write lock is kept. * * \retval 0 no error occured * \retval -EPROTO network protocol error @@ -391,7 +448,7 @@ static int ll_xattr_cache_refill(struct inode *inode) GOTO(err_req, rc); /* Do we have the data at this point? */ - if (ll_xattr_cache_valid(lli)) { + if (ll_xattr_cache_filled(lli)) { ll_stats_ops_tally(sbi, LPROC_LL_GETXATTR_HITS, 1); ll_intent_drop_lock(&oit); GOTO(err_req, rc = 0); @@ -427,7 +484,8 @@ static int ll_xattr_cache_refill(struct inode *inode) CDEBUG(D_CACHE, "caching: xdata=%p xtail=%p\n", xdata, xtail); - ll_xattr_cache_init(lli); + if (!ll_xattr_cache_valid(lli)) + ll_xattr_cache_init(lli); for (i = 0; i < body->mbo_max_mdsize; i++) { CDEBUG(D_CACHE, "caching [%s]=%.*s\n", xdata, *xsizes, xval); @@ -464,6 +522,8 @@ static int ll_xattr_cache_refill(struct inode *inode) if (xdata != xtail || xval != xvtail) CERROR("a hole in xattr data\n"); + else + set_bit(LLIF_XATTR_CACHE_FILLED, &lli->lli_flags); ll_set_lock_data(sbi->ll_md_exp, inode, &oit, NULL); ll_intent_drop_lock(&oit); @@ -513,16 +573,27 @@ int ll_xattr_cache_get(struct inode *inode, LASSERT(!!(valid & OBD_MD_FLXATTR) ^ !!(valid & OBD_MD_FLXATTRLS)); down_read(&lli->lli_xattrs_list_rwsem); - if (!ll_xattr_cache_valid(lli)) { + /* For performance reasons, we do not want to refill complete xattr + * cache if we are just interested in encryption context. + */ + if ((valid & OBD_MD_FLXATTRLS || + strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) != 0) && + !ll_xattr_cache_filled(lli)) { up_read(&lli->lli_xattrs_list_rwsem); rc = ll_xattr_cache_refill(inode); if (rc) RETURN(rc); + /* Turn the write lock obtained in ll_xattr_cache_refill() + * into a read lock. + */ downgrade_write(&lli->lli_xattrs_list_rwsem); } else { ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR_HITS, 1); } + if (!ll_xattr_cache_valid(lli)) + GOTO(out, rc = -ENODATA); + if (valid & OBD_MD_FLXATTR) { struct ll_xattr_entry *xattr; @@ -570,18 +641,10 @@ int ll_xattr_cache_insert(struct inode *inode, ENTRY; - down_read(&lli->lli_xattrs_list_rwsem); + down_write(&lli->lli_xattrs_list_rwsem); if (!ll_xattr_cache_valid(lli)) ll_xattr_cache_init(lli); - rc = ll_xattr_cache_add(&lli->lli_xattrs, name, buffer, - size); - up_read(&lli->lli_xattrs_list_rwsem); - - if (rc == -EPROTO && - strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) - /* it means enc ctx was already in cache, - * ignore error as it cannot be modified - */ - rc = 0; + rc = ll_xattr_cache_add(&lli->lli_xattrs, name, buffer, size); + up_write(&lli->lli_xattrs_list_rwsem); RETURN(rc); }