ReactOS  0.4.12-dev-102-g4b7f1e0
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 
35 static __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 */
48 static int superblock_create(
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 
58  superblock = calloc(1, sizeof(nfs41_superblock));
59  if (superblock == NULL) {
60  status = GetLastError();
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));
67  InitializeSRWLock(&superblock->lock);
68 
69  *superblock_out = superblock;
70 out:
71  return status;
72 }
73 
75  IN nfs41_session *session,
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 
98  status = nfs41_superblock_getattr(session, file,
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 
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 */
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 
146  nfs41_superblock_supported_attrs(superblock, &superblock->default_getattr);
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);
160 out:
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)
229  free(superblock_entry(entry));
230 }
231 
232 
234  IN nfs41_session *session,
235  IN const nfs41_fsid *fsid,
236  IN const nfs41_fh *parent OPTIONAL,
238 {
239  int status = NFS4_OK;
240  nfs41_server *server = client_server(session->client);
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 */
273  status = superblock_create(fsid, &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 */
282  AcquireSRWLockExclusive(&superblock->lock);
283  if (superblock->supported_attrs.count == 0)
284  status = get_superblock_attrs(session, superblock, file);
285  ReleaseSRWLockExclusive(&superblock->lock);
286  }
287 
288  file->fh.superblock = superblock;
289 out:
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 */
299  AcquireSRWLockExclusive(&superblock->lock);
300  superblock->cache_expiration = 0;
301  ReleaseSRWLockExclusive(&superblock->lock);
302 }
#define SBLVL
static int get_superblock_attrs(IN nfs41_session *session, IN nfs41_superblock *superblock, IN nfs41_path_fh *file)
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
#define IN
Definition: typedefs.h:38
uint32_t fs_layout_types
Definition: nfs41_types.h:234
Definition: get.c:139
SRWLOCK lock
Definition: nfs41.h:65
bitmap4 * supported_attrs
Definition: nfs41_types.h:217
static rfbScreenInfoPtr server
Definition: vnc.c:74
#define NFS41_MAX_COMPONENT_LEN
Definition: nfs41_const.h:45
void nfs41_superblock_list_init(IN nfs41_superblock_list *superblocks)
int32_t bool_t
Definition: types.h:101
#define free
Definition: debug_ros.c:5
uint8_t entry
Definition: isohybrid.c:63
static int superblock_create(IN const nfs41_fsid *fsid, OUT nfs41_superblock **superblock_out)
struct list_entry entry
Definition: nfs41.h:39
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
#define FILE_SUPPORTS_REPARSE_POINTS
Definition: from_kernel.h:240
bool_t symlink_support
Definition: nfs41_types.h:242
#define NO_ERROR
Definition: dderror.h:5
uint32_t arr[3]
Definition: nfs41_types.h:97
static __inline int compare_fsid(IN const nfs41_fsid *lhs, IN const nfs41_fsid *rhs)
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
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
bool_t case_preserving
Definition: nfs41_types.h:240
#define dprintf
Definition: regdump.c:33
uint32_t count
Definition: nfs41_types.h:96
smooth NULL
Definition: ftsmooth.c:416
nfs41_fsid fsid
Definition: nfs41.h:38
void nfs41_superblock_space_changed(IN nfs41_superblock *superblock)
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
r parent
Definition: btrfs.c:2659
static nfs41_superblock * find_superblock(IN nfs41_superblock_list *superblocks, IN const nfs41_fsid *fsid)
struct list_entry head
Definition: nfs41.h:69
#define FILE_CASE_SENSITIVE_SEARCH
Definition: from_kernel.h:233
static FILE * out
Definition: regtests2xml.c:44
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
uint32_t aclsupport
Definition: nfs41_types.h:246
void nfs41_superblock_fs_attributes(IN const nfs41_superblock *superblock, OUT PFILE_FS_ATTRIBUTE_INFORMATION FsAttrs)
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)
bitmap4 * suppattr_exclcreat
Definition: nfs41_types.h:218
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
static int superblock_compare(const struct list_entry *entry, const void *value)
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define FILE_CASE_PRESERVED_NAMES
Definition: from_kernel.h:234
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
static struct list_entry * list_search(const struct list_entry *head, const void *value, list_compare_fn compare)
Definition: list.h:102
nfs41_superblock_list superblocks
Definition: nfs41.h:83
#define FILE_SUPPORTS_HARD_LINKS
Definition: from_kernel.h:249
nfstime4 * time_delta
Definition: nfs41_types.h:215
Definition: list.h:27
#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES
Definition: from_kernel.h:250
#define list_for_each_tmp(entry, tmp, head)
Definition: list.h:39
#define calloc
Definition: rosglue.h:14
#define OUT
Definition: typedefs.h:39
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
#define FILE_PERSISTENT_ACLS
Definition: from_kernel.h:236
#define FILE_SUPPORTS_REMOTE_STORAGE
Definition: from_kernel.h:241
bool_t case_insensitive
Definition: nfs41_types.h:239
#define superblock_entry(pos)
#define uint32_t
Definition: nsiface.idl:61
static SERVICE_STATUS status
Definition: service.c:31
void nfs41_superblock_list_free(IN nfs41_superblock_list *superblocks)
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
bitmap4 supported_attrs
Definition: nfs41.h:41
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
static __inline bool_t bitmap_isset(IN const bitmap4 *mask, IN uint32_t word, IN uint32_t flag)
Definition: util.h:55
Definition: fci.c:126
Definition: ps.c:97
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68