Hi, This patch implements what Marcus and Roland proposed to fix the fatfs locking issue. This patch only deals with the reading problem of fatfs, the writing part will be a lot more work. I will do that later.
Thanks, Marco 2004-03-08 Marco Gerards <[EMAIL PROTECTED]> * diskfs.h (diskfs_cached_lookup): Add DIR argument. * fsys-getfile.c (diskfs_S_fsys_getfile): Use the DIR argument of diskfs_cached_lookup. * name-cache.c (diskfs_check_lookup_cache): Likewise. Index: diskfs.h =================================================================== RCS file: /cvsroot/hurd/hurd/libdiskfs/diskfs.h,v retrieving revision 1.98 diff -u -p -r1.98 diskfs.h --- diskfs.h 27 Jun 2002 19:19:13 -0000 1.98 +++ diskfs.h 7 Mar 2004 14:59:01 -0000 @@ -1,5 +1,5 @@ /* Definitions for fileserver helper functions - Copyright (C) 1994,95,96,97,98,99,2001,02 Free Software Foundation, Inc. + Copyright (C) 1994,95,96,97,98,99,2001,02,2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -751,8 +751,10 @@ error_t diskfs_dirrewrite (struct node * error_t diskfs_dirremove (struct node *dp, struct node *np, const char *name, struct dirstat *ds); -/* Return the node corresponding to CACHE_ID in *NPP. */ -error_t diskfs_cached_lookup (ino64_t cache_id, struct node **npp); +/* Return the node corresponding to CACHE_ID in *NPP. If the + directory containing the node is locked DIR is set to its node. */ +error_t diskfs_cached_lookup (ino64_t cache_id, struct node **npp, + struct node *dir); /* Create a new node. Give it MODE; if that includes IFDIR, also initialize `.' and `..' in the new directory. Return the node in NPP. Index: fsys-getfile.c =================================================================== RCS file: /cvsroot/hurd/hurd/libdiskfs/fsys-getfile.c,v retrieving revision 1.9 diff -u -p -r1.9 fsys-getfile.c --- fsys-getfile.c 26 Mar 2002 14:59:52 -0000 1.9 +++ fsys-getfile.c 7 Mar 2004 14:59:02 -0000 @@ -1,6 +1,6 @@ /* Return the file for a given handle (for nfs server support) - Copyright (C) 1997,99,2001,02 Free Software Foundation, Inc. + Copyright (C) 1997,99,2001,02,2004 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -55,7 +55,7 @@ diskfs_S_fsys_getfile (mach_port_t fsys, f = (const union diskfs_fhandle *) handle; - err = diskfs_cached_lookup (f->data.cache_id, &node); + err = diskfs_cached_lookup (f->data.cache_id, &node, 0); if (err) { ports_port_deref (pt); Index: name-cache.c =================================================================== RCS file: /cvsroot/hurd/hurd/libdiskfs/name-cache.c,v retrieving revision 1.12 diff -u -p -r1.12 name-cache.c --- name-cache.c 24 Oct 1998 07:50:11 -0000 1.12 +++ name-cache.c 7 Mar 2004 14:59:02 -0000 @@ -1,6 +1,6 @@ /* Directory name lookup caching - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 2004 Free Software Foundation, Inc. Written by Michael I. Bushnell, p/BSG, & Miles Bader. This file is part of the GNU Hurd. @@ -238,7 +238,7 @@ diskfs_check_lookup_cache (struct node * if (name[0] == '.' && name[1] == '.' && name[2] == '\0') { mutex_unlock (&dir->lock); - err = diskfs_cached_lookup (id, &np); + err = diskfs_cached_lookup (id, &np, 0); mutex_lock (&dir->lock); /* In the window where DP was unlocked, we might @@ -253,7 +253,7 @@ diskfs_check_lookup_cache (struct node * } } else - err = diskfs_cached_lookup (id, &np); + err = diskfs_cached_lookup (id, &np, dir); return err ? 0 : np; } } 2004-03-08 Marco Gerards <[EMAIL PROTECTED]> * hurd.texi (Diskfs Callbacks): Added argument to diskfs_cached_lookup. Index: hurd.texi =================================================================== RCS file: /cvsroot/hurd/hurd/doc/hurd.texi,v retrieving revision 1.26 diff -u -p -r1.26 hurd.texi --- hurd.texi 1 Feb 2004 22:04:51 -0000 1.26 +++ hurd.texi 7 Mar 2004 15:02:26 -0000 @@ -98,7 +98,7 @@ @end direntry @ifinfo -Copyright @copyright{} 1994-2002 Free Software Foundation, Inc. +Copyright @copyright{} 1994-2004 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -3969,8 +3969,9 @@ not exist, then return -1. Otherwise, r with a newly-allocated reference. @end deftypefun [EMAIL PROTECTED] error_t diskfs_cached_lookup (@w{int @var{cache_id}}, @w{struct node [EMAIL PROTECTED]) [EMAIL PROTECTED] error_t diskfs_cached_lookup (@w{int @var{cache_id}}, @w{struct node [EMAIL PROTECTED], @w{struct node [EMAIL PROTECTED]) Return the node corresponding to @var{cache_id} in @[EMAIL PROTECTED] +If the directory containing the node is locked @[EMAIL PROTECTED] is set to its node. @end deftypefun @deftypefun void diskfs_enter_lookup_cache (@w{struct node [EMAIL PROTECTED], @w{struct node [EMAIL PROTECTED], @w{char [EMAIL PROTECTED]) 2004-03-08 Marco Gerards <[EMAIL PROTECTED]> * inode.c (read_node): Add DIR argument to prototype. (diskfs_cached_lookup): Add DIR argument, change all callers. (read_node): Add DIR argument and change all callers. Do not lookup the directory when DIR already holds it, in that case don't call diskfs_nput before returning. Index: inode.c =================================================================== RCS file: /cvsroot/hurd/hurd/fatfs/inode.c,v retrieving revision 1.5 diff -u -p -r1.5 inode.c --- inode.c 6 Aug 2003 21:47:57 -0000 1.5 +++ inode.c 7 Mar 2004 14:59:49 -0000 @@ -1,5 +1,5 @@ /* inode.c - Inode management routines. - Copyright (C) 1994,95,96,97,98,99,2000,02,03 Free Software Foundation, Inc. + Copyright (C) 1994,95,96,97,98,99,2000,02,03,2004 Free Software Foundation, Inc. Modified for fatfs by Marcus Brinkmann <[EMAIL PROTECTED]> This file is part of the GNU Hurd. @@ -42,7 +42,7 @@ static struct node *nodehash[INOHSZ]; -static error_t read_node (struct node *np, vm_address_t buf); +static error_t read_node (struct node *np, vm_address_t buf, struct node *dir); /* Initialize the inode hash table. */ void @@ -56,7 +56,7 @@ inode_init () /* Fetch inode INUM, set *NPP to the node structure; gain one user reference and lock the node. */ error_t -diskfs_cached_lookup (ino64_t inum, struct node **npp) +diskfs_cached_lookup (ino64_t inum, struct node **npp, struct node *dir) { error_t err; struct node *np; @@ -106,7 +106,7 @@ diskfs_cached_lookup (ino64_t inum, stru spin_unlock (&diskfs_node_refcnt_lock); /* Get the contents of NP off disk. */ - err = read_node (np, 0); + err = read_node (np, 0, dir); if (err) return err; @@ -171,7 +171,7 @@ diskfs_cached_lookup_in_dirbuf (int inum spin_unlock (&diskfs_node_refcnt_lock); /* Get the contents of NP off disk. */ - err = read_node (np, buf); + err = read_node (np, buf, 0); if (err) return err; @@ -262,14 +262,14 @@ diskfs_new_hardrefs (struct node *np) /* Read stat information out of the directory entry. */ static error_t -read_node (struct node *np, vm_address_t buf) +read_node (struct node *np, vm_address_t buf, struct node *dir) { /* XXX This needs careful investigation. */ error_t err; struct stat *st = &np->dn_stat; struct disknode *dn = np->dn; struct dirrect *dr; - struct node *dp = 0; + struct node *dp = dir; struct vi_key vk = vi_key(np->dn->inode); vm_prot_t prot = VM_PROT_READ; memory_object_t memobj; @@ -306,17 +306,22 @@ read_node (struct node *np, vm_address_t { if (buf == 0) { - /* FIXME: We know intimately that the parent dir is locked - by libdiskfs. The only case it is not locked is for NFS - (fsys_getfile) and we disabled that. */ - dp = ifind (vk.dir_inode); - assert (dp); - + if (!dp) + { + err = diskfs_cached_lookup (vk.dir_inode, &dp, 0); + if (err) + return err; + } + /* Map in the directory contents. */ memobj = diskfs_get_filemap (dp, prot); if (memobj == MACH_PORT_NULL) - return errno; + { + if (!dir) + diskfs_nput (dp); + return errno; + } buflen = round_page (dp->dn_stat.st_size); err = vm_map (mach_task_self (), @@ -359,6 +364,8 @@ read_node (struct node *np, vm_address_t { if (our_buf && buf) munmap ((caddr_t) buf, buflen); + if (dp && !dir) + diskfs_nput (np); return err; } st->st_size = np->allocsize; @@ -394,6 +401,8 @@ read_node (struct node *np, vm_address_t if (our_buf && buf) munmap ((caddr_t) buf, buflen); + if (dp && !dir) + diskfs_nput (dp); return 0; } @@ -532,7 +541,7 @@ diskfs_node_reload (struct node *node) last = next; } flush_node_pager (node); - read_node (node, 0); + read_node (node, 0, 0); return 0; } @@ -770,7 +779,7 @@ diskfs_alloc_node (struct node *dir, mod if (err) return err; - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); if (err) return err; Index: main.c =================================================================== RCS file: /cvsroot/hurd/hurd/fatfs/main.c,v retrieving revision 1.3 diff -u -p -r1.3 main.c --- main.c 2 Aug 2003 21:32:52 -0000 1.3 +++ main.c 7 Mar 2004 14:59:49 -0000 @@ -201,7 +201,7 @@ fetch_root () /* Allocate a node for the root directory disknode in diskfs_root_node. */ if (!err) - err = diskfs_cached_lookup (inum, &diskfs_root_node); + err = diskfs_cached_lookup (inum, &diskfs_root_node, 0); assert_perror (err); 2004-03-08 Marco Gerards <[EMAIL PROTECTED]> * node.c (diskfs_cached_lookup): Added DIR argument and changed all callers. Index: alloc.c =================================================================== RCS file: /cvsroot/hurd/hurd/ufs/alloc.c,v retrieving revision 1.24 diff -u -p -r1.24 alloc.c --- alloc.c 11 Jun 2002 21:41:03 -0000 1.24 +++ alloc.c 7 Mar 2004 14:57:20 -0000 @@ -1,5 +1,5 @@ /* Disk allocation routines - Copyright (C) 1993,94,95,96,98,2002 Free Software Foundation, Inc. + Copyright (C) 1993,94,95,96,98,2002,2004 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -681,7 +681,7 @@ diskfs_alloc_node (struct node *dir, spin_unlock (&alloclock); if (ino == 0) goto noinodes; - error = diskfs_cached_lookup (ino, &np); + error = diskfs_cached_lookup (ino, &np, 0); assert ("duplicate allocation" && !np->dn_stat.st_mode); assert (! (np->dn_stat.st_mode & S_IPTRANS)); if (np->dn_stat.st_blocks) { Index: dir.c =================================================================== RCS file: /cvsroot/hurd/hurd/ufs/dir.c,v retrieving revision 1.45 diff -u -p -r1.45 dir.c --- dir.c 1 Aug 2002 00:59:18 -0000 1.45 +++ dir.c 7 Mar 2004 14:57:26 -0000 @@ -220,7 +220,7 @@ diskfs_lookup_hard (struct node *dp, con } else { - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); if (err) goto out; } @@ -245,7 +245,7 @@ diskfs_lookup_hard (struct node *dp, con try *again*. */ diskfs_nput (np); mutex_unlock (&dp->lock); - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); mutex_lock (&dp->lock); if (err) goto out; @@ -260,7 +260,7 @@ diskfs_lookup_hard (struct node *dp, con repeat the directory scan to see if this is still right. */ mutex_unlock (&dp->lock); - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); mutex_lock (&dp->lock); if (err) goto out; @@ -275,7 +275,7 @@ diskfs_lookup_hard (struct node *dp, con else if (type == LOOKUP) { diskfs_nput (dp); - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); if (err) goto out; } Index: inode.c =================================================================== RCS file: /cvsroot/hurd/hurd/ufs/inode.c,v retrieving revision 1.59 diff -u -p -r1.59 inode.c --- inode.c 11 Jun 2002 21:41:06 -0000 1.59 +++ inode.c 7 Mar 2004 14:57:27 -0000 @@ -1,5 +1,5 @@ /* Inode management routines - Copyright (C) 1994,95,96,97,98,2000,01,02 Free Software Foundation, Inc. + Copyright (C) 1994,95,96,97,98,2000,01,02,2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -47,7 +47,7 @@ inode_init () /* Fetch inode INUM, set *NPP to the node structure; gain one user reference and lock the node. */ error_t -diskfs_cached_lookup (ino_t inum, struct node **npp) +diskfs_cached_lookup (ino_t inum, struct node **npp, struct node *dir) { struct disknode *dn; struct node *np; Index: main.c =================================================================== RCS file: /cvsroot/hurd/hurd/ufs/main.c,v retrieving revision 1.50 diff -u -p -r1.50 main.c --- main.c 8 May 2002 09:59:52 -0000 1.50 +++ main.c 7 Mar 2004 14:57:27 -0000 @@ -44,7 +44,7 @@ static void warp_root (void) { error_t err; - err = diskfs_cached_lookup (2, &diskfs_root_node); + err = diskfs_cached_lookup (2, &diskfs_root_node, 0); assert (!err); mutex_unlock (&diskfs_root_node->lock); } 2004-03-08 Marco Gerards <[EMAIL PROTECTED]> * node.c (diskfs_cached_lookup): Added DIR argument and changed all callers. Index: dir.c =================================================================== RCS file: /cvsroot/hurd/hurd/tmpfs/dir.c,v retrieving revision 1.12 diff -u -p -r1.12 dir.c --- dir.c 13 Jun 2002 21:27:13 -0000 1.12 +++ dir.c 7 Mar 2004 14:53:54 -0000 @@ -198,7 +198,7 @@ diskfs_lookup_hard (struct node *dp, else { mutex_unlock (&dp->lock); - err = diskfs_cached_lookup ((ino_t) (intptr_t) dddn, np); + err = diskfs_cached_lookup ((ino_t) (intptr_t) dddn, np, 0); if (type == (LOOKUP|SPEC_DOTDOT)) diskfs_nrele (dp); @@ -220,7 +220,7 @@ diskfs_lookup_hard (struct node *dp, ds->prevp = prevp; if (np) - return diskfs_cached_lookup ((ino_t) (uintptr_t) d->dn, np); + return diskfs_cached_lookup ((ino_t) (uintptr_t) d->dn, np, 0); else return 0; } Index: node.c =================================================================== RCS file: /cvsroot/hurd/hurd/tmpfs/node.c,v retrieving revision 1.12 diff -u -p -r1.12 node.c --- node.c 11 Jun 2002 21:40:50 -0000 1.12 +++ node.c 7 Mar 2004 14:53:54 -0000 @@ -1,5 +1,5 @@ /* Node state and file contents for tmpfs. - Copyright (C) 2000,01,02 Free Software Foundation, Inc. + Copyright (C) 2000,01,02,2004 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -52,7 +52,7 @@ diskfs_alloc_node (struct node *dp, mode spin_unlock (&diskfs_node_refcnt_lock); dn->type = IFTODT (mode & S_IFMT); - return diskfs_cached_lookup ((ino_t) (uintptr_t) dn, npp); + return diskfs_cached_lookup ((ino_t) (uintptr_t) dn, npp, 0); } void @@ -154,7 +154,7 @@ recompute_blocks (struct node *np) /* Fetch inode INUM, set *NPP to the node structure; gain one user reference and lock the node. */ error_t -diskfs_cached_lookup (ino_t inum, struct node **npp) +diskfs_cached_lookup (ino_t inum, struct node **npp, struct node *dir) { struct disknode *dn = (void *) (uintptr_t) inum; struct node *np; 2004-03-08 Marco Gerards <[EMAIL PROTECTED]> * node.c (diskfs_cached_lookup): Added DIR argument and changed all callers. Index: dir.c =================================================================== RCS file: /cvsroot/hurd/hurd/ext2fs/dir.c,v retrieving revision 1.45 diff -u -p -r1.45 dir.c --- dir.c 10 Jan 2004 22:08:58 -0000 1.45 +++ dir.c 7 Mar 2004 14:58:26 -0000 @@ -254,7 +254,7 @@ diskfs_lookup_hard (struct node *dp, con } else { - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); if (err) goto out; } @@ -279,7 +279,7 @@ diskfs_lookup_hard (struct node *dp, con try *again*. */ diskfs_nput (np); mutex_unlock (&dp->lock); - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); mutex_lock (&dp->lock); if (err) goto out; @@ -294,7 +294,7 @@ diskfs_lookup_hard (struct node *dp, con repeat the directory scan to see if this is still right. */ mutex_unlock (&dp->lock); - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); mutex_lock (&dp->lock); if (err) goto out; @@ -309,7 +309,7 @@ diskfs_lookup_hard (struct node *dp, con else if (type == LOOKUP) { diskfs_nput (dp); - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); if (err) goto out; } Index: ext2fs.c =================================================================== RCS file: /cvsroot/hurd/hurd/ext2fs/ext2fs.c,v retrieving revision 1.55 diff -u -p -r1.55 ext2fs.c --- ext2fs.c 2 Jun 2002 21:40:56 -0000 1.55 +++ ext2fs.c 7 Mar 2004 14:58:29 -0000 @@ -188,7 +188,7 @@ main (int argc, char **argv) inode_init (); /* Set diskfs_root_node to the root inode. */ - err = diskfs_cached_lookup (EXT2_ROOT_INO, &diskfs_root_node); + err = diskfs_cached_lookup (EXT2_ROOT_INO, &diskfs_root_node, 0); if (err) ext2_panic ("can't get root: %s", strerror (err)); else if ((diskfs_root_node->dn_stat.st_mode & S_IFMT) == 0) Index: ialloc.c =================================================================== RCS file: /cvsroot/hurd/hurd/ext2fs/ialloc.c,v retrieving revision 1.38 diff -u -p -r1.38 ialloc.c --- ialloc.c 8 Oct 2002 23:10:09 -0000 1.38 +++ ialloc.c 7 Mar 2004 14:58:29 -0000 @@ -283,7 +283,7 @@ diskfs_alloc_node (struct node *dir, mod if (inum == 0) return ENOSPC; - err = diskfs_cached_lookup (inum, &np); + err = diskfs_cached_lookup (inum, &np, 0); if (err) return err; Index: inode.c =================================================================== RCS file: /cvsroot/hurd/hurd/ext2fs/inode.c,v retrieving revision 1.62 diff -u -p -r1.62 inode.c --- inode.c 8 Oct 2002 23:10:09 -0000 1.62 +++ inode.c 7 Mar 2004 14:58:31 -0000 @@ -1,6 +1,6 @@ /* Inode management routines - Copyright (C) 1994,95,96,97,98,99,2000,01,02 Free Software Foundation, Inc. + Copyright (C) 1994,95,96,97,98,99,2000,01,02,04 Free Software Foundation, Inc. Converted for ext2fs by Miles Bader <[EMAIL PROTECTED]> @@ -63,7 +63,7 @@ inode_init () /* Fetch inode INUM, set *NPP to the node structure; gain one user reference and lock the node. */ error_t -diskfs_cached_lookup (ino_t inum, struct node **npp) +diskfs_cached_lookup (ino_t inum, struct node **npp, struct node *dir) { error_t err; struct node *np; 2004-03-08 Marco Gerards <[EMAIL PROTECTED]> * inode.c (diskfs_cached_lookup): Added DIR argument. Index: inode.c =================================================================== RCS file: /cvsroot/hurd/hurd/isofs/inode.c,v retrieving revision 1.16 diff -u -p -r1.16 inode.c --- inode.c 6 Aug 2002 12:33:17 -0000 1.16 +++ inode.c 7 Mar 2004 15:07:01 -0000 @@ -1,5 +1,5 @@ /* - Copyright (C) 1997,98,2002 Free Software Foundation, Inc. + Copyright (C) 1997,98,2002,2004 Free Software Foundation, Inc. Written by Thomas Bushnell, n/BSG. This file is part of the GNU Hurd. @@ -145,7 +145,7 @@ cache_inode (struct node *np, struct dir /* Fetch inode with cache id ID; set *NPP to the node structure; gain one user reference and lock the node. */ error_t -diskfs_cached_lookup (ino_t id, struct node **npp) +diskfs_cached_lookup (ino_t id, struct node **npp, struct node *dir) { struct node *np; error_t err; _______________________________________________ Bug-hurd mailing list [EMAIL PROTECTED] http://mail.gnu.org/mailman/listinfo/bug-hurd