Subject: [PATCH 1 of 6] PCI Hotplug core update
From: Greg KH <[email-masked]>
To: [email-masked]
Cc: [email-masked]

Hi,

Here's a patch against 2.4.19-pre1 for the PCI Hotplug core that cleans
up the filesystem a lot, and adds support for the timestamp of the
device attributes to be updated properly when the information has
changed.

thanks,

greg k-h

diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
--- a/drivers/hotplug/pci_hotplug_core.c	Tue Feb 26 13:19:27 2002
+++ b/drivers/hotplug/pci_hotplug_core.c	Tue Feb 26 13:19:27 2002
@@ -1,8 +1,8 @@
 /*
  * PCI HotPlug Controller Core
  *
- * Copyright (c) 2001 Greg Kroah-Hartman ([email-masked])
- * Copyright (c) 2001 IBM Corp.
+ * Copyright (c) 2001-2002 Greg Kroah-Hartman ([email-masked])
+ * Copyright (c) 2001-2002 IBM Corp.
  *
  * All rights reserved.
  *
@@ -23,6 +23,8 @@
  *
  * Send feedback to <[email-masked]>
  *
+ * Filesystem portion based on work done by Pat Mochel on ddfs/driverfs
+ *
  */
 
 #include <linux/config.h>
@@ -54,7 +56,7 @@
 /* local variables */
 static int debug;
 
-#define DRIVER_VERSION	"0.3"
+#define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Greg Kroah-Hartman <[email-masked]>"
 #define DRIVER_DESC	"PCI Hot Plug PCI Core"
 
@@ -74,7 +76,6 @@
 };
 
 static struct super_operations pcihpfs_ops;
-static struct address_space_operations pcihpfs_aops;
 static struct file_operations pcihpfs_dir_operations;
 static struct file_operations default_file_operations;
 static struct inode_operations pcihpfs_dir_inode_operations;
@@ -111,7 +112,6 @@
 		inode->i_blksize = PAGE_CACHE_SIZE;
 		inode->i_blocks = 0;
 		inode->i_rdev = NODEV;
-		inode->i_mapping->a_ops = &pcihpfs_aops;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		switch (mode & S_IFMT) {
 		default:
@@ -152,21 +152,6 @@
  	return pcihpfs_mknod (dir, dentry, mode | S_IFREG, 0);
 }
 
-static int pcihpfs_link (struct dentry *old_dentry, struct inode *dir,
-			 struct dentry *dentry)
-{
-	struct inode *inode = old_dentry->d_inode;
-
-	if(S_ISDIR(inode->i_mode))
-		return -EPERM;
-
-	inode->i_nlink++;
-	atomic_inc(&inode->i_count);
- 	dget(dentry);
-	d_instantiate(dentry, inode);
-	return 0;
-}
-
 static inline int pcihpfs_positive (struct dentry *dentry)
 {
 	return dentry->d_inode && !d_unhashed(dentry);
@@ -204,22 +189,6 @@
 	return error;
 }
 
-static int pcihpfs_rename (struct inode *old_dir, struct dentry *old_dentry,
-			   struct inode *new_dir, struct dentry *new_dentry)
-{
-	int error = -ENOTEMPTY;
-
-	if (pcihpfs_empty(new_dentry)) {
-		struct inode *inode = new_dentry->d_inode;
-		if (inode) {
-			inode->i_nlink--;
-			dput(new_dentry);
-		}
-		error = 0;
-	}
-	return error;
-}
-
 #define pcihpfs_rmdir pcihpfs_unlink
 
 /* default file operations */
@@ -266,18 +235,9 @@
 	return 0;
 }
 
