ReactOS 0.4.15-dev-7994-gb388cb6
nfs41_superblock.c
Go to the documentation of this file.
1/* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
3 *
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
6 *
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * without any warranty; without even the implied warranty of merchantability
14 * or fitness for a particular purpose. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 */
21
22#include <windows.h>
23#include <stdio.h>
24
25#include "daemon_debug.h"
26#include "nfs41.h"
27#include "nfs41_ops.h"
28#include "from_kernel.h"
29#include "util.h"
30
31
32#define SBLVL 3 /* dprintf level for superblock logging */
33
34
35static __inline int compare_fsid(
36 IN const nfs41_fsid *lhs,
37 IN const nfs41_fsid *rhs)
38{
39 if (lhs->major > rhs->major) return 1;
40 if (lhs->major < rhs->major) return -1;
41 if (lhs->minor > rhs->minor) return 1;
42 if (lhs->minor < rhs->minor) return -1;
43 return 0;
44}
45
46
47/* nfs41_superblock */
49 IN const nfs41_fsid *fsid,
50 OUT nfs41_superblock **superblock_out)
51{
52 int status = NO_ERROR;
54
55 dprintf(SBLVL, "creating superblock for fsid(%llu,%llu)\n",
56 fsid->major, fsid->minor);
57
59 if (superblock == NULL) {
61 eprintf("failed to allocate superblock "
62 "for fsid(%llu,%llu)\n", fsid->major, fsid->minor);
63 goto out;
64 }
65
66 memcpy(&superblock->fsid, fsid, sizeof(nfs41_fsid));
68
69 *superblock_out = superblock;
70out:
71 return status;
72}
73
78{
79 bool_t supports_named_attrs;
80 int status;
81 bitmap4 attr_request;
82 nfs41_file_info info = { 0 };
83
84 attr_request.arr[0] = FATTR4_WORD0_SUPPORTED_ATTRS |
89 attr_request.arr[1] = FATTR4_WORD1_FS_LAYOUT_TYPE |
91 attr_request.arr[2] = FATTR4_WORD2_SUPPATTR_EXCLCREAT;
92 attr_request.count = 3;
93
94 info.supported_attrs = &superblock->supported_attrs;
95 info.suppattr_exclcreat = &superblock->suppattr_exclcreat;
96 info.time_delta = &superblock->time_delta;
97
99 &attr_request, &info, &supports_named_attrs);
100 if (status) {
101 eprintf("nfs41_superblock_getattr() failed with %s when fetching "
102 "attributes for fsid(%llu,%llu)\n", nfs_error_string(status),
103 superblock->fsid.major, superblock->fsid.minor);
104 goto out;
105 }
106
107 if (info.maxread)
108 superblock->maxread = info.maxread;
109 else
110 superblock->maxread = session->fore_chan_attrs.ca_maxresponsesize;
111
112 if (info.maxwrite)
113 superblock->maxwrite = info.maxwrite;
114 else
115 superblock->maxwrite = session->fore_chan_attrs.ca_maxrequestsize;
116
117 superblock->layout_types = info.fs_layout_types;
118 superblock->aclsupport = info.aclsupport;
119 superblock->link_support = info.link_support;
120 superblock->symlink_support = info.symlink_support;
121 superblock->ea_support = supports_named_attrs;
122 superblock->case_preserving = info.case_preserving;
123 superblock->case_insensitive = info.case_insensitive;
124
125 if (bitmap_isset(&info.attrmask, 0, FATTR4_WORD0_CANSETTIME))
126 superblock->cansettime = info.cansettime;
127 else /* cansettime is not supported, try setting them anyway */
128 superblock->cansettime = 1;
129
130 /* if time_delta is not supported, default to 1s */
131 if (!bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_TIME_DELTA))
132 superblock->time_delta.seconds = 1;
133
134 /* initialize the default getattr mask */
135 superblock->default_getattr.count = 2;
136 superblock->default_getattr.arr[0] = FATTR4_WORD0_TYPE
140 superblock->default_getattr.arr[1] = FATTR4_WORD1_MODE
144 superblock->default_getattr.arr[2] = 0;
145
147
148 dprintf(SBLVL, "attributes for fsid(%llu,%llu): "
149 "maxread=%llu, maxwrite=%llu, layout_types: 0x%X, "
150 "cansettime=%u, time_delta={%llu,%u}, aclsupport=%u, "
151 "link_support=%u, symlink_support=%u, case_preserving=%u, "
152 "case_insensitive=%u\n",
153 superblock->fsid.major, superblock->fsid.minor,
154 superblock->maxread, superblock->maxwrite,
155 superblock->layout_types, superblock->cansettime,
156 superblock->time_delta.seconds, superblock->time_delta.nseconds,
157 superblock->aclsupport, superblock->link_support,
158 superblock->symlink_support, superblock->case_preserving,
159 superblock->case_insensitive);
160out:
161 return status;
162}
163
167{
168 FsAttrs->FileSystemAttributes = FILE_SUPPORTS_REMOTE_STORAGE;
169 if (superblock->link_support)
170 FsAttrs->FileSystemAttributes |= FILE_SUPPORTS_HARD_LINKS;
171 if (superblock->symlink_support)
172 FsAttrs->FileSystemAttributes |= FILE_SUPPORTS_REPARSE_POINTS;
173 if (superblock->ea_support)
174 FsAttrs->FileSystemAttributes |= FILE_SUPPORTS_EXTENDED_ATTRIBUTES;
175 if (superblock->case_preserving)
176 FsAttrs->FileSystemAttributes |= FILE_CASE_PRESERVED_NAMES;
177 if (!superblock->case_insensitive)
178 FsAttrs->FileSystemAttributes |= FILE_CASE_SENSITIVE_SEARCH;
179 if (superblock->aclsupport)
180 FsAttrs->FileSystemAttributes |= FILE_PERSISTENT_ACLS;
181
182 FsAttrs->MaximumComponentNameLength = NFS41_MAX_COMPONENT_LEN;
183
184 /* let the driver fill in FileSystemName */
185 FsAttrs->FileSystemNameLength = 0;
186
187 dprintf(SBLVL, "FileFsAttributeInformation: case_preserving %u, "
188 "case_insensitive %u, max component %u\n",
189 superblock->case_preserving, superblock->case_insensitive,
190 FsAttrs->MaximumComponentNameLength);
191}
192
193
194/* nfs41_superblock_list */
195#define superblock_entry(pos) list_container(pos, nfs41_superblock, entry)
196
198 const struct list_entry *entry,
199 const void *value)
200{
202 return compare_fsid(&superblock->fsid, (const nfs41_fsid*)value);
203}
204
206 IN nfs41_superblock_list *superblocks,
207 IN const nfs41_fsid *fsid)
208{
209 struct list_entry *entry;
210 entry = list_search(&superblocks->head, fsid, superblock_compare);
211 return entry ? superblock_entry(entry) : NULL;
212}
213
215 IN nfs41_superblock_list *superblocks)
216{
217 list_init(&superblocks->head);
218 InitializeSRWLock(&superblocks->lock);
219}
220
222 IN nfs41_superblock_list *superblocks)
223{
224 struct list_entry *entry, *tmp;
225
226 dprintf(SBLVL, "nfs41_superblock_list_free()\n");
227
228 list_for_each_tmp(entry, tmp, &superblocks->head)
230}
231
232
235 IN const nfs41_fsid *fsid,
236 IN const nfs41_fh *parent OPTIONAL,
238{
239 int status = NFS4_OK;
241 nfs41_superblock_list *superblocks = &server->superblocks;
243
244 dprintf(SBLVL, "--> nfs41_superblock_for_fh(fsid(%llu,%llu))\n",
245 fsid->major, fsid->minor);
246
247 /* compare with the parent's fsid, and use that if it matches */
248 if (parent && parent->superblock &&
249 compare_fsid(fsid, &parent->superblock->fsid) == 0) {
250 file->fh.superblock = parent->superblock;
251 dprintf(SBLVL, "using superblock from parent\n");
252 goto out;
253 }
254
255 /* using a shared lock, search for an existing superblock */
256 AcquireSRWLockShared(&superblocks->lock);
257 superblock = find_superblock(superblocks, fsid);
258 ReleaseSRWLockShared(&superblocks->lock);
259
260 if (superblock) {
261 dprintf(SBLVL, "found existing superblock in server list "
262 "[shared lock]\n");
263 } else {
264 AcquireSRWLockExclusive(&superblocks->lock);
265 /* must search again under an exclusive lock, in case another thread
266 * created it after our first search */
267 superblock = find_superblock(superblocks, fsid);
268 if (superblock) {
269 dprintf(SBLVL, "found newly created superblock in server list "
270 "[exclusive lock]\n");
271 } else {
272 /* create the superblock */
274 if (status == NO_ERROR) /* add it to the list */
275 list_add_tail(&superblocks->head, &superblock->entry);
276 }
277 ReleaseSRWLockExclusive(&superblocks->lock);
278 }
279
280 if (status == NO_ERROR && superblock->supported_attrs.count == 0) {
281 /* exclusive lock on the superblock while fetching attributes */
283 if (superblock->supported_attrs.count == 0)
286 }
287
288 file->fh.superblock = superblock;
289out:
290 dprintf(SBLVL, "<-- nfs41_superblock_for_fh() returning %p, status %d\n",
291 file->fh.superblock, status);
292 return status;
293}
294
297{
298 /* invalidate cached volume size attributes */
300 superblock->cache_expiration = 0;
302}
#define list_for_each_tmp(entry, tmp, head)
Definition: list.h:39
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static struct list_entry * list_search(const struct list_entry *head, const void *value, list_compare_fn compare)
Definition: list.h:102
static void list_init(struct list_entry *head)
Definition: list.h:51
static __inline bool_t bitmap_isset(IN const bitmap4 *mask, IN uint32_t word, IN uint32_t flag)
Definition: util.h:55
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
#define NO_ERROR
Definition: dderror.h:5
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
int32_t bool_t
Definition: types.h:101
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
r parent
Definition: btrfs.c:3010
#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES
Definition: from_kernel.h:250
#define FILE_SUPPORTS_REPARSE_POINTS
Definition: from_kernel.h:240
#define FILE_SUPPORTS_HARD_LINKS
Definition: from_kernel.h:249
#define FILE_SUPPORTS_REMOTE_STORAGE
Definition: from_kernel.h:241
#define FILE_PERSISTENT_ACLS
Definition: from_kernel.h:236
#define FILE_CASE_SENSITIVE_SEARCH
Definition: from_kernel.h:233
#define FILE_CASE_PRESERVED_NAMES
Definition: from_kernel.h:234
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static __inline void nfs41_superblock_supported_attrs(IN const nfs41_superblock *superblock, IN OUT bitmap4 *attrs)
Definition: nfs41.h:454
static __inline nfs41_server * client_server(IN nfs41_client *client)
Definition: nfs41.h:428
@ FATTR4_WORD0_HIDDEN
Definition: nfs41_const.h:237
@ FATTR4_WORD1_TIME_DELTA
Definition: nfs41_const.h:263
@ FATTR4_WORD1_TIME_CREATE
Definition: nfs41_const.h:262
@ FATTR4_WORD1_MODE
Definition: nfs41_const.h:245
@ FATTR4_WORD1_TIME_MODIFY
Definition: nfs41_const.h:265
@ FATTR4_WORD0_LINK_SUPPORT
Definition: nfs41_const.h:212
@ FATTR4_WORD0_CANSETTIME
Definition: nfs41_const.h:228
@ FATTR4_WORD0_CASE_PRESERVING
Definition: nfs41_const.h:230
@ FATTR4_WORD0_ARCHIVE
Definition: nfs41_const.h:227
@ FATTR4_WORD1_TIME_ACCESS
Definition: nfs41_const.h:259
@ FATTR4_WORD0_MAXWRITE
Definition: nfs41_const.h:243
@ FATTR4_WORD0_ACLSUPPORT
Definition: nfs41_const.h:226
@ FATTR4_WORD0_SYMLINK_SUPPORT
Definition: nfs41_const.h:213
@ FATTR4_WORD0_TYPE
Definition: nfs41_const.h:208
@ FATTR4_WORD1_SYSTEM
Definition: nfs41_const.h:258
@ FATTR4_WORD0_CHANGE
Definition: nfs41_const.h:210
@ FATTR4_WORD1_NUMLINKS
Definition: nfs41_const.h:247
@ FATTR4_WORD0_SUPPORTED_ATTRS
Definition: nfs41_const.h:207
@ FATTR4_WORD0_FILEID
Definition: nfs41_const.h:232
@ FATTR4_WORD2_SUPPATTR_EXCLCREAT
Definition: nfs41_const.h:220
@ FATTR4_WORD0_SIZE
Definition: nfs41_const.h:211
@ FATTR4_WORD1_FS_LAYOUT_TYPE
Definition: nfs41_const.h:274
@ FATTR4_WORD0_CASE_INSENSITIVE
Definition: nfs41_const.h:229
@ FATTR4_WORD0_MAXREAD
Definition: nfs41_const.h:242
#define NFS41_MAX_COMPONENT_LEN
Definition: nfs41_const.h:45
@ NFS4_OK
Definition: nfs41_const.h:87
int nfs41_superblock_getattr(IN nfs41_session *session, IN nfs41_path_fh *file, IN bitmap4 *attr_request, OUT nfs41_file_info *info, OUT bool_t *supports_named_attrs)
Definition: nfs41_ops.c:1116
static nfs41_superblock * find_superblock(IN nfs41_superblock_list *superblocks, IN const nfs41_fsid *fsid)
void nfs41_superblock_list_init(IN nfs41_superblock_list *superblocks)
#define superblock_entry(pos)
void nfs41_superblock_list_free(IN nfs41_superblock_list *superblocks)
#define SBLVL
static int superblock_create(IN const nfs41_fsid *fsid, OUT nfs41_superblock **superblock_out)
void nfs41_superblock_fs_attributes(IN const nfs41_superblock *superblock, OUT PFILE_FS_ATTRIBUTE_INFORMATION FsAttrs)
static __inline int compare_fsid(IN const nfs41_fsid *lhs, IN const nfs41_fsid *rhs)
void nfs41_superblock_space_changed(IN nfs41_superblock *superblock)
int nfs41_superblock_for_fh(IN nfs41_session *session, IN const nfs41_fsid *fsid, IN const nfs41_fh *parent OPTIONAL, OUT nfs41_path_fh *file)
static int superblock_compare(const struct list_entry *entry, const void *value)
static int get_superblock_attrs(IN nfs41_session *session, IN nfs41_superblock *superblock, IN nfs41_path_fh *file)
#define uint32_t
Definition: nsiface.idl:61
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
uint32_t count
Definition: nfs41_types.h:96
uint32_t arr[3]
Definition: nfs41_types.h:97
struct list_entry head
Definition: nfs41.h:69
Definition: fci.c:127
Definition: list.h:27
Definition: ps.c:97
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
Definition: pdh_main.c:94
static rfbScreenInfoPtr server
Definition: vnc.c:74
DWORD WINAPI GetLastError(void)
Definition: except.c:1042