summaryrefslogtreecommitdiff
path: root/tmpfs
diff options
context:
space:
mode:
Diffstat (limited to 'tmpfs')
-rw-r--r--tmpfs/dir.c22
-rw-r--r--tmpfs/node.c25
-rw-r--r--tmpfs/pager-stubs.c4
-rw-r--r--tmpfs/tmpfs.c28
4 files changed, 62 insertions, 17 deletions
diff --git a/tmpfs/dir.c b/tmpfs/dir.c
index 65386e0a..c0ae9785 100644
--- a/tmpfs/dir.c
+++ b/tmpfs/dir.c
@@ -29,6 +29,12 @@ diskfs_init_dir (struct node *dp, struct node *pdp, struct protid *cred)
{
dp->dn->u.dir.dotdot = pdp->dn;
dp->dn->u.dir.entries = 0;
+
+ /* Increase hardlink count for parent directory */
+ pdp->dn_stat.st_nlink++;
+ /* Take '.' directory into account */
+ dp->dn_stat.st_nlink++;
+
return 0;
}
@@ -40,6 +46,12 @@ diskfs_clear_directory (struct node *dp, struct node *pdp,
return ENOTEMPTY;
assert (dp->dn_stat.st_size == 0);
assert (dp->dn->u.dir.dotdot == pdp->dn);
+
+ /* Decrease hardlink count for parent directory */
+ pdp->dn_stat.st_nlink--;
+ /* Take '.' directory into account */
+ dp->dn_stat.st_nlink--;
+
return 0;
}
@@ -138,6 +150,7 @@ diskfs_get_directs (struct node *dp, int entry, int n,
struct dirstat
{
struct tmpfs_dirent **prevp;
+ int dotdot;
};
const size_t diskfs_dirstat_size = sizeof (struct dirstat);
@@ -166,6 +179,9 @@ diskfs_lookup_hard (struct node *dp,
if (type == REMOVE || type == RENAME)
assert (np);
+ if (ds)
+ ds->dotdot = type & SPEC_DOTDOT;
+
if (namelen == 1 && name[0] == '.')
{
if (np != 0)
@@ -267,7 +283,11 @@ error_t
diskfs_dirrewrite_hard (struct node *dp, struct node *np,
struct dirstat *ds)
{
- (*ds->prevp)->dn = np->dn;
+ if (ds->dotdot)
+ dp->dn->u.dir.dotdot = np->dn;
+ else
+ (*ds->prevp)->dn = np->dn;
+
return 0;
}
diff --git a/tmpfs/node.c b/tmpfs/node.c
index 17fe8ce7..bce15370 100644
--- a/tmpfs/node.c
+++ b/tmpfs/node.c
@@ -332,6 +332,7 @@ static error_t
create_symlink_hook (struct node *np, const char *target)
{
assert (np->dn->u.lnk == 0);
+ np->dn_stat.st_size = strlen (target);
if (np->dn_stat.st_size > 0)
{
const size_t size = np->dn_stat.st_size + 1;
@@ -339,6 +340,7 @@ create_symlink_hook (struct node *np, const char *target)
if (np->dn->u.lnk == 0)
return ENOSPC;
memcpy (np->dn->u.lnk, target, size);
+ np->dn->type = DT_LNK;
adjust_used (size);
recompute_blocks (np);
}
@@ -382,9 +384,6 @@ diskfs_node_reload (struct node *node)
error_t
diskfs_truncate (struct node *np, off_t size)
{
- if (np->allocsize <= size)
- return 0;
-
if (np->dn->type == DT_LNK)
{
free (np->dn->u.lnk);
@@ -394,6 +393,9 @@ diskfs_truncate (struct node *np, off_t size)
return 0;
}
+ if (np->allocsize <= size)
+ return 0;
+
assert (np->dn->type == DT_REG);
if (default_pager == MACH_PORT_NULL)
@@ -401,13 +403,12 @@ diskfs_truncate (struct node *np, off_t size)
np->dn_stat.st_size = size;
+ off_t set_size = size;
size = round_page (size);
- if (size == np->allocsize)
- return 0;
if (np->dn->u.reg.memobj != MACH_PORT_NULL)
{
- error_t err = default_pager_object_set_size (np->dn->u.reg.memobj, size);
+ error_t err = default_pager_object_set_size (np->dn->u.reg.memobj, set_size);
if (err == MIG_BAD_ID)
/* This is an old default pager. We have no way to truncate the
memory object. Note that the behavior here will be wrong in
@@ -440,8 +441,10 @@ diskfs_grow (struct node *np, off_t size, struct protid *cred)
if (np->allocsize >= size)
return 0;
+ off_t set_size = size;
size = round_page (size);
- if (round_page (tmpfs_space_used + size) / vm_page_size > tmpfs_page_limit)
+ if (round_page (tmpfs_space_used + size - np->allocsize)
+ / vm_page_size > tmpfs_page_limit)
return ENOSPC;
if (default_pager == MACH_PORT_NULL)
@@ -450,7 +453,7 @@ diskfs_grow (struct node *np, off_t size, struct protid *cred)
if (np->dn->u.reg.memobj != MACH_PORT_NULL)
{
/* Increase the limit the memory object will allow to be accessed. */
- error_t err = default_pager_object_set_size (np->dn->u.reg.memobj, size);
+ error_t err = default_pager_object_set_size (np->dn->u.reg.memobj, set_size);
if (err == MIG_BAD_ID) /* Old default pager, never limited it. */
err = 0;
if (err)
@@ -498,17 +501,13 @@ diskfs_get_filemap (struct node *np, vm_prot_t prot)
return MACH_PORT_NULL;
}
assert (np->dn->u.reg.memobj != MACH_PORT_NULL);
- /* A new-fangled default pager lets us prevent user accesses
- past the specified size of the file. */
- err = default_pager_object_set_size (np->dn->u.reg.memobj,
- np->allocsize);
- assert_perror (err);
/* XXX we need to keep a reference to the object, or GNU Mach
will terminate it when we release the map. */
vm_map (mach_task_self (), &np->dn->u.reg.memref, 4096, 0, 1,
np->dn->u.reg.memobj, 0, 0, VM_PROT_NONE, VM_PROT_NONE,
VM_INHERIT_NONE);
+ assert_perror (err);
}
/* XXX always writable */
diff --git a/tmpfs/pager-stubs.c b/tmpfs/pager-stubs.c
index 361724a9..25d70fe2 100644
--- a/tmpfs/pager-stubs.c
+++ b/tmpfs/pager-stubs.c
@@ -24,7 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* The user must define this function. For pager PAGER, read one
page from offset PAGE. Set *BUF to be the address of the page,
and set *WRITE_LOCK if the page must be provided read-only.
- The only permissable error returns are EIO, EDQUOT, and ENOSPC. */
+ The only permissible error returns are EIO, EDQUOT, and ENOSPC. */
error_t
pager_read_page (struct user_pager_info *pager,
vm_offset_t page,
@@ -37,7 +37,7 @@ pager_read_page (struct user_pager_info *pager,
/* The user must define this function. For pager PAGER, synchronously
write one page from BUF to offset PAGE. In addition, mfree
- (or equivalent) BUF. The only permissable error returns are EIO,
+ (or equivalent) BUF. The only permissible error returns are EIO,
EDQUOT, and ENOSPC. */
error_t
pager_write_page (struct user_pager_info *pager,
diff --git a/tmpfs/tmpfs.c b/tmpfs/tmpfs.c
index cd67dd74..b72459fe 100644
--- a/tmpfs/tmpfs.c
+++ b/tmpfs/tmpfs.c
@@ -255,6 +255,30 @@ diskfs_append_args (char **argz, size_t *argz_len)
return err;
}
+/* Handling of operations for the ports in diskfs_port_bucket, calling
+ * demuxer for each incoming message */
+static any_t
+diskfs_thread_function (any_t demuxer)
+{
+ error_t err;
+
+ do
+ {
+ ports_manage_port_operations_multithread (diskfs_port_bucket,
+ (ports_demuxer_type) demuxer,
+ 0,
+ 0,
+ 0);
+ err = diskfs_shutdown (0);
+ }
+ while (err);
+
+ exit (0);
+ /* NOTREACHED */
+ return (any_t) 0;
+}
+
+
/* Add our startup arguments to the standard diskfs set. */
static const struct argp_child startup_children[] =
{{&diskfs_startup_argp}, {0}};
@@ -317,7 +341,9 @@ main (int argc, char **argv)
if (err)
error (4, err, "cannot create root directory");
- diskfs_spawn_first_thread (diskfs_demuxer);
+ /* Like diskfs_spawn_first_thread. But do it manually, without timeout */
+ cthread_detach (cthread_fork ((cthread_fn_t) diskfs_thread_function,
+ (any_t) diskfs_demuxer));
/* Now that we are all set up to handle requests, and diskfs_root_node is
set properly, it is safe to export our fsys control port to the