-static int default_sync_file (struct file *file, struct dentry *dentry, int datasync)
-{
-	return 0;
-}
-
-static struct address_space_operations pcihpfs_aops = {
-};
-
 static struct file_operations pcihpfs_dir_operations = {
 	read:		generic_read_dir,
 	readdir:	dcache_readdir,
-	fsync:		default_sync_file,
 };
 
 static struct file_operations default_file_operations = {
@@ -285,8 +245,6 @@
 	write:		default_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "power" files */
@@ -297,8 +255,6 @@
 	write:		power_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "attention" files */
@@ -309,8 +265,6 @@
 	write:		attention_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "latch" files */
@@ -320,8 +274,6 @@
 	write:		default_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "presence" files */
@@ -331,8 +283,6 @@
 	write:		default_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 /* file ops for the "test" files */
@@ -342,19 +292,15 @@
 	write:		test_write_file,
 	open:		default_open,
 	llseek:		default_file_lseek,
-	fsync:		default_sync_file,
-	mmap:		generic_file_mmap,
 };
 
 static struct inode_operations pcihpfs_dir_inode_operations = {
 	create:		pcihpfs_create,
 	lookup:		pcihpfs_lookup,
-	link:		pcihpfs_link,
 	unlink:		pcihpfs_unlink,
 	mkdir:		pcihpfs_mkdir,
 	rmdir:		pcihpfs_rmdir,
 	mknod:		pcihpfs_mknod,
-	rename:		pcihpfs_rename,
 };
 
 static struct super_operations pcihpfs_ops = {
@@ -475,7 +421,7 @@
 
 	if (!parent) {
 		dbg("Ah! can not find a parent!\n");
-		return -EFAULT;
+		return -EINVAL;
 	}
 
 	*dentry = NULL;
@@ -676,7 +622,7 @@
 
 		default:
 			err ("Illegal value specified for power\n");
-			retval = -EFAULT;
+			retval = -EINVAL;
 	}
 
 exit:	
@@ -1009,7 +955,7 @@
 	if (slot == NULL)
 		return -ENODEV;
 	if ((slot->info == NULL) || (slot->ops == NULL))
-		return -EFAULT;
+		return -EINVAL;
 
 	core = kmalloc (sizeof (struct hotplug_slot_core), GFP_KERNEL);
 	if (!core)
@@ -1020,7 +966,7 @@
 	if (get_slot_from_name (slot->name) != NULL) {
 		spin_unlock (&list_lock);
 		kfree (core);
-		return -EFAULT;
+		return -EINVAL;
 	}
 
 	slot->core_priv = core;
@@ -1066,6 +1012,12 @@
 	return 0;
 }
 
+static inline void update_inode_time (struct inode *inode)
+{
+	if (inode)
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+
 /**
  * pci_hp_change_slot_info - changes the slot's information structure in the core
  * @name: the name of the slot whose info has changed
@@ -1079,6 +1031,7 @@
 int pci_hp_change_slot_info (const char *name, struct hotplug_slot_info *info)
 {
 	struct hotplug_slot *temp;
+	struct hotplug_slot_core *core;
 
 	if (info == NULL)
 		return -ENODEV;
@@ -1089,6 +1042,24 @@
 		spin_unlock (&list_lock);
 		return -ENODEV;
 	}
+
+	/*
+	 * check all fields in the info structure, and update timestamps
+	 * for the files referring to the fields that have now changed.
+	 */
+	core = temp->core_priv;
+	if ((core->power_dentry) &&
+	    (temp->info->power_status != info->power_status))
+		update_inode_time (core->power_dentry->d_inode);
+	if ((core->attention_dentry) &&
+	    (temp->info->attention_status != info->attention_status))
+		update_inode_time (core->attention_dentry->d_inode);
+	if ((core->latch_dentry) &&
+	    (temp->info->latch_status != info->latch_status))
+		update_inode_time (core->latch_dentry->d_inode);
+	if ((core->adapter_dentry) &&
+	    (temp->info->adapter_status != info->adapter_status))
+		update_inode_time (core->adapter_dentry->d_inode);
 
 	memcpy (temp->info, info, sizeof (struct hotplug_slot_info));
 	spin_unlock (&list_lock);