]>
Commit | Line | Data |
---|---|---|
1557aca7 BF |
1 | /* Copyright (C) 1995, 1996, 1997 Olaf Kirch <[email protected]> */ |
2 | ||
3 | #ifndef _LINUX_NFSD_FH_INT_H | |
4 | #define _LINUX_NFSD_FH_INT_H | |
5 | ||
6 | #include <linux/nfsd/nfsfh.h> | |
7 | ||
8 | enum nfsd_fsid { | |
9 | FSID_DEV = 0, | |
10 | FSID_NUM, | |
11 | FSID_MAJOR_MINOR, | |
12 | FSID_ENCODE_DEV, | |
13 | FSID_UUID4_INUM, | |
14 | FSID_UUID8, | |
15 | FSID_UUID16, | |
16 | FSID_UUID16_INUM, | |
17 | }; | |
18 | ||
19 | enum fsid_source { | |
20 | FSIDSOURCE_DEV, | |
21 | FSIDSOURCE_FSID, | |
22 | FSIDSOURCE_UUID, | |
23 | }; | |
24 | extern enum fsid_source fsid_source(struct svc_fh *fhp); | |
25 | ||
26 | ||
27 | /* This might look a little large to "inline" but in all calls except | |
28 | * one, 'vers' is constant so moste of the function disappears. | |
29 | */ | |
30 | static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino, | |
31 | u32 fsid, unsigned char *uuid) | |
32 | { | |
33 | u32 *up; | |
34 | switch(vers) { | |
35 | case FSID_DEV: | |
36 | fsidv[0] = htonl((MAJOR(dev)<<16) | | |
37 | MINOR(dev)); | |
38 | fsidv[1] = ino_t_to_u32(ino); | |
39 | break; | |
40 | case FSID_NUM: | |
41 | fsidv[0] = fsid; | |
42 | break; | |
43 | case FSID_MAJOR_MINOR: | |
44 | fsidv[0] = htonl(MAJOR(dev)); | |
45 | fsidv[1] = htonl(MINOR(dev)); | |
46 | fsidv[2] = ino_t_to_u32(ino); | |
47 | break; | |
48 | ||
49 | case FSID_ENCODE_DEV: | |
50 | fsidv[0] = new_encode_dev(dev); | |
51 | fsidv[1] = ino_t_to_u32(ino); | |
52 | break; | |
53 | ||
54 | case FSID_UUID4_INUM: | |
55 | /* 4 byte fsid and inode number */ | |
56 | up = (u32*)uuid; | |
57 | fsidv[0] = ino_t_to_u32(ino); | |
58 | fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3]; | |
59 | break; | |
60 | ||
61 | case FSID_UUID8: | |
62 | /* 8 byte fsid */ | |
63 | up = (u32*)uuid; | |
64 | fsidv[0] = up[0] ^ up[2]; | |
65 | fsidv[1] = up[1] ^ up[3]; | |
66 | break; | |
67 | ||
68 | case FSID_UUID16: | |
69 | /* 16 byte fsid - NFSv3+ only */ | |
70 | memcpy(fsidv, uuid, 16); | |
71 | break; | |
72 | ||
73 | case FSID_UUID16_INUM: | |
74 | /* 8 byte inode and 16 byte fsid */ | |
75 | *(u64*)fsidv = (u64)ino; | |
76 | memcpy(fsidv+2, uuid, 16); | |
77 | break; | |
78 | default: BUG(); | |
79 | } | |
80 | } | |
81 | ||
82 | static inline int key_len(int type) | |
83 | { | |
84 | switch(type) { | |
85 | case FSID_DEV: return 8; | |
86 | case FSID_NUM: return 4; | |
87 | case FSID_MAJOR_MINOR: return 12; | |
88 | case FSID_ENCODE_DEV: return 8; | |
89 | case FSID_UUID4_INUM: return 8; | |
90 | case FSID_UUID8: return 8; | |
91 | case FSID_UUID16: return 16; | |
92 | case FSID_UUID16_INUM: return 24; | |
93 | default: return 0; | |
94 | } | |
95 | } | |
96 | ||
97 | /* | |
98 | * Shorthand for dprintk()'s | |
99 | */ | |
100 | extern char * SVCFH_fmt(struct svc_fh *fhp); | |
101 | ||
102 | /* | |
103 | * Function prototypes | |
104 | */ | |
175a4eb7 | 105 | __be32 fh_verify(struct svc_rqst *, struct svc_fh *, umode_t, int); |
1557aca7 BF |
106 | __be32 fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *); |
107 | __be32 fh_update(struct svc_fh *); | |
108 | void fh_put(struct svc_fh *); | |
109 | ||
110 | static __inline__ struct svc_fh * | |
111 | fh_copy(struct svc_fh *dst, struct svc_fh *src) | |
112 | { | |
113 | WARN_ON(src->fh_dentry || src->fh_locked); | |
114 | ||
115 | *dst = *src; | |
116 | return dst; | |
117 | } | |
118 | ||
119 | static inline void | |
120 | fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src) | |
121 | { | |
122 | dst->fh_size = src->fh_size; | |
123 | memcpy(&dst->fh_base, &src->fh_base, src->fh_size); | |
124 | } | |
125 | ||
126 | static __inline__ struct svc_fh * | |
127 | fh_init(struct svc_fh *fhp, int maxsize) | |
128 | { | |
129 | memset(fhp, 0, sizeof(*fhp)); | |
130 | fhp->fh_maxsize = maxsize; | |
131 | return fhp; | |
132 | } | |
133 | ||
134 | #ifdef CONFIG_NFSD_V3 | |
135 | /* | |
136 | * Fill in the pre_op attr for the wcc data | |
137 | */ | |
138 | static inline void | |
139 | fill_pre_wcc(struct svc_fh *fhp) | |
140 | { | |
141 | struct inode *inode; | |
142 | ||
143 | inode = fhp->fh_dentry->d_inode; | |
144 | if (!fhp->fh_pre_saved) { | |
145 | fhp->fh_pre_mtime = inode->i_mtime; | |
146 | fhp->fh_pre_ctime = inode->i_ctime; | |
147 | fhp->fh_pre_size = inode->i_size; | |
148 | fhp->fh_pre_change = inode->i_version; | |
149 | fhp->fh_pre_saved = 1; | |
150 | } | |
151 | } | |
152 | ||
153 | extern void fill_post_wcc(struct svc_fh *); | |
154 | #else | |
155 | #define fill_pre_wcc(ignored) | |
156 | #define fill_post_wcc(notused) | |
157 | #endif /* CONFIG_NFSD_V3 */ | |
158 | ||
159 | ||
160 | /* | |
161 | * Lock a file handle/inode | |
162 | * NOTE: both fh_lock and fh_unlock are done "by hand" in | |
163 | * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once | |
164 | * so, any changes here should be reflected there. | |
165 | */ | |
166 | ||
167 | static inline void | |
168 | fh_lock_nested(struct svc_fh *fhp, unsigned int subclass) | |
169 | { | |
170 | struct dentry *dentry = fhp->fh_dentry; | |
171 | struct inode *inode; | |
172 | ||
173 | BUG_ON(!dentry); | |
174 | ||
175 | if (fhp->fh_locked) { | |
176 | printk(KERN_WARNING "fh_lock: %s/%s already locked!\n", | |
177 | dentry->d_parent->d_name.name, dentry->d_name.name); | |
178 | return; | |
179 | } | |
180 | ||
181 | inode = dentry->d_inode; | |
182 | mutex_lock_nested(&inode->i_mutex, subclass); | |
183 | fill_pre_wcc(fhp); | |
184 | fhp->fh_locked = 1; | |
185 | } | |
186 | ||
187 | static inline void | |
188 | fh_lock(struct svc_fh *fhp) | |
189 | { | |
190 | fh_lock_nested(fhp, I_MUTEX_NORMAL); | |
191 | } | |
192 | ||
193 | /* | |
194 | * Unlock a file handle/inode | |
195 | */ | |
196 | static inline void | |
197 | fh_unlock(struct svc_fh *fhp) | |
198 | { | |
1557aca7 BF |
199 | if (fhp->fh_locked) { |
200 | fill_post_wcc(fhp); | |
201 | mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex); | |
202 | fhp->fh_locked = 0; | |
203 | } | |
204 | } | |
205 | ||
206 | #endif /* _LINUX_NFSD_FH_INT_H */ |