linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alan Cox <alan@lxorguk.ukuu.org.uk>
To: torvalds@linux-foundation.org, linux-kernel@vger.kernel.org
Subject: [PATCH 57/80] tty: kref the tty driver object
Date: Mon, 13 Oct 2008 10:42:09 +0100	[thread overview]
Message-ID: <20081013094206.21645.56045.stgit@localhost.localdomain> (raw)
In-Reply-To: <20081013092758.21645.2359.stgit@localhost.localdomain>

From: Alan Cox <alan@redhat.com>

Signed-off-by: Alan Cox <alan@redhat.com>
---

 drivers/char/ip2/ip2main.c |    6 +-
 drivers/char/pty.c         |    5 ++
 drivers/char/tty_io.c      |  110 ++++++++++++++++++++++++--------------------
 drivers/net/wan/Kconfig    |    2 -
 include/linux/tty_driver.h |   15 ++++--
 5 files changed, 80 insertions(+), 58 deletions(-)


diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 66f52a2..6774572 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -264,8 +264,8 @@ static int tracewrap;
 /**********/
 
 #if defined(MODULE) && defined(IP2DEBUG_OPEN)
-#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \
-		    tty->name,(pCh->flags),ip2_tty_driver->refcount, \
+#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
+		    tty->name,(pCh->flags), \
 		    tty->count,/*GET_USE_COUNT(module)*/0,s)
 #else
 #define DBG_CNT(s)
@@ -2893,7 +2893,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
 	case 13:
 		switch ( cmd ) {
 		case 64:	/* Driver - ip2stat */
-			rc = put_user(ip2_tty_driver->refcount, pIndex++ );
+			rc = put_user(-1, pIndex++ );
 			rc = put_user(irq_counter, pIndex++  );
 			rc = put_user(bh_counter, pIndex++  );
 			break;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 6e148ad..0fdfa05 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -571,8 +571,11 @@ static void __init unix98_pty_init(void)
 	if (tty_register_driver(pts_driver))
 		panic("Couldn't register Unix98 pts driver");
 
+	/* FIXME: WTF */
+#if 0	
 	pty_table[1].data = &ptm_driver->refcount;
-	register_sysctl_table(pty_root_table);
+#endif	
+	register_sysctl_table(pty_root_table);	
 
 	/* Now create the /dev/ptmx special device */
 	tty_default_fops(&ptmx_fops);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index ac41af8..47aa437 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -276,7 +276,7 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
 		if (device < base || device >= base + p->num)
 			continue;
 		*index = device - base;
-		return p;
+		return tty_driver_kref_get(p);
 	}
 	return NULL;
 }
@@ -320,7 +320,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
 
 		if (tty_line >= 0 && tty_line <= p->num && p->ops &&
 		    p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) {
-			res = p;
+			res = tty_driver_kref_get(p);
 			*line = tty_line;
 			break;
 		}
