#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/iversion.h>
#include <linux/fs.h>
#include <linux/namei.h>
#ifndef COMPAT_DETECT_LOOKUP_ONE_LEN_6_16
#include <linux/mnt_idmapping.h>
#endif
#include <linux/dcache.h>

#ifndef COMPAT_DETECT_INODE_UPDATE_TIMESTAMPS_6_6

int inode_update_timestamps(struct inode *inode, int flags)
{
	int updated = 0;
	struct timespec64 now;

	if (flags & (S_MTIME|S_CTIME|S_VERSION)) {
		struct timespec64 ctime = inode_get_ctime(inode);
		struct timespec64 mtime = inode_get_mtime(inode);

		now = inode_set_ctime_current(inode);
		if (!timespec64_equal(&now, &ctime))
			updated |= S_CTIME;
		if (!timespec64_equal(&now, &mtime)) {
			inode_set_mtime_to_ts(inode, now);
			updated |= S_MTIME;
		}
		if (IS_I_VERSION(inode) && inode_maybe_inc_iversion(inode, updated))
			updated |= S_VERSION;
	} else {
		now = current_time(inode);
	}

	if (flags & S_ATIME) {
		struct timespec64 atime = inode_get_atime(inode);

		if (!timespec64_equal(&now, &atime)) {
			inode_set_atime_to_ts(inode, now);
			updated |= S_ATIME;
		}
	}
	return updated;
}
EXPORT_SYMBOL(inode_update_timestamps);

#endif /* COMPAT_DETECT_INODE_UPDATE_TIMESTAMPS_6_6 */

#ifndef COMPAT_DETECT_LOOKUP_ONE_LEN_6_16
struct dentry *lookup_one_len_unlocked(const char *name,
				       struct dentry *base,
				       int len)
{
	struct qstr this = QSTR_INIT(name, len);
	return lookup_one_unlocked(&nop_mnt_idmap, &this, base);
}
EXPORT_SYMBOL_GPL(lookup_one_len_unlocked);

struct dentry *lookup_one_len(const char *name,
			     struct dentry *base, int len)
{
	struct qstr this = QSTR_INIT(name, len);
	return lookup_one(&nop_mnt_idmap, &this, base);
}
EXPORT_SYMBOL_GPL(lookup_one_len);

struct dentry *lookup_positive_unlocked(const char *name,
					struct dentry *base,
					int len)
{
	struct qstr this = QSTR_INIT(name, len);
	return lookup_one_positive_unlocked(&nop_mnt_idmap, &this, base);
}
EXPORT_SYMBOL_GPL(lookup_positive_unlocked);
#endif /* COMPAT_DETECT_LOOKUP_ONE_LEN_6_16 */

#ifndef COMPAT_DETECT_D_HASH_AND_LOOKUP_6_16
struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
{
	return try_lookup_noperm(name, dir);
}
EXPORT_SYMBOL_GPL(d_hash_and_lookup);
#endif /* COMPAT_DETECT_D_HASH_AND_LOOKUP_6_16 */
