[PATCH] Add autofs_v6_packet with same packet size on x86 and x86_64.

Thomas Meyer thomas at m3y3r.de
Sun Nov 13 04:13:57 PST 2011


autofs_v5_packet is 300 bytes on x86 and 304 bytes on x86_64.
This leads to an error in at least systemd when running a x86_64 kernel
on an x86 userspace. Fix this by adding a new protocol version 6 packet
that has the same size on x86 and x86_64.

Signed-off-by: Thomas Meyer <thomas at m3y3r.de>
---
 fs/autofs4/inode.c       |   30 ++++++++++++++++++++++------
 fs/autofs4/waitq.c       |   47 +++++++++++++++++++++++++++++++--------------
 include/linux/auto_fs4.h |   19 ++++++++++++++++-
 3 files changed, 72 insertions(+), 24 deletions(-)

diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 8179f1a..10a57fc 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -197,6 +197,28 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
 	return (*pipefd < 0);
 }
 
+static bool check_protocol_version(int minproto, int maxproto)
+{
+	bool rc = true;
+
+	if (minproto > maxproto || maxproto < minproto) {
+		printk("autofs: protocol min(%d)/max(%d) version error!",
+			minproto, maxproto);
+		rc = false;
+	}
+
+	if (maxproto < AUTOFS_MIN_PROTO_VERSION ||
+	    minproto > AUTOFS_MAX_PROTO_VERSION) {
+		printk("autofs: kernel does not match daemon version "
+		       "daemon (%d, %d) kernel (%d, %d)\n",
+			minproto, maxproto,
+			AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
+		rc = false;
+	}
+
+	return rc;
+}
+
 int autofs4_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct inode * root_inode;
@@ -269,14 +291,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
 	root_inode->i_op = &autofs4_dir_inode_operations;
 
 	/* Couldn't this be tested earlier? */
-	if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION ||
-	    sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) {
-		printk("autofs: kernel does not match daemon version "
-		       "daemon (%d, %d) kernel (%d, %d)\n",
-			sbi->min_proto, sbi->max_proto,
-			AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
+	if(check_protocol_version(sbi->min_proto, sbi->max_proto) == false)
 		goto fail_dput;
-	}
 
 	/* Establish highest kernel protocol version */
 	if (sbi->max_proto > AUTOFS_MAX_PROTO_VERSION)
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index e1fbdee..2e455be 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -99,6 +99,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
 		struct autofs_packet_hdr hdr;
 		union autofs_packet_union v4_pkt;
 		union autofs_v5_packet_union v5_pkt;
+		struct autofs_v6_packet v6_pkt;
 	} pkt;
 	struct file *pipe = NULL;
 	size_t pktsz;
@@ -137,7 +138,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
 		break;
 	}
 	/*
-	 * Kernel protocol v5 packet for handling indirect and direct
+	 * Kernel protocol v5/v6 packet for handling indirect and direct
 	 * mount missing and expire requests
 	 */
 	case autofs_ptype_missing_indirect:
@@ -145,20 +146,36 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
 	case autofs_ptype_missing_direct:
 	case autofs_ptype_expire_direct:
 	{
-		struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet;
-
-		pktsz = sizeof(*packet);
-
-		packet->wait_queue_token = wq->wait_queue_token;
-		packet->len = wq->name.len;
-		memcpy(packet->name, wq->name.name, wq->name.len);
-		packet->name[wq->name.len] = '\0';
-		packet->dev = wq->dev;
-		packet->ino = wq->ino;
-		packet->uid = wq->uid;
-		packet->gid = wq->gid;
-		packet->pid = wq->pid;
-		packet->tgid = wq->tgid;
+		if(sbi->version == 5) {
+			struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet;
+	
+			packet->wait_queue_token = wq->wait_queue_token;
+			packet->len = wq->name.len;
+			memcpy(packet->name, wq->name.name, wq->name.len);
+			packet->name[wq->name.len] = '\0';
+			packet->dev = wq->dev;
+			packet->ino = wq->ino;
+			packet->uid = wq->uid;
+			packet->gid = wq->gid;
+			packet->pid = wq->pid;
+			packet->tgid = wq->tgid;
+			pktsz = sizeof(packet);
+		}
+		if(sbi->version == 6) {
+			struct autofs_v6_packet *packet = &pkt.v6_pkt;
+	
+			packet->wait_queue_token = wq->wait_queue_token;
+			packet->len = wq->name.len;
+			memcpy(packet->name, wq->name.name, wq->name.len);
+			packet->name[wq->name.len] = '\0';
+			packet->dev = wq->dev;
+			packet->ino = wq->ino;
+			packet->uid = wq->uid;
+			packet->gid = wq->gid;
+			packet->pid = wq->pid;
+			packet->tgid = wq->tgid;
+			pktsz = sizeof(packet);
+		}
 		break;
 	}
 	default:
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h
index e02982f..e16b105 100644
--- a/include/linux/auto_fs4.h
+++ b/include/linux/auto_fs4.h
@@ -20,9 +20,9 @@
 #undef AUTOFS_MIN_PROTO_VERSION
 #undef AUTOFS_MAX_PROTO_VERSION
 
-#define AUTOFS_PROTO_VERSION		5
+#define AUTOFS_PROTO_VERSION		6
 #define AUTOFS_MIN_PROTO_VERSION	3
-#define AUTOFS_MAX_PROTO_VERSION	5
+#define AUTOFS_MAX_PROTO_VERSION	6
 
 #define AUTOFS_PROTO_SUBVERSION		2
 
@@ -154,6 +154,21 @@ union autofs_v5_packet_union {
 	autofs_packet_expire_direct_t expire_direct;
 };
 
+/* autofs v6 common packet struct */
+/* packed structure for same packet size on x86 and x86_64 */
+struct autofs_v6_packet {
+	struct autofs_packet_hdr hdr;
+	autofs_wqt_t wait_queue_token;
+	__u32 dev;
+	__u64 ino;
+	__u32 uid;
+	__u32 gid;
+	__u32 pid;
+	__u32 tgid;
+	__u32 len;
+	char name[NAME_MAX+1];
+} __attribute__ ((packed));
+
 #define AUTOFS_IOC_EXPIRE_MULTI		_IOW(0x93,0x66,int)
 #define AUTOFS_IOC_EXPIRE_INDIRECT	AUTOFS_IOC_EXPIRE_MULTI
 #define AUTOFS_IOC_EXPIRE_DIRECT	AUTOFS_IOC_EXPIRE_MULTI
-- 
1.7.7.1





More information about the systemd-devel mailing list