@@ -1410,7 +1410,7 @@ int tty_init_dev(struct tty_driver *driver, int idx,
 			*o_ltp_loc = o_ltp;
 		o_tty->termios = *o_tp_loc;
 		o_tty->termios_locked = *o_ltp_loc;
-		driver->other->refcount++;
+		tty_driver_kref_get(driver->other);
 		if (driver->subtype == PTY_TYPE_MASTER)
 			o_tty->count++;
 
@@ -1438,7 +1438,7 @@ int tty_init_dev(struct tty_driver *driver, int idx,
 	/* Compatibility until drivers always set this */
 	tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
 	tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
-	driver->refcount++;
+	tty_driver_kref_get(driver);
 	tty->count++;
 
 	/*
@@ -1530,8 +1530,7 @@ static void release_one_tty(struct kref *kref)
 	else
 		tty_shutdown(tty);
 	tty->magic = 0;
-	/* FIXME: locking on tty->driver->refcount */
-	tty->driver->refcount--;
+	tty_driver_kref_put(driver);
 	module_put(driver->owner);
 
 	file_list_lock();
@@ -1854,7 +1853,7 @@ retry_open:
 			mutex_unlock(&tty_mutex);
 			return -ENXIO;
 		}
-		driver = tty->driver;
+		driver = tty_driver_kref_get(tty->driver);
 		index = tty->index;
 		filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
 		/* noctty = 1; */
@@ -1865,14 +1864,14 @@ retry_open:
 #ifdef CONFIG_VT
 	if (device == MKDEV(TTY_MAJOR, 0)) {
 		extern struct tty_driver *console_driver;
-		driver = console_driver;
+		driver = tty_driver_kref_get(console_driver);
 		index = fg_console;
 		noctty = 1;
 		goto got_driver;
 	}
 #endif
 	if (device == MKDEV(TTYAUX_MAJOR, 1)) {
-		driver = console_device(&index);
+		driver = tty_driver_kref_get(console_device(&index));
 		if (driver) {
 			/* Don't let /dev/console block */
 			filp->f_flags |= O_NONBLOCK;
@@ -1891,6 +1890,7 @@ retry_open:
 got_driver:
 	retval = tty_init_dev(driver, index, &tty, 0);
 	mutex_unlock(&tty_mutex);
+	tty_driver_kref_put(driver);
 	if (retval)
 		return retval;
 
@@ -2866,7 +2866,6 @@ int tty_put_char(struct tty_struct *tty, unsigned char ch)
 		return tty->ops->put_char(tty, ch);
 	return tty->ops->write(tty, &ch, 1);
 }
-
 EXPORT_SYMBOL_GPL(tty_put_char);
 
 struct class *tty_class;
@@ -2909,6 +2908,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
 
 	return device_create_drvdata(tty_class, device, dev, NULL, name);
 }
+EXPORT_SYMBOL(tty_register_device);
 
 /**
  * 	tty_unregister_device - unregister a tty device
@@ -2926,8 +2926,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
 	device_destroy(tty_class,
 		MKDEV(driver->major, driver->minor_start) + index);
 }
-
-EXPORT_SYMBOL(tty_register_device);
 EXPORT_SYMBOL(tty_unregister_device);
 
 struct tty_driver *alloc_tty_driver(int lines)
@@ -2936,27 +2934,70 @@ struct tty_driver *alloc_tty_driver(int lines)
 
 	driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
 	if (driver) {
+		kref_init(&driver->kref);
 		driver->magic = TTY_DRIVER_MAGIC;
 		driver->num = lines;
 		/* later we'll move allocation of tables here */
 	}
 	return driver;
 }
+EXPORT_SYMBOL(alloc_tty_driver);
 
-void put_tty_driver(struct tty_driver *driver)
+static void destruct_tty_driver(struct kref *kref)
 {
+	struct tty_driver *driver = container_of(kref, struct tty_driver, kref);
+	int i;
+	struct ktermios *tp;
+	void *p;
+
+	if (driver->flags & TTY_DRIVER_INSTALLED) {
+		/*
+		 * Free the termios and termios_locked structures because
+		 * we don't want to get memory leaks when modular tty
+		 * drivers are removed from the kernel.
+		 */
+		for (i = 0; i < driver->num; i++) {
+			tp = driver->termios[i];
+			if (tp) {
+				driver->termios[i] = NULL;
+				kfree(tp);
+			}
+			tp = driver->termios_locked[i];
+			if (tp) {
+				driver->termios_locked[i] = NULL;
+				kfree(tp);
+			}
+			if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
+				tty_unregister_device(driver, i);
+		}
+		p = driver->ttys;
+		proc_tty_unregister_driver(driver);
+		driver->ttys = NULL;
+		driver->termios = driver->termios_locked = NULL;
+		kfree(p);
+		cdev_del(&driver->cdev);
+	}
 	kfree(driver);
 }
 
+void tty_driver_kref_put(struct tty_driver *driver)
+{
+	kref_put(&driver->kref, destruct_tty_driver);
+}
+EXPORT_SYMBOL(tty_driver_kref_put);
+
 void tty_set_operations(struct tty_driver *driver,
 			const struct tty_operations *op)
 {
 	driver->ops = op;
 };
+EXPORT_SYMBOL(tty_set_operations);
 
-EXPORT_SYMBOL(alloc_tty_driver);
+void put_tty_driver(struct tty_driver *d)
+{
+	tty_driver_kref_put(d);
+}
 EXPORT_SYMBOL(put_tty_driver);
