patch-2.3.99-pre9 linux/fs/proc/base.c

Next file: linux/fs/proc/generic.c
Previous file: linux/fs/pipe.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre8/linux/fs/proc/base.c linux/fs/proc/base.c
@@ -22,6 +22,7 @@
 #include <linux/stat.h>
 #include <linux/init.h>
 #include <linux/file.h>
+#include <linux/string.h>
 
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -651,6 +652,11 @@
 	return 0;
 }
 
+/*
+ *	Exceptional case: normally we are not allowed to unhash a busy
+ * directory. In this case, however, we can do it - no aliasing problems
+ * due to the way we treat inodes.
+ */
 static int pid_base_revalidate(struct dentry * dentry, int flags)
 {
 	if (dentry->d_inode->u.proc_i.task->p_pptr)
@@ -659,9 +665,9 @@
 	return 0;
 }
 
-static void pid_delete_dentry(struct dentry * dentry)
+static int pid_delete_dentry(struct dentry * dentry)
 {
-	d_drop(dentry);
+	return 1;
 }
 
 static struct dentry_operations pid_fd_dentry_operations =
@@ -861,6 +867,28 @@
 	lookup:		proc_base_lookup,
 };
 
+/*
+ * /proc/self:
+ */
+static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+	char tmp[30];
+	sprintf(tmp, "%d", current->pid);
+	return vfs_readlink(dentry,buffer,buflen,tmp);
+}
+
+static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	char tmp[30];
+	sprintf(tmp, "%d", current->pid);
+	return vfs_follow_link(nd,tmp);
+}	
+
+static struct inode_operations proc_self_inode_operations = {
+	readlink:	proc_self_readlink,
+	follow_link:	proc_self_follow_link,
+};
+
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
 {
 	unsigned int pid, c;
@@ -872,6 +900,23 @@
 	pid = 0;
 	name = dentry->d_name.name;
 	len = dentry->d_name.len;
+	if (len == 4 && !memcmp(name, "self", 4)) {
+		inode = get_empty_inode();
+		if (!inode)
+			return ERR_PTR(-ENOMEM);
+		inode->i_sb = dir->i_sb;
+		inode->i_dev = dir->i_sb->s_dev;
+		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+		inode->i_ino = fake_ino(0, PROC_PID_INO);
+		inode->u.proc_i.file = NULL;
+		inode->u.proc_i.task = NULL;
+		inode->i_mode = S_IFLNK|S_IRWXUGO;
+		inode->i_uid = inode->i_gid = 0;
+		inode->i_size = 64;
+		inode->i_op = &proc_self_inode_operations;
+		d_add(dentry, inode);
+		return NULL;
+	}
 	while (len-- > 0) {
 		c = *name - '0';
 		name++;
@@ -916,7 +961,8 @@
 {
 	if (inode->u.proc_i.file)
 		fput(inode->u.proc_i.file);
-	free_task_struct(inode->u.proc_i.task);
+	if (inode->u.proc_i.task)
+		free_task_struct(inode->u.proc_i.task);
 }
 
 #define PROC_NUMBUF 10
@@ -932,7 +978,7 @@
 	struct task_struct *p;
 	int nr_pids = 0;
 
-	index -= FIRST_PROCESS_ENTRY;
+	index--;
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		int pid = p->pid;
@@ -953,9 +999,17 @@
 {
 	unsigned int pid_array[PROC_MAXPIDS];
 	char buf[PROC_NUMBUF];
-	unsigned int nr = filp->f_pos;
+	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
 	unsigned int nr_pids, i;
 
+	if (!nr) {
+		ino_t ino = fake_ino(0,PROC_PID_INO);
+		if (filldir(dirent, "self", 4, filp->f_pos, ino) < 0)
+			return 0;
+		filp->f_pos++;
+		nr++;
+	}
+
 	nr_pids = get_pid_list(nr, pid_array);
 
 	for (i = 0; i < nr_pids; i++) {
@@ -963,11 +1017,7 @@
 		ino_t ino = fake_ino(pid,PROC_PID_INO);
 		unsigned long j = PROC_NUMBUF;
 
-		do {
-			j--;
-			buf[j] = '0' + (pid % 10);
-			pid /= 10;
-		} while (pid);
+		do buf[--j] = '0' + (pid % 10); while (pid/=10);
 
 		if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0)
 			break;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)