summaryrefslogtreecommitdiff
path: root/libdiskfs
diff options
context:
space:
mode:
Diffstat (limited to 'libdiskfs')
-rw-r--r--libdiskfs/ChangeLog31
-rw-r--r--libdiskfs/boot-start.c4
-rw-r--r--libdiskfs/dir-chg.c31
-rw-r--r--libdiskfs/diskfs.h18
-rw-r--r--libdiskfs/file-chauthor.c3
-rw-r--r--libdiskfs/file-chflags.c3
-rw-r--r--libdiskfs/file-chg.c48
-rw-r--r--libdiskfs/file-chmod.c4
-rw-r--r--libdiskfs/file-chown.c4
-rw-r--r--libdiskfs/file-set-size.c12
-rw-r--r--libdiskfs/io-prenotify.c2
-rw-r--r--libdiskfs/io-write.c4
-rw-r--r--libdiskfs/node-drop.c26
-rw-r--r--libdiskfs/node-make.c1
-rw-r--r--libdiskfs/node-rdwr.c2
15 files changed, 168 insertions, 25 deletions
diff --git a/libdiskfs/ChangeLog b/libdiskfs/ChangeLog
index 95c76749..ceb5d123 100644
--- a/libdiskfs/ChangeLog
+++ b/libdiskfs/ChangeLog
@@ -1,3 +1,34 @@
+Sun Aug 9 21:09:24 1998 Jose M. Moya <josem@gnu.org>
+
+ * diskfs.h (struct node): Add filemod_reqs member.
+ (struct modreq): Rename struct dirmod to reqmod as it is used for
+ directory and file notifications.
+ (diskfs_notice_filechange): Add prototype.
+ * dir-chg.c (diskfs_S_dir_notice_changes): Check
+ nowait_dir_changed return value for errors.
+ (diskfs_notice_dirchange): Remove requests when the notification
+ fails.
+ * file-chg.c (diskfs_S_file_notice_changes): Implement.
+ (diskfs_notice_filechange): New function.
+ * node-make.c (diskfs_make_node): Initialize filemod_reqs.
+ * node-drop.c (free_modreqs): New function.
+ (diskfs_drop_node): Free filemod_reqs.
+ * file-chauthor.c (dithkfth_TH_file_chauthor): Add file
+ notifications.
+ * file-chflags.c (diskfs_S_file_chflags): Likewise.
+ * file-chmod.c (diskfs_S_file_chmod): Likewise.
+ * file-chown.c (diskfs_S_file_chown): Likewise.
+ * file-set-size.c (diskfs_S_file_set_size): Likewise.
+ * io-prenotify.c (diskfs_S_io_prenotify): Likewise.
+ * io-write.c (diskfs_S_io_write): Likewise.
+ * node-rdwr.c (diskfs_node_rdwr): Likewise.
+
+Sat Aug 8 17:01:58 1998 Thomas Bushnell, BSG <tb@mit.edu>
+
+ * boot-start.c (diskfs_S_fsys_init): __vm_allocate -> vm_allocate
+ and __mach_task_self -> mach_task_self. Reported by Mark Kettenis
+ (kettenis@phys.uva.nl).
+
1998-07-25 Roland McGrath <roland@baalperazim.frob.com>
* shutdown.c (diskfs_shutdown): Sync and set the clean flag even if we
diff --git a/libdiskfs/boot-start.c b/libdiskfs/boot-start.c
index 711881a6..030f440a 100644
--- a/libdiskfs/boot-start.c
+++ b/libdiskfs/boot-start.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998 Free Software Foundation
This file is part of the GNU Hurd.
@@ -442,7 +442,7 @@ diskfs_S_fsys_init (mach_port_t port,
and call _hurd_init. */
mach_port_t *portarray;
unsigned int i;
- __vm_allocate (__mach_task_self (), (vm_address_t *) &portarray,
+ vm_allocate (mach_task_self (), (vm_address_t *) &portarray,
INIT_PORT_MAX * sizeof *portarray, 1);
if (MACH_PORT_NULL != (mach_port_t) 0)
for (i = 0; i < INIT_PORT_MAX; ++i)
diff --git a/libdiskfs/dir-chg.c b/libdiskfs/dir-chg.c
index 42dfb161..12b169c6 100644
--- a/libdiskfs/dir-chg.c
+++ b/libdiskfs/dir-chg.c
@@ -23,24 +23,30 @@ kern_return_t
diskfs_S_dir_notice_changes (struct protid *cred,
mach_port_t notify)
{
- struct dirmod *req;
+ error_t err;
+ struct modreq *req;
struct node *np;
if (!cred)
return EOPNOTSUPP;
np = cred->po->np;
- req = malloc (sizeof (struct dirmod));
mutex_lock (&np->lock);
if (!S_ISDIR (np->dn_stat.st_mode))
{
mutex_unlock (&np->lock);
return ENOTDIR;
}
+ err = nowait_dir_changed (notify, DIR_CHANGED_NULL, "");
+ if (err)
+ {
+ mutex_unlock (&np->lock);
+ return err;
+ }
+ req = malloc (sizeof (struct modreq));
req->port = notify;
req->next = np->dirmod_reqs;
np->dirmod_reqs = req;
- nowait_dir_changed (notify, DIR_CHANGED_NULL, "");
mutex_unlock (&np->lock);
return 0;
}
@@ -49,8 +55,21 @@ void
diskfs_notice_dirchange (struct node *dp, enum dir_changed_type type,
char *name)
{
- struct dirmod *req;
+ error_t err;
+ struct modreq **preq;
- for (req = dp->dirmod_reqs; req; req = req->next)
- nowait_dir_changed (req->port, type, name);
+ preq = &dp->dirmod_reqs;
+ while (*preq)
+ {
+ struct modreq *req = *preq;
+ err = nowait_dir_changed (req->port, type, name);
+ if (err)
+ { /* remove notify port */
+ *preq = req->next;
+ mach_port_deallocate (mach_task_self (), req->port);
+ free (req);
+ }
+ else
+ preq = &req->next;
+ }
}
diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h
index c0bf5a06..33717f80 100644
--- a/libdiskfs/diskfs.h
+++ b/libdiskfs/diskfs.h
@@ -100,7 +100,9 @@ struct node
struct conch conch;
- struct dirmod *dirmod_reqs;
+ struct modreq *dirmod_reqs;
+
+ struct modreq *filemod_reqs;
off_t allocsize;
@@ -118,11 +120,11 @@ enum lookup_type
RENAME,
};
-/* Pending directory modification request */
-struct dirmod
+/* Pending directory and file modification request */
+struct modreq
{
mach_port_t port;
- struct dirmod *next;
+ struct modreq *next;
};
@@ -748,6 +750,14 @@ void
diskfs_notice_dirchange (struct node *dp, enum dir_changed_type type,
char *name);
+/* Send notifications to users who have requested them with
+ file_notice_changes for file NP. The type of modification is TYPE.
+ START and END identify the affected region of the file's data.
+ This should be called after the change is fully completed. */
+void
+diskfs_notice_filechange (struct node *np, enum file_changed_type type,
+ off_t start, off_t end);
+
/* Create a new node structure with DS as its physical disknode.
The new node will have one hard reference and no light references. */
struct node *diskfs_make_node (struct disknode *dn);
diff --git a/libdiskfs/file-chauthor.c b/libdiskfs/file-chauthor.c
index 753ee561..6e49c53f 100644
--- a/libdiskfs/file-chauthor.c
+++ b/libdiskfs/file-chauthor.c
@@ -34,6 +34,9 @@ dithkfth_TH_file_chauthor (struct protid *cred,
{
np->dn_thtat.tht_author = author;
np->dn_thet_theetime = 1;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange(np, FILE_CHANGED_META,
+ 0, 0);
}
}));
}
diff --git a/libdiskfs/file-chflags.c b/libdiskfs/file-chflags.c
index d70cc712..55a6f3eb 100644
--- a/libdiskfs/file-chflags.c
+++ b/libdiskfs/file-chflags.c
@@ -30,5 +30,8 @@ diskfs_S_file_chflags (struct protid *cred,
err = diskfs_validate_flags_change (np, flags);
if (!err)
np->dn_stat.st_flags = flags;
+ if (!err && np->filemod_reqs)
+ diskfs_notice_filechange(np, FILE_CHANGED_META,
+ 0, 0);
}));
}
diff --git a/libdiskfs/file-chg.c b/libdiskfs/file-chg.c
index 27d932e6..e9535591 100644
--- a/libdiskfs/file-chg.c
+++ b/libdiskfs/file-chg.c
@@ -17,11 +17,53 @@
#include "priv.h"
#include "fs_S.h"
+#include "ourfs_notify_U.h"
kern_return_t
-diskfs_S_file_notice_changes (struct protid *cred __attribute__ ((unused)),
- mach_port_t notify __attribute__ ((unused)))
+diskfs_S_file_notice_changes (struct protid *cred, mach_port_t notify)
{
- return EOPNOTSUPP;
+ error_t err;
+ struct modreq *req;
+ struct node *np;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ mutex_lock (&np->lock);
+ err = nowait_file_changed (notify, FILE_CHANGED_NULL, 0, 0);
+ if (err)
+ {
+ mutex_unlock (&np->lock);
+ return err;
+ }
+ req = malloc (sizeof (struct modreq));
+ req->port = notify;
+ req->next = np->filemod_reqs;
+ np->filemod_reqs = req;
+ mutex_unlock (&np->lock);
+ return 0;
}
+void
+diskfs_notice_filechange (struct node *dp, enum file_changed_type type,
+ off_t start, off_t end)
+{
+ error_t err;
+ struct modreq **preq;
+
+ preq = &dp->filemod_reqs;
+ while (*preq)
+ {
+ struct modreq *req = *preq;
+ err = nowait_file_changed (req->port, type, start, end);
+ if (err)
+ { /* remove notify port */
+ *preq = req->next;
+ mach_port_deallocate (mach_task_self (), req->port);
+ free (req);
+ }
+ else
+ preq = &req->next;
+ }
+}
diff --git a/libdiskfs/file-chmod.c b/libdiskfs/file-chmod.c
index 66c51a32..09bbe0ea 100644
--- a/libdiskfs/file-chmod.c
+++ b/libdiskfs/file-chmod.c
@@ -45,6 +45,10 @@ diskfs_S_file_chmod (struct protid *cred,
{
np->dn_stat.st_mode = mode;
np->dn_set_ctime = 1;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange(np,
+ FILE_CHANGED_META,
+ 0, 0);
}
}
}));
diff --git a/libdiskfs/file-chown.c b/libdiskfs/file-chown.c
index 0a614338..80477eb8 100644
--- a/libdiskfs/file-chown.c
+++ b/libdiskfs/file-chown.c
@@ -44,6 +44,10 @@ diskfs_S_file_chown (struct protid *cred,
if (np->author_tracks_uid)
np->dn_stat.st_author = uid;
np->dn_set_ctime = 1;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange(np,
+ FILE_CHANGED_META,
+ 0, 0);
}
}
}));
diff --git a/libdiskfs/file-set-size.c b/libdiskfs/file-set-size.c
index f4d3f110..18abb469 100644
--- a/libdiskfs/file-set-size.c
+++ b/libdiskfs/file-set-size.c
@@ -29,7 +29,13 @@ diskfs_S_file_set_size (struct protid *cred,
if (!(cred->po->openstat & O_WRITE))
err = EINVAL;
else if (size < np->dn_stat.st_size)
- err = diskfs_truncate (np, size);
+ {
+ err = diskfs_truncate (np, size);
+ if (!err && np->filemod_reqs)
+ diskfs_notice_filechange (np,
+ FILE_CHANGED_TRUNCATE,
+ 0, size);
+ }
else if (size > np->dn_stat.st_size)
{
err = diskfs_grow (np, size, cred);
@@ -37,6 +43,10 @@ diskfs_S_file_set_size (struct protid *cred,
{
np->dn_stat.st_size = size;
np->dn_set_ctime = np->dn_set_mtime = 1;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange (np,
+ FILE_CHANGED_EXTEND,
+ 0, size);
}
}
else
diff --git a/libdiskfs/io-prenotify.c b/libdiskfs/io-prenotify.c
index 4ae3967b..f88cb286 100644
--- a/libdiskfs/io-prenotify.c
+++ b/libdiskfs/io-prenotify.c
@@ -64,6 +64,8 @@ diskfs_S_io_prenotify (struct protid *cred,
err = diskfs_grow (np, end, cred);
if (diskfs_synchronous)
diskfs_node_update (np, 1);
+ if (!err && np->filemod_reqs)
+ diskfs_notice_filechange (np, FILE_CHANGED_EXTEND, 0, end);
out:
mutex_unlock (&np->lock);
return err;
diff --git a/libdiskfs/io-write.c b/libdiskfs/io-write.c
index e84bdecb..adbfc6d5 100644
--- a/libdiskfs/io-write.c
+++ b/libdiskfs/io-write.c
@@ -64,6 +64,8 @@ diskfs_S_io_write (struct protid *cred,
diskfs_node_update (np, 1);
if (err)
goto out;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange (np, FILE_CHANGED_EXTEND, 0, off + datalen);
}
if (off + (off_t) datalen > np->dn_stat.st_size)
@@ -84,6 +86,8 @@ diskfs_S_io_write (struct protid *cred,
&& ((cred->po->openstat & O_FSYNC) || diskfs_synchronous))
diskfs_file_update (np, 1);
+ if (!err && np->filemod_reqs)
+ diskfs_notice_filechange (np, FILE_CHANGED_WRITE, off, off + *amt);
out:
mutex_unlock (&np->lock);
return err;
diff --git a/libdiskfs/node-drop.c b/libdiskfs/node-drop.c
index 7c30f946..f44966ba 100644
--- a/libdiskfs/node-drop.c
+++ b/libdiskfs/node-drop.c
@@ -17,6 +17,20 @@
#include "priv.h"
+/* Free the list of modification requests MR */
+static void
+free_modreqs (struct modreq *mr)
+{
+ struct modreq *tmp;
+ for (; mr; mr = tmp)
+ {
+ mach_port_deallocate (mach_task_self (), mr->port);
+ tmp = mr->next;
+ free (mr);
+ }
+}
+
+
/* Node NP now has no more references; clean all state. The
diskfs_node_refcnt_lock must be held, and will be released
upon return. NP must be locked. */
@@ -73,15 +87,9 @@ diskfs_drop_node (struct node *np)
fshelp_drop_transbox (&np->transbox);
if (np->dirmod_reqs)
- {
- struct dirmod *dm, *tmp;
- for (dm = np->dirmod_reqs; dm; dm = tmp)
- {
- mach_port_deallocate (mach_task_self (), dm->port);
- tmp = dm->next;
- free (dm);
- }
- }
+ free_modreqs (np->dirmod_reqs);
+ if (np->filemod_reqs)
+ free_modreqs (np->filemod_reqs);
assert (!np->sockaddr);
diff --git a/libdiskfs/node-make.c b/libdiskfs/node-make.c
index 972167a2..ca5119a0 100644
--- a/libdiskfs/node-make.c
+++ b/libdiskfs/node-make.c
@@ -39,6 +39,7 @@ diskfs_make_node (struct disknode *dn)
np->sockaddr = MACH_PORT_NULL;
np->dirmod_reqs = 0;
+ np->filemod_reqs = 0;
fshelp_transbox_init (&np->transbox, &np->lock, np);
iohelp_initialize_conch (&np->conch, &np->lock);
diff --git a/libdiskfs/node-rdwr.c b/libdiskfs/node-rdwr.c
index 319a985c..ed94df44 100644
--- a/libdiskfs/node-rdwr.c
+++ b/libdiskfs/node-rdwr.c
@@ -45,6 +45,8 @@ diskfs_node_rdwr (struct node *np,
err = diskfs_grow (np, off + amt, cred);
if (err)
return err;
+ if (np->filemod_reqs)
+ diskfs_notice_filechange (np, FILE_CHANGED_EXTEND, 0, off + amt);
}
if (off + amt > np->dn_stat.st_size)