-EXPORT_SYMBOL(tty_set_operations);
 
 /*
  * Called by a tty driver to register itself.
@@ -2968,9 +3009,6 @@ int tty_register_driver(struct tty_driver *driver)
 	dev_t dev;
 	void **p = NULL;
 
-	if (driver->flags & TTY_DRIVER_INSTALLED)
-		return 0;
-
 	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
 		p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
 		if (!p)
@@ -3024,6 +3062,7 @@ int tty_register_driver(struct tty_driver *driver)
 		    tty_register_device(driver, i, NULL);
 	}
 	proc_tty_register_driver(driver);
+	driver->flags |= TTY_DRIVER_INSTALLED;
 	return 0;
 }
 
@@ -3034,46 +3073,19 @@ EXPORT_SYMBOL(tty_register_driver);
  */
 int tty_unregister_driver(struct tty_driver *driver)
 {
-	int i;
-	struct ktermios *tp;
-	void *p;
-
+#if 0
+	/* FIXME */
 	if (driver->refcount)
 		return -EBUSY;
-
+#endif
 	unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
 				driver->num);
 	mutex_lock(&tty_mutex);
 	list_del(&driver->tty_drivers);
 	mutex_unlock(&tty_mutex);
-
-	/*
-	 * Free the termios and termios_locked structures because
-	 * we don't want to get memory leaks when modular tty
-	 * drivers are removed from the kernel.
-	 */
-	for (i = 0; i < driver->num; i++) {
-		tp = driver->termios[i];
-		if (tp) {
-			driver->termios[i] = NULL;
-			kfree(tp);
-		}
-		tp = driver->termios_locked[i];
-		if (tp) {
-			driver->termios_locked[i] = NULL;
-			kfree(tp);
-		}
-		if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
-			tty_unregister_device(driver, i);
-	}
-	p = driver->ttys;
-	proc_tty_unregister_driver(driver);
-	driver->ttys = NULL;
-	driver->termios = driver->termios_locked = NULL;
-	kfree(p);
-	cdev_del(&driver->cdev);
 	return 0;
 }
+
 EXPORT_SYMBOL(tty_unregister_driver);
 
 dev_t tty_devnum(struct tty_struct *tty)
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 2ae2ec4..21efd99 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -205,7 +205,7 @@ config WANXL_BUILD_FIRMWARE
 
 config PC300
 	tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
-	depends on HDLC && PCI
+	depends on HDLC && PCI && BROKEN
 	---help---
 	  Driver for the Cyclades-PC300 synchronous communication boards.
 
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 2c5c35c..ba891dd 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -253,6 +253,7 @@ struct tty_operations {
 
 struct tty_driver {
 	int	magic;		/* magic number for this structure */
+	struct kref kref;	/* Reference management */
 	struct cdev cdev;
 	struct module	*owner;
 	const char	*driver_name;
@@ -266,7 +267,6 @@ struct tty_driver {
 	short	subtype;	/* subtype of tty driver */
 	struct ktermios init_termios; /* Initial termios */
 	int	flags;		/* tty driver flags */
-	int	refcount;	/* for loadable tty drivers */
 	struct proc_dir_entry *proc_entry; /* /proc fs entry */
 	struct tty_driver *other; /* only used for the PTY driver */
 
@@ -288,12 +288,19 @@ struct tty_driver {
 
 extern struct list_head tty_drivers;
 
-struct tty_driver *alloc_tty_driver(int lines);
-void put_tty_driver(struct tty_driver *driver);
-void tty_set_operations(struct tty_driver *driver,
+extern struct tty_driver *alloc_tty_driver(int lines);
+extern void put_tty_driver(struct tty_driver *driver);
+extern void tty_set_operations(struct tty_driver *driver,
 			const struct tty_operations *op);
 extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
 
+extern void tty_driver_kref_put(struct tty_driver *driver);
+extern inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
+{
+	kref_get(&d->kref);
+	return d;
+}
+
 /* tty driver magic number */
 #define TTY_DRIVER_MAGIC		0x5402
 


  parent reply	other threads:[~2008-10-13  9:54 UTC|newest]

Thread overview: 86+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-10-13  9:31 [PATCH 00/80] TTY updates for 2.6.28 Alan Cox
2008-10-13  9:31 ` [PATCH 01/80] drivers/serial/crisv10.c: add missing put_tty_driver Alan Cox
2008-10-13  9:31 ` [PATCH 02/80] drivers/char/hvc_console.c: adjust call to put_tty_driver Alan Cox
2008-10-13  9:31 ` [PATCH 03/80] coldfire: scheduled SERIAL_COLDFIRE removal Alan Cox
2008-10-13  9:32 ` [PATCH 04/80] epca: call tty_port_init Alan Cox
2008-10-13  9:32 ` [PATCH 05/80] Blackfin Serial Driver: use __initdata for data, not __init Alan Cox
2008-10-13  9:32 ` [PATCH 06/80] Blackfin Serial Driver: Fix bug - should suspend/resume/remove all uart ports Alan Cox
2008-10-13  9:33 ` [PATCH 07/80] Blackfin Serial Driver: trim trailing whitespace -- no functional changes Alan Cox
2008-10-13  9:33 ` [PATCH 08/80] Blackfin Serial Driver: move common variables out of serial headers and into the serial driver Alan Cox
2008-10-13  9:33 ` [PATCH 09/80] Blackfin Serial Driver: Remove useless stop Alan Cox
2008-10-13  9:33 ` [PATCH 10/80] Blackfin Serial Driver: Fix bug - Don't call tx_stop in tx_transfer Alan Cox
2008-10-13  9:33 ` [PATCH 11/80] Blackfin Serial Driver: Fix bug - ircp fails on sir over Blackfin UART Alan Cox
2008-10-13  9:33 ` [PATCH 12/80] Blackfin Serial Driver: Fix bug - request UART2/3 peripheral mapped interrupts in PIO mode Alan Cox
2008-10-13  9:34 ` [PATCH 13/80] Fix oti6858 debug level Alan Cox
2008-10-13  9:34 ` [PATCH 14/80] Char: cyclades. remove bogus iomap Alan Cox
2008-10-13  9:34 ` [PATCH 15/80] Char: sx, fix io unmapping Alan Cox
2008-10-13  9:34 ` [PATCH 16/80] Char: merge ip2main and ip2base Alan Cox
2008-10-13  9:34 ` [PATCH 17/80] ip2, cleanup globals Alan Cox
2008-10-13  9:34 ` [PATCH 18/80] ip2, fix sparse warnings Alan Cox
2008-10-13  9:34 ` [PATCH 19/80] ip2, init/deinit cleanup Alan Cox
2008-10-13  9:35 ` [PATCH 20/80] ip2: avoid add_timer with pending timer Alan Cox
2008-10-13  9:35 ` [PATCH 21/80] audit: Handle embedded NUL in TTY input auditing Alan Cox
2008-10-13  9:35 ` [PATCH 22/80] serial: Make uart_port's ioport "unsigned long" Alan Cox
2008-10-13  9:35 ` [PATCH 23/80] nozomi: Fix close on error Alan Cox
2008-10-13  9:35 ` [PATCH 24/80] serial-make-uart_ports-ioport-unsigned-long-fix Alan Cox
2008-10-13  9:35 ` [PATCH 25/80] usb: fix pl2303 initialization Alan Cox
2008-10-13  9:36 ` [PATCH 26/80] ftdi: A few errors are err() that should be debug which causes much spewage Alan Cox
2008-10-13  9:36 ` [PATCH 27/80] serial_8250: pci_enable_device fail is not fully handled Alan Cox
2008-10-13  9:36 ` [PATCH 28/80] 8250: remove a few inlines of dubious value Alan Cox
2008-10-13  9:36 ` [PATCH 29/80] serial: allow 8250 to be used on sparc Alan Cox
2008-10-13  9:36 ` [PATCH 30/80] tty: move tioclinux from a special case Alan Cox
2008-10-13  9:36 ` [PATCH 31/80] uml: small cleanups and note bugs to be dealt with by uml authors Alan Cox
2008-10-13  9:36 ` [PATCH 32/80] tty: split the buffering from tty_io Alan Cox
2008-10-13  9:37 ` [PATCH 33/80] tty: Split tty_port into its own file Alan Cox
2008-10-13  9:37 ` [PATCH 34/80] pps: Reserve a line discipline number for PPS Alan Cox
2008-10-13  9:37 ` [PATCH 35/80] tty: Add a kref count Alan Cox
2008-10-13  9:37 ` [PATCH 36/80] tty: use krefs to protect driver module counts Alan Cox
2008-10-13  9:37 ` [PATCH 37/80] tty: Cris has a nice RS485 ioctl so we should steal it Alan Cox
2008-10-13  9:38 ` [PATCH 38/80] tty: ipw need reworking Alan Cox
2008-10-13  9:38 ` [PATCH 39/80] tty: Add termiox Alan Cox
2008-10-13  9:38 ` [PATCH 40/80] tty: Termios locking - sort out real_tty confusions and lock reads Alan Cox
2008-10-13  9:39 ` [PATCH 41/80] tty: compare the tty winsize Alan Cox
2008-10-13  9:39 ` [PATCH 42/80] tty: Make get_current_tty use a kref Alan Cox
2008-10-13  9:39 ` [PATCH 43/80] tty: Move tty_write_message out of kernel/printk Alan Cox
2008-10-13  9:39 ` [PATCH 44/80] tty: usb-serial krefs Alan Cox
2008-10-13  9:39 ` [PATCH 45/80] tty: kref usage for isicom and moxa Alan Cox
2008-10-13  9:40 ` [PATCH 46/80] stallion: Use krefs Alan Cox
2008-10-13  9:40 ` [PATCH 47/80] mxser: Switch to kref tty Alan Cox
2008-10-13  9:40 ` [PATCH 48/80] tty: the vhangup syscall is racy Alan Cox
2008-10-13  9:40 ` [PATCH 49/80] tty: Redo current tty locking Alan Cox
2008-10-13  9:40 ` [PATCH 50/80] tty: Fix abusers of current->sighand->tty Alan Cox
2008-10-13  9:41 ` [PATCH 51/80] pty: If the administrator creates a device for a ptmx slave we should not error Alan Cox
2008-10-13  9:41 ` [PATCH 52/80] vt: remove bogus lock dropping Alan Cox
2008-10-13  9:41 ` [PATCH 53/80] tty: shutdown method Alan Cox
2008-10-13  9:41 ` [PATCH 54/80] tty: Remove more special casing and out of place code Alan Cox
2008-10-13  9:41 ` [PATCH 55/80] tty: Move parts of tty_init_dev into new functions Alan Cox
2008-10-13  9:42 ` [PATCH 56/80] tty: Clean up the tty_init_dev changes further Alan Cox
2008-10-13  9:42 ` Alan Cox [this message]
2008-10-13  9:42 ` [PATCH 58/80] tty: More driver operations Alan Cox
2008-10-13  9:42 ` [PATCH 59/80] tty: Finish fixing up the init_dev interface to use ERR_PTR Alan Cox
2008-10-13  9:42 ` [PATCH 60/80] tty: extract the pty init time special cases Alan Cox
2008-10-13  9:42 ` [PATCH 61/80] Move tty lookup/reopen to caller Alan Cox
2008-10-13  9:42 ` [PATCH 62/80] Add an instance parameter devpts interfaces Alan Cox
2008-10-13  9:43 ` [PATCH 63/80] Simplify devpts_get_tty() Alan Cox
2008-10-13  9:43 ` [PATCH 64/80] Simplify devpts_pty_new() Alan Cox
2008-10-13  9:43 ` [PATCH 65/80] Simplify devpts_pty_kill Alan Cox
2008-10-13  9:43 ` [PATCH 66/80] pty: Coding style and polish Alan Cox
2008-10-13  9:43 ` [PATCH 67/80] pty: Fix allocation failure double free Alan Cox
2008-10-13  9:43 ` [PATCH 68/80] pty: simplify unix98 allocation Alan Cox
2008-10-13  9:44 ` [PATCH 69/80] tty: simplify ktermios allocation Alan Cox
2008-10-13  9:44 ` [PATCH 70/80] tty: some ICANON magic is in the wrong places Alan Cox
2008-10-13  9:44 ` [PATCH 71/80] tty: Fallout from tty-move-canon-specials Alan Cox
2008-10-13  9:44 ` [PATCH 72/80] tty: fix up gigaset a bit Alan Cox
2008-10-16 15:50   ` Tilman Schmidt
2008-10-17 11:40     ` Alan Cox
2008-10-19 12:28       ` Tilman Schmidt
2008-10-22  9:00         ` Alan Cox
2008-10-24 11:21           ` Tilman Schmidt
2008-10-13  9:44 ` [PATCH 73/80] tty: Remove lots of NULL checks Alan Cox
2008-10-13  9:45 ` [PATCH 74/80] tty: Minor tidyups and document fixes for n_tty Alan Cox
2008-10-13  9:45 ` [PATCH 75/80] applicom: Fix an unchecked user ioctl range and an error return Alan Cox
2008-10-13  9:45 ` [PATCH 76/80] serial: fix device name reporting when minor space is shared between drivers Alan Cox
2008-10-13  9:45 ` [PATCH 77/80] tty: tty_io.c shadows sparse fix Alan Cox
2008-10-13  9:45 ` [PATCH 78/80] fs3270: remove extra locks Alan Cox
2008-10-13  9:46 ` [PATCH 79/80] fs3270: Correct error returns Alan Cox
2008-10-13  9:46 ` [PATCH 80/80] tty: rename the remaining oddly named n_tty functions Alan Cox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20081013094206.21645.56045.stgit@localhost.localdomain \
    --to=alan@lxorguk.ukuu.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).