diff options
-rw-r--r-- | libdiskfs/ChangeLog | 31 | ||||
-rw-r--r-- | libdiskfs/boot-start.c | 4 | ||||
-rw-r--r-- | libdiskfs/dir-chg.c | 31 | ||||
-rw-r--r-- | libdiskfs/diskfs.h | 18 | ||||
-rw-r--r-- | libdiskfs/file-chauthor.c | 3 | ||||
-rw-r--r-- | libdiskfs/file-chflags.c | 3 | ||||
-rw-r--r-- | libdiskfs/file-chg.c | 48 | ||||
-rw-r--r-- | libdiskfs/file-chmod.c | 4 | ||||
-rw-r--r-- | libdiskfs/file-chown.c | 4 | ||||
-rw-r--r-- | libdiskfs/file-set-size.c | 12 | ||||
-rw-r--r-- | libdiskfs/io-prenotify.c | 2 | ||||
-rw-r--r-- | libdiskfs/io-write.c | 4 | ||||
-rw-r--r-- | libdiskfs/node-drop.c | 26 | ||||
-rw-r--r-- | libdiskfs/node-make.c | 1 | ||||
-rw-r--r-- | libdiskfs/node-rdwr.c | 2 |
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) |