/*
* Copyright 2012 Xyratex Technology Limited
*
+ * Copyright (c) 2013, 2014, Intel Corporation.
+ *
* Author: Andrew Perepechko <Andrew_Perepechko@xyratex.com>
*
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <obd_support.h>
-#include <lustre_lite.h>
#include <lustre_dlm.h>
#include <lustre_ver.h>
#include "llite_internal.h"
LASSERT(lli != NULL);
- CFS_INIT_LIST_HEAD(&lli->lli_xattrs);
- lli->lli_flags |= LLIF_XATTR_CACHE;
+ INIT_LIST_HEAD(&lli->lli_xattrs);
+ ll_file_set_flag(lli, LLIF_XATTR_CACHE);
}
/**
}
/**
- * This adds or updates an xattr.
+ * This adds an xattr.
*
* Add @xattr_name attr with @xattr_val value and @xattr_val_len length,
- * if the attribute already exists, then update its value.
*
* \retval 0 success
* \retval -ENOMEM if no memory could be allocated for the cached attr
+ * \retval -EPROTO if duplicate xattr is being added
*/
static int ll_xattr_cache_add(struct list_head *cache,
const char *xattr_name,
ENTRY;
if (ll_xattr_cache_find(cache, xattr_name, &xattr) == 0) {
- /* Found a cached EA, update it */
-
- if (xattr_val_len != xattr->xe_vallen) {
- char *val;
- OBD_ALLOC(val, xattr_val_len);
- if (val == NULL) {
- CDEBUG(D_CACHE, "failed to allocate %u bytes "
- "for xattr %s update\n",
- xattr_val_len,
- xattr_name);
- RETURN(-ENOMEM);
- }
- OBD_FREE(xattr->xe_value, xattr->xe_vallen);
- xattr->xe_value = val;
- xattr->xe_vallen = xattr_val_len;
- }
- memcpy(xattr->xe_value, xattr_val, xattr_val_len);
-
- CDEBUG(D_CACHE, "update: [%s]=%.*s\n", xattr_name,
- xattr_val_len, xattr_val);
-
- RETURN(0);
+ CDEBUG(D_CACHE, "duplicate xattr: [%s]\n", xattr_name);
+ RETURN(-EPROTO);
}
- OBD_SLAB_ALLOC_PTR_GFP(xattr, xattr_kmem, __GFP_IO);
+ OBD_SLAB_ALLOC_PTR_GFP(xattr, xattr_kmem, GFP_NOFS);
if (xattr == NULL) {
CDEBUG(D_CACHE, "failed to allocate xattr\n");
RETURN(-ENOMEM);
* \retval 0 @cache is not initialized
* \retval 1 @cache is initialized
*/
-int ll_xattr_cache_valid(struct ll_inode_info *lli)
+static int ll_xattr_cache_valid(struct ll_inode_info *lli)
{
- return !!(lli->lli_flags & LLIF_XATTR_CACHE);
+ return ll_file_test_flag(lli, LLIF_XATTR_CACHE);
}
/**
while (ll_xattr_cache_del(&lli->lli_xattrs, NULL) == 0)
/* empty loop */ ;
- lli->lli_flags &= ~LLIF_XATTR_CACHE;
+
+ ll_file_clear_flag(lli, LLIF_XATTR_CACHE);
RETURN(0);
}
}
/**
- * Match or enqueue a PR or PW LDLM lock.
+ * 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,
struct lustre_handle lockh = { 0 };
struct md_op_data *op_data;
struct ll_inode_info *lli = ll_i2info(inode);
- struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS,
- .ei_mode = it_to_lock_mode(oit),
- .ei_cb_bl = ll_md_blocking_ast,
- .ei_cb_cp = ldlm_completion_ast };
+ struct ldlm_enqueue_info einfo = {
+ .ei_type = LDLM_IBITS,
+ .ei_mode = it_to_lock_mode(oit),
+ .ei_cb_bl = &ll_md_blocking_ast,
+ .ei_cb_cp = &ldlm_completion_ast,
+ };
struct ll_sb_info *sbi = ll_i2sbi(inode);
struct obd_export *exp = sbi->ll_md_exp;
int rc;
ENTRY;
mutex_lock(&lli->lli_xattrs_enq_lock);
- /* Try matching first. */
- mode = ll_take_md_lock(inode, MDS_INODELOCK_XATTR, &lockh, 0,
- oit->it_op == IT_SETXATTR ? LCK_PW :
- (LCK_PR | LCK_PW));
- if (mode != 0) {
- /* fake oit in mdc_revalidate_lock() manner */
- oit->d.lustre.it_lock_handle = lockh.cookie;
- oit->d.lustre.it_lock_mode = mode;
- goto out;
+ /* inode may have been shrunk and recreated, so data is gone, match lock
+ * only when data exists. */
+ if (ll_xattr_cache_valid(lli)) {
+ /* Try matching first. */
+ mode = ll_take_md_lock(inode, MDS_INODELOCK_XATTR, &lockh, 0,
+ LCK_PR);
+ if (mode != 0) {
+ /* fake oit in mdc_revalidate_lock() manner */
+ oit->d.lustre.it_lock_handle = lockh.cookie;
+ oit->d.lustre.it_lock_mode = mode;
+ goto out;
+ }
}
/* Enqueue if the lock isn't cached locally. */
RETURN(PTR_ERR(op_data));
}
- op_data->op_valid = OBD_MD_FLXATTR | OBD_MD_FLXATTRLS |
- OBD_MD_FLXATTRLOCKED;
-#ifdef CONFIG_FS_POSIX_ACL
- /* If working with ACLs, we would like to cache local ACLs */
- if (sbi->ll_flags & LL_SBI_RMT_CLIENT)
- op_data->op_valid |= OBD_MD_FLRMTLGETFACL;
-#endif
+ op_data->op_valid = OBD_MD_FLXATTR | OBD_MD_FLXATTRLS;
- rc = md_enqueue(exp, &einfo, oit, op_data, &lockh, NULL, 0, NULL, 0);
+ rc = md_enqueue(exp, &einfo, NULL, oit, op_data, &lockh, 0);
ll_finish_md_op_data(op_data);
if (rc < 0) {
if (oit->d.lustre.it_status < 0) {
CDEBUG(D_CACHE, "getxattr intent returned %d for fid "DFID"\n",
oit->d.lustre.it_status, PFID(ll_inode2fid(inode)));
- GOTO(out_destroy, rc = oit->d.lustre.it_status);
+ rc = oit->d.lustre.it_status;
+ /* xattr data is so large that we don't want to cache it */
+ if (rc == -ERANGE)
+ rc = -EAGAIN;
+ GOTO(out_destroy, rc);
}
body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
}
/* do not need swab xattr data */
xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA,
- body->eadatasize);
+ body->mbo_eadatasize);
xval = req_capsule_server_sized_get(&req->rq_pill, &RMF_EAVALS,
- body->aclsize);
+ body->mbo_aclsize);
xsizes = req_capsule_server_sized_get(&req->rq_pill, &RMF_EAVALS_LENS,
- body->max_mdsize * sizeof(__u32));
+ body->mbo_max_mdsize *
+ sizeof(__u32));
if (xdata == NULL || xval == NULL || xsizes == NULL) {
CERROR("wrong setxattr reply\n");
GOTO(out_destroy, rc = -EPROTO);
}
- xtail = xdata + body->eadatasize;
- xvtail = xval + body->aclsize;
+ xtail = xdata + body->mbo_eadatasize;
+ xvtail = xval + body->mbo_aclsize;
CDEBUG(D_CACHE, "caching: xdata=%p xtail=%p\n", xdata, xtail);
ll_xattr_cache_init(lli);
- for (i = 0; i < body->max_mdsize; i++) {
+ for (i = 0; i < body->mbo_max_mdsize; i++) {
CDEBUG(D_CACHE, "caching [%s]=%.*s\n", xdata, *xsizes, xval);
/* Perform consistency checks: attr names and vals in pill */
if (memchr(xdata, 0, xtail - xdata) == NULL) {
rc = -EPROTO;
} else if (OBD_FAIL_CHECK(OBD_FAIL_LLITE_XATTR_ENOMEM)) {
rc = -ENOMEM;
+ } else if (!strcmp(xdata, XATTR_NAME_ACL_ACCESS)) {
+ /* Filter out ACL ACCESS since it's cached separately */
+ CDEBUG(D_CACHE, "not caching %s\n",
+ XATTR_NAME_ACL_ACCESS);
+ rc = 0;
+ } else if (!strcmp(xdata, "security.selinux")) {
+ /* Filter out security.selinux, it is cached in slab */
+ CDEBUG(D_CACHE, "not caching security.selinux\n");
+ rc = 0;
} else {
rc = ll_xattr_cache_add(&lli->lli_xattrs, xdata, xval,
*xsizes);
GOTO(out_maybe_drop, rc);
out_maybe_drop:
- /* drop lock on error or getxattr */
- if (rc != 0 || oit->it_op != IT_SETXATTR)
- ll_intent_drop_lock(oit);
+
+ ll_intent_drop_lock(oit);
if (rc != 0)
up_write(&lli->lli_xattrs_list_rwsem);
return rc;
}
-
-/**
- * Set/update an xattr value or remove xattr using the write-through cache.
- *
- * Set/update the xattr value (if @valid has OBD_MD_FLXATTR) of @name to @newval
- * or
- * remove the xattr @name (@valid has OBD_MD_FLXATTRRM set) from @inode.
- * @flags is either XATTR_CREATE or XATTR_REPLACE as defined by setxattr(2)
- *
- * \retval 0 no error occured
- * \retval -EPROTO network protocol error
- * \retval -ENOMEM not enough memory for the cache
- * \retval -ERANGE the buffer is not large enough
- * \retval -ENODATA no such attr (in the removal case)
- */
-int ll_xattr_cache_update(struct inode *inode,
- const char *name,
- const char *newval,
- size_t size,
- __u64 valid,
- int flags)
-{
- struct lookup_intent oit = { .it_op = IT_SETXATTR };
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ptlrpc_request *req = NULL;
- struct ll_inode_info *lli = ll_i2info(inode);
- struct obd_capa *oc;
- int rc;
-
- ENTRY;
-
- LASSERT(!!(valid & OBD_MD_FLXATTR) ^ !!(valid & OBD_MD_FLXATTRRM));
-
- rc = ll_xattr_cache_refill(inode, &oit);
- if (rc)
- RETURN(rc);
-
- oc = ll_mdscapa_get(inode);
- rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
- valid | OBD_MD_FLXATTRLOCKED, name, newval,
- size, 0, flags, ll_i2suppgid(inode), &req);
- capa_put(oc);
-
- if (rc) {
- ll_intent_drop_lock(&oit);
- GOTO(out, rc);
- }
-
- if (valid & OBD_MD_FLXATTR)
- rc = ll_xattr_cache_add(&lli->lli_xattrs, name, newval, size);
- else if (valid & OBD_MD_FLXATTRRM)
- rc = ll_xattr_cache_del(&lli->lli_xattrs, name);
-
- ll_intent_drop_lock(&oit);
- GOTO(out, rc);
-out:
- up_write(&lli->lli_xattrs_list_rwsem);
- ptlrpc_req_finished(req);
-
- return rc;
-}