Viewing: fs.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This file is part of Lustre, http://www.lustre.org/
*
* Basic library routines.
*/
#ifndef __LIBCFS_LINUX_CFS_FS_H__
#define __LIBCFS_LINUX_CFS_FS_H__
#include <linux/fs.h>
#include <linux/dcache.h>
#include <lustre_compat/linux/time64.h>
#ifndef HAVE_D_MAKE_PERSISTENT
/*
* Linux commit v6.18-rc5-9-gbacdf1d70bbe2 introduced d_make_persistent() and
* d_make_discardable() so that filesystems can mark dentries as pinned without
* leaking unbalanced dget()s. On older kernels we fall back to the equivalent
* open-coded sequence: d_instantiate() (or d_add() for unhashed dentries) plus
* an extra dget() to pin, and a matching dput() to unpin. Older kernels still
* have kill_litter_super() available, which uses d_genocide() to drop these
* extra references at unmount.
*/
static inline struct dentry *d_make_persistent(struct dentry *dentry,
struct inode *inode)
{
if (d_unhashed(dentry))
d_add(dentry, inode);
else
d_instantiate(dentry, inode);
dget(dentry);
return dentry;
}
static inline void d_make_discardable(struct dentry *dentry)
{
dput(dentry);
}
#endif /* !HAVE_D_MAKE_PERSISTENT */
#ifndef S_DT_SHIFT
#define S_DT_SHIFT 12
#endif
#ifndef S_DT
#define S_DT(type) (((type) & S_IFMT) >> S_DT_SHIFT)
#endif
#ifndef DTTOIF
#define DTTOIF(dirtype) ((dirtype) << S_DT_SHIFT)
#endif
#ifndef SB_I_CGROUPWB
#define SB_I_CGROUPWB 0
#endif
/* Really belongs in mnt_idmapping.h but it doesn't exist for
* older kernels. mnt_idmapping.h is always included with fs.h.
*/
#ifndef HAVE_MNT_IDMAP_ARG
#define mnt_idmap user_namespace
#define nop_mnt_idmap init_user_ns
#endif
#if !defined(HAVE_VFS_CREATE_DELEGATE)
#if !defined(HAVE_USER_NAMESPACE_ARG) && !defined(HAVE_MNT_IDMAP_ARG)
#define vfs_create(ns, de, mode, di) \
vfs_create(d_inode((de)->d_parent), (de), (mode), !!(di))
#else
#define vfs_create(ns, de, mode, di) \
vfs_create((ns), d_inode((de)->d_parent), (de), (mode), !!(di))
#endif
#endif /* HAVE_VFS_CREATE_DELEGATE */
#ifdef HAVE_VFS_MKDIR_DELEGATE
#define VFS_MKDIR_DELEGATE(id, inode, dentry, mode) \
vfs_mkdir((id), (inode), (dentry), (mode), NULL)
#else
#define VFS_MKDIR_DELEGATE(id, inode, dentry, mode) \
vfs_mkdir((id), (inode), (dentry), (mode))
#endif /* HAVE_VFS_MKDIR_DELEGATE */
#ifdef HAVE_IOPS_MKDIR_RETURNS_DENTRY
#define ll_vfs_mkdir(id, inode, dentry, mode) \
VFS_MKDIR_DELEGATE((id), (inode), (dentry), (mode))
#else
#define ll_vfs_mkdir(i, inode, dentry, mode) ({ \
int rc = VFS_MKDIR_DELEGATE((i), (inode), (dentry), (mode)); \
if (rc) { \
dput((dentry)); \
dentry = ERR_PTR(rc); \
} \
(dentry); \
})
#endif /* HAVE_IOPS_MKDIR_RETURNS_DENTRY */
#ifndef ATTR_CTIME_SET /* added in v6.17-rc7-14-gafc5b36e29 */
#define ATTR_CTIME_SET (1 << 28) /* safe for at least v4.18..v6.17 */
#endif
static inline int ll_vfs_getattr(struct path *path, struct kstat *st,
u32 request_mask, unsigned int flags)
{
#ifdef AT_GETATTR_NOSEC /* added in v6.7-rc1-1-g8a924db2d7b5 */
if (flags & AT_GETATTR_NOSEC)
return vfs_getattr_nosec(path, st, request_mask, flags);
#endif /* AT_GETATTR_NOSEC */
return vfs_getattr(path, st, request_mask, flags);
}
#ifndef HAVE_INODE_JUST_DROP
static inline int inode_just_drop(struct inode *inode)
{
return generic_delete_inode(inode);
}
static inline int inode_generic_drop(struct inode *inode)
{
return generic_drop_inode(inode);
}
#endif
#ifndef HAVE_ILOOKUP5_NOWAIT_ISNEW
#define ilookup5_nowait(sb, hash, fn, data, isnew) \
ilookup5_nowait((sb), (hash), (fn), (data))
#endif
#ifndef F_GETLK64
#define F_GETLK64 12 /* using 'struct flock64' */
#define F_SETLK64 13
#define F_SETLKW64 14
#endif
#ifndef HAVE_INODE_GET_CTIME
#define inode_get_ctime(i) ((i)->i_ctime)
#define inode_set_ctime_to_ts(i, ts) ((i)->i_ctime = ts)
#define inode_set_ctime_current(i) \
inode_set_ctime_to_ts((i), current_time((i)))
static inline struct timespec64 inode_set_ctime(struct inode *inode,
time64_t sec, long nsec)
{
struct timespec64 ts = { .tv_sec = sec,
.tv_nsec = nsec };
return inode_set_ctime_to_ts(inode, ts);
}
#endif /* !HAVE_INODE_GET_CTIME */
#ifndef HAVE_INODE_GET_MTIME_SEC
#define inode_get_ctime_sec(i) (inode_get_ctime((i)).tv_sec)
#define inode_get_atime(i) ((i)->i_atime)
#define inode_get_atime_sec(i) ((i)->i_atime.tv_sec)
#define inode_set_atime_to_ts(i, ts) ((i)->i_atime = ts)
static inline struct timespec64 inode_set_atime(struct inode *inode,
time64_t sec, long nsec)
{
struct timespec64 ts = { .tv_sec = sec,
.tv_nsec = nsec };
return inode_set_atime_to_ts(inode, ts);
}
#define inode_get_mtime(i) ((i)->i_mtime)
#define inode_get_mtime_sec(i) ((i)->i_mtime.tv_sec)
#define inode_set_mtime_to_ts(i, ts) ((i)->i_mtime = ts)
static inline struct timespec64 inode_set_mtime(struct inode *inode,
time64_t sec, long nsec)
{
struct timespec64 ts = { .tv_sec = sec,
.tv_nsec = nsec };
return inode_set_mtime_to_ts(inode, ts);
}
#endif /* !HAVE_INODE_GET_MTIME_SEC */
/* Inode timestamp helpers returning nanoseconds since epoch */
static inline s64 inode_get_atime_ns(struct inode *inode)
{
struct timespec64 ts;
ts = inode_get_atime(inode);
return timespec64_to_ns(&ts);
}
static inline s64 inode_get_mtime_ns(struct inode *inode)
{
struct timespec64 ts;
ts = inode_get_mtime(inode);
return timespec64_to_ns(&ts);
}
static inline s64 inode_get_ctime_ns(struct inode *inode)
{
struct timespec64 ts;
ts = inode_get_ctime(inode);
return timespec64_to_ns(&ts);
}
#endif /* __LIBCFS_LINUX_CFS_FS_H__ */