summaryrefslogtreecommitdiff
path: root/fs/pidfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/pidfs.c')
-rw-r--r--fs/pidfs.c101
1 files changed, 47 insertions, 54 deletions
diff --git a/fs/pidfs.c b/fs/pidfs.c
index 8fd71a00be9c..a63d5d24aa02 100644
--- a/fs/pidfs.c
+++ b/fs/pidfs.c
@@ -16,17 +16,6 @@
#include "internal.h"
-static int pidfd_release(struct inode *inode, struct file *file)
-{
-#ifndef CONFIG_FS_PID
- struct pid *pid = file->private_data;
-
- file->private_data = NULL;
- put_pid(pid);
-#endif
- return 0;
-}
-
#ifdef CONFIG_PROC_FS
/**
* pidfd_show_fdinfo - print information about a pidfd
@@ -120,7 +109,6 @@ static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts)
}
static const struct file_operations pidfs_file_operations = {
- .release = pidfd_release,
.poll = pidfd_poll,
#ifdef CONFIG_PROC_FS
.show_fdinfo = pidfd_show_fdinfo,
@@ -131,16 +119,45 @@ struct pid *pidfd_pid(const struct file *file)
{
if (file->f_op != &pidfs_file_operations)
return ERR_PTR(-EBADF);
-#ifdef CONFIG_FS_PID
return file_inode(file)->i_private;
-#else
- return file->private_data;
-#endif
}
-#ifdef CONFIG_FS_PID
static struct vfsmount *pidfs_mnt __ro_after_init;
+#if BITS_PER_LONG == 32
+/*
+ * Provide a fallback mechanism for 32-bit systems so processes remain
+ * reliably comparable by inode number even on those systems.
+ */
+static DEFINE_IDA(pidfd_inum_ida);
+
+static int pidfs_inum(struct pid *pid, unsigned long *ino)
+{
+ int ret;
+
+ ret = ida_alloc_range(&pidfd_inum_ida, RESERVED_PIDS + 1,
+ UINT_MAX, GFP_ATOMIC);
+ if (ret < 0)
+ return -ENOSPC;
+
+ *ino = ret;
+ return 0;
+}
+
+static inline void pidfs_free_inum(unsigned long ino)
+{
+ if (ino > 0)
+ ida_free(&pidfd_inum_ida, ino);
+}
+#else
+static inline int pidfs_inum(struct pid *pid, unsigned long *ino)
+{
+ *ino = pid->ino;
+ return 0;
+}
+#define pidfs_free_inum(ino) ((void)(ino))
+#endif
+
/*
* The vfs falls back to simple_setattr() if i_op->setattr() isn't
* implemented. Let's reject it completely until we have a clean
@@ -173,6 +190,7 @@ static void pidfs_evict_inode(struct inode *inode)
clear_inode(inode);
put_pid(pid);
+ pidfs_free_inum(inode->i_ino);
}
static const struct super_operations pidfs_sops = {
@@ -183,8 +201,10 @@ static const struct super_operations pidfs_sops = {
static char *pidfs_dname(struct dentry *dentry, char *buffer, int buflen)
{
- return dynamic_dname(buffer, buflen, "pidfd:[%lu]",
- d_inode(dentry)->i_ino);
+ struct inode *inode = d_inode(dentry);
+ struct pid *pid = inode->i_private;
+
+ return dynamic_dname(buffer, buflen, "pidfd:[%llu]", pid->ino);
}
static const struct dentry_operations pidfs_dentry_operations = {
@@ -193,13 +213,19 @@ static const struct dentry_operations pidfs_dentry_operations = {
.d_prune = stashed_dentry_prune,
};
-static void pidfs_init_inode(struct inode *inode, void *data)
+static int pidfs_init_inode(struct inode *inode, void *data)
{
inode->i_private = data;
inode->i_flags |= S_PRIVATE;
inode->i_mode |= S_IRWXU;
inode->i_op = &pidfs_inode_operations;
inode->i_fop = &pidfs_file_operations;
+ /*
+ * Inode numbering for pidfs start at RESERVED_PIDS + 1. This
+ * avoids collisions with the root inode which is 1 for pseudo
+ * filesystems.
+ */
+ return pidfs_inum(data, &inode->i_ino);
}
static void pidfs_put_data(void *data)
@@ -240,13 +266,7 @@ struct file *pidfs_alloc_file(struct pid *pid, unsigned int flags)
struct path path;
int ret;
- /*
- * Inode numbering for pidfs start at RESERVED_PIDS + 1.
- * This avoids collisions with the root inode which is 1
- * for pseudo filesystems.
- */
- ret = path_from_stashed(&pid->stashed, pid->ino, pidfs_mnt,
- get_pid(pid), &path);
+ ret = path_from_stashed(&pid->stashed, pidfs_mnt, get_pid(pid), &path);
if (ret < 0)
return ERR_PTR(ret);
@@ -261,30 +281,3 @@ void __init pidfs_init(void)
if (IS_ERR(pidfs_mnt))
panic("Failed to mount pidfs pseudo filesystem");
}
-
-bool is_pidfs_sb(const struct super_block *sb)
-{
- return sb == pidfs_mnt->mnt_sb;
-}
-
-#else /* !CONFIG_FS_PID */
-
-struct file *pidfs_alloc_file(struct pid *pid, unsigned int flags)
-{
- struct file *pidfd_file;
-
- pidfd_file = anon_inode_getfile("[pidfd]", &pidfs_file_operations, pid,
- flags | O_RDWR);
- if (IS_ERR(pidfd_file))
- return pidfd_file;
-
- get_pid(pid);
- return pidfd_file;
-}
-
-void __init pidfs_init(void) { }
-bool is_pidfs_sb(const struct super_block *sb)
-{
- return false;
-}
-#endif