]) # LC_LOCK_PAGE_MEMCG
#
+# LC_D_INIT
+#
+# Kernel version 4.7-rc5 commit 285b102d3b745f3c2c110c9c327741d87e64aacc
+# add new d_init to initialize dentry at allocation time
+#
+AC_DEFUN([LC_D_INIT], [
+LB_CHECK_COMPILE([if dentry operations supports 'd_init'],
+d_init, [
+ #include <linux/dcache.h>
+],[
+ struct dentry_operations ops = { };
+ int rc;
+
+ rc = ops.d_init(NULL);
+],[
+ AC_DEFINE(HAVE_D_INIT, 1, ['d_init' exists])
+])
+]) # LC_D_INIT
+
+#
# LC_DIRECTIO_2ARGS
#
# Kernel version 4.7 commit c8b8e32d700fe943a935e435ae251364d016c497
# 4.7
LC_D_IN_LOOKUP
+ LC_D_INIT
LC_DIRECTIO_2ARGS
LC_GENERIC_WRITE_SYNC_2ARGS
LC_FOP_ITERATE_SHARED
RETURN(0);
}
-int ll_d_init(struct dentry *de)
+#ifdef HAVE_D_INIT
+static int ll_d_init(struct dentry *de)
{
- ENTRY;
- LASSERT(de != NULL);
+ struct ll_dentry_data *lld;
- CDEBUG(D_DENTRY, "ldd on dentry %pd (%p) parent %p inode %p refc %d\n",
- de, de, de->d_parent, de->d_inode,
- ll_d_count(de));
-
- if (de->d_fsdata == NULL) {
- struct ll_dentry_data *lld;
-
- OBD_ALLOC_PTR(lld);
- if (likely(lld != NULL)) {
- spin_lock(&de->d_lock);
- if (likely(de->d_fsdata == NULL)) {
- de->d_fsdata = lld;
- __d_lustre_invalidate(de);
- } else {
- OBD_FREE_PTR(lld);
- }
- spin_unlock(&de->d_lock);
- } else {
- RETURN(-ENOMEM);
+ OBD_ALLOC_PTR(lld);
+ lld->lld_invalid = 1;
+ de->d_fsdata = lld;
+ return 0;
+}
+#else /* !HAVE_D_INIT */
+
+bool ll_d_setup(struct dentry *de, bool do_put)
+{
+ struct ll_dentry_data *lld;
+ bool success = true;
+
+ if (de->d_fsdata)
+ return success;
+
+ OBD_ALLOC_PTR(lld);
+ if (likely(lld)) {
+ spin_lock(&de->d_lock);
+ /* Since the first d_fsdata test was not
+ * done under the spinlock it could have
+ * changed by time the memory is allocated.
+ */
+ if (!de->d_fsdata) {
+ lld->lld_invalid = 1;
+ de->d_fsdata = lld;
}
+ spin_unlock(&de->d_lock);
+ /* See if we lost the race to set d_fsdata. */
+ if (de->d_fsdata != lld)
+ OBD_FREE_PTR(lld);
+ } else {
+ success = false;
+ if (do_put)
+ dput(de);
}
- LASSERT(de->d_op == &ll_d_ops);
- RETURN(0);
+ return success;
}
+#endif /* !HAVE_D_INIT */
void ll_intent_drop_lock(struct lookup_intent *it)
{
}
const struct dentry_operations ll_d_ops = {
+#ifdef HAVE_D_INIT
+ .d_init = ll_d_init,
+#endif
.d_revalidate = ll_revalidate_dentry,
- .d_release = ll_release,
- .d_delete = ll_ddelete,
- .d_compare = ll_dcompare,
+ .d_release = ll_release,
+ .d_delete = ll_ddelete,
+ .d_compare = ll_dcompare,
};
/* llite/dcache.c */
-int ll_d_init(struct dentry *de);
extern const struct dentry_operations ll_d_ops;
+#ifndef HAVE_D_INIT
+bool ll_d_setup(struct dentry *de, bool do_put);
+
+static inline bool lld_is_init(struct dentry *dentry)
+{
+ return ll_d2d(dentry);
+}
+#else
+#define ll_d_setup(de, do_put) (true)
+#define lld_is_init(dentry) (true)
+#endif
+
void ll_intent_drop_lock(struct lookup_intent *);
void ll_intent_release(struct lookup_intent *);
void ll_prune_aliases(struct inode *inode);
static inline int d_lustre_invalid(const struct dentry *dentry)
{
- struct ll_dentry_data *lld = ll_d2d(dentry);
-
- return (lld == NULL) || lld->lld_invalid;
-}
-
-static inline void __d_lustre_invalidate(struct dentry *dentry)
-{
- struct ll_dentry_data *lld = ll_d2d(dentry);
-
- if (lld != NULL)
- lld->lld_invalid = 1;
+ return !ll_d2d(dentry) || ll_d2d(dentry)->lld_invalid;
}
/*
dentry->d_parent, dentry->d_inode, ll_d_count(dentry));
spin_lock(&dentry->d_lock);
- __d_lustre_invalidate(dentry);
+ if (lld_is_init(dentry))
+ ll_d2d(dentry)->lld_invalid = 1;
spin_unlock(&dentry->d_lock);
}
static inline void d_lustre_revalidate(struct dentry *dentry)
{
spin_lock(&dentry->d_lock);
- LASSERT(ll_d2d(dentry) != NULL);
+ LASSERT(ll_d2d(dentry));
ll_d2d(dentry)->lld_invalid = 0;
spin_unlock(&dentry->d_lock);
}
/* N.B. d_obtain_alias() drops inode ref on error */
result = d_obtain_alias(inode);
if (!IS_ERR(result)) {
- int rc;
-
- rc = ll_d_init(result);
- if (rc < 0) {
- dput(result);
- result = ERR_PTR(rc);
- } else {
- struct ll_dentry_data *ldd = ll_d2d(result);
-
- /*
- * Need to signal to the ll_file_open that
- * we came from NFS and so opencache needs to be
- * enabled for this one
- */
- spin_lock(&result->d_lock);
- ldd->lld_nfs_dentry = 1;
- spin_unlock(&result->d_lock);
- }
+ struct ll_dentry_data *ldd;
+
+ if (!ll_d_setup(result, true))
+ RETURN(ERR_PTR(-ENOMEM));
+ ldd = ll_d2d(result);
+ /*
+ * Need to signal to the ll_file_open that
+ * we came from NFS and so opencache needs to be
+ * enabled for this one
+ */
+ spin_lock(&result->d_lock);
+ ldd->lld_nfs_dentry = 1;
+ spin_unlock(&result->d_lock);
}
RETURN(result);
continue;
spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
- __d_lustre_invalidate(child);
+ if (lld_is_init(child))
+ ll_d2d(child)->lld_invalid = 1;
if (!ll_d_count(child)) {
dget_dlock(child);
__d_drop(child);
struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
{
struct dentry *new;
- int rc;
if (inode) {
new = ll_find_alias(inode, de);
if (new) {
- rc = ll_d_init(new);
- if (rc < 0) {
- dput(new);
- return ERR_PTR(rc);
- }
+ if (!ll_d_setup(new, true))
+ return ERR_PTR(-ENOMEM);
d_move(new, de);
iput(inode);
CDEBUG(D_DENTRY,
return new;
}
}
- rc = ll_d_init(de);
- if (rc < 0)
- return ERR_PTR(rc);
+ if (!ll_d_setup(de, false))
+ return ERR_PTR(-ENOMEM);
d_add(de, inode);
/* this needs only to be done for foreign symlink dirs as
bool unplug)
{
struct sa_entry *entry = NULL;
- struct ll_dentry_data *ldd;
struct ll_inode_info *lli = ll_i2info(dir);
int rc = 0;
* stat this file again, we know we've done statahead before, see
* dentry_may_statahead().
*/
- ldd = ll_d2d(*dentryp);
- /* ldd can be NULL if llite lookup failed. */
- if (ldd)
- ldd->lld_sa_generation = lli->lli_sa_generation;
+ if (lld_is_init(*dentryp))
+ ll_d2d(*dentryp)->lld_sa_generation = lli->lli_sa_generation;
sa_put(sai, entry);
spin_lock(&lli->lli_sa_lock);
if (sai->sai_task)