Commit 7dec9e04 authored by Phoebe Buckheister's avatar Phoebe Buckheister 🦎

Merge branch 'v6-kernel-410-411' into 'v6'

V6 kernel 410 411

See merge request !161
parents 301e73ac f46b21d5
......@@ -70,6 +70,8 @@ kernel_version:
- x86_64/linux-4.7
- x86_64/linux-4.8
- x86_64/linux-4.9-rc7
- x86_64/linux-4.10
- x86_64/linux-4.11
- x86_64/linux-3.10.0-514.el7
- x86/linux-2.6.30.3
- x86_64/linux-4.8-debian
......
......@@ -4,13 +4,27 @@ set -e
CFLAGS="-D__KERNEL__ $LINUXINCLUDE $KBUILD_CFLAGS $KBUILD_CPPFLAGS -DKBUILD_BASENAME=\"beegfs\""
_generate_includes() {
for i in "$@"; do
echo "#include <$i>"
done
}
_marker_if_compiles() {
local marker=$1
shift
if $CC $CFLAGS -x c -o /dev/null -c - 2>/dev/null
then
echo -D$marker
fi
}
_check_struct_field_input() {
local field=$1
shift 1
for i in "$@"; do
echo "#include <$i>"
done
_generate_includes "$@"
cat <<EOF
void want_symbol(void) {
......@@ -25,10 +39,39 @@ check_struct_field() {
local marker=$2
shift 2
if _check_struct_field_input "$field" "$@" | $CC $CFLAGS -x c -o /dev/null -c - 2>/dev/null
then
echo -D$marker
fi
_check_struct_field_input "$field" "$@" | _marker_if_compiles "$marker"
}
_check_function_input() {
local name=$1
local signature=$2
shift 2
_generate_includes "$@"
cat <<EOF
void want_fn(void) {
char predicate[
2 * __builtin_types_compatible_p(__typeof($name), $signature) - 1
];
}
EOF
}
check_function() {
local name=$1
local signature=$2
local marker=$3
shift 3
_check_function_input "$name" "$signature" "$@" | _marker_if_compiles "$marker"
}
check_header() {
local header=$1
local marker=$2
shift 2
_generate_includes "$header" | _marker_if_compiles "$marker"
}
cd $srctree
......@@ -38,6 +81,36 @@ check_struct_field \
KERNEL_HAS_LAUNDER_PAGE \
linux/fs.h
check_function \
generic_readlink "int (struct dentry *, char __user *, int)" \
KERNEL_HAS_GENERIC_READLINK \
linux/fs.h
check_header \
linux/sched/signal.h \
KERNEL_HAS_SCHED_SIG_H
# older kernels (RHEL5) don't have linux/cred.h
check_header \
linux/cred.h \
KERNEL_HAS_CRED_H
# cryptohash does not include linux/types.h, so the type comparison fails
check_function \
half_md4_transform "__u32 (__u32[4], __u32 const in[8])" \
KERNEL_HAS_HALF_MD4_TRANSFORM \
linux/types.h linux/cryptohash.h
check_function \
vfs_getattr "int (const struct path *, struct kstat *, u32, unsigned int)" \
KERNEL_HAS_STATX \
linux/fs.h
check_function \
kref_read "unsigned int (const struct kref*)" \
KERNEL_HAS_KREF_READ \
linux/kref.h
# we have to communicate with the calling makefile somehow. since we can't really use the return
# code of this script, we'll echo a special string at the end of our output for the caller to
# detect and remove again.
......
......@@ -464,7 +464,9 @@ bool __App_initInodeOperations(App* this)
this->fileInodeOps->permission = FhgfsOps_permission;
this->fileInodeOps->setattr = FhgfsOps_setattr;
#ifdef KERNEL_HAS_GENERIC_READLINK
this->symlinkInodeOps->readlink = generic_readlink; // default is fine for us currently
#endif
#ifdef KERNEL_HAS_GET_LINK
this->symlinkInodeOps->get_link = FhgfsOps_get_link;
#else
......
......@@ -16,9 +16,16 @@
#include <stdarg.h>
#include <linux/types.h>
#include <linux/stddef.h>
#ifdef KERNEL_HAS_CRED_H
#include <linux/cred.h>
#endif
//#include <linux/compiler.h>
#include <asm/div64.h>
#ifdef KERNEL_HAS_SCHED_SIG_H
#include <linux/sched/signal.h>
#endif
#include <common/FhgfsTypes.h>
#include <os/OsDeps.h>
......
......@@ -110,6 +110,71 @@ uint32_t HashTk_HsiehHash32(const char* data, int len)
return hash;
}
/* half_md4_transform and macros taken from lib/halfmd4.c */
#ifndef KERNEL_HAS_HALF_MD4_TRANSFORM
/* F, G and H are basic MD4 functions: selection, majority, parity */
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/*
* The generic round function. The application is so specific that
* we don't bother protecting all the arguments with parens, as is generally
* good macro practice, in favor of extra legibility.
* Rotation is separate from addition to prevent recomputation
*/
#define ROUND(f, a, b, c, d, x, s) \
(a += f(b, c, d) + x, a = rol32(a, s))
#define K1 0
#define K2 013240474631UL
#define K3 015666365641UL
/*
* Basic cut-down MD4 transform. Returns only 32 bits of result.
*/
static __u32 half_md4_transform(__u32 buf[4], __u32 const in[8])
{
__u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
ROUND(F, a, b, c, d, in[0] + K1, 3);
ROUND(F, d, a, b, c, in[1] + K1, 7);
ROUND(F, c, d, a, b, in[2] + K1, 11);
ROUND(F, b, c, d, a, in[3] + K1, 19);
ROUND(F, a, b, c, d, in[4] + K1, 3);
ROUND(F, d, a, b, c, in[5] + K1, 7);
ROUND(F, c, d, a, b, in[6] + K1, 11);
ROUND(F, b, c, d, a, in[7] + K1, 19);
/* Round 2 */
ROUND(G, a, b, c, d, in[1] + K2, 3);
ROUND(G, d, a, b, c, in[3] + K2, 5);
ROUND(G, c, d, a, b, in[5] + K2, 9);
ROUND(G, b, c, d, a, in[7] + K2, 13);
ROUND(G, a, b, c, d, in[0] + K2, 3);
ROUND(G, d, a, b, c, in[2] + K2, 5);
ROUND(G, c, d, a, b, in[4] + K2, 9);
ROUND(G, b, c, d, a, in[6] + K2, 13);
/* Round 3 */
ROUND(H, a, b, c, d, in[3] + K3, 3);
ROUND(H, d, a, b, c, in[7] + K3, 9);
ROUND(H, c, d, a, b, in[2] + K3, 11);
ROUND(H, b, c, d, a, in[6] + K3, 15);
ROUND(H, a, b, c, d, in[1] + K3, 3);
ROUND(H, d, a, b, c, in[5] + K3, 9);
ROUND(H, c, d, a, b, in[0] + K3, 11);
ROUND(H, b, c, d, a, in[4] + K3, 15);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
return buf[1]; /* "most hashed" word */
}
#endif
/**
* Do the halfMD4 hash computation.
* Note: OutBuf must be an array of size HashTk_HALFMD4_OUT_BUF_SIZE
......
......@@ -79,18 +79,7 @@ int FhgfsOps_revalidateIntent(struct dentry* dentry, unsigned flags)
FhgfsOpsHelper_logOp(Log_SPAM, app, dentry, inode, logContext);
if(!inode || !parentInode || is_bad_inode(inode) )
{
if(inode && S_ISDIR(inode->i_mode) )
{
if(have_submounts(dentry) )
goto cleanup_put_parent;
shrink_dcache_parent(dentry);
}
d_drop(dentry);
goto cleanup_put_parent;
}
// active dentry => remote-stat and local-compare
......@@ -132,8 +121,6 @@ int __FhgfsOps_revalidateIntent(struct dentry* parentDentry, struct dentry* dent
FhgfsInode* fhgfsInode = BEEGFS_INODE(inode);
bool cacheValid = FhgfsInode_isCacheValid(fhgfsInode, inode->i_mode, cfg);
int isValid = 0; // quasi-boolean (return value)
bool needDrop = false;
FhgfsIsizeHints iSizeHints;
......@@ -142,10 +129,7 @@ int __FhgfsOps_revalidateIntent(struct dentry* parentDentry, struct dentry* dent
if (cacheValid)
{
isValid = 1;
return isValid;
}
return 1;
if(IS_ROOT(dentry) )
fhgfsStatPtr = NULL;
......@@ -181,10 +165,7 @@ int __FhgfsOps_revalidateIntent(struct dentry* parentDentry, struct dentry* dent
FhgfsInode_entryInfoReadUnlock(parentFhgfsInode); // UNLOCK parentInfo
if (unlikely(remotingRes != FhgfsOpsErr_SUCCESS) )
{
needDrop = true;
goto out;
}
return 0;
if (outInfo.revalidateRes != FhgfsOpsErr_SUCCESS)
{
......@@ -192,8 +173,7 @@ int __FhgfsOps_revalidateIntent(struct dentry* parentDentry, struct dentry* dent
Logger_logErrFormatted(log, logContext, "Unexpected revalidate info missing: %s",
entryInfo->fileName);
needDrop = true;
goto out;
return 0;
}
// check the stat result here and set fhgfsStatPtr accordingly
......@@ -209,21 +189,11 @@ int __FhgfsOps_revalidateIntent(struct dentry* parentDentry, struct dentry* dent
entryInfo->fileName);
// now its getting difficult as there is an unexpected error
needDrop = true;
goto out;
return 0;
}
}
if (!__FhgfsOps_refreshInode(app, inode, fhgfsStatPtr, &iSizeHints) )
isValid = 1;
else
isValid = 0;
out:
if (needDrop)
d_drop(dentry);
return isValid;
return !__FhgfsOps_refreshInode(app, inode, fhgfsStatPtr, &iSizeHints);
}
/**
......
......@@ -32,13 +32,14 @@ static struct kmem_cache* FhgfsInodeCache = NULL;
static void FhgfsOps_newAttrToInode(struct iattr* iAttr, struct inode* outInode);
static __always_inline int maybeRefreshInode(struct inode* inode, bool whenCacheInvalid,
bool withFileSize)
bool withFileSize, bool force)
{
App* app = FhgfsOps_getApp(inode->i_sb);
Config* cfg = app->cfg;
if(unlikely(!FhgfsOps_getIsRootInited(inode->i_sb) && inode->i_ino == BEEGFS_INODE_ROOT_INO)
|| (!FhgfsInode_isCacheValid(BEEGFS_INODE(inode), inode->i_mode, cfg) && whenCacheInvalid) )
|| (!FhgfsInode_isCacheValid(BEEGFS_INODE(inode), inode->i_mode, cfg) && whenCacheInvalid)
|| unlikely(force))
{
FhgfsIsizeHints iSizeHints;
int refreshRes;
......@@ -101,7 +102,7 @@ struct dentry* FhgfsOps_lookupIntent(struct inode* parentDir, struct dentry* den
(because the kernel doesn't do lookup/revalidate for the root inode) */
{
int refreshRes = maybeRefreshInode(parentDir, true, false);
int refreshRes = maybeRefreshInode(parentDir, true, false, false);
// root permissions might have changed now => recheck permissions
if (!refreshRes)
......@@ -233,8 +234,21 @@ struct dentry* FhgfsOps_lookupIntent(struct inode* parentDir, struct dentry* den
}
#ifdef KERNEL_HAS_STATX
int FhgfsOps_getattr(const struct path* path, struct kstat* kstat, u32 request_mask,
unsigned int query_flags)
{
struct vfsmount* mnt = path->mnt;
struct dentry* dentry = path->dentry;
bool mustQuery = (query_flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC;
#else
int FhgfsOps_getattr(struct vfsmount* mnt, struct dentry* dentry, struct kstat* kstat)
{
const bool mustQuery = false;
#endif
App* app = FhgfsOps_getApp(dentry->d_sb);
Config* cfg = App_getConfig(app);
const char* logContext = "FhgfsOps_getattr";
......@@ -262,7 +276,7 @@ int FhgfsOps_getattr(struct vfsmount* mnt, struct dentry* dentry, struct kstat*
can never be up-to-date, so that would also be quite useless. */
retVal = maybeRefreshInode(inode,
isRoot || FhgfsInode_getIsFileOpen(fhgfsInode) || refreshOnGetAttr, true);
isRoot || FhgfsInode_getIsFileOpen(fhgfsInode) || refreshOnGetAttr, true, mustQuery);
if(!retVal)
{
......@@ -299,7 +313,7 @@ ssize_t FhgfsOps_listxattr(struct dentry* dentry, char* value, size_t size)
FhgfsInode* fhgfsInode = BEEGFS_INODE(dentry->d_inode);
int refreshRes = maybeRefreshInode(dentry->d_inode, true, false);
int refreshRes = maybeRefreshInode(dentry->d_inode, true, false, false);
if (refreshRes)
return refreshRes;
......@@ -344,7 +358,7 @@ ssize_t FhgfsOps_getxattr(struct inode* inode, const char* name, void* value, si
FhgfsOpsErr remotingRes;
ssize_t resSize;
int refreshRes = maybeRefreshInode(inode, true, false);
int refreshRes = maybeRefreshInode(inode, true, false, false);
if (refreshRes)
return refreshRes;
......@@ -386,7 +400,7 @@ int FhgfsOps_removexattrInode(struct inode* inode, const char* name)
FhgfsInode* fhgfsInode = BEEGFS_INODE(inode);
int refreshRes = maybeRefreshInode(inode, true, false);
int refreshRes = maybeRefreshInode(inode, true, false, false);
if (refreshRes)
return refreshRes;
......@@ -420,7 +434,7 @@ int FhgfsOps_setxattr(struct inode* inode, const char* name, const void* value,
FhgfsInode* fhgfsInode = BEEGFS_INODE(inode);
FhgfsOpsErr remotingRes;
int refreshRes = maybeRefreshInode(inode, true, false);
int refreshRes = maybeRefreshInode(inode, true, false, false);
if (refreshRes)
return refreshRes;
......@@ -451,7 +465,7 @@ struct posix_acl* FhgfsOps_get_acl(struct inode* inode, int type)
FhgfsInode* fhgfsInode = BEEGFS_INODE(inode);
const EntryInfo* entryInfo = FhgfsInode_getEntryInfo(fhgfsInode);
int refreshRes = maybeRefreshInode(inode, true, false);
int refreshRes = maybeRefreshInode(inode, true, false, false);
if (refreshRes)
return ERR_PTR(refreshRes);
......@@ -520,7 +534,7 @@ int FhgfsOps_set_acl(struct inode* inode, struct posix_acl* acl, int type)
FhgfsInode* fhgfsInode = BEEGFS_INODE(inode);
const EntryInfo* entryInfo = FhgfsInode_getEntryInfo(fhgfsInode);
int refreshRes = maybeRefreshInode(inode, true, false);
int refreshRes = maybeRefreshInode(inode, true, false, false);
if (refreshRes)
return refreshRes;
......
......@@ -31,7 +31,12 @@ typedef struct FhgfsInodeComparisonInfo FhgfsInodeComparisonInfo;
unsigned flags);
#endif // KERNEL_HAS_ATOMIC_OPEN
#ifdef KERNEL_HAS_STATX
extern int FhgfsOps_getattr(const struct path* path, struct kstat* kstat, u32 request_mask,
unsigned int query_flags);
#else
extern int FhgfsOps_getattr(struct vfsmount* mnt, struct dentry* dentry, struct kstat* kstat);
#endif
extern int FhgfsOps_setattr(struct dentry* dentry, struct iattr* iattr);
extern ssize_t FhgfsOps_listxattr(struct dentry* dentry, char* value, size_t size);
......
......@@ -162,17 +162,21 @@ Node* NodeStoreEx_referenceNode(NodeStoreEx* this, NumNodeID id)
RWLock_readLock(&this->rwLock); // L O C K
node = NodeTree_find(&this->nodeTree, id);
if(likely(node) )
if (likely(node))
{ // found it
Node_get(node);
// check for unusually high reference count
#ifdef BEEGFS_DEBUG
#ifdef BEEGFS_DEBUG
# ifdef KERNEL_HAS_KREF_READ
if (kref_read(&node->references) > NODESTORE_WARN_REFNUM)
# else
if(atomic_read(&node->references.refcount) > NODESTORE_WARN_REFNUM)
#endif
Logger_logFormatted(log, Log_CRITICAL, __func__,
"WARNING: Lots of references to node (=> leak?): %s %s; ref count: %d",
Node_getNodeTypeStr(node), Node_getID(node), node->references);
#endif // BEEGFS_DEBUG
#endif // BEEGFS_DEBUG
}
RWLock_readUnlock(&this->rwLock); // U N L O C K
......
mount0 = node.properties["client0"]["mount"]
mount1 = node.properties["client1"]["mount"]
on node do
cd mount0 do
shell "mkdir a"
shell "sudo mount -t tmpfs 66144c9bbabe13ecd8b5a43dfdee150a44ef6edc a"
end
cd mount1 do
shell "while ! stat a >/dev/null 2>&1; do sleep 0.1; done"
shell "rmdir a"
end
cd mount0 do
# need to stat the directory to cause d_revalidate. unmount will work too.
# stat must fail at some point, because the directory is gone.
shell "while stat a >/dev/null 2>&1; do sleep 0.1; done"
shell "! mount | grep 66144c9bbabe13ecd8b5a43dfdee150a44ef6edc"
end
end
# vim:ft=ruby
desc:
check that mounts are removed properly when their mountpoints are removed by a peer.
hosts:
node: [mgmtd, meta, storage, helperd, client, client]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment