Page MenuHomeFreeBSD

D27047.diff
No OneTemporary

D27047.diff

Index: head/sys/compat/linprocfs/linprocfs.c
===================================================================
--- head/sys/compat/linprocfs/linprocfs.c
+++ head/sys/compat/linprocfs/linprocfs.c
@@ -1252,10 +1252,6 @@
*name ? " " : " ",
name
);
- if (error == -1) {
- linux_msg(td, "cannot fill /proc/self/maps; "
- "consider bumping PFS_MAXBUFSIZ");
- }
if (freename)
free(freename, M_TEMP);
vm_map_lock_read(map);
@@ -1890,7 +1886,7 @@
pfs_create_link(dir, "exe", &procfs_doprocfile,
NULL, &procfs_notsystem, NULL, 0);
pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
- NULL, NULL, NULL, PFS_RD);
+ NULL, NULL, NULL, PFS_RD | PFS_AUTODRAIN);
pfs_create_file(dir, "mem", &linprocfs_doprocmem,
procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR | PFS_RAW);
pfs_create_file(dir, "mounts", &linprocfs_domtab,
Index: head/sys/fs/pseudofs/pseudofs.h
===================================================================
--- head/sys/fs/pseudofs/pseudofs.h
+++ head/sys/fs/pseudofs/pseudofs.h
@@ -78,6 +78,7 @@
#define PFS_RAW (PFS_RAWRD|PFS_RAWWR)
#define PFS_PROCDEP 0x0010 /* process-dependent */
#define PFS_NOWAIT 0x0020 /* allow malloc to fail */
+#define PFS_AUTODRAIN 0x0040 /* sbuf_print can sleep to drain */
/*
* Data structures
Index: head/sys/fs/pseudofs/pseudofs_vnops.c
===================================================================
--- head/sys/fs/pseudofs/pseudofs_vnops.c
+++ head/sys/fs/pseudofs/pseudofs_vnops.c
@@ -623,6 +623,50 @@
PFS_RETURN (0);
}
+struct sbuf_seek_helper {
+ off_t skip_bytes;
+ struct uio *uio;
+};
+
+static int
+pfs_sbuf_uio_drain(void *arg, const char *data, int len)
+{
+ struct sbuf_seek_helper *ssh;
+ struct uio *uio;
+ int error, skipped;
+
+ ssh = arg;
+ uio = ssh->uio;
+ skipped = 0;
+
+ /* Need to discard first uio_offset bytes. */
+ if (ssh->skip_bytes > 0) {
+ if (ssh->skip_bytes >= len) {
+ ssh->skip_bytes -= len;
+ return (len);
+ }
+
+ data += ssh->skip_bytes;
+ len -= ssh->skip_bytes;
+ skipped = ssh->skip_bytes;
+ ssh->skip_bytes = 0;
+ }
+
+ error = uiomove(__DECONST(void *, data), len, uio);
+ if (error != 0)
+ return (-error);
+
+ /*
+ * The fill function has more to emit, but the reader is finished.
+ * This is similar to the truncated read case for non-draining PFS
+ * sbufs, and should be handled appropriately in fill-routines.
+ */
+ if (uio->uio_resid == 0)
+ return (-ENOBUFS);
+
+ return (skipped + len);
+}
+
/*
* Read from a file
*/
@@ -636,7 +680,8 @@
struct proc *proc;
struct sbuf *sb = NULL;
int error, locked;
- off_t buflen;
+ off_t buflen, buflim;
+ struct sbuf_seek_helper ssh;
PFS_TRACE(("%s", pn->pn_name));
pfs_assert_not_owned(pn);
@@ -678,16 +723,30 @@
error = EINVAL;
goto ret;
}
- buflen = uio->uio_offset + uio->uio_resid;
- if (buflen > PFS_MAXBUFSIZ)
- buflen = PFS_MAXBUFSIZ;
+ buflen = uio->uio_offset + uio->uio_resid + 1;
+ if (pn->pn_flags & PFS_AUTODRAIN)
+ /*
+ * We can use a smaller buffer if we can stream output to the
+ * consumer.
+ */
+ buflim = PAGE_SIZE;
+ else
+ buflim = PFS_MAXBUFSIZ;
+ if (buflen > buflim)
+ buflen = buflim;
- sb = sbuf_new(sb, NULL, buflen + 1, 0);
+ sb = sbuf_new(sb, NULL, buflen, 0);
if (sb == NULL) {
error = EIO;
goto ret;
}
+ if (pn->pn_flags & PFS_AUTODRAIN) {
+ ssh.skip_bytes = uio->uio_offset;
+ ssh.uio = uio;
+ sbuf_set_drain(sb, pfs_sbuf_uio_drain, &ssh);
+ }
+
error = pn_fill(curthread, proc, pn, sb, uio);
if (error) {
@@ -700,9 +759,23 @@
* the data length. Then just use the full length because an
* overflowed sbuf must be full.
*/
- if (sbuf_finish(sb) == 0)
- buflen = sbuf_len(sb);
- error = uiomove_frombuf(sbuf_data(sb), buflen, uio);
+ error = sbuf_finish(sb);
+ if ((pn->pn_flags & PFS_AUTODRAIN)) {
+ /*
+ * ENOBUFS just indicates early termination of the fill
+ * function as the caller's buffer was already filled. Squash
+ * to zero.
+ */
+ if (uio->uio_resid == 0 && error == ENOBUFS)
+ error = 0;
+ } else {
+ if (error == 0)
+ buflen = sbuf_len(sb);
+ else
+ /* The trailing byte is not valid. */
+ buflen--;
+ error = uiomove_frombuf(sbuf_data(sb), buflen, uio);
+ }
sbuf_delete(sb);
ret:
vn_lock(vn, locked | LK_RETRY);

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 9, 11:53 PM (6 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17077505
Default Alt Text
D27047.diff (4 KB)

Event Timeline