1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
/* Private declarations for fileserver library
Copyright (C) 1994 Free Software Foundation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
extern mach_port_t fs_control_port; /* receive right */
spin_lock_t _diskfs_node_refcnt_lock = SPIN_LOCK_INITIALIZER;
/* Called by MiG to translate ports into struct protid *.
fsmutations.h arranges for this to happen for the io and
fs interfaces. */
extern inline struct protid *
begin_using_protid_port (file_t port)
{
return ports_check_port_type (port, PT_PROTID);
}
/* Called by MiG after server routines have been run; this
balances begin_using_protid_port, and is arranged for the io
and fs interfaces by fsmutations.h. */
extern inline void
diskfs_end_using_protid_port (struct protid *cred)
{
ports_done_with_port (cred);
}
/* Add a reference to a node. */
extern inline void
diskfs_nref (struct node *np)
{
spin_lock (&_diskfs_node_refcnt_lock);
np->references++;
spin_unlock (&_diskfs_node_refcnt_lock);
}
/* Unlock node NP and release a reference */
extern inline void
diskfs_nput (struct node *np)
{
spin_lock (&_diskfs_node_refcnt_lock);
np->references--;
if (np->references == 0)
{
diskfs_drop_node (np);
spin_unlock (&_diskfs_node_refcnt_lock);
}
else
{
spin_unlock (&_diskfs_node_refcnt_lock);
mutex_unlock (&np->lock);
}
}
/* Release a reference on NP. If NP is locked by anyone, then this cannot
be the last reference (because you must hold a reference in order to
hold the lock). */
extern inline void
diskfs_nrele (struct node *np)
{
spin_lock (&_diskfs_node_refcnt_lock);
np->references--;
if (np->references == 0)
diskfs_drop_node (np);
spin_unlock (&_diskfs_node_refcnt_lock);
}
/* This macro locks the node associated with PROTID, and then
evaluates the expression OPERATION; then it syncs the inode
(without waiting) and unlocks everything, and then returns
the value `err' (which can be set by OPERATION if desired). */
#define CHANGE_NODE_FIELD(PROTID, OPERATION) \
({ \
error_t err = 0; \
struct node *np; \
\
if (!(PROTID)) \
return EOPNOTSUPP; \
\
if (readonly) \
return EROFS; \
\
np = (PROTID)->po->np; \
\
mutex_lock (&np->lock); \
(OPERATION); \
diskfs_node_update (np, 0); \
mutex_unlock (&np->lock); \
return err; \
})
|