Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111829889
D27047.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D27047.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D27047: Add sbuf streaming mode to pseudofs(9), use in linprocfs(5)
Attached
Detach File
Event Timeline
Log In to Comment