Print this page
cstyle
Fix missing logic for ESTALE and NFS_EOF
Implement ioctl _FIODIRECTIO
Kill flags arg in smbfs_purge_caches
Lots of comment cleanup
5404 smbfs needs mmap support
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
+++ new/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
1 1 /*
2 2 * Copyright (c) 2000-2001 Boris Popov
3 3 * All rights reserved.
4 4 *
5 5 * Redistribution and use in source and binary forms, with or without
6 6 * modification, are permitted provided that the following conditions
7 7 * are met:
8 8 * 1. Redistributions of source code must retain the above copyright
9 9 * notice, this list of conditions and the following disclaimer.
10 10 * 2. Redistributions in binary form must reproduce the above copyright
11 11 * notice, this list of conditions and the following disclaimer in the
12 12 * documentation and/or other materials provided with the distribution.
13 13 * 3. All advertising materials mentioning features or use of this software
14 14 * must display the following acknowledgement:
15 15 * This product includes software developed by Boris Popov.
16 16 * 4. Neither the name of the author nor the names of any co-contributors
17 17 * may be used to endorse or promote products derived from this software
18 18 * without specific prior written permission.
19 19 *
20 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
29 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 30 * SUCH DAMAGE.
31 31 *
32 32 * $Id: smbfs_vnops.c,v 1.128.36.1 2005/05/27 02:35:28 lindak Exp $
33 33 */
34 34
35 35 /*
36 36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
37 37 */
38 38
39 +/*
40 + * Vnode operations
41 + *
42 + * This file is similar to nfs3_vnops.c
43 + */
44 +
45 +#include <sys/param.h>
39 46 #include <sys/systm.h>
40 47 #include <sys/cred.h>
41 48 #include <sys/vnode.h>
42 49 #include <sys/vfs.h>
43 50 #include <sys/filio.h>
44 51 #include <sys/uio.h>
45 52 #include <sys/dirent.h>
46 53 #include <sys/errno.h>
47 54 #include <sys/sunddi.h>
48 55 #include <sys/sysmacros.h>
49 56 #include <sys/kmem.h>
50 57 #include <sys/cmn_err.h>
51 58 #include <sys/vfs_opreg.h>
52 59 #include <sys/policy.h>
60 +#include <sys/sdt.h>
61 +#include <sys/zone.h>
62 +#include <sys/vmsystm.h>
53 63
64 +#include <vm/hat.h>
65 +#include <vm/as.h>
66 +#include <vm/page.h>
67 +#include <vm/pvn.h>
68 +#include <vm/seg.h>
69 +#include <vm/seg_map.h>
70 +#include <vm/seg_kpm.h>
71 +#include <vm/seg_vn.h>
72 +
54 73 #include <netsmb/smb_osdep.h>
55 74 #include <netsmb/smb.h>
56 75 #include <netsmb/smb_conn.h>
57 76 #include <netsmb/smb_subr.h>
58 77
59 78 #include <smbfs/smbfs.h>
60 79 #include <smbfs/smbfs_node.h>
61 80 #include <smbfs/smbfs_subr.h>
62 81
63 82 #include <sys/fs/smbfs_ioctl.h>
64 83 #include <fs/fs_subr.h>
65 84
66 85 /*
67 86 * We assign directory offsets like the NFS client, where the
68 87 * offset increments by _one_ after each directory entry.
69 88 * Further, the entries "." and ".." are always at offsets
70 89 * zero and one (respectively) and the "real" entries from
71 90 * the server appear at offsets starting with two. This
72 91 * macro is used to initialize the n_dirofs field after
73 92 * setting n_dirseq with a _findopen call.
74 93 */
75 94 #define FIRST_DIROFS 2
76 95
77 96 /*
78 97 * These characters are illegal in NTFS file names.
79 98 * ref: http://support.microsoft.com/kb/147438
80 99 *
81 100 * Careful! The check in the XATTR case skips the
82 101 * first character to allow colon in XATTR names.
83 102 */
84 103 static const char illegal_chars[] = {
85 104 ':', /* colon - keep this first! */
86 105 '\\', /* back slash */
87 106 '/', /* slash */
88 107 '*', /* asterisk */
89 108 '?', /* question mark */
90 109 '"', /* double quote */
91 110 '<', /* less than sign */
92 111 '>', /* greater than sign */
93 112 '|', /* vertical bar */
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
94 113 0
95 114 };
96 115
97 116 /*
98 117 * Turning this on causes nodes to be created in the cache
99 118 * during directory listings, normally avoiding a second
100 119 * OtW attribute fetch just after a readdir.
101 120 */
102 121 int smbfs_fastlookup = 1;
103 122
123 +struct vnodeops *smbfs_vnodeops = NULL;
124 +
104 125 /* local static function defines */
105 126
106 127 static int smbfslookup_cache(vnode_t *, char *, int, vnode_t **,
107 128 cred_t *);
108 129 static int smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
109 130 int cache_ok, caller_context_t *);
110 131 static int smbfsremove(vnode_t *dvp, vnode_t *vp, struct smb_cred *scred,
111 132 int flags);
112 133 static int smbfsrename(vnode_t *odvp, vnode_t *ovp, vnode_t *ndvp,
113 134 char *nnm, struct smb_cred *scred, int flags);
114 135 static int smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
115 136 static int smbfs_accessx(void *, int, cred_t *);
116 137 static int smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
117 138 caller_context_t *);
118 139 static void smbfs_rele_fid(smbnode_t *, struct smb_cred *);
119 140 static uint32_t xvattr_to_dosattr(smbnode_t *, struct vattr *);
120 141
142 +static int smbfs_rdwrlbn(vnode_t *, page_t *, u_offset_t, size_t, int,
143 + cred_t *);
144 +static int smbfs_bio(struct buf *, int, cred_t *);
145 +static int smbfs_writenp(smbnode_t *np, caddr_t base, int tcount,
146 + struct uio *uiop, int pgcreated);
147 +
148 +static int smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *);
149 +static int smbfs_putpage(vnode_t *, offset_t, size_t, int, cred_t *,
150 + caller_context_t *);
151 +static int smbfs_getapage(vnode_t *, u_offset_t, size_t, uint_t *,
152 + page_t *[], size_t, struct seg *, caddr_t,
153 + enum seg_rw, cred_t *);
154 +static int smbfs_putapage(vnode_t *, page_t *, u_offset_t *, size_t *,
155 + int, cred_t *);
156 +static void smbfs_delmap_callback(struct as *, void *, uint_t);
157 +
121 158 /*
159 + * Error flags used to pass information about certain special errors
160 + * which need to be handled specially.
161 + */
162 +#define SMBFS_EOF -98
163 +
164 +/* When implementing OtW locks, make this a real function. */
165 +#define smbfs_lm_has_sleep(vp) 0
166 +
167 +/*
122 168 * These are the vnode ops routines which implement the vnode interface to
123 169 * the networked file system. These routines just take their parameters,
124 170 * make them look networkish by putting the right info into interface structs,
125 171 * and then calling the appropriate remote routine(s) to do the work.
126 172 *
127 173 * Note on directory name lookup cacheing: If we detect a stale fhandle,
128 174 * we purge the directory cache relative to that vnode. This way, the
129 175 * user won't get burned by the cache repeatedly. See <smbfs/smbnode.h> for
130 176 * more details on smbnode locking.
131 177 */
132 178
133 -static int smbfs_open(vnode_t **, int, cred_t *, caller_context_t *);
134 -static int smbfs_close(vnode_t *, int, int, offset_t, cred_t *,
135 - caller_context_t *);
136 -static int smbfs_read(vnode_t *, struct uio *, int, cred_t *,
137 - caller_context_t *);
138 -static int smbfs_write(vnode_t *, struct uio *, int, cred_t *,
139 - caller_context_t *);
140 -static int smbfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
141 - caller_context_t *);
142 -static int smbfs_getattr(vnode_t *, struct vattr *, int, cred_t *,
143 - caller_context_t *);
144 -static int smbfs_setattr(vnode_t *, struct vattr *, int, cred_t *,
145 - caller_context_t *);
146 -static int smbfs_access(vnode_t *, int, int, cred_t *, caller_context_t *);
147 -static int smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *);
148 -static void smbfs_inactive(vnode_t *, cred_t *, caller_context_t *);
149 -static int smbfs_lookup(vnode_t *, char *, vnode_t **, struct pathname *,
150 - int, vnode_t *, cred_t *, caller_context_t *,
151 - int *, pathname_t *);
152 -static int smbfs_create(vnode_t *, char *, struct vattr *, enum vcexcl,
153 - int, vnode_t **, cred_t *, int, caller_context_t *,
154 - vsecattr_t *);
155 -static int smbfs_remove(vnode_t *, char *, cred_t *, caller_context_t *,
156 - int);
157 -static int smbfs_rename(vnode_t *, char *, vnode_t *, char *, cred_t *,
158 - caller_context_t *, int);
159 -static int smbfs_mkdir(vnode_t *, char *, struct vattr *, vnode_t **,
160 - cred_t *, caller_context_t *, int, vsecattr_t *);
161 -static int smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
162 - caller_context_t *, int);
163 -static int smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *,
164 - caller_context_t *, int);
165 -static int smbfs_rwlock(vnode_t *, int, caller_context_t *);
166 -static void smbfs_rwunlock(vnode_t *, int, caller_context_t *);
167 -static int smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
168 -static int smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t,
169 - struct flk_callback *, cred_t *, caller_context_t *);
170 -static int smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t,
171 - cred_t *, caller_context_t *);
172 -static int smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *,
173 - caller_context_t *);
174 -static int smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
175 - caller_context_t *);
176 -static int smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
177 - caller_context_t *);
178 -static int smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *,
179 - caller_context_t *);
180 179
181 -/* Dummy function to use until correct function is ported in */
182 -int noop_vnodeop() {
183 - return (0);
184 -}
185 -
186 -struct vnodeops *smbfs_vnodeops = NULL;
187 -
188 180 /*
189 - * Most unimplemented ops will return ENOSYS because of fs_nosys().
190 - * The only ops where that won't work are ACCESS (due to open(2)
191 - * failures) and ... (anything else left?)
192 - */
193 -const fs_operation_def_t smbfs_vnodeops_template[] = {
194 - { VOPNAME_OPEN, { .vop_open = smbfs_open } },
195 - { VOPNAME_CLOSE, { .vop_close = smbfs_close } },
196 - { VOPNAME_READ, { .vop_read = smbfs_read } },
197 - { VOPNAME_WRITE, { .vop_write = smbfs_write } },
198 - { VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl } },
199 - { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } },
200 - { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } },
201 - { VOPNAME_ACCESS, { .vop_access = smbfs_access } },
202 - { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } },
203 - { VOPNAME_CREATE, { .vop_create = smbfs_create } },
204 - { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } },
205 - { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */
206 - { VOPNAME_RENAME, { .vop_rename = smbfs_rename } },
207 - { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } },
208 - { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } },
209 - { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } },
210 - { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */
211 - { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */
212 - { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } },
213 - { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } },
214 - { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */
215 - { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } },
216 - { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } },
217 - { VOPNAME_SEEK, { .vop_seek = smbfs_seek } },
218 - { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } },
219 - { VOPNAME_SPACE, { .vop_space = smbfs_space } },
220 - { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */
221 - { VOPNAME_GETPAGE, { .error = fs_nosys } }, /* smbfs_getpage, */
222 - { VOPNAME_PUTPAGE, { .error = fs_nosys } }, /* smbfs_putpage, */
223 - { VOPNAME_MAP, { .error = fs_nosys } }, /* smbfs_map, */
224 - { VOPNAME_ADDMAP, { .error = fs_nosys } }, /* smbfs_addmap, */
225 - { VOPNAME_DELMAP, { .error = fs_nosys } }, /* smbfs_delmap, */
226 - { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */
227 - { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } },
228 - { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */
229 - { VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr } },
230 - { VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr } },
231 - { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } },
232 - { NULL, NULL }
233 -};
234 -
235 -/*
236 181 * XXX
237 182 * When new and relevant functionality is enabled, we should be
238 183 * calling vfs_set_feature() to inform callers that pieces of
239 184 * functionality are available, per PSARC 2007/227.
240 185 */
241 186 /* ARGSUSED */
242 187 static int
243 188 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
244 189 {
245 190 smbnode_t *np;
246 191 vnode_t *vp;
247 192 smbfattr_t fa;
248 193 u_int32_t rights, rightsrcvd;
249 194 u_int16_t fid, oldfid;
250 195 int oldgenid;
251 196 struct smb_cred scred;
252 197 smbmntinfo_t *smi;
253 198 smb_share_t *ssp;
254 199 cred_t *oldcr;
255 200 int tmperror;
256 201 int error = 0;
257 202
258 203 vp = *vpp;
259 204 np = VTOSMB(vp);
260 205 smi = VTOSMI(vp);
261 206 ssp = smi->smi_share;
262 207
263 208 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
264 209 return (EIO);
265 210
266 211 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
267 212 return (EIO);
268 213
269 214 if (vp->v_type != VREG && vp->v_type != VDIR) { /* XXX VLNK? */
270 215 SMBVDEBUG("open eacces vtype=%d\n", vp->v_type);
271 216 return (EACCES);
272 217 }
273 218
274 219 /*
275 220 * Get exclusive access to n_fid and related stuff.
276 221 * No returns after this until out.
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
277 222 */
278 223 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
279 224 return (EINTR);
280 225 smb_credinit(&scred, cr);
281 226
282 227 /*
283 228 * Keep track of the vnode type at first open.
284 229 * It may change later, and we need close to do
285 230 * cleanup for the type we opened. Also deny
286 231 * open of new types until old type is closed.
287 - * XXX: Per-open instance nodes whould help.
288 232 */
289 233 if (np->n_ovtype == VNON) {
290 234 ASSERT(np->n_dirrefs == 0);
291 235 ASSERT(np->n_fidrefs == 0);
292 236 } else if (np->n_ovtype != vp->v_type) {
293 237 SMBVDEBUG("open n_ovtype=%d v_type=%d\n",
294 238 np->n_ovtype, vp->v_type);
295 239 error = EACCES;
296 240 goto out;
297 241 }
298 242
299 243 /*
300 244 * Directory open. See smbfs_readvdir()
301 245 */
302 246 if (vp->v_type == VDIR) {
303 247 if (np->n_dirseq == NULL) {
304 248 /* first open */
305 249 error = smbfs_smb_findopen(np, "*", 1,
306 250 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
307 251 &scred, &np->n_dirseq);
308 252 if (error != 0)
309 253 goto out;
310 254 }
311 255 np->n_dirofs = FIRST_DIROFS;
312 256 np->n_dirrefs++;
313 257 goto have_fid;
314 258 }
315 259
316 260 /*
317 261 * If caller specified O_TRUNC/FTRUNC, then be sure to set
318 262 * FWRITE (to drive successful setattr(size=0) after open)
319 263 */
320 264 if (flag & FTRUNC)
321 265 flag |= FWRITE;
322 266
323 267 /*
324 268 * If we already have it open, and the FID is still valid,
325 269 * check whether the rights are sufficient for FID reuse.
326 270 */
327 271 if (np->n_fidrefs > 0 &&
328 272 np->n_vcgenid == ssp->ss_vcgenid) {
329 273 int upgrade = 0;
330 274
331 275 if ((flag & FWRITE) &&
332 276 !(np->n_rights & SA_RIGHT_FILE_WRITE_DATA))
333 277 upgrade = 1;
334 278 if ((flag & FREAD) &&
335 279 !(np->n_rights & SA_RIGHT_FILE_READ_DATA))
336 280 upgrade = 1;
337 281 if (!upgrade) {
338 282 /*
339 283 * the existing open is good enough
340 284 */
341 285 np->n_fidrefs++;
342 286 goto have_fid;
343 287 }
344 288 }
345 289 rights = np->n_fidrefs ? np->n_rights : 0;
346 290
347 291 /*
348 292 * we always ask for READ_CONTROL so we can always get the
349 293 * owner/group IDs to satisfy a stat. Ditto attributes.
350 294 */
351 295 rights |= (STD_RIGHT_READ_CONTROL_ACCESS |
352 296 SA_RIGHT_FILE_READ_ATTRIBUTES);
353 297 if ((flag & FREAD))
354 298 rights |= SA_RIGHT_FILE_READ_DATA;
355 299 if ((flag & FWRITE))
356 300 rights |= SA_RIGHT_FILE_WRITE_DATA |
357 301 SA_RIGHT_FILE_APPEND_DATA |
358 302 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
359 303
360 304 bzero(&fa, sizeof (fa));
361 305 error = smbfs_smb_open(np,
362 306 NULL, 0, 0, /* name nmlen xattr */
363 307 rights, &scred,
364 308 &fid, &rightsrcvd, &fa);
365 309 if (error)
366 310 goto out;
367 311 smbfs_attrcache_fa(vp, &fa);
368 312
369 313 /*
370 314 * We have a new FID and access rights.
371 315 */
372 316 oldfid = np->n_fid;
373 317 oldgenid = np->n_vcgenid;
374 318 np->n_fid = fid;
375 319 np->n_vcgenid = ssp->ss_vcgenid;
376 320 np->n_rights = rightsrcvd;
377 321 np->n_fidrefs++;
378 322 if (np->n_fidrefs > 1 &&
379 323 oldgenid == ssp->ss_vcgenid) {
380 324 /*
381 325 * We already had it open (presumably because
382 326 * it was open with insufficient rights.)
383 327 * Close old wire-open.
384 328 */
385 329 tmperror = smbfs_smb_close(ssp,
386 330 oldfid, NULL, &scred);
387 331 if (tmperror)
388 332 SMBVDEBUG("error %d closing %s\n",
389 333 tmperror, np->n_rpath);
390 334 }
391 335
392 336 /*
393 337 * This thread did the open.
394 338 * Save our credentials too.
395 339 */
396 340 mutex_enter(&np->r_statelock);
397 341 oldcr = np->r_cred;
398 342 np->r_cred = cr;
399 343 crhold(cr);
400 344 if (oldcr)
401 345 crfree(oldcr);
402 346 mutex_exit(&np->r_statelock);
403 347
404 348 have_fid:
405 349 /*
406 350 * Keep track of the vnode type at first open.
407 351 * (see comments above)
408 352 */
409 353 if (np->n_ovtype == VNON)
410 354 np->n_ovtype = vp->v_type;
411 355
412 356 out:
413 357 smb_credrele(&scred);
414 358 smbfs_rw_exit(&np->r_lkserlock);
415 359 return (error);
↓ open down ↓ |
118 lines elided |
↑ open up ↑ |
416 360 }
417 361
418 362 /*ARGSUSED*/
419 363 static int
420 364 smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
421 365 caller_context_t *ct)
422 366 {
423 367 smbnode_t *np;
424 368 smbmntinfo_t *smi;
425 369 struct smb_cred scred;
370 + int error = 0;
426 371
427 372 np = VTOSMB(vp);
428 373 smi = VTOSMI(vp);
429 374
430 375 /*
431 376 * Don't "bail out" for VFS_UNMOUNTED here,
432 377 * as we want to do cleanup, etc.
433 378 */
434 379
435 380 /*
436 381 * zone_enter(2) prevents processes from changing zones with SMBFS files
437 382 * open; if we happen to get here from the wrong zone we can't do
438 383 * anything over the wire.
439 384 */
440 385 if (smi->smi_zone_ref.zref_zone != curproc->p_zone) {
441 386 /*
442 387 * We could attempt to clean up locks, except we're sure
443 388 * that the current process didn't acquire any locks on
444 389 * the file: any attempt to lock a file belong to another zone
445 390 * will fail, and one can't lock an SMBFS file and then change
446 391 * zones, as that fails too.
447 392 *
448 393 * Returning an error here is the sane thing to do. A
449 394 * subsequent call to VN_RELE() which translates to a
450 395 * smbfs_inactive() will clean up state: if the zone of the
451 396 * vnode's origin is still alive and kicking, an async worker
452 397 * thread will handle the request (from the correct zone), and
453 398 * everything (minus the final smbfs_getattr_otw() call) should
454 399 * be OK. If the zone is going away smbfs_async_inactive() will
455 400 * throw away cached pages inline.
456 401 */
457 402 return (EIO);
458 403 }
459 404
460 405 /*
461 406 * If we are using local locking for this filesystem, then
462 407 * release all of the SYSV style record locks. Otherwise,
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
463 408 * we are doing network locking and we need to release all
464 409 * of the network locks. All of the locks held by this
465 410 * process on this file are released no matter what the
466 411 * incoming reference count is.
467 412 */
468 413 if (smi->smi_flags & SMI_LLOCK) {
469 414 pid_t pid = ddi_get_pid();
470 415 cleanlocks(vp, pid, 0);
471 416 cleanshares(vp, pid);
472 417 }
418 + /*
419 + * else doing OtW locking. SMB servers drop all locks
420 + * on the file ID we close here, so no _lockrelease()
421 + */
473 422
474 423 /*
475 424 * This (passed in) count is the ref. count from the
476 425 * user's file_t before the closef call (fio.c).
477 - * We only care when the reference goes away.
426 + * The rest happens only on last close.
478 427 */
479 428 if (count > 1)
480 429 return (0);
481 430
431 + /* NFS has DNLC purge here. */
432 +
482 433 /*
434 + * If the file was open for write and there are pages,
435 + * then make sure dirty pages written back.
436 + *
437 + * NFS does this async when "close-to-open" is off
438 + * (MI_NOCTO flag is set) to avoid blocking the caller.
439 + * For now, always do this synchronously (no B_ASYNC).
440 + */
441 + if ((flag & FWRITE) && vn_has_cached_data(vp)) {
442 + error = smbfs_putpage(vp, (offset_t)0, 0, 0, cr, ct);
443 + if (error == EAGAIN)
444 + error = 0;
445 + }
446 + if (error == 0) {
447 + mutex_enter(&np->r_statelock);
448 + np->r_flags &= ~RSTALE;
449 + np->r_error = 0;
450 + mutex_exit(&np->r_statelock);
451 + }
452 +
453 + /*
483 454 * Decrement the reference count for the FID
484 455 * and possibly do the OtW close.
485 456 *
486 457 * Exclusive lock for modifying n_fid stuff.
487 458 * Don't want this one ever interruptible.
488 459 */
489 460 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
490 461 smb_credinit(&scred, cr);
491 462
492 463 smbfs_rele_fid(np, &scred);
493 464
494 465 smb_credrele(&scred);
495 466 smbfs_rw_exit(&np->r_lkserlock);
496 467
497 468 return (0);
498 469 }
499 470
500 471 /*
501 472 * Helper for smbfs_close. Decrement the reference count
502 473 * for an SMB-level file or directory ID, and when the last
503 474 * reference for the fid goes away, do the OtW close.
504 475 * Also called in smbfs_inactive (defensive cleanup).
505 476 */
506 477 static void
507 478 smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred)
508 479 {
509 480 smb_share_t *ssp;
510 481 cred_t *oldcr;
511 482 struct smbfs_fctx *fctx;
512 483 int error;
513 484 uint16_t ofid;
514 485
515 486 ssp = np->n_mount->smi_share;
516 487 error = 0;
517 488
518 489 /* Make sure we serialize for n_dirseq use. */
519 490 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
520 491
521 492 /*
522 493 * Note that vp->v_type may change if a remote node
523 494 * is deleted and recreated as a different type, and
524 495 * our getattr may change v_type accordingly.
525 496 * Now use n_ovtype to keep track of the v_type
526 497 * we had during open (see comments above).
527 498 */
528 499 switch (np->n_ovtype) {
529 500 case VDIR:
530 501 ASSERT(np->n_dirrefs > 0);
531 502 if (--np->n_dirrefs)
532 503 return;
533 504 if ((fctx = np->n_dirseq) != NULL) {
534 505 np->n_dirseq = NULL;
535 506 np->n_dirofs = 0;
536 507 error = smbfs_smb_findclose(fctx, scred);
537 508 }
538 509 break;
539 510
540 511 case VREG:
541 512 ASSERT(np->n_fidrefs > 0);
542 513 if (--np->n_fidrefs)
543 514 return;
544 515 if ((ofid = np->n_fid) != SMB_FID_UNUSED) {
545 516 np->n_fid = SMB_FID_UNUSED;
546 517 /* After reconnect, n_fid is invalid */
547 518 if (np->n_vcgenid == ssp->ss_vcgenid) {
548 519 error = smbfs_smb_close(
549 520 ssp, ofid, NULL, scred);
550 521 }
551 522 }
552 523 break;
553 524
554 525 default:
555 526 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
556 527 break;
557 528 }
558 529 if (error) {
559 530 SMBVDEBUG("error %d closing %s\n",
560 531 error, np->n_rpath);
561 532 }
562 533
563 534 /* Allow next open to use any v_type. */
564 535 np->n_ovtype = VNON;
565 536
566 537 /*
567 538 * Other "last close" stuff.
568 539 */
569 540 mutex_enter(&np->r_statelock);
570 541 if (np->n_flag & NATTRCHANGED)
571 542 smbfs_attrcache_rm_locked(np);
572 543 oldcr = np->r_cred;
573 544 np->r_cred = NULL;
574 545 mutex_exit(&np->r_statelock);
575 546 if (oldcr != NULL)
576 547 crfree(oldcr);
577 548 }
578 549
579 550 /* ARGSUSED */
580 551 static int
581 552 smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
582 553 caller_context_t *ct)
↓ open down ↓ |
90 lines elided |
↑ open up ↑ |
583 554 {
584 555 struct smb_cred scred;
585 556 struct vattr va;
586 557 smbnode_t *np;
587 558 smbmntinfo_t *smi;
588 559 smb_share_t *ssp;
589 560 offset_t endoff;
590 561 ssize_t past_eof;
591 562 int error;
592 563
564 + caddr_t base;
565 + u_offset_t off;
566 + size_t n;
567 + int on;
568 + uint_t flags;
569 +
593 570 np = VTOSMB(vp);
594 571 smi = VTOSMI(vp);
595 572 ssp = smi->smi_share;
596 573
597 574 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
598 575 return (EIO);
599 576
600 577 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
601 578 return (EIO);
602 579
603 580 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
604 581
605 582 if (vp->v_type != VREG)
606 583 return (EISDIR);
607 584
608 585 if (uiop->uio_resid == 0)
609 586 return (0);
610 587
611 588 /*
612 589 * Like NFS3, just check for 63-bit overflow.
613 590 * Our SMB layer takes care to return EFBIG
614 591 * when it has to fallback to a 32-bit call.
615 592 */
616 593 endoff = uiop->uio_loffset + uiop->uio_resid;
617 594 if (uiop->uio_loffset < 0 || endoff < 0)
618 595 return (EINVAL);
619 596
620 597 /* get vnode attributes from server */
621 598 va.va_mask = AT_SIZE | AT_MTIME;
622 599 if (error = smbfsgetattr(vp, &va, cr))
623 600 return (error);
624 601
625 602 /* Update mtime with mtime from server here? */
626 603
627 604 /* if offset is beyond EOF, read nothing */
628 605 if (uiop->uio_loffset >= va.va_size)
629 606 return (0);
630 607
631 608 /*
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
632 609 * Limit the read to the remaining file size.
633 610 * Do this by temporarily reducing uio_resid
634 611 * by the amount the lies beyoned the EOF.
635 612 */
636 613 if (endoff > va.va_size) {
637 614 past_eof = (ssize_t)(endoff - va.va_size);
638 615 uiop->uio_resid -= past_eof;
639 616 } else
640 617 past_eof = 0;
641 618
642 - /* Shared lock for n_fid use in smb_rwuio */
643 - if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
644 - return (EINTR);
645 - smb_credinit(&scred, cr);
619 + /*
620 + * Bypass VM if caching has been disabled (e.g., locking) or if
621 + * using client-side direct I/O and the file is not mmap'd and
622 + * there are no cached pages.
623 + */
624 + if ((vp->v_flag & VNOCACHE) ||
625 + (((np->r_flags & RDIRECTIO) || (smi->smi_flags & SMI_DIRECTIO)) &&
626 + np->r_mapcnt == 0 && np->r_inmap == 0 &&
627 + !vn_has_cached_data(vp))) {
646 628
647 - /* After reconnect, n_fid is invalid */
648 - if (np->n_vcgenid != ssp->ss_vcgenid)
649 - error = ESTALE;
650 - else
651 - error = smb_rwuio(ssp, np->n_fid, UIO_READ,
652 - uiop, &scred, smb_timo_read);
629 + /* Shared lock for n_fid use in smb_rwuio */
630 + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
631 + return (EINTR);
632 + smb_credinit(&scred, cr);
653 633
654 - smb_credrele(&scred);
655 - smbfs_rw_exit(&np->r_lkserlock);
634 + /* After reconnect, n_fid is invalid */
635 + if (np->n_vcgenid != ssp->ss_vcgenid)
636 + error = ESTALE;
637 + else
638 + error = smb_rwuio(ssp, np->n_fid, UIO_READ,
639 + uiop, &scred, smb_timo_read);
656 640
641 + smb_credrele(&scred);
642 + smbfs_rw_exit(&np->r_lkserlock);
643 +
644 + /* undo adjustment of resid */
645 + uiop->uio_resid += past_eof;
646 +
647 + return (error);
648 + }
649 +
650 + /* (else) Do I/O through segmap. */
651 + do {
652 + off = uiop->uio_loffset & MAXBMASK; /* mapping offset */
653 + on = uiop->uio_loffset & MAXBOFFSET; /* Relative offset */
654 + n = MIN(MAXBSIZE - on, uiop->uio_resid);
655 +
656 + error = smbfs_validate_caches(vp, cr);
657 + if (error)
658 + break;
659 +
660 + /* NFS waits for RINCACHEPURGE here. */
661 +
662 + if (vpm_enable) {
663 + /*
664 + * Copy data.
665 + */
666 + error = vpm_data_copy(vp, off + on, n, uiop,
667 + 1, NULL, 0, S_READ);
668 + } else {
669 + base = segmap_getmapflt(segkmap, vp, off + on, n, 1,
670 + S_READ);
671 +
672 + error = uiomove(base + on, n, UIO_READ, uiop);
673 + }
674 +
675 + if (!error) {
676 + /*
677 + * If read a whole block or read to eof,
678 + * won't need this buffer again soon.
679 + */
680 + mutex_enter(&np->r_statelock);
681 + if (n + on == MAXBSIZE ||
682 + uiop->uio_loffset == np->r_size)
683 + flags = SM_DONTNEED;
684 + else
685 + flags = 0;
686 + mutex_exit(&np->r_statelock);
687 + if (vpm_enable) {
688 + error = vpm_sync_pages(vp, off, n, flags);
689 + } else {
690 + error = segmap_release(segkmap, base, flags);
691 + }
692 + } else {
693 + if (vpm_enable) {
694 + (void) vpm_sync_pages(vp, off, n, 0);
695 + } else {
696 + (void) segmap_release(segkmap, base, 0);
697 + }
698 + }
699 + } while (!error && uiop->uio_resid > 0);
700 +
657 701 /* undo adjustment of resid */
658 702 uiop->uio_resid += past_eof;
659 703
660 704 return (error);
661 705 }
662 706
663 707
664 708 /* ARGSUSED */
665 709 static int
666 710 smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
667 711 caller_context_t *ct)
668 712 {
669 713 struct smb_cred scred;
670 - struct vattr va;
714 + struct vattr va;
671 715 smbnode_t *np;
672 716 smbmntinfo_t *smi;
673 717 smb_share_t *ssp;
674 718 offset_t endoff, limit;
675 719 ssize_t past_limit;
676 720 int error, timo;
721 + caddr_t base;
722 + u_offset_t off;
723 + size_t n;
724 + int on;
725 + uint_t flags;
726 + u_offset_t last_off;
727 + size_t last_resid;
728 + uint_t bsize;
677 729
678 730 np = VTOSMB(vp);
679 731 smi = VTOSMI(vp);
680 732 ssp = smi->smi_share;
681 733
682 734 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
683 735 return (EIO);
684 736
685 737 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
686 738 return (EIO);
687 739
688 740 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
689 741
690 742 if (vp->v_type != VREG)
691 743 return (EISDIR);
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
692 744
693 745 if (uiop->uio_resid == 0)
694 746 return (0);
695 747
696 748 /*
697 749 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
698 750 */
699 751 if (ioflag & (FAPPEND | FSYNC)) {
700 752 if (np->n_flag & NMODIFIED) {
701 753 smbfs_attrcache_remove(np);
702 - /* XXX: smbfs_vinvalbuf? */
703 754 }
704 755 }
705 756 if (ioflag & FAPPEND) {
706 757 /*
707 758 * File size can be changed by another client
759 + *
760 + * Todo: Consider redesigning this to use a
761 + * handle opened for append instead.
708 762 */
709 763 va.va_mask = AT_SIZE;
710 764 if (error = smbfsgetattr(vp, &va, cr))
711 765 return (error);
712 766 uiop->uio_loffset = va.va_size;
713 767 }
714 768
715 769 /*
716 770 * Like NFS3, just check for 63-bit overflow.
717 771 */
718 772 endoff = uiop->uio_loffset + uiop->uio_resid;
719 773 if (uiop->uio_loffset < 0 || endoff < 0)
720 774 return (EINVAL);
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
721 775
722 776 /*
723 777 * Check to make sure that the process will not exceed
724 778 * its limit on file size. It is okay to write up to
725 779 * the limit, but not beyond. Thus, the write which
726 780 * reaches the limit will be short and the next write
727 781 * will return an error.
728 782 *
729 783 * So if we're starting at or beyond the limit, EFBIG.
730 784 * Otherwise, temporarily reduce resid to the amount
731 - * the falls after the limit.
785 + * that is after the limit.
732 786 */
733 787 limit = uiop->uio_llimit;
734 788 if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
735 789 limit = MAXOFFSET_T;
736 - if (uiop->uio_loffset >= limit)
790 + if (uiop->uio_loffset >= limit) {
791 + proc_t *p = ttoproc(curthread);
792 +
793 + mutex_enter(&p->p_lock);
794 + (void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE],
795 + p->p_rctls, p, RCA_UNSAFE_SIGINFO);
796 + mutex_exit(&p->p_lock);
737 797 return (EFBIG);
798 + }
738 799 if (endoff > limit) {
739 800 past_limit = (ssize_t)(endoff - limit);
740 801 uiop->uio_resid -= past_limit;
741 802 } else
742 803 past_limit = 0;
743 804
744 - /* Timeout: longer for append. */
745 - timo = smb_timo_write;
746 - if (endoff > np->r_size)
747 - timo = smb_timo_append;
805 + /*
806 + * Bypass VM if caching has been disabled (e.g., locking) or if
807 + * using client-side direct I/O and the file is not mmap'd and
808 + * there are no cached pages.
809 + */
810 + if ((vp->v_flag & VNOCACHE) ||
811 + (((np->r_flags & RDIRECTIO) || (smi->smi_flags & SMI_DIRECTIO)) &&
812 + np->r_mapcnt == 0 && np->r_inmap == 0 &&
813 + !vn_has_cached_data(vp))) {
748 814
815 +smbfs_fwrite:
816 + if (np->r_flags & RSTALE) {
817 + last_resid = uiop->uio_resid;
818 + last_off = uiop->uio_loffset;
819 + error = np->r_error;
820 + /*
821 + * A close may have cleared r_error, if so,
822 + * propagate ESTALE error return properly
823 + */
824 + if (error == 0)
825 + error = ESTALE;
826 + goto bottom;
827 + }
828 +
829 + /* Timeout: longer for append. */
830 + timo = smb_timo_write;
831 + if (endoff > np->r_size)
832 + timo = smb_timo_append;
833 +
834 + /* Shared lock for n_fid use in smb_rwuio */
835 + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
836 + return (EINTR);
837 + smb_credinit(&scred, cr);
838 +
839 + /* After reconnect, n_fid is invalid */
840 + if (np->n_vcgenid != ssp->ss_vcgenid)
841 + error = ESTALE;
842 + else
843 + error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
844 + uiop, &scred, timo);
845 +
846 + if (error == 0) {
847 + mutex_enter(&np->r_statelock);
848 + np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
849 + if (uiop->uio_loffset > (offset_t)np->r_size)
850 + np->r_size = (len_t)uiop->uio_loffset;
851 + mutex_exit(&np->r_statelock);
852 + if (ioflag & (FSYNC | FDSYNC)) {
853 + /* Don't error the I/O if this fails. */
854 + (void) smbfs_smb_flush(np, &scred);
855 + }
856 + }
857 +
858 + smb_credrele(&scred);
859 + smbfs_rw_exit(&np->r_lkserlock);
860 +
861 + /* undo adjustment of resid */
862 + uiop->uio_resid += past_limit;
863 +
864 + return (error);
865 + }
866 +
867 + /* (else) Do I/O through segmap. */
868 + bsize = vp->v_vfsp->vfs_bsize;
869 +
870 + do {
871 + off = uiop->uio_loffset & MAXBMASK; /* mapping offset */
872 + on = uiop->uio_loffset & MAXBOFFSET; /* Relative offset */
873 + n = MIN(MAXBSIZE - on, uiop->uio_resid);
874 +
875 + last_resid = uiop->uio_resid;
876 + last_off = uiop->uio_loffset;
877 +
878 + if (np->r_flags & RSTALE) {
879 + error = np->r_error;
880 + /*
881 + * A close may have cleared r_error, if so,
882 + * propagate ESTALE error return properly
883 + */
884 + if (error == 0)
885 + error = ESTALE;
886 + break;
887 + }
888 +
889 + /*
890 + * From NFS: Don't create dirty pages faster than they
891 + * can be cleaned.
892 + *
893 + * Here NFS also checks for async writes (np->r_awcount)
894 + */
895 + mutex_enter(&np->r_statelock);
896 + while (np->r_gcount > 0) {
897 + if (SMBINTR(vp)) {
898 + klwp_t *lwp = ttolwp(curthread);
899 +
900 + if (lwp != NULL)
901 + lwp->lwp_nostop++;
902 + if (!cv_wait_sig(&np->r_cv, &np->r_statelock)) {
903 + mutex_exit(&np->r_statelock);
904 + if (lwp != NULL)
905 + lwp->lwp_nostop--;
906 + error = EINTR;
907 + goto bottom;
908 + }
909 + if (lwp != NULL)
910 + lwp->lwp_nostop--;
911 + } else
912 + cv_wait(&np->r_cv, &np->r_statelock);
913 + }
914 + mutex_exit(&np->r_statelock);
915 +
916 + /*
917 + * Touch the page and fault it in if it is not in core
918 + * before segmap_getmapflt or vpm_data_copy can lock it.
919 + * This is to avoid the deadlock if the buffer is mapped
920 + * to the same file through mmap which we want to write.
921 + */
922 + uio_prefaultpages((long)n, uiop);
923 +
924 + if (vpm_enable) {
925 + /*
926 + * It will use kpm mappings, so no need to
927 + * pass an address.
928 + */
929 + error = smbfs_writenp(np, NULL, n, uiop, 0);
930 + } else {
931 + if (segmap_kpm) {
932 + int pon = uiop->uio_loffset & PAGEOFFSET;
933 + size_t pn = MIN(PAGESIZE - pon,
934 + uiop->uio_resid);
935 + int pagecreate;
936 +
937 + mutex_enter(&np->r_statelock);
938 + pagecreate = (pon == 0) && (pn == PAGESIZE ||
939 + uiop->uio_loffset + pn >= np->r_size);
940 + mutex_exit(&np->r_statelock);
941 +
942 + base = segmap_getmapflt(segkmap, vp, off + on,
943 + pn, !pagecreate, S_WRITE);
944 +
945 + error = smbfs_writenp(np, base + pon, n, uiop,
946 + pagecreate);
947 +
948 + } else {
949 + base = segmap_getmapflt(segkmap, vp, off + on,
950 + n, 0, S_READ);
951 + error = smbfs_writenp(np, base + on, n, uiop, 0);
952 + }
953 + }
954 +
955 + if (!error) {
956 + if (smi->smi_flags & SMI_NOAC)
957 + flags = SM_WRITE;
958 + else if ((uiop->uio_loffset % bsize) == 0 ||
959 + IS_SWAPVP(vp)) {
960 + /*
961 + * Have written a whole block.
962 + * Start an asynchronous write
963 + * and mark the buffer to
964 + * indicate that it won't be
965 + * needed again soon.
966 + */
967 + flags = SM_WRITE | SM_ASYNC | SM_DONTNEED;
968 + } else
969 + flags = 0;
970 + if ((ioflag & (FSYNC|FDSYNC)) ||
971 + (np->r_flags & ROUTOFSPACE)) {
972 + flags &= ~SM_ASYNC;
973 + flags |= SM_WRITE;
974 + }
975 + if (vpm_enable) {
976 + error = vpm_sync_pages(vp, off, n, flags);
977 + } else {
978 + error = segmap_release(segkmap, base, flags);
979 + }
980 + } else {
981 + if (vpm_enable) {
982 + (void) vpm_sync_pages(vp, off, n, 0);
983 + } else {
984 + (void) segmap_release(segkmap, base, 0);
985 + }
986 + /*
987 + * In the event that we got an access error while
988 + * faulting in a page for a write-only file just
989 + * force a write.
990 + */
991 + if (error == EACCES)
992 + goto smbfs_fwrite;
993 + }
994 + } while (!error && uiop->uio_resid > 0);
995 +
996 +bottom:
997 + /* undo adjustment of resid */
998 + if (error) {
999 + uiop->uio_resid = last_resid + past_limit;
1000 + uiop->uio_loffset = last_off;
1001 + } else {
1002 + uiop->uio_resid += past_limit;
1003 + }
1004 +
1005 + return (error);
1006 +}
1007 +
1008 +/*
1009 + * Like nfs_client.c: writerp()
1010 + *
1011 + * Write by creating pages and uiomove data onto them.
1012 + */
1013 +
1014 +int
1015 +smbfs_writenp(smbnode_t *np, caddr_t base, int tcount, struct uio *uio,
1016 + int pgcreated)
1017 +{
1018 + int pagecreate;
1019 + int n;
1020 + int saved_n;
1021 + caddr_t saved_base;
1022 + u_offset_t offset;
1023 + int error;
1024 + int sm_error;
1025 + vnode_t *vp = SMBTOV(np);
1026 +
1027 + ASSERT(tcount <= MAXBSIZE && tcount <= uio->uio_resid);
1028 + ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
1029 + if (!vpm_enable) {
1030 + ASSERT(((uintptr_t)base & MAXBOFFSET) + tcount <= MAXBSIZE);
1031 + }
1032 +
1033 + /*
1034 + * Move bytes in at most PAGESIZE chunks. We must avoid
1035 + * spanning pages in uiomove() because page faults may cause
1036 + * the cache to be invalidated out from under us. The r_size is not
1037 + * updated until after the uiomove. If we push the last page of a
1038 + * file before r_size is correct, we will lose the data written past
1039 + * the current (and invalid) r_size.
1040 + */
1041 + do {
1042 + offset = uio->uio_loffset;
1043 + pagecreate = 0;
1044 +
1045 + /*
1046 + * n is the number of bytes required to satisfy the request
1047 + * or the number of bytes to fill out the page.
1048 + */
1049 + n = (int)MIN((PAGESIZE - (offset & PAGEOFFSET)), tcount);
1050 +
1051 + /*
1052 + * Check to see if we can skip reading in the page
1053 + * and just allocate the memory. We can do this
1054 + * if we are going to rewrite the entire mapping
1055 + * or if we are going to write to or beyond the current
1056 + * end of file from the beginning of the mapping.
1057 + *
1058 + * The read of r_size is now protected by r_statelock.
1059 + */
1060 + mutex_enter(&np->r_statelock);
1061 + /*
1062 + * When pgcreated is nonzero the caller has already done
1063 + * a segmap_getmapflt with forcefault 0 and S_WRITE. With
1064 + * segkpm this means we already have at least one page
1065 + * created and mapped at base.
1066 + */
1067 + pagecreate = pgcreated ||
1068 + ((offset & PAGEOFFSET) == 0 &&
1069 + (n == PAGESIZE || ((offset + n) >= np->r_size)));
1070 +
1071 + mutex_exit(&np->r_statelock);
1072 + if (!vpm_enable && pagecreate) {
1073 + /*
1074 + * The last argument tells segmap_pagecreate() to
1075 + * always lock the page, as opposed to sometimes
1076 + * returning with the page locked. This way we avoid a
1077 + * fault on the ensuing uiomove(), but also
1078 + * more importantly (to fix bug 1094402) we can
1079 + * call segmap_fault() to unlock the page in all
1080 + * cases. An alternative would be to modify
1081 + * segmap_pagecreate() to tell us when it is
1082 + * locking a page, but that's a fairly major
1083 + * interface change.
1084 + */
1085 + if (pgcreated == 0)
1086 + (void) segmap_pagecreate(segkmap, base,
1087 + (uint_t)n, 1);
1088 + saved_base = base;
1089 + saved_n = n;
1090 + }
1091 +
1092 + /*
1093 + * The number of bytes of data in the last page can not
1094 + * be accurately be determined while page is being
1095 + * uiomove'd to and the size of the file being updated.
1096 + * Thus, inform threads which need to know accurately
1097 + * how much data is in the last page of the file. They
1098 + * will not do the i/o immediately, but will arrange for
1099 + * the i/o to happen later when this modify operation
1100 + * will have finished.
1101 + */
1102 + ASSERT(!(np->r_flags & RMODINPROGRESS));
1103 + mutex_enter(&np->r_statelock);
1104 + np->r_flags |= RMODINPROGRESS;
1105 + np->r_modaddr = (offset & MAXBMASK);
1106 + mutex_exit(&np->r_statelock);
1107 +
1108 + if (vpm_enable) {
1109 + /*
1110 + * Copy data. If new pages are created, part of
1111 + * the page that is not written will be initizliazed
1112 + * with zeros.
1113 + */
1114 + error = vpm_data_copy(vp, offset, n, uio,
1115 + !pagecreate, NULL, 0, S_WRITE);
1116 + } else {
1117 + error = uiomove(base, n, UIO_WRITE, uio);
1118 + }
1119 +
1120 + /*
1121 + * r_size is the maximum number of
1122 + * bytes known to be in the file.
1123 + * Make sure it is at least as high as the
1124 + * first unwritten byte pointed to by uio_loffset.
1125 + */
1126 + mutex_enter(&np->r_statelock);
1127 + if (np->r_size < uio->uio_loffset)
1128 + np->r_size = uio->uio_loffset;
1129 + np->r_flags &= ~RMODINPROGRESS;
1130 + np->r_flags |= RDIRTY;
1131 + mutex_exit(&np->r_statelock);
1132 +
1133 + /* n = # of bytes written */
1134 + n = (int)(uio->uio_loffset - offset);
1135 +
1136 + if (!vpm_enable) {
1137 + base += n;
1138 + }
1139 + tcount -= n;
1140 + /*
1141 + * If we created pages w/o initializing them completely,
1142 + * we need to zero the part that wasn't set up.
1143 + * This happens on a most EOF write cases and if
1144 + * we had some sort of error during the uiomove.
1145 + */
1146 + if (!vpm_enable && pagecreate) {
1147 + if ((uio->uio_loffset & PAGEOFFSET) || n == 0)
1148 + (void) kzero(base, PAGESIZE - n);
1149 +
1150 + if (pgcreated) {
1151 + /*
1152 + * Caller is responsible for this page,
1153 + * it was not created in this loop.
1154 + */
1155 + pgcreated = 0;
1156 + } else {
1157 + /*
1158 + * For bug 1094402: segmap_pagecreate locks
1159 + * page. Unlock it. This also unlocks the
1160 + * pages allocated by page_create_va() in
1161 + * segmap_pagecreate().
1162 + */
1163 + sm_error = segmap_fault(kas.a_hat, segkmap,
1164 + saved_base, saved_n,
1165 + F_SOFTUNLOCK, S_WRITE);
1166 + if (error == 0)
1167 + error = sm_error;
1168 + }
1169 + }
1170 + } while (tcount > 0 && error == 0);
1171 +
1172 + return (error);
1173 +}
1174 +
1175 +/*
1176 + * Flags are composed of {B_ASYNC, B_INVAL, B_FREE, B_DONTNEED}
1177 + * Like nfs3_rdwrlbn()
1178 + */
1179 +static int
1180 +smbfs_rdwrlbn(vnode_t *vp, page_t *pp, u_offset_t off, size_t len,
1181 + int flags, cred_t *cr)
1182 +{
1183 + smbmntinfo_t *smi = VTOSMI(vp);
1184 + struct buf *bp;
1185 + int error;
1186 + int sync;
1187 +
1188 + if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1189 + return (EIO);
1190 +
1191 + if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1192 + return (EIO);
1193 +
1194 + bp = pageio_setup(pp, len, vp, flags);
1195 + ASSERT(bp != NULL);
1196 +
1197 + /*
1198 + * pageio_setup should have set b_addr to 0. This
1199 + * is correct since we want to do I/O on a page
1200 + * boundary. bp_mapin will use this addr to calculate
1201 + * an offset, and then set b_addr to the kernel virtual
1202 + * address it allocated for us.
1203 + */
1204 + ASSERT(bp->b_un.b_addr == 0);
1205 +
1206 + bp->b_edev = 0;
1207 + bp->b_dev = 0;
1208 + bp->b_lblkno = lbtodb(off);
1209 + bp->b_file = vp;
1210 + bp->b_offset = (offset_t)off;
1211 + bp_mapin(bp);
1212 +
1213 + /*
1214 + * Calculate the desired level of stability to write data.
1215 + */
1216 + if ((flags & (B_WRITE|B_ASYNC)) == (B_WRITE|B_ASYNC) &&
1217 + freemem > desfree) {
1218 + sync = 0;
1219 + } else {
1220 + sync = 1;
1221 + }
1222 +
1223 + error = smbfs_bio(bp, sync, cr);
1224 +
1225 + bp_mapout(bp);
1226 + pageio_done(bp);
1227 +
1228 + return (error);
1229 +}
1230 +
1231 +
1232 +/*
1233 + * Corresponds to nfs3_vnopc.c : nfs3_bio(), though the NFS code
1234 + * uses nfs3read()/nfs3write() where we use smb_rwuio(). Also,
1235 + * NFS has this later in the file. Move it up here closer to
1236 + * the one call site just above.
1237 + */
1238 +
1239 +static int
1240 +smbfs_bio(struct buf *bp, int sync, cred_t *cr)
1241 +{
1242 + struct iovec aiov[1];
1243 + struct uio auio;
1244 + struct smb_cred scred;
1245 + smbnode_t *np = VTOSMB(bp->b_vp);
1246 + smbmntinfo_t *smi = np->n_mount;
1247 + smb_share_t *ssp = smi->smi_share;
1248 + offset_t offset;
1249 + offset_t endoff;
1250 + size_t count;
1251 + size_t past_eof;
1252 + int error;
1253 +
1254 + ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
1255 +
1256 + offset = ldbtob(bp->b_lblkno);
1257 + count = bp->b_bcount;
1258 + endoff = offset + count;
1259 + if (offset < 0 || endoff < 0)
1260 + return (EINVAL);
1261 +
1262 + /*
1263 + * Limit file I/O to the remaining file size, but see
1264 + * the notes in smbfs_getpage about SMBFS_EOF.
1265 + */
1266 + mutex_enter(&np->r_statelock);
1267 + if (offset >= np->r_size) {
1268 + mutex_exit(&np->r_statelock);
1269 + if (bp->b_flags & B_READ) {
1270 + return (SMBFS_EOF);
1271 + } else {
1272 + return (EINVAL);
1273 + }
1274 + }
1275 + if (endoff > np->r_size) {
1276 + past_eof = (size_t)(endoff - np->r_size);
1277 + count -= past_eof;
1278 + } else
1279 + past_eof = 0;
1280 + mutex_exit(&np->r_statelock);
1281 + ASSERT(count > 0);
1282 +
1283 + /* Caller did bpmapin(). Mapped address is... */
1284 + aiov[0].iov_base = bp->b_un.b_addr;
1285 + aiov[0].iov_len = count;
1286 + auio.uio_iov = aiov;
1287 + auio.uio_iovcnt = 1;
1288 + auio.uio_loffset = offset;
1289 + auio.uio_segflg = UIO_SYSSPACE;
1290 + auio.uio_fmode = 0;
1291 + auio.uio_resid = count;
1292 +
749 1293 /* Shared lock for n_fid use in smb_rwuio */
750 - if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1294 + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER,
1295 + smi->smi_flags & SMI_INT))
751 1296 return (EINTR);
752 1297 smb_credinit(&scred, cr);
753 1298
754 - /* After reconnect, n_fid is invalid */
755 - if (np->n_vcgenid != ssp->ss_vcgenid)
756 - error = ESTALE;
757 - else
758 - error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
759 - uiop, &scred, timo);
1299 + DTRACE_IO1(start, struct buf *, bp);
760 1300
761 - if (error == 0) {
762 - mutex_enter(&np->r_statelock);
763 - np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
764 - if (uiop->uio_loffset > (offset_t)np->r_size)
765 - np->r_size = (len_t)uiop->uio_loffset;
766 - mutex_exit(&np->r_statelock);
767 - if (ioflag & (FSYNC|FDSYNC)) {
768 - /* Don't error the I/O if this fails. */
1301 + if (bp->b_flags & B_READ) {
1302 +
1303 + /* After reconnect, n_fid is invalid */
1304 + if (np->n_vcgenid != ssp->ss_vcgenid)
1305 + error = ESTALE;
1306 + else
1307 + error = smb_rwuio(ssp, np->n_fid, UIO_READ,
1308 + &auio, &scred, smb_timo_read);
1309 +
1310 + /* Like NFS, only set b_error here. */
1311 + bp->b_error = error;
1312 + bp->b_resid = auio.uio_resid;
1313 +
1314 + if (!error && auio.uio_resid != 0)
1315 + error = EIO;
1316 + if (!error && past_eof != 0) {
1317 + /* Zero the memory beyond EOF. */
1318 + bzero(bp->b_un.b_addr + count, past_eof);
1319 + }
1320 + } else {
1321 +
1322 + /* After reconnect, n_fid is invalid */
1323 + if (np->n_vcgenid != ssp->ss_vcgenid)
1324 + error = ESTALE;
1325 + else
1326 + error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
1327 + &auio, &scred, smb_timo_write);
1328 +
1329 + /* Like NFS, only set b_error here. */
1330 + bp->b_error = error;
1331 + bp->b_resid = auio.uio_resid;
1332 +
1333 + if (!error && auio.uio_resid != 0)
1334 + error = EIO;
1335 + if (!error && sync) {
769 1336 (void) smbfs_smb_flush(np, &scred);
770 1337 }
771 1338 }
772 1339
1340 + /*
1341 + * This comes from nfs3_commit()
1342 + */
1343 + if (error != 0) {
1344 + mutex_enter(&np->r_statelock);
1345 + if (error == ESTALE)
1346 + np->r_flags |= RSTALE;
1347 + if (!np->r_error)
1348 + np->r_error = error;
1349 + mutex_exit(&np->r_statelock);
1350 + bp->b_flags |= B_ERROR;
1351 + }
1352 +
1353 + DTRACE_IO1(done, struct buf *, bp);
1354 +
773 1355 smb_credrele(&scred);
774 1356 smbfs_rw_exit(&np->r_lkserlock);
775 1357
776 - /* undo adjustment of resid */
777 - uiop->uio_resid += past_limit;
1358 + if (error == ESTALE)
1359 + smbfs_attrcache_remove(np);
778 1360
779 1361 return (error);
780 1362 }
781 1363
1364 +/*
1365 + * Here NFS has: nfs3write, nfs3read
1366 + * We use smb_rwuio instead.
1367 + */
782 1368
783 1369 /* ARGSUSED */
784 1370 static int
785 1371 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag,
786 1372 cred_t *cr, int *rvalp, caller_context_t *ct)
787 1373 {
788 1374 int error;
789 1375 smbmntinfo_t *smi;
790 1376
791 1377 smi = VTOSMI(vp);
792 1378
793 1379 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
794 1380 return (EIO);
795 1381
796 1382 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
797 1383 return (EIO);
798 1384
799 1385 switch (cmd) {
800 - /* First three from ZFS. XXX - need these? */
801 1386
802 1387 case _FIOFFS:
803 1388 error = smbfs_fsync(vp, 0, cr, ct);
804 1389 break;
805 1390
806 1391 /*
807 1392 * The following two ioctls are used by bfu.
808 1393 * Silently ignore to avoid bfu errors.
809 1394 */
810 1395 case _FIOGDIO:
811 1396 case _FIOSDIO:
812 1397 error = 0;
813 1398 break;
814 1399
815 -#ifdef NOT_YET /* XXX - from the NFS code. */
1400 +#if 0 /* Todo - SMB ioctl query regions */
1401 + case _FIO_SEEK_DATA:
1402 + case _FIO_SEEK_HOLE:
1403 +#endif
1404 +
816 1405 case _FIODIRECTIO:
817 1406 error = smbfs_directio(vp, (int)arg, cr);
818 -#endif
1407 + break;
819 1408
820 1409 /*
821 1410 * Allow get/set with "raw" security descriptor (SD) data.
822 1411 * Useful for testing, diagnosing idmap problems, etc.
823 1412 */
824 1413 case SMBFSIO_GETSD:
825 1414 error = smbfs_acl_iocget(vp, arg, flag, cr);
826 1415 break;
827 1416
828 1417 case SMBFSIO_SETSD:
829 1418 error = smbfs_acl_iocset(vp, arg, flag, cr);
830 1419 break;
831 1420
832 1421 default:
833 1422 error = ENOTTY;
834 1423 break;
835 1424 }
836 1425
837 1426 return (error);
838 1427 }
839 1428
840 1429
841 1430 /*
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
842 1431 * Return either cached or remote attributes. If get remote attr
843 1432 * use them to check and invalidate caches, then cache the new attributes.
844 1433 */
845 1434 /* ARGSUSED */
846 1435 static int
847 1436 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
848 1437 caller_context_t *ct)
849 1438 {
850 1439 smbnode_t *np;
851 1440 smbmntinfo_t *smi;
1441 + int error;
852 1442
853 1443 smi = VTOSMI(vp);
854 1444
855 1445 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
856 1446 return (EIO);
857 1447
858 1448 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
859 1449 return (EIO);
860 1450
861 1451 /*
862 1452 * If it has been specified that the return value will
863 1453 * just be used as a hint, and we are only being asked
864 1454 * for size, fsid or rdevid, then return the client's
865 1455 * notion of these values without checking to make sure
866 1456 * that the attribute cache is up to date.
867 1457 * The whole point is to avoid an over the wire GETATTR
868 1458 * call.
869 1459 */
870 1460 np = VTOSMB(vp);
871 1461 if (flags & ATTR_HINT) {
872 1462 if (vap->va_mask ==
873 1463 (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) {
874 1464 mutex_enter(&np->r_statelock);
875 1465 if (vap->va_mask | AT_SIZE)
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
876 1466 vap->va_size = np->r_size;
877 1467 if (vap->va_mask | AT_FSID)
878 1468 vap->va_fsid = vp->v_vfsp->vfs_dev;
879 1469 if (vap->va_mask | AT_RDEV)
880 1470 vap->va_rdev = vp->v_rdev;
881 1471 mutex_exit(&np->r_statelock);
882 1472 return (0);
883 1473 }
884 1474 }
885 1475
1476 + /*
1477 + * Only need to flush pages if asking for the mtime
1478 + * and if there any dirty pages.
1479 + *
1480 + * Here NFS also checks for async writes (np->r_awcount)
1481 + */
1482 + if (vap->va_mask & AT_MTIME) {
1483 + if (vn_has_cached_data(vp) &&
1484 + ((np->r_flags & RDIRTY) != 0)) {
1485 + mutex_enter(&np->r_statelock);
1486 + np->r_gcount++;
1487 + mutex_exit(&np->r_statelock);
1488 + error = smbfs_putpage(vp, (offset_t)0, 0, 0, cr, ct);
1489 + mutex_enter(&np->r_statelock);
1490 + if (error && (error == ENOSPC || error == EDQUOT)) {
1491 + if (!np->r_error)
1492 + np->r_error = error;
1493 + }
1494 + if (--np->r_gcount == 0)
1495 + cv_broadcast(&np->r_cv);
1496 + mutex_exit(&np->r_statelock);
1497 + }
1498 + }
1499 +
886 1500 return (smbfsgetattr(vp, vap, cr));
887 1501 }
888 1502
889 1503 /* smbfsgetattr() in smbfs_client.c */
890 1504
891 1505 /*ARGSUSED4*/
892 1506 static int
893 1507 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
894 1508 caller_context_t *ct)
895 1509 {
896 1510 vfs_t *vfsp;
897 1511 smbmntinfo_t *smi;
898 1512 int error;
899 1513 uint_t mask;
900 1514 struct vattr oldva;
901 1515
902 1516 vfsp = vp->v_vfsp;
903 1517 smi = VFTOSMI(vfsp);
904 1518
905 1519 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
906 1520 return (EIO);
907 1521
908 1522 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
909 1523 return (EIO);
910 1524
911 1525 mask = vap->va_mask;
912 1526 if (mask & AT_NOSET)
913 1527 return (EINVAL);
914 1528
915 1529 if (vfsp->vfs_flag & VFS_RDONLY)
916 1530 return (EROFS);
917 1531
918 1532 /*
919 1533 * This is a _local_ access check so that only the owner of
920 1534 * this mount can set attributes. With ACLs enabled, the
921 1535 * file owner can be different from the mount owner, and we
922 1536 * need to check the _mount_ owner here. See _access_rwx
923 1537 */
924 1538 bzero(&oldva, sizeof (oldva));
925 1539 oldva.va_mask = AT_TYPE | AT_MODE;
926 1540 error = smbfsgetattr(vp, &oldva, cr);
927 1541 if (error)
928 1542 return (error);
929 1543 oldva.va_mask |= AT_UID | AT_GID;
930 1544 oldva.va_uid = smi->smi_uid;
931 1545 oldva.va_gid = smi->smi_gid;
932 1546
933 1547 error = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
934 1548 smbfs_accessx, vp);
935 1549 if (error)
936 1550 return (error);
937 1551
938 1552 if (mask & (AT_UID | AT_GID)) {
939 1553 if (smi->smi_flags & SMI_ACL)
940 1554 error = smbfs_acl_setids(vp, vap, cr);
941 1555 else
942 1556 error = ENOSYS;
943 1557 if (error != 0) {
944 1558 SMBVDEBUG("error %d seting UID/GID on %s",
945 1559 error, VTOSMB(vp)->n_rpath);
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
946 1560 /*
947 1561 * It might be more correct to return the
948 1562 * error here, but that causes complaints
949 1563 * when root extracts a cpio archive, etc.
950 1564 * So ignore this error, and go ahead with
951 1565 * the rest of the setattr work.
952 1566 */
953 1567 }
954 1568 }
955 1569
956 - return (smbfssetattr(vp, vap, flags, cr));
1570 + error = smbfssetattr(vp, vap, flags, cr);
1571 +
1572 +#ifdef SMBFS_VNEVENT
1573 + if (error == 0 && (vap->va_mask & AT_SIZE) && vap->va_size == 0)
1574 + vnevent_truncate(vp, ct);
1575 +#endif
1576 +
1577 + return (error);
957 1578 }
958 1579
959 1580 /*
960 1581 * Mostly from Darwin smbfs_setattr()
961 1582 * but then modified a lot.
962 1583 */
963 1584 /* ARGSUSED */
964 1585 static int
965 1586 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
966 1587 {
967 1588 int error = 0;
968 1589 smbnode_t *np = VTOSMB(vp);
969 1590 uint_t mask = vap->va_mask;
970 1591 struct timespec *mtime, *atime;
971 1592 struct smb_cred scred;
972 1593 int cerror, modified = 0;
973 1594 unsigned short fid;
974 1595 int have_fid = 0;
975 1596 uint32_t rights = 0;
976 1597 uint32_t dosattr = 0;
977 1598
978 1599 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
979 1600
980 1601 /*
981 1602 * There are no settable attributes on the XATTR dir,
982 1603 * so just silently ignore these. On XATTR files,
983 1604 * you can set the size but nothing else.
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
984 1605 */
985 1606 if (vp->v_flag & V_XATTRDIR)
986 1607 return (0);
987 1608 if (np->n_flag & N_XATTR) {
988 1609 if (mask & AT_TIMES)
989 1610 SMBVDEBUG("ignore set time on xattr\n");
990 1611 mask &= AT_SIZE;
991 1612 }
992 1613
993 1614 /*
1615 + * Only need to flush pages if there are any pages and
1616 + * if the file is marked as dirty in some fashion. The
1617 + * file must be flushed so that we can accurately
1618 + * determine the size of the file and the cached data
1619 + * after the SETATTR returns. A file is considered to
1620 + * be dirty if it is either marked with RDIRTY, has
1621 + * outstanding i/o's active, or is mmap'd. In this
1622 + * last case, we can't tell whether there are dirty
1623 + * pages, so we flush just to be sure.
1624 + */
1625 + if (vn_has_cached_data(vp) &&
1626 + ((np->r_flags & RDIRTY) ||
1627 + np->r_count > 0 ||
1628 + np->r_mapcnt > 0)) {
1629 + ASSERT(vp->v_type != VCHR);
1630 + error = smbfs_putpage(vp, (offset_t)0, 0, 0, cr, NULL);
1631 + if (error && (error == ENOSPC || error == EDQUOT)) {
1632 + mutex_enter(&np->r_statelock);
1633 + if (!np->r_error)
1634 + np->r_error = error;
1635 + mutex_exit(&np->r_statelock);
1636 + }
1637 + }
1638 +
1639 + /*
994 1640 * If our caller is trying to set multiple attributes, they
995 1641 * can make no assumption about what order they are done in.
996 1642 * Here we try to do them in order of decreasing likelihood
997 1643 * of failure, just to minimize the chance we'll wind up
998 1644 * with a partially complete request.
999 1645 */
1000 1646
1001 1647 /* Shared lock for (possible) n_fid use. */
1002 1648 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1003 1649 return (EINTR);
1004 1650 smb_credinit(&scred, cr);
1005 1651
1006 1652 /*
1007 1653 * If the caller has provided extensible attributes,
1008 1654 * map those into DOS attributes supported by SMB.
1009 1655 * Note: zero means "no change".
1010 1656 */
1011 1657 if (mask & AT_XVATTR)
1012 1658 dosattr = xvattr_to_dosattr(np, vap);
1013 1659
1014 1660 /*
1015 1661 * Will we need an open handle for this setattr?
1016 1662 * If so, what rights will we need?
1017 1663 */
1018 1664 if (dosattr || (mask & (AT_ATIME | AT_MTIME))) {
1019 1665 rights |=
1020 1666 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
1021 1667 }
1022 1668 if (mask & AT_SIZE) {
1023 1669 rights |=
1024 1670 SA_RIGHT_FILE_WRITE_DATA |
1025 1671 SA_RIGHT_FILE_APPEND_DATA;
1026 1672 }
1027 1673
1028 1674 /*
1029 1675 * Only SIZE really requires a handle, but it's
1030 1676 * simpler and more reliable to set via a handle.
1031 1677 * Some servers like NT4 won't set times by path.
1032 1678 * Also, we're usually setting everything anyway.
1033 1679 */
1034 1680 if (rights != 0) {
1035 1681 error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
1036 1682 if (error) {
1037 1683 SMBVDEBUG("error %d opening %s\n",
1038 1684 error, np->n_rpath);
1039 1685 goto out;
1040 1686 }
1041 1687 have_fid = 1;
1042 1688 }
1043 1689
1044 1690 /*
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
1045 1691 * If the server supports the UNIX extensions, right here is where
1046 1692 * we'd support changes to uid, gid, mode, and possibly va_flags.
1047 1693 * For now we claim to have made any such changes.
1048 1694 */
1049 1695
1050 1696 if (mask & AT_SIZE) {
1051 1697 /*
1052 1698 * If the new file size is less than what the client sees as
1053 1699 * the file size, then just change the size and invalidate
1054 1700 * the pages.
1055 - * I am commenting this code at present because the function
1056 - * smbfs_putapage() is not yet implemented.
1057 1701 */
1058 1702
1059 1703 /*
1060 1704 * Set the file size to vap->va_size.
1061 1705 */
1062 1706 ASSERT(have_fid);
1063 1707 error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred);
1064 1708 if (error) {
1065 1709 SMBVDEBUG("setsize error %d file %s\n",
1066 1710 error, np->n_rpath);
1067 1711 } else {
1068 1712 /*
1069 1713 * Darwin had code here to zero-extend.
1070 1714 * Tests indicate the server will zero-fill,
1071 - * so looks like we don't need to do this.
1072 - * Good thing, as this could take forever.
1073 - *
1074 - * XXX: Reportedly, writing one byte of zero
1075 - * at the end offset avoids problems here.
1715 + * so looks like we don't need to do that.
1076 1716 */
1077 1717 mutex_enter(&np->r_statelock);
1078 1718 np->r_size = vap->va_size;
1079 1719 mutex_exit(&np->r_statelock);
1080 1720 modified = 1;
1081 1721 }
1082 1722 }
1083 1723
1084 1724 /*
1085 - * XXX: When Solaris has create_time, set that too.
1086 - * Note: create_time is different from ctime.
1725 + * Todo: Implement setting create_time (which is
1726 + * different from ctime).
1087 1727 */
1088 1728 mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0);
1089 1729 atime = ((mask & AT_ATIME) ? &vap->va_atime : 0);
1090 1730
1091 1731 if (dosattr || mtime || atime) {
1092 1732 /*
1093 1733 * Always use the handle-based set attr call now.
1094 1734 */
1095 1735 ASSERT(have_fid);
1096 1736 error = smbfs_smb_setfattr(np, fid,
1097 1737 dosattr, mtime, atime, &scred);
1098 1738 if (error) {
1099 1739 SMBVDEBUG("set times error %d file %s\n",
1100 1740 error, np->n_rpath);
1101 1741 } else {
1102 1742 modified = 1;
1103 1743 }
1104 1744 }
1105 1745
1106 1746 out:
1107 - if (modified) {
1108 - /*
1109 - * Invalidate attribute cache in case the server
1110 - * doesn't set exactly the attributes we asked.
1111 - */
1112 - smbfs_attrcache_remove(np);
1113 - }
1114 -
1115 1747 if (have_fid) {
1116 1748 cerror = smbfs_smb_tmpclose(np, fid, &scred);
1117 1749 if (cerror)
1118 1750 SMBVDEBUG("error %d closing %s\n",
1119 1751 cerror, np->n_rpath);
1120 1752 }
1121 1753
1122 1754 smb_credrele(&scred);
1123 1755 smbfs_rw_exit(&np->r_lkserlock);
1124 1756
1757 + if (modified) {
1758 + /*
1759 + * Invalidate attribute cache in case the server
1760 + * doesn't set exactly the attributes we asked.
1761 + */
1762 + smbfs_attrcache_remove(np);
1763 +
1764 + /*
1765 + * If changing the size of the file, invalidate
1766 + * any local cached data which is no longer part
1767 + * of the file. We also possibly invalidate the
1768 + * last page in the file. We could use
1769 + * pvn_vpzero(), but this would mark the page as
1770 + * modified and require it to be written back to
1771 + * the server for no particularly good reason.
1772 + * This way, if we access it, then we bring it
1773 + * back in. A read should be cheaper than a
1774 + * write.
1775 + */
1776 + if (mask & AT_SIZE) {
1777 + smbfs_invalidate_pages(vp,
1778 + (vap->va_size & PAGEMASK), cr);
1779 + }
1780 + }
1781 +
1125 1782 return (error);
1126 1783 }
1127 1784
1128 1785 /*
1129 1786 * Helper function for extensible system attributes (PSARC 2007/315)
1130 1787 * Compute the DOS attribute word to pass to _setfattr (see above).
1131 1788 * This returns zero IFF no change is being made to attributes.
1132 1789 * Otherwise return the new attributes or SMB_EFA_NORMAL.
1133 1790 */
1134 1791 static uint32_t
1135 1792 xvattr_to_dosattr(smbnode_t *np, struct vattr *vap)
1136 1793 {
1137 1794 xvattr_t *xvap = (xvattr_t *)vap;
1138 1795 xoptattr_t *xoap = NULL;
1139 1796 uint32_t attr = np->r_attr.fa_attr;
1140 1797 boolean_t anyset = B_FALSE;
1141 1798
1142 1799 if ((xoap = xva_getxoptattr(xvap)) == NULL)
1143 1800 return (0);
1144 1801
1145 1802 if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
1146 1803 if (xoap->xoa_archive)
1147 1804 attr |= SMB_FA_ARCHIVE;
1148 1805 else
1149 1806 attr &= ~SMB_FA_ARCHIVE;
1150 1807 XVA_SET_RTN(xvap, XAT_ARCHIVE);
1151 1808 anyset = B_TRUE;
1152 1809 }
1153 1810 if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
1154 1811 if (xoap->xoa_system)
1155 1812 attr |= SMB_FA_SYSTEM;
1156 1813 else
1157 1814 attr &= ~SMB_FA_SYSTEM;
1158 1815 XVA_SET_RTN(xvap, XAT_SYSTEM);
1159 1816 anyset = B_TRUE;
1160 1817 }
1161 1818 if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
1162 1819 if (xoap->xoa_readonly)
1163 1820 attr |= SMB_FA_RDONLY;
1164 1821 else
1165 1822 attr &= ~SMB_FA_RDONLY;
1166 1823 XVA_SET_RTN(xvap, XAT_READONLY);
1167 1824 anyset = B_TRUE;
1168 1825 }
1169 1826 if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
1170 1827 if (xoap->xoa_hidden)
1171 1828 attr |= SMB_FA_HIDDEN;
1172 1829 else
1173 1830 attr &= ~SMB_FA_HIDDEN;
1174 1831 XVA_SET_RTN(xvap, XAT_HIDDEN);
1175 1832 anyset = B_TRUE;
1176 1833 }
1177 1834
1178 1835 if (anyset == B_FALSE)
1179 1836 return (0); /* no change */
1180 1837 if (attr == 0)
1181 1838 attr = SMB_EFA_NORMAL;
1182 1839
1183 1840 return (attr);
1184 1841 }
1185 1842
1186 1843 /*
1187 1844 * smbfs_access_rwx()
1188 1845 * Common function for smbfs_access, etc.
1189 1846 *
1190 1847 * The security model implemented by the FS is unusual
1191 1848 * due to the current "single user mounts" restriction:
1192 1849 * All access under a given mount point uses the CIFS
1193 1850 * credentials established by the owner of the mount.
1194 1851 *
1195 1852 * Most access checking is handled by the CIFS server,
1196 1853 * but we need sufficient Unix access checks here to
1197 1854 * prevent other local Unix users from having access
1198 1855 * to objects under this mount that the uid/gid/mode
1199 1856 * settings in the mount would not allow.
1200 1857 *
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
1201 1858 * With this model, there is a case where we need the
1202 1859 * ability to do an access check before we have the
1203 1860 * vnode for an object. This function takes advantage
1204 1861 * of the fact that the uid/gid/mode is per mount, and
1205 1862 * avoids the need for a vnode.
1206 1863 *
1207 1864 * We still (sort of) need a vnode when we call
1208 1865 * secpolicy_vnode_access, but that only uses
1209 1866 * the vtype field, so we can use a pair of fake
1210 1867 * vnodes that have only v_type filled in.
1211 - *
1212 - * XXX: Later, add a new secpolicy_vtype_access()
1213 - * that takes the vtype instead of a vnode, and
1214 - * get rid of the tmpl_vxxx fake vnodes below.
1215 1868 */
1216 1869 static int
1217 1870 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
1218 1871 {
1219 1872 /* See the secpolicy call below. */
1220 1873 static const vnode_t tmpl_vdir = { .v_type = VDIR };
1221 1874 static const vnode_t tmpl_vreg = { .v_type = VREG };
1222 1875 vattr_t va;
1223 1876 vnode_t *tvp;
1224 1877 struct smbmntinfo *smi = VFTOSMI(vfsp);
1225 1878 int shift = 0;
1226 1879
1227 1880 /*
1228 1881 * Build our (fabricated) vnode attributes.
1229 - * XXX: Could make these templates in the
1230 - * per-mount struct and use them here.
1231 1882 */
1232 1883 bzero(&va, sizeof (va));
1233 1884 va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1234 1885 va.va_type = vtype;
1235 1886 va.va_mode = (vtype == VDIR) ?
1236 1887 smi->smi_dmode : smi->smi_fmode;
1237 1888 va.va_uid = smi->smi_uid;
1238 1889 va.va_gid = smi->smi_gid;
1239 1890
1240 1891 /*
1241 1892 * Disallow write attempts on read-only file systems,
1242 1893 * unless the file is a device or fifo node. Note:
1243 1894 * Inline vn_is_readonly and IS_DEVVP here because
1244 1895 * we may not have a vnode ptr. Original expr. was:
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
1245 1896 * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp))
1246 1897 */
1247 1898 if ((mode & VWRITE) &&
1248 1899 (vfsp->vfs_flag & VFS_RDONLY) &&
1249 1900 !(vtype == VCHR || vtype == VBLK || vtype == VFIFO))
1250 1901 return (EROFS);
1251 1902
1252 1903 /*
1253 1904 * Disallow attempts to access mandatory lock files.
1254 1905 * Similarly, expand MANDLOCK here.
1255 - * XXX: not sure we need this.
1256 1906 */
1257 1907 if ((mode & (VWRITE | VREAD | VEXEC)) &&
1258 1908 va.va_type == VREG && MANDMODE(va.va_mode))
1259 1909 return (EACCES);
1260 1910
1261 1911 /*
1262 1912 * Access check is based on only
1263 1913 * one of owner, group, public.
1264 1914 * If not owner, then check group.
1265 1915 * If not a member of the group,
1266 1916 * then check public access.
1267 1917 */
1268 1918 if (crgetuid(cr) != va.va_uid) {
1269 1919 shift += 3;
1270 1920 if (!groupmember(va.va_gid, cr))
1271 1921 shift += 3;
1272 1922 }
1273 1923
1274 1924 /*
1275 1925 * We need a vnode for secpolicy_vnode_access,
1276 1926 * but the only thing it looks at is v_type,
1277 1927 * so pass one of the templates above.
1278 1928 */
1279 1929 tvp = (va.va_type == VDIR) ?
1280 1930 (vnode_t *)&tmpl_vdir :
1281 1931 (vnode_t *)&tmpl_vreg;
1282 1932
1283 1933 return (secpolicy_vnode_access2(cr, tvp, va.va_uid,
1284 1934 va.va_mode << shift, mode));
1285 1935 }
1286 1936
1287 1937 /*
1288 1938 * See smbfs_setattr
1289 1939 */
1290 1940 static int
1291 1941 smbfs_accessx(void *arg, int mode, cred_t *cr)
1292 1942 {
1293 1943 vnode_t *vp = arg;
1294 1944 /*
1295 1945 * Note: The caller has checked the current zone,
1296 1946 * the SMI_DEAD and VFS_UNMOUNTED flags, etc.
1297 1947 */
1298 1948 return (smbfs_access_rwx(vp->v_vfsp, vp->v_type, mode, cr));
1299 1949 }
1300 1950
1301 1951 /*
1302 1952 * XXX
1303 1953 * This op should support PSARC 2007/403, Modified Access Checks for CIFS
1304 1954 */
1305 1955 /* ARGSUSED */
1306 1956 static int
1307 1957 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
1308 1958 {
1309 1959 vfs_t *vfsp;
1310 1960 smbmntinfo_t *smi;
1311 1961
1312 1962 vfsp = vp->v_vfsp;
1313 1963 smi = VFTOSMI(vfsp);
1314 1964
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
1315 1965 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1316 1966 return (EIO);
1317 1967
1318 1968 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1319 1969 return (EIO);
1320 1970
1321 1971 return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr));
1322 1972 }
1323 1973
1324 1974
1975 +/* ARGSUSED */
1976 +static int
1977 +smbfs_readlink(vnode_t *vp, struct uio *uiop, cred_t *cr, caller_context_t *ct)
1978 +{
1979 + /* Not yet... */
1980 + return (ENOSYS);
1981 +}
1982 +
1983 +
1325 1984 /*
1326 1985 * Flush local dirty pages to stable storage on the server.
1327 1986 *
1328 1987 * If FNODSYNC is specified, then there is nothing to do because
1329 1988 * metadata changes are not cached on the client before being
1330 1989 * sent to the server.
1331 1990 */
1332 1991 /* ARGSUSED */
1333 1992 static int
1334 1993 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
1335 1994 {
1336 1995 int error = 0;
1337 1996 smbmntinfo_t *smi;
1338 1997 smbnode_t *np;
1339 1998 struct smb_cred scred;
1340 1999
1341 2000 np = VTOSMB(vp);
1342 2001 smi = VTOSMI(vp);
1343 2002
1344 2003 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1345 2004 return (EIO);
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
1346 2005
1347 2006 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1348 2007 return (EIO);
1349 2008
1350 2009 if ((syncflag & FNODSYNC) || IS_SWAPVP(vp))
1351 2010 return (0);
1352 2011
1353 2012 if ((syncflag & (FSYNC|FDSYNC)) == 0)
1354 2013 return (0);
1355 2014
2015 + error = smbfs_putpage(vp, (offset_t)0, 0, 0, cr, ct);
2016 + if (error)
2017 + return (error);
2018 +
1356 2019 /* Shared lock for n_fid use in _flush */
1357 2020 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1358 2021 return (EINTR);
1359 2022 smb_credinit(&scred, cr);
1360 2023
1361 2024 error = smbfs_smb_flush(np, &scred);
1362 2025
1363 2026 smb_credrele(&scred);
1364 2027 smbfs_rw_exit(&np->r_lkserlock);
1365 2028
1366 2029 return (error);
1367 2030 }
1368 2031
1369 2032 /*
1370 2033 * Last reference to vnode went away.
1371 2034 */
1372 2035 /* ARGSUSED */
1373 2036 static void
1374 2037 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
1375 2038 {
1376 - smbnode_t *np;
1377 2039 struct smb_cred scred;
2040 + smbnode_t *np = VTOSMB(vp);
2041 + int error;
1378 2042
1379 2043 /*
1380 2044 * Don't "bail out" for VFS_UNMOUNTED here,
1381 2045 * as we want to do cleanup, etc.
1382 2046 * See also pcfs_inactive
1383 2047 */
1384 2048
1385 - np = VTOSMB(vp);
1386 -
1387 2049 /*
1388 2050 * If this is coming from the wrong zone, we let someone in the right
1389 2051 * zone take care of it asynchronously. We can get here due to
1390 2052 * VN_RELE() being called from pageout() or fsflush(). This call may
1391 2053 * potentially turn into an expensive no-op if, for instance, v_count
1392 2054 * gets incremented in the meantime, but it's still correct.
1393 2055 */
1394 2056
1395 2057 /*
2058 + * From NFS:rinactive()
2059 + *
2060 + * Before freeing anything, wait until all asynchronous
2061 + * activity is done on this rnode. This will allow all
2062 + * asynchronous read ahead and write behind i/o's to
2063 + * finish.
2064 + */
2065 + mutex_enter(&np->r_statelock);
2066 + while (np->r_count > 0)
2067 + cv_wait(&np->r_cv, &np->r_statelock);
2068 + mutex_exit(&np->r_statelock);
2069 +
2070 + /*
2071 + * Flush and invalidate all pages associated with the vnode.
2072 + */
2073 + if (vn_has_cached_data(vp)) {
2074 + if ((np->r_flags & RDIRTY) && !np->r_error) {
2075 + error = smbfs_putpage(vp, (u_offset_t)0, 0, 0, cr, ct);
2076 + if (error && (error == ENOSPC || error == EDQUOT)) {
2077 + mutex_enter(&np->r_statelock);
2078 + if (!np->r_error)
2079 + np->r_error = error;
2080 + mutex_exit(&np->r_statelock);
2081 + }
2082 + }
2083 + smbfs_invalidate_pages(vp, (u_offset_t)0, cr);
2084 + }
2085 + /*
2086 + * This vnode should have lost all cached data.
2087 + */
2088 + ASSERT(vn_has_cached_data(vp) == 0);
2089 +
2090 + /*
1396 2091 * Defend against the possibility that higher-level callers
1397 2092 * might not correctly balance open and close calls. If we
1398 2093 * get here with open references remaining, it means there
1399 2094 * was a missing VOP_CLOSE somewhere. If that happens, do
1400 2095 * the close here so we don't "leak" FIDs on the server.
1401 2096 *
1402 2097 * Exclusive lock for modifying n_fid stuff.
1403 2098 * Don't want this one ever interruptible.
1404 2099 */
1405 2100 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
1406 2101 smb_credinit(&scred, cr);
1407 2102
1408 2103 switch (np->n_ovtype) {
1409 2104 case VNON:
1410 2105 /* not open (OK) */
1411 2106 break;
1412 2107
1413 2108 case VDIR:
1414 2109 if (np->n_dirrefs == 0)
1415 2110 break;
1416 2111 SMBVDEBUG("open dir: refs %d path %s\n",
1417 2112 np->n_dirrefs, np->n_rpath);
1418 2113 /* Force last close. */
1419 2114 np->n_dirrefs = 1;
1420 2115 smbfs_rele_fid(np, &scred);
1421 2116 break;
1422 2117
1423 2118 case VREG:
1424 2119 if (np->n_fidrefs == 0)
1425 2120 break;
1426 2121 SMBVDEBUG("open file: refs %d id 0x%x path %s\n",
1427 2122 np->n_fidrefs, np->n_fid, np->n_rpath);
1428 2123 /* Force last close. */
1429 2124 np->n_fidrefs = 1;
1430 2125 smbfs_rele_fid(np, &scred);
1431 2126 break;
1432 2127
1433 2128 default:
1434 2129 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
1435 2130 np->n_ovtype = VNON;
1436 2131 break;
1437 2132 }
1438 2133
1439 2134 smb_credrele(&scred);
1440 2135 smbfs_rw_exit(&np->r_lkserlock);
1441 2136
1442 2137 /*
1443 2138 * XATTR directories (and the files under them) have
1444 2139 * little value for reclaim, so just remove them from
1445 2140 * the "hash" (AVL) as soon as they go inactive.
1446 2141 * Note that the node may already have been removed
1447 2142 * from the hash by smbfsremove.
1448 2143 */
1449 2144 if ((np->n_flag & N_XATTR) != 0 &&
1450 2145 (np->r_flags & RHASHED) != 0)
1451 2146 smbfs_rmhash(np);
1452 2147
1453 2148 smbfs_addfree(np);
1454 2149 }
1455 2150
1456 2151 /*
1457 2152 * Remote file system operations having to do with directory manipulation.
1458 2153 */
1459 2154 /* ARGSUSED */
1460 2155 static int
1461 2156 smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
1462 2157 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
1463 2158 int *direntflags, pathname_t *realpnp)
1464 2159 {
1465 2160 vfs_t *vfs;
1466 2161 smbmntinfo_t *smi;
1467 2162 smbnode_t *dnp;
1468 2163 int error;
1469 2164
1470 2165 vfs = dvp->v_vfsp;
1471 2166 smi = VFTOSMI(vfs);
1472 2167
1473 2168 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1474 2169 return (EPERM);
1475 2170
1476 2171 if (smi->smi_flags & SMI_DEAD || vfs->vfs_flag & VFS_UNMOUNTED)
1477 2172 return (EIO);
1478 2173
1479 2174 dnp = VTOSMB(dvp);
1480 2175
1481 2176 /*
1482 2177 * Are we looking up extended attributes? If so, "dvp" is
1483 2178 * the file or directory for which we want attributes, and
1484 2179 * we need a lookup of the (faked up) attribute directory
1485 2180 * before we lookup the rest of the path.
1486 2181 */
1487 2182 if (flags & LOOKUP_XATTR) {
1488 2183 /*
1489 2184 * Require the xattr mount option.
1490 2185 */
1491 2186 if ((vfs->vfs_flag & VFS_XATTR) == 0)
1492 2187 return (EINVAL);
1493 2188
1494 2189 error = smbfs_get_xattrdir(dvp, vpp, cr, flags);
1495 2190 return (error);
1496 2191 }
1497 2192
1498 2193 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp)))
1499 2194 return (EINTR);
1500 2195
1501 2196 error = smbfslookup(dvp, nm, vpp, cr, 1, ct);
1502 2197
1503 2198 smbfs_rw_exit(&dnp->r_rwlock);
1504 2199
1505 2200 return (error);
1506 2201 }
1507 2202
1508 2203 /* ARGSUSED */
1509 2204 static int
1510 2205 smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
1511 2206 int cache_ok, caller_context_t *ct)
1512 2207 {
1513 2208 int error;
1514 2209 int supplen; /* supported length */
1515 2210 vnode_t *vp;
1516 2211 smbnode_t *np;
1517 2212 smbnode_t *dnp;
1518 2213 smbmntinfo_t *smi;
1519 2214 /* struct smb_vc *vcp; */
1520 2215 const char *ill;
1521 2216 const char *name = (const char *)nm;
1522 2217 int nmlen = strlen(nm);
1523 2218 int rplen;
1524 2219 struct smb_cred scred;
1525 2220 struct smbfattr fa;
1526 2221
1527 2222 smi = VTOSMI(dvp);
1528 2223 dnp = VTOSMB(dvp);
1529 2224
1530 2225 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
1531 2226
1532 2227 #ifdef NOT_YET
↓ open down ↓ |
127 lines elided |
↑ open up ↑ |
1533 2228 vcp = SSTOVC(smi->smi_share);
1534 2229
1535 2230 /* XXX: Should compute this once and store it in smbmntinfo_t */
1536 2231 supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12;
1537 2232 #else
1538 2233 supplen = 255;
1539 2234 #endif
1540 2235
1541 2236 /*
1542 2237 * RWlock must be held, either reader or writer.
1543 - * XXX: Can we check without looking directly
1544 - * inside the struct smbfs_rwlock_t?
1545 2238 */
1546 2239 ASSERT(dnp->r_rwlock.count != 0);
1547 2240
1548 2241 /*
1549 2242 * If lookup is for "", just return dvp.
1550 2243 * No need to perform any access checks.
1551 2244 */
1552 2245 if (nmlen == 0) {
1553 2246 VN_HOLD(dvp);
1554 2247 *vpp = dvp;
1555 2248 return (0);
1556 2249 }
1557 2250
1558 2251 /*
1559 2252 * Can't do lookups in non-directories.
1560 2253 */
1561 2254 if (dvp->v_type != VDIR)
1562 2255 return (ENOTDIR);
1563 2256
1564 2257 /*
1565 2258 * Need search permission in the directory.
1566 2259 */
1567 2260 error = smbfs_access(dvp, VEXEC, 0, cr, ct);
1568 2261 if (error)
1569 2262 return (error);
1570 2263
1571 2264 /*
1572 2265 * If lookup is for ".", just return dvp.
1573 2266 * Access check was done above.
1574 2267 */
1575 2268 if (nmlen == 1 && name[0] == '.') {
1576 2269 VN_HOLD(dvp);
1577 2270 *vpp = dvp;
1578 2271 return (0);
1579 2272 }
1580 2273
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
1581 2274 /*
1582 2275 * Now some sanity checks on the name.
1583 2276 * First check the length.
1584 2277 */
1585 2278 if (nmlen > supplen)
1586 2279 return (ENAMETOOLONG);
1587 2280
1588 2281 /*
1589 2282 * Avoid surprises with characters that are
1590 2283 * illegal in Windows file names.
1591 - * Todo: CATIA mappings XXX
2284 + * Todo: CATIA mappings?
1592 2285 */
1593 2286 ill = illegal_chars;
1594 2287 if (dnp->n_flag & N_XATTR)
1595 2288 ill++; /* allow colon */
1596 2289 if (strpbrk(nm, ill))
1597 2290 return (EINVAL);
1598 2291
1599 2292 /*
1600 2293 * Special handling for lookup of ".."
1601 2294 *
1602 2295 * We keep full pathnames (as seen on the server)
1603 2296 * so we can just trim off the last component to
1604 2297 * get the full pathname of the parent. Note:
1605 2298 * We don't actually copy and modify, but just
1606 2299 * compute the trimmed length and pass that with
1607 2300 * the current dir path (not null terminated).
1608 2301 *
1609 2302 * We don't go over-the-wire to get attributes
1610 2303 * for ".." because we know it's a directory,
1611 2304 * and we can just leave the rest "stale"
1612 2305 * until someone does a getattr.
1613 2306 */
1614 2307 if (nmlen == 2 && name[0] == '.' && name[1] == '.') {
1615 2308 if (dvp->v_flag & VROOT) {
1616 2309 /*
1617 2310 * Already at the root. This can happen
1618 2311 * with directory listings at the root,
1619 2312 * which lookup "." and ".." to get the
1620 2313 * inode numbers. Let ".." be the same
1621 2314 * as "." in the FS root.
1622 2315 */
1623 2316 VN_HOLD(dvp);
1624 2317 *vpp = dvp;
1625 2318 return (0);
1626 2319 }
1627 2320
1628 2321 /*
1629 2322 * Special case for XATTR directory
1630 2323 */
1631 2324 if (dvp->v_flag & V_XATTRDIR) {
1632 2325 error = smbfs_xa_parent(dvp, vpp);
1633 2326 return (error);
1634 2327 }
1635 2328
1636 2329 /*
1637 2330 * Find the parent path length.
1638 2331 */
1639 2332 rplen = dnp->n_rplen;
1640 2333 ASSERT(rplen > 0);
1641 2334 while (--rplen >= 0) {
1642 2335 if (dnp->n_rpath[rplen] == '\\')
1643 2336 break;
1644 2337 }
1645 2338 if (rplen <= 0) {
1646 2339 /* Found our way to the root. */
1647 2340 vp = SMBTOV(smi->smi_root);
1648 2341 VN_HOLD(vp);
1649 2342 *vpp = vp;
1650 2343 return (0);
1651 2344 }
1652 2345 np = smbfs_node_findcreate(smi,
1653 2346 dnp->n_rpath, rplen, NULL, 0, 0,
1654 2347 &smbfs_fattr0); /* force create */
1655 2348 ASSERT(np != NULL);
1656 2349 vp = SMBTOV(np);
1657 2350 vp->v_type = VDIR;
1658 2351
1659 2352 /* Success! */
1660 2353 *vpp = vp;
1661 2354 return (0);
1662 2355 }
1663 2356
1664 2357 /*
1665 2358 * Normal lookup of a name under this directory.
1666 2359 * Note we handled "", ".", ".." above.
1667 2360 */
1668 2361 if (cache_ok) {
1669 2362 /*
1670 2363 * The caller indicated that it's OK to use a
1671 2364 * cached result for this lookup, so try to
1672 2365 * reclaim a node from the smbfs node cache.
1673 2366 */
1674 2367 error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr);
1675 2368 if (error)
1676 2369 return (error);
1677 2370 if (vp != NULL) {
1678 2371 /* hold taken in lookup_cache */
1679 2372 *vpp = vp;
1680 2373 return (0);
1681 2374 }
1682 2375 }
1683 2376
1684 2377 /*
1685 2378 * OK, go over-the-wire to get the attributes,
1686 2379 * then create the node.
1687 2380 */
1688 2381 smb_credinit(&scred, cr);
1689 2382 /* Note: this can allocate a new "name" */
1690 2383 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred);
1691 2384 smb_credrele(&scred);
1692 2385 if (error == ENOTDIR) {
1693 2386 /*
1694 2387 * Lookup failed because this directory was
1695 2388 * removed or renamed by another client.
1696 2389 * Remove any cached attributes under it.
1697 2390 */
1698 2391 smbfs_attrcache_remove(dnp);
1699 2392 smbfs_attrcache_prune(dnp);
1700 2393 }
1701 2394 if (error)
1702 2395 goto out;
1703 2396
1704 2397 error = smbfs_nget(dvp, name, nmlen, &fa, &vp);
1705 2398 if (error)
1706 2399 goto out;
1707 2400
1708 2401 /* Success! */
1709 2402 *vpp = vp;
1710 2403
1711 2404 out:
1712 2405 /* smbfs_smb_lookup may have allocated name. */
1713 2406 if (name != nm)
1714 2407 smbfs_name_free(name, nmlen);
1715 2408
1716 2409 return (error);
1717 2410 }
1718 2411
1719 2412 /*
1720 2413 * smbfslookup_cache
1721 2414 *
1722 2415 * Try to reclaim a node from the smbfs node cache.
1723 2416 * Some statistics for DEBUG.
1724 2417 *
1725 2418 * This mechanism lets us avoid many of the five (or more)
1726 2419 * OtW lookup calls per file seen with "ls -l" if we search
1727 2420 * the smbfs node cache for recently inactive(ated) nodes.
1728 2421 */
1729 2422 #ifdef DEBUG
1730 2423 int smbfs_lookup_cache_calls = 0;
1731 2424 int smbfs_lookup_cache_error = 0;
1732 2425 int smbfs_lookup_cache_miss = 0;
1733 2426 int smbfs_lookup_cache_stale = 0;
1734 2427 int smbfs_lookup_cache_hits = 0;
1735 2428 #endif /* DEBUG */
1736 2429
1737 2430 /* ARGSUSED */
1738 2431 static int
1739 2432 smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen,
1740 2433 vnode_t **vpp, cred_t *cr)
1741 2434 {
1742 2435 struct vattr va;
1743 2436 smbnode_t *dnp;
1744 2437 smbnode_t *np;
1745 2438 vnode_t *vp;
1746 2439 int error;
1747 2440 char sep;
1748 2441
1749 2442 dnp = VTOSMB(dvp);
1750 2443 *vpp = NULL;
1751 2444
1752 2445 #ifdef DEBUG
1753 2446 smbfs_lookup_cache_calls++;
1754 2447 #endif
1755 2448
1756 2449 /*
1757 2450 * First make sure we can get attributes for the
1758 2451 * directory. Cached attributes are OK here.
1759 2452 * If we removed or renamed the directory, this
1760 2453 * will return ENOENT. If someone else removed
1761 2454 * this directory or file, we'll find out when we
1762 2455 * try to open or get attributes.
1763 2456 */
1764 2457 va.va_mask = AT_TYPE | AT_MODE;
1765 2458 error = smbfsgetattr(dvp, &va, cr);
1766 2459 if (error) {
1767 2460 #ifdef DEBUG
1768 2461 smbfs_lookup_cache_error++;
1769 2462 #endif
1770 2463 return (error);
1771 2464 }
1772 2465
1773 2466 /*
1774 2467 * Passing NULL smbfattr here so we will
1775 2468 * just look, not create.
1776 2469 */
1777 2470 sep = SMBFS_DNP_SEP(dnp);
1778 2471 np = smbfs_node_findcreate(dnp->n_mount,
1779 2472 dnp->n_rpath, dnp->n_rplen,
1780 2473 nm, nmlen, sep, NULL);
1781 2474 if (np == NULL) {
1782 2475 #ifdef DEBUG
1783 2476 smbfs_lookup_cache_miss++;
1784 2477 #endif
1785 2478 return (0);
1786 2479 }
1787 2480
1788 2481 /*
1789 2482 * Found it. Attributes still valid?
1790 2483 */
1791 2484 vp = SMBTOV(np);
1792 2485 if (np->r_attrtime <= gethrtime()) {
1793 2486 /* stale */
1794 2487 #ifdef DEBUG
1795 2488 smbfs_lookup_cache_stale++;
1796 2489 #endif
1797 2490 VN_RELE(vp);
1798 2491 return (0);
1799 2492 }
1800 2493
1801 2494 /*
↓ open down ↓ |
200 lines elided |
↑ open up ↑ |
1802 2495 * Success!
1803 2496 * Caller gets hold from smbfs_node_findcreate
1804 2497 */
1805 2498 #ifdef DEBUG
1806 2499 smbfs_lookup_cache_hits++;
1807 2500 #endif
1808 2501 *vpp = vp;
1809 2502 return (0);
1810 2503 }
1811 2504
2505 +
1812 2506 /*
1813 2507 * XXX
1814 2508 * vsecattr_t is new to build 77, and we need to eventually support
1815 2509 * it in order to create an ACL when an object is created.
1816 2510 *
1817 2511 * This op should support the new FIGNORECASE flag for case-insensitive
1818 2512 * lookups, per PSARC 2007/244.
1819 2513 */
1820 2514 /* ARGSUSED */
1821 2515 static int
1822 2516 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
1823 2517 int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct,
1824 2518 vsecattr_t *vsecp)
1825 2519 {
1826 2520 int error;
1827 2521 int cerror;
1828 2522 vfs_t *vfsp;
1829 2523 vnode_t *vp;
1830 -#ifdef NOT_YET
1831 2524 smbnode_t *np;
1832 -#endif
1833 2525 smbnode_t *dnp;
1834 2526 smbmntinfo_t *smi;
1835 2527 struct vattr vattr;
1836 2528 struct smbfattr fattr;
1837 2529 struct smb_cred scred;
1838 2530 const char *name = (const char *)nm;
1839 2531 int nmlen = strlen(nm);
1840 2532 uint32_t disp;
1841 2533 uint16_t fid;
1842 2534 int xattr;
1843 2535
1844 2536 vfsp = dvp->v_vfsp;
1845 2537 smi = VFTOSMI(vfsp);
1846 2538 dnp = VTOSMB(dvp);
1847 2539 vp = NULL;
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
1848 2540
1849 2541 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1850 2542 return (EPERM);
1851 2543
1852 2544 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1853 2545 return (EIO);
1854 2546
1855 2547 /*
1856 2548 * Note: this may break mknod(2) calls to create a directory,
1857 2549 * but that's obscure use. Some other filesystems do this.
1858 - * XXX: Later, redirect VDIR type here to _mkdir.
2550 + * Todo: redirect VDIR type here to _mkdir.
1859 2551 */
1860 2552 if (va->va_type != VREG)
1861 2553 return (EINVAL);
1862 2554
1863 2555 /*
1864 2556 * If the pathname is "", just use dvp, no checks.
1865 2557 * Do this outside of the rwlock (like zfs).
1866 2558 */
1867 2559 if (nmlen == 0) {
1868 2560 VN_HOLD(dvp);
1869 2561 *vpp = dvp;
1870 2562 return (0);
1871 2563 }
1872 2564
1873 2565 /* Don't allow "." or ".." through here. */
1874 2566 if ((nmlen == 1 && name[0] == '.') ||
1875 2567 (nmlen == 2 && name[0] == '.' && name[1] == '.'))
1876 2568 return (EISDIR);
1877 2569
1878 2570 /*
1879 2571 * We make a copy of the attributes because the caller does not
1880 2572 * expect us to change what va points to.
1881 2573 */
1882 2574 vattr = *va;
1883 2575
1884 2576 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
1885 2577 return (EINTR);
1886 2578 smb_credinit(&scred, cr);
1887 2579
1888 2580 /*
1889 2581 * NFS needs to go over the wire, just to be sure whether the
1890 2582 * file exists or not. Using a cached result is dangerous in
1891 2583 * this case when making a decision regarding existence.
1892 2584 *
1893 2585 * The SMB protocol does NOT really need to go OTW here
1894 2586 * thanks to the expressive NTCREATE disposition values.
1895 2587 * Unfortunately, to do Unix access checks correctly,
1896 2588 * we need to know if the object already exists.
1897 2589 * When the object does not exist, we need VWRITE on
1898 2590 * the directory. Note: smbfslookup() checks VEXEC.
1899 2591 */
1900 2592 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
1901 2593 if (error == 0) {
1902 2594 /*
1903 2595 * The file already exists. Error?
1904 2596 * NB: have a hold from smbfslookup
1905 2597 */
1906 2598 if (exclusive == EXCL) {
1907 2599 error = EEXIST;
1908 2600 VN_RELE(vp);
1909 2601 goto out;
1910 2602 }
1911 2603 /*
1912 2604 * Verify requested access.
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
1913 2605 */
1914 2606 error = smbfs_access(vp, mode, 0, cr, ct);
1915 2607 if (error) {
1916 2608 VN_RELE(vp);
1917 2609 goto out;
1918 2610 }
1919 2611
1920 2612 /*
1921 2613 * Truncate (if requested).
1922 2614 */
1923 - if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) {
2615 + if ((vattr.va_mask & AT_SIZE) && vp->v_type == VREG) {
2616 + np = VTOSMB(vp);
2617 + /*
2618 + * Check here for large file truncation by
2619 + * LF-unaware process, like ufs_create().
2620 + */
2621 + if (!(lfaware & FOFFMAX)) {
2622 + mutex_enter(&np->r_statelock);
2623 + if (np->r_size > MAXOFF32_T)
2624 + error = EOVERFLOW;
2625 + mutex_exit(&np->r_statelock);
2626 + }
2627 + if (error) {
2628 + VN_RELE(vp);
2629 + goto out;
2630 + }
1924 2631 vattr.va_mask = AT_SIZE;
1925 2632 error = smbfssetattr(vp, &vattr, 0, cr);
1926 2633 if (error) {
1927 2634 VN_RELE(vp);
1928 2635 goto out;
1929 2636 }
2637 +#ifdef SMBFS_VNEVENT
2638 + /* Existing file was truncated */
2639 + vnevent_create(vp, ct);
2640 +#endif
2641 + /* invalidate pages done in smbfssetattr() */
1930 2642 }
1931 2643 /* Success! */
1932 -#ifdef NOT_YET
1933 - vnevent_create(vp, ct);
1934 -#endif
1935 2644 *vpp = vp;
1936 2645 goto out;
1937 2646 }
1938 2647
1939 2648 /*
1940 2649 * The file did not exist. Need VWRITE in the directory.
1941 2650 */
1942 2651 error = smbfs_access(dvp, VWRITE, 0, cr, ct);
1943 2652 if (error)
1944 2653 goto out;
1945 2654
1946 2655 /*
1947 2656 * Now things get tricky. We also need to check the
1948 2657 * requested open mode against the file we may create.
1949 2658 * See comments at smbfs_access_rwx
1950 2659 */
1951 2660 error = smbfs_access_rwx(vfsp, VREG, mode, cr);
1952 2661 if (error)
1953 2662 goto out;
1954 2663
1955 2664 /*
1956 2665 * Now the code derived from Darwin,
1957 2666 * but with greater use of NT_CREATE
1958 2667 * disposition options. Much changed.
1959 2668 *
1960 2669 * Create (or open) a new child node.
1961 2670 * Note we handled "." and ".." above.
1962 2671 */
1963 2672
1964 2673 if (exclusive == EXCL)
1965 2674 disp = NTCREATEX_DISP_CREATE;
1966 2675 else {
1967 2676 /* Truncate regular files if requested. */
1968 2677 if ((va->va_type == VREG) &&
1969 2678 (va->va_mask & AT_SIZE) &&
1970 2679 (va->va_size == 0))
1971 2680 disp = NTCREATEX_DISP_OVERWRITE_IF;
1972 2681 else
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
1973 2682 disp = NTCREATEX_DISP_OPEN_IF;
1974 2683 }
1975 2684 xattr = (dnp->n_flag & N_XATTR) ? 1 : 0;
1976 2685 error = smbfs_smb_create(dnp,
1977 2686 name, nmlen, xattr,
1978 2687 disp, &scred, &fid);
1979 2688 if (error)
1980 2689 goto out;
1981 2690
1982 2691 /*
1983 - * XXX: Missing some code here to deal with
1984 - * the case where we opened an existing file,
1985 - * it's size is larger than 32-bits, and we're
1986 - * setting the size from a process that's not
1987 - * aware of large file offsets. i.e.
1988 - * from the NFS3 code:
1989 - */
1990 -#if NOT_YET /* XXX */
1991 - if ((vattr.va_mask & AT_SIZE) &&
1992 - vp->v_type == VREG) {
1993 - np = VTOSMB(vp);
1994 - /*
1995 - * Check here for large file handled
1996 - * by LF-unaware process (as
1997 - * ufs_create() does)
1998 - */
1999 - if (!(lfaware & FOFFMAX)) {
2000 - mutex_enter(&np->r_statelock);
2001 - if (np->r_size > MAXOFF32_T)
2002 - error = EOVERFLOW;
2003 - mutex_exit(&np->r_statelock);
2004 - }
2005 - if (!error) {
2006 - vattr.va_mask = AT_SIZE;
2007 - error = smbfssetattr(vp,
2008 - &vattr, 0, cr);
2009 - }
2010 - }
2011 -#endif /* XXX */
2012 - /*
2013 2692 * Should use the fid to get/set the size
2014 2693 * while we have it opened here. See above.
2015 2694 */
2016 2695
2017 2696 cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred);
2018 2697 if (cerror)
2019 2698 SMBVDEBUG("error %d closing %s\\%s\n",
2020 2699 cerror, dnp->n_rpath, name);
2021 2700
2022 2701 /*
2023 2702 * In the open case, the name may differ a little
2024 2703 * from what we passed to create (case, etc.)
2025 2704 * so call lookup to get the (opened) name.
2026 2705 *
2027 2706 * XXX: Could avoid this extra lookup if the
2028 2707 * "createact" result from NT_CREATE says we
2029 2708 * created the object.
2030 2709 */
2031 2710 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
2032 2711 if (error)
2033 2712 goto out;
2034 2713
2035 2714 /* update attr and directory cache */
2036 2715 smbfs_attr_touchdir(dnp);
2037 2716
2038 2717 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2039 2718 if (error)
2040 2719 goto out;
2041 2720
2042 - /* XXX invalidate pages if we truncated? */
2043 -
2044 2721 /* Success! */
2045 2722 *vpp = vp;
2046 2723 error = 0;
2047 2724
2048 2725 out:
2049 2726 smb_credrele(&scred);
2050 2727 smbfs_rw_exit(&dnp->r_rwlock);
2051 2728 if (name != nm)
2052 2729 smbfs_name_free(name, nmlen);
2053 2730 return (error);
2054 2731 }
2055 2732
2056 2733 /*
2057 2734 * XXX
2058 2735 * This op should support the new FIGNORECASE flag for case-insensitive
2059 2736 * lookups, per PSARC 2007/244.
2060 2737 */
2061 2738 /* ARGSUSED */
2062 2739 static int
2063 2740 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
2064 2741 int flags)
2065 2742 {
2066 2743 struct smb_cred scred;
2067 2744 vnode_t *vp = NULL;
2068 2745 smbnode_t *dnp = VTOSMB(dvp);
2069 2746 smbmntinfo_t *smi = VTOSMI(dvp);
2070 2747 int error;
2071 2748
2072 2749 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2073 2750 return (EPERM);
2074 2751
2075 2752 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2076 2753 return (EIO);
2077 2754
2078 2755 /*
2079 2756 * Verify access to the dirctory.
2080 2757 */
2081 2758 error = smbfs_access(dvp, VWRITE|VEXEC, 0, cr, ct);
2082 2759 if (error)
2083 2760 return (error);
2084 2761
2085 2762 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2086 2763 return (EINTR);
2087 2764 smb_credinit(&scred, cr);
2088 2765
2089 2766 /* Lookup the file to remove. */
2090 2767 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2091 2768 if (error == 0) {
2092 2769 /*
2093 2770 * Do the real remove work
2094 2771 */
2095 2772 error = smbfsremove(dvp, vp, &scred, flags);
2096 2773 VN_RELE(vp);
2097 2774 }
2098 2775
2099 2776 smb_credrele(&scred);
2100 2777 smbfs_rw_exit(&dnp->r_rwlock);
2101 2778
2102 2779 return (error);
2103 2780 }
2104 2781
2105 2782 /*
2106 2783 * smbfsremove does the real work of removing in SMBFS
2107 2784 * Caller has done dir access checks etc.
2108 2785 *
2109 2786 * The normal way to delete a file over SMB is open it (with DELETE access),
2110 2787 * set the "delete-on-close" flag, and close the file. The problem for Unix
2111 2788 * applications is that they expect the file name to be gone once the unlink
2112 2789 * completes, and the SMB server does not actually delete the file until ALL
2113 2790 * opens of that file are closed. We can't assume our open handles are the
2114 2791 * only open handles on a file we're deleting, so to be safe we'll try to
2115 2792 * rename the file to a temporary name and then set delete-on-close. If we
2116 2793 * fail to set delete-on-close (i.e. because other opens prevent it) then
2117 2794 * undo the changes we made and give up with EBUSY. Note that we might have
2118 2795 * permission to delete a file but lack permission to rename, so we want to
2119 2796 * continue in cases where rename fails. As an optimization, only do the
2120 2797 * rename when we have the file open.
2121 2798 *
2122 2799 * This is similar to what NFS does when deleting a file that has local opens,
2123 2800 * but thanks to SMB delete-on-close, we don't need to keep track of when the
2124 2801 * last local open goes away and send a delete. The server does that for us.
2125 2802 */
2126 2803 /* ARGSUSED */
2127 2804 static int
2128 2805 smbfsremove(vnode_t *dvp, vnode_t *vp, struct smb_cred *scred,
2129 2806 int flags)
2130 2807 {
2131 2808 smbnode_t *dnp = VTOSMB(dvp);
2132 2809 smbnode_t *np = VTOSMB(vp);
2133 2810 char *tmpname = NULL;
2134 2811 int tnlen;
2135 2812 int error;
2136 2813 unsigned short fid;
2137 2814 boolean_t have_fid = B_FALSE;
2138 2815 boolean_t renamed = B_FALSE;
↓ open down ↓ |
85 lines elided |
↑ open up ↑ |
2139 2816
2140 2817 /*
2141 2818 * The dvp RWlock must be held as writer.
2142 2819 */
2143 2820 ASSERT(dnp->r_rwlock.owner == curthread);
2144 2821
2145 2822 /* Never allow link/unlink directories on SMB. */
2146 2823 if (vp->v_type == VDIR)
2147 2824 return (EPERM);
2148 2825
2826 + /*
2827 + * We need to flush any dirty pages which happen to
2828 + * be hanging around before removing the file. This
2829 + * shouldn't happen very often and mostly on file
2830 + * systems mounted "nocto".
2831 + */
2832 + if (vn_has_cached_data(vp) &&
2833 + ((np->r_flags & RDIRTY) || np->r_count > 0)) {
2834 + error = smbfs_putpage(vp, (offset_t)0, 0, 0,
2835 + scred->scr_cred, NULL);
2836 + if (error && (error == ENOSPC || error == EDQUOT)) {
2837 + mutex_enter(&np->r_statelock);
2838 + if (!np->r_error)
2839 + np->r_error = error;
2840 + mutex_exit(&np->r_statelock);
2841 + }
2842 + }
2843 +
2149 2844 /* Shared lock for n_fid use in smbfs_smb_setdisp etc. */
2150 2845 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
2151 2846 return (EINTR);
2152 2847
2153 - /* Force lookup to go OtW */
2154 - smbfs_attrcache_remove(np);
2155 -
2156 2848 /*
2157 2849 * Get a file handle with delete access.
2158 2850 * Close this FID before return.
2159 2851 */
2160 2852 error = smbfs_smb_tmpopen(np, STD_RIGHT_DELETE_ACCESS,
2161 2853 scred, &fid);
2162 2854 if (error) {
2163 2855 SMBVDEBUG("error %d opening %s\n",
2164 2856 error, np->n_rpath);
2165 2857 goto out;
2166 2858 }
2167 2859 have_fid = B_TRUE;
2168 2860
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
2169 2861 /*
2170 2862 * If we have the file open, try to rename it to a temporary name.
2171 2863 * If we can't rename, continue on and try setting DoC anyway.
2172 2864 */
2173 2865 if ((vp->v_count > 1) && (np->n_fidrefs > 0)) {
2174 2866 tmpname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
2175 2867 tnlen = smbfs_newname(tmpname, MAXNAMELEN);
2176 2868 error = smbfs_smb_t2rename(np, tmpname, tnlen, scred, fid, 0);
2177 2869 if (error != 0) {
2178 2870 SMBVDEBUG("error %d renaming %s -> %s\n",
2179 - error, np->n_rpath, tmpname);
2871 + error, np->n_rpath, tmpname);
2180 2872 /* Keep going without the rename. */
2181 2873 } else {
2182 2874 renamed = B_TRUE;
2183 2875 }
2184 2876 }
2185 2877
2186 2878 /*
2187 2879 * Mark the file as delete-on-close. If we can't,
2188 2880 * undo what we did and err out.
2189 2881 */
2190 2882 error = smbfs_smb_setdisp(np, fid, 1, scred);
2191 2883 if (error != 0) {
2192 2884 SMBVDEBUG("error %d setting DoC on %s\n",
2193 2885 error, np->n_rpath);
2194 2886 /*
2195 2887 * Failed to set DoC. If we renamed, undo that.
2196 2888 * Need np->n_rpath relative to parent (dnp).
2197 2889 * Use parent path name length plus one for
2198 2890 * the separator ('/' or ':')
2199 2891 */
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
2200 2892 if (renamed) {
2201 2893 char *oldname;
2202 2894 int oldnlen;
2203 2895 int err2;
2204 2896
2205 2897 oldname = np->n_rpath + (dnp->n_rplen + 1);
2206 2898 oldnlen = np->n_rplen - (dnp->n_rplen + 1);
2207 2899 err2 = smbfs_smb_t2rename(np, oldname, oldnlen,
2208 2900 scred, fid, 0);
2209 2901 SMBVDEBUG("error %d un-renaming %s -> %s\n",
2210 - err2, tmpname, np->n_rpath);
2902 + err2, tmpname, np->n_rpath);
2211 2903 }
2212 2904 error = EBUSY;
2213 2905 goto out;
2214 2906 }
2215 2907 /* Done! */
2216 2908 smbfs_attrcache_prune(np);
2217 2909
2910 +#ifdef SMBFS_VNEVENT
2911 + vnevent_remove(vp, dvp, nm, ct);
2912 +#endif
2913 +
2218 2914 out:
2219 2915 if (tmpname != NULL)
2220 2916 kmem_free(tmpname, MAXNAMELEN);
2221 2917
2222 2918 if (have_fid)
2223 2919 (void) smbfs_smb_tmpclose(np, fid, scred);
2224 2920 smbfs_rw_exit(&np->r_lkserlock);
2225 2921
2226 2922 if (error == 0) {
2227 2923 /* Keep lookup from finding this node anymore. */
2228 2924 smbfs_rmhash(np);
2229 2925 }
2230 2926
2231 2927 return (error);
2232 2928 }
2233 2929
2234 2930
2931 +/* ARGSUSED */
2932 +static int
2933 +smbfs_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr,
2934 + caller_context_t *ct, int flags)
2935 +{
2936 + /* Not yet... */
2937 + return (ENOSYS);
2938 +}
2939 +
2940 +
2235 2941 /*
2236 2942 * XXX
2237 2943 * This op should support the new FIGNORECASE flag for case-insensitive
2238 2944 * lookups, per PSARC 2007/244.
2239 2945 */
2240 2946 /* ARGSUSED */
2241 2947 static int
2242 2948 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2243 2949 caller_context_t *ct, int flags)
2244 2950 {
2245 2951 struct smb_cred scred;
2246 2952 smbnode_t *odnp = VTOSMB(odvp);
2247 2953 smbnode_t *ndnp = VTOSMB(ndvp);
2248 2954 vnode_t *ovp;
2249 2955 int error;
2250 2956
2251 2957 if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone ||
2252 2958 curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone)
2253 2959 return (EPERM);
2254 2960
2255 2961 if (VTOSMI(odvp)->smi_flags & SMI_DEAD ||
2256 2962 VTOSMI(ndvp)->smi_flags & SMI_DEAD ||
2257 2963 odvp->v_vfsp->vfs_flag & VFS_UNMOUNTED ||
2258 2964 ndvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2259 2965 return (EIO);
2260 2966
2261 2967 if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 ||
2262 2968 strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0)
2263 2969 return (EINVAL);
2264 2970
2265 2971 /*
2266 2972 * Check that everything is on the same filesystem.
2267 2973 * vn_rename checks the fsid's, but in case we don't
2268 2974 * fill those in correctly, check here too.
2269 2975 */
2270 2976 if (odvp->v_vfsp != ndvp->v_vfsp)
2271 2977 return (EXDEV);
2272 2978
2273 2979 /*
2274 2980 * Need write access on source and target.
2275 2981 * Server takes care of most checks.
2276 2982 */
2277 2983 error = smbfs_access(odvp, VWRITE|VEXEC, 0, cr, ct);
2278 2984 if (error)
2279 2985 return (error);
2280 2986 if (odvp != ndvp) {
2281 2987 error = smbfs_access(ndvp, VWRITE, 0, cr, ct);
2282 2988 if (error)
2283 2989 return (error);
2284 2990 }
2285 2991
2286 2992 /*
2287 2993 * Need to lock both old/new dirs as writer.
2288 2994 *
2289 2995 * Avoid deadlock here on old vs new directory nodes
2290 2996 * by always taking the locks in order of address.
2291 2997 * The order is arbitrary, but must be consistent.
2292 2998 */
2293 2999 if (odnp < ndnp) {
2294 3000 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2295 3001 SMBINTR(odvp)))
2296 3002 return (EINTR);
2297 3003 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2298 3004 SMBINTR(ndvp))) {
2299 3005 smbfs_rw_exit(&odnp->r_rwlock);
2300 3006 return (EINTR);
2301 3007 }
2302 3008 } else {
2303 3009 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2304 3010 SMBINTR(ndvp)))
2305 3011 return (EINTR);
2306 3012 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2307 3013 SMBINTR(odvp))) {
2308 3014 smbfs_rw_exit(&ndnp->r_rwlock);
2309 3015 return (EINTR);
2310 3016 }
2311 3017 }
2312 3018 smb_credinit(&scred, cr);
2313 3019
2314 3020 /* Lookup the "old" name */
2315 3021 error = smbfslookup(odvp, onm, &ovp, cr, 0, ct);
2316 3022 if (error == 0) {
2317 3023 /*
2318 3024 * Do the real rename work
2319 3025 */
2320 3026 error = smbfsrename(odvp, ovp, ndvp, nnm, &scred, flags);
2321 3027 VN_RELE(ovp);
2322 3028 }
2323 3029
2324 3030 smb_credrele(&scred);
2325 3031 smbfs_rw_exit(&odnp->r_rwlock);
2326 3032 smbfs_rw_exit(&ndnp->r_rwlock);
2327 3033
2328 3034 return (error);
2329 3035 }
2330 3036
2331 3037 /*
2332 3038 * smbfsrename does the real work of renaming in SMBFS
2333 3039 * Caller has done dir access checks etc.
2334 3040 */
2335 3041 /* ARGSUSED */
2336 3042 static int
2337 3043 smbfsrename(vnode_t *odvp, vnode_t *ovp, vnode_t *ndvp, char *nnm,
2338 3044 struct smb_cred *scred, int flags)
2339 3045 {
2340 3046 smbnode_t *odnp = VTOSMB(odvp);
2341 3047 smbnode_t *onp = VTOSMB(ovp);
2342 3048 smbnode_t *ndnp = VTOSMB(ndvp);
2343 3049 vnode_t *nvp = NULL;
2344 3050 int error;
2345 3051 int nvp_locked = 0;
2346 3052
2347 3053 /* Things our caller should have checked. */
2348 3054 ASSERT(curproc->p_zone == VTOSMI(odvp)->smi_zone_ref.zref_zone);
2349 3055 ASSERT(odvp->v_vfsp == ndvp->v_vfsp);
2350 3056 ASSERT(odnp->r_rwlock.owner == curthread);
2351 3057 ASSERT(ndnp->r_rwlock.owner == curthread);
2352 3058
2353 3059 /*
2354 3060 * Lookup the target file. If it exists, it needs to be
2355 3061 * checked to see whether it is a mount point and whether
2356 3062 * it is active (open).
2357 3063 */
2358 3064 error = smbfslookup(ndvp, nnm, &nvp, scred->scr_cred, 0, NULL);
2359 3065 if (!error) {
2360 3066 /*
2361 3067 * Target (nvp) already exists. Check that it
2362 3068 * has the same type as the source. The server
2363 3069 * will check this also, (and more reliably) but
2364 3070 * this lets us return the correct error codes.
2365 3071 */
2366 3072 if (ovp->v_type == VDIR) {
2367 3073 if (nvp->v_type != VDIR) {
2368 3074 error = ENOTDIR;
2369 3075 goto out;
2370 3076 }
2371 3077 } else {
2372 3078 if (nvp->v_type == VDIR) {
2373 3079 error = EISDIR;
2374 3080 goto out;
2375 3081 }
2376 3082 }
2377 3083
2378 3084 /*
2379 3085 * POSIX dictates that when the source and target
2380 3086 * entries refer to the same file object, rename
2381 3087 * must do nothing and exit without error.
2382 3088 */
2383 3089 if (ovp == nvp) {
2384 3090 error = 0;
2385 3091 goto out;
2386 3092 }
2387 3093
2388 3094 /*
2389 3095 * Also must ensure the target is not a mount point,
2390 3096 * and keep mount/umount away until we're done.
2391 3097 */
2392 3098 if (vn_vfsrlock(nvp)) {
2393 3099 error = EBUSY;
2394 3100 goto out;
2395 3101 }
2396 3102 nvp_locked = 1;
2397 3103 if (vn_mountedvfs(nvp) != NULL) {
2398 3104 error = EBUSY;
2399 3105 goto out;
2400 3106 }
2401 3107
2402 3108 /*
2403 3109 * CIFS may give a SHARING_VIOLATION error when
2404 3110 * trying to rename onto an exising object,
2405 3111 * so try to remove the target first.
2406 3112 * (Only for files, not directories.)
2407 3113 */
2408 3114 if (nvp->v_type == VDIR) {
2409 3115 error = EEXIST;
2410 3116 goto out;
2411 3117 }
2412 3118 error = smbfsremove(ndvp, nvp, scred, flags);
2413 3119 if (error != 0)
2414 3120 goto out;
2415 3121
2416 3122 /*
↓ open down ↓ |
172 lines elided |
↑ open up ↑ |
2417 3123 * OK, removed the target file. Continue as if
2418 3124 * lookup target had failed (nvp == NULL).
2419 3125 */
2420 3126 vn_vfsunlock(nvp);
2421 3127 nvp_locked = 0;
2422 3128 VN_RELE(nvp);
2423 3129 nvp = NULL;
2424 3130 } /* nvp */
2425 3131
2426 3132 smbfs_attrcache_remove(onp);
2427 -
2428 3133 error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), scred);
2429 3134
2430 3135 /*
2431 3136 * If the old name should no longer exist,
2432 3137 * discard any cached attributes under it.
2433 3138 */
2434 - if (error == 0)
3139 + if (error == 0) {
2435 3140 smbfs_attrcache_prune(onp);
3141 + /* SMBFS_VNEVENT... */
3142 + }
2436 3143
2437 3144 out:
2438 3145 if (nvp) {
2439 3146 if (nvp_locked)
2440 3147 vn_vfsunlock(nvp);
2441 3148 VN_RELE(nvp);
2442 3149 }
2443 3150
2444 3151 return (error);
2445 3152 }
2446 3153
2447 3154 /*
2448 3155 * XXX
2449 3156 * vsecattr_t is new to build 77, and we need to eventually support
2450 3157 * it in order to create an ACL when an object is created.
2451 3158 *
2452 3159 * This op should support the new FIGNORECASE flag for case-insensitive
2453 3160 * lookups, per PSARC 2007/244.
2454 3161 */
2455 3162 /* ARGSUSED */
2456 3163 static int
2457 3164 smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp,
2458 3165 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
2459 3166 {
2460 3167 vnode_t *vp;
2461 3168 struct smbnode *dnp = VTOSMB(dvp);
2462 3169 struct smbmntinfo *smi = VTOSMI(dvp);
2463 3170 struct smb_cred scred;
2464 3171 struct smbfattr fattr;
2465 3172 const char *name = (const char *) nm;
2466 3173 int nmlen = strlen(name);
2467 3174 int error, hiderr;
2468 3175
2469 3176 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2470 3177 return (EPERM);
2471 3178
2472 3179 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2473 3180 return (EIO);
2474 3181
2475 3182 if ((nmlen == 1 && name[0] == '.') ||
2476 3183 (nmlen == 2 && name[0] == '.' && name[1] == '.'))
2477 3184 return (EEXIST);
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
2478 3185
2479 3186 /* Only plain files are allowed in V_XATTRDIR. */
2480 3187 if (dvp->v_flag & V_XATTRDIR)
2481 3188 return (EINVAL);
2482 3189
2483 3190 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2484 3191 return (EINTR);
2485 3192 smb_credinit(&scred, cr);
2486 3193
2487 3194 /*
2488 - * XXX: Do we need r_lkserlock too?
2489 - * No use of any shared fid or fctx...
2490 - */
2491 -
2492 - /*
2493 3195 * Require write access in the containing directory.
2494 3196 */
2495 3197 error = smbfs_access(dvp, VWRITE, 0, cr, ct);
2496 3198 if (error)
2497 3199 goto out;
2498 3200
2499 3201 error = smbfs_smb_mkdir(dnp, name, nmlen, &scred);
2500 3202 if (error)
2501 3203 goto out;
2502 3204
2503 3205 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2504 3206 if (error)
2505 3207 goto out;
2506 3208
2507 3209 smbfs_attr_touchdir(dnp);
2508 3210
2509 3211 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2510 3212 if (error)
2511 3213 goto out;
2512 3214
2513 3215 if (name[0] == '.')
2514 3216 if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred)))
2515 3217 SMBVDEBUG("hide failure %d\n", hiderr);
2516 3218
2517 3219 /* Success! */
2518 3220 *vpp = vp;
2519 3221 error = 0;
2520 3222 out:
2521 3223 smb_credrele(&scred);
2522 3224 smbfs_rw_exit(&dnp->r_rwlock);
2523 3225
2524 3226 if (name != nm)
2525 3227 smbfs_name_free(name, nmlen);
2526 3228
2527 3229 return (error);
2528 3230 }
2529 3231
2530 3232 /*
2531 3233 * XXX
2532 3234 * This op should support the new FIGNORECASE flag for case-insensitive
2533 3235 * lookups, per PSARC 2007/244.
2534 3236 */
2535 3237 /* ARGSUSED */
2536 3238 static int
2537 3239 smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
2538 3240 caller_context_t *ct, int flags)
2539 3241 {
2540 3242 vnode_t *vp = NULL;
2541 3243 int vp_locked = 0;
2542 3244 struct smbmntinfo *smi = VTOSMI(dvp);
2543 3245 struct smbnode *dnp = VTOSMB(dvp);
2544 3246 struct smbnode *np;
2545 3247 struct smb_cred scred;
2546 3248 int error;
2547 3249
2548 3250 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2549 3251 return (EPERM);
2550 3252
2551 3253 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2552 3254 return (EIO);
2553 3255
2554 3256 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2555 3257 return (EINTR);
2556 3258 smb_credinit(&scred, cr);
2557 3259
2558 3260 /*
2559 3261 * Require w/x access in the containing directory.
2560 3262 * Server handles all other access checks.
2561 3263 */
2562 3264 error = smbfs_access(dvp, VEXEC|VWRITE, 0, cr, ct);
2563 3265 if (error)
2564 3266 goto out;
2565 3267
2566 3268 /*
2567 3269 * First lookup the entry to be removed.
2568 3270 */
2569 3271 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2570 3272 if (error)
2571 3273 goto out;
2572 3274 np = VTOSMB(vp);
2573 3275
2574 3276 /*
2575 3277 * Disallow rmdir of "." or current dir, or the FS root.
2576 3278 * Also make sure it's a directory, not a mount point,
2577 3279 * and lock to keep mount/umount away until we're done.
2578 3280 */
2579 3281 if ((vp == dvp) || (vp == cdir) || (vp->v_flag & VROOT)) {
2580 3282 error = EINVAL;
2581 3283 goto out;
2582 3284 }
2583 3285 if (vp->v_type != VDIR) {
2584 3286 error = ENOTDIR;
2585 3287 goto out;
2586 3288 }
2587 3289 if (vn_vfsrlock(vp)) {
2588 3290 error = EBUSY;
2589 3291 goto out;
2590 3292 }
2591 3293 vp_locked = 1;
2592 3294 if (vn_mountedvfs(vp) != NULL) {
2593 3295 error = EBUSY;
2594 3296 goto out;
2595 3297 }
2596 3298
2597 3299 smbfs_attrcache_remove(np);
2598 3300 error = smbfs_smb_rmdir(np, &scred);
2599 3301
2600 3302 /*
2601 3303 * Similar to smbfs_remove
2602 3304 */
2603 3305 switch (error) {
2604 3306 case 0:
2605 3307 case ENOENT:
2606 3308 case ENOTDIR:
2607 3309 smbfs_attrcache_prune(np);
2608 3310 break;
2609 3311 }
2610 3312
2611 3313 if (error)
2612 3314 goto out;
2613 3315
2614 3316 mutex_enter(&np->r_statelock);
2615 3317 dnp->n_flag |= NMODIFIED;
2616 3318 mutex_exit(&np->r_statelock);
2617 3319 smbfs_attr_touchdir(dnp);
2618 3320 smbfs_rmhash(np);
2619 3321
2620 3322 out:
2621 3323 if (vp) {
2622 3324 if (vp_locked)
2623 3325 vn_vfsunlock(vp);
2624 3326 VN_RELE(vp);
↓ open down ↓ |
122 lines elided |
↑ open up ↑ |
2625 3327 }
2626 3328 smb_credrele(&scred);
2627 3329 smbfs_rw_exit(&dnp->r_rwlock);
2628 3330
2629 3331 return (error);
2630 3332 }
2631 3333
2632 3334
2633 3335 /* ARGSUSED */
2634 3336 static int
3337 +smbfs_symlink(vnode_t *dvp, char *lnm, struct vattr *tva, char *tnm, cred_t *cr,
3338 + caller_context_t *ct, int flags)
3339 +{
3340 + /* Not yet... */
3341 + return (ENOSYS);
3342 +}
3343 +
3344 +
3345 +/* ARGSUSED */
3346 +static int
2635 3347 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp,
2636 3348 caller_context_t *ct, int flags)
2637 3349 {
2638 3350 struct smbnode *np = VTOSMB(vp);
2639 3351 int error = 0;
2640 3352 smbmntinfo_t *smi;
2641 3353
2642 3354 smi = VTOSMI(vp);
2643 3355
2644 3356 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2645 3357 return (EIO);
2646 3358
2647 3359 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2648 3360 return (EIO);
2649 3361
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
2650 3362 /*
2651 3363 * Require read access in the directory.
2652 3364 */
2653 3365 error = smbfs_access(vp, VREAD, 0, cr, ct);
2654 3366 if (error)
2655 3367 return (error);
2656 3368
2657 3369 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
2658 3370
2659 3371 /*
2660 - * XXX: Todo readdir cache here
2661 - * Note: NFS code is just below this.
3372 + * Todo readdir cache here
2662 3373 *
2663 3374 * I am serializing the entire readdir opreation
2664 3375 * now since we have not yet implemented readdir
2665 3376 * cache. This fix needs to be revisited once
2666 3377 * we implement readdir cache.
2667 3378 */
2668 3379 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
2669 3380 return (EINTR);
2670 3381
2671 3382 error = smbfs_readvdir(vp, uiop, cr, eofp, ct);
2672 3383
2673 3384 smbfs_rw_exit(&np->r_lkserlock);
2674 3385
2675 3386 return (error);
2676 3387 }
2677 3388
2678 3389 /* ARGSUSED */
2679 3390 static int
2680 3391 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
2681 3392 caller_context_t *ct)
2682 3393 {
2683 3394 /*
2684 3395 * Note: "limit" tells the SMB-level FindFirst/FindNext
2685 3396 * functions how many directory entries to request in
2686 3397 * each OtW call. It needs to be large enough so that
2687 3398 * we don't make lots of tiny OtW requests, but there's
2688 3399 * no point making it larger than the maximum number of
2689 3400 * OtW entries that would fit in a maximum sized trans2
2690 3401 * response (64k / 48). Beyond that, it's just tuning.
2691 3402 * WinNT used 512, Win2k used 1366. We use 1000.
2692 3403 */
2693 3404 static const int limit = 1000;
2694 3405 /* Largest possible dirent size. */
2695 3406 static const size_t dbufsiz = DIRENT64_RECLEN(SMB_MAXFNAMELEN);
2696 3407 struct smb_cred scred;
2697 3408 vnode_t *newvp;
2698 3409 struct smbnode *np = VTOSMB(vp);
2699 3410 struct smbfs_fctx *ctx;
2700 3411 struct dirent64 *dp;
2701 3412 ssize_t save_resid;
2702 3413 offset_t save_offset; /* 64 bits */
2703 3414 int offset; /* yes, 32 bits */
2704 3415 int nmlen, error;
2705 3416 ushort_t reclen;
2706 3417
2707 3418 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
2708 3419
2709 3420 /* Make sure we serialize for n_dirseq use. */
2710 3421 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
2711 3422
2712 3423 /*
2713 3424 * Make sure smbfs_open filled in n_dirseq
2714 3425 */
2715 3426 if (np->n_dirseq == NULL)
2716 3427 return (EBADF);
2717 3428
2718 3429 /* Check for overflow of (32-bit) directory offset. */
2719 3430 if (uio->uio_loffset < 0 || uio->uio_loffset > INT32_MAX ||
2720 3431 (uio->uio_loffset + uio->uio_resid) > INT32_MAX)
2721 3432 return (EINVAL);
2722 3433
2723 3434 /* Require space for at least one dirent. */
2724 3435 if (uio->uio_resid < dbufsiz)
2725 3436 return (EINVAL);
2726 3437
2727 3438 SMBVDEBUG("dirname='%s'\n", np->n_rpath);
2728 3439 smb_credinit(&scred, cr);
2729 3440 dp = kmem_alloc(dbufsiz, KM_SLEEP);
2730 3441
2731 3442 save_resid = uio->uio_resid;
2732 3443 save_offset = uio->uio_loffset;
2733 3444 offset = uio->uio_offset;
2734 3445 SMBVDEBUG("in: offset=%d, resid=%d\n",
2735 3446 (int)uio->uio_offset, (int)uio->uio_resid);
2736 3447 error = 0;
2737 3448
2738 3449 /*
2739 3450 * Generate the "." and ".." entries here so we can
2740 3451 * (1) make sure they appear (but only once), and
2741 3452 * (2) deal with getting their I numbers which the
2742 3453 * findnext below does only for normal names.
2743 3454 */
2744 3455 while (offset < FIRST_DIROFS) {
2745 3456 /*
2746 3457 * Tricky bit filling in the first two:
2747 3458 * offset 0 is ".", offset 1 is ".."
2748 3459 * so strlen of these is offset+1.
2749 3460 */
2750 3461 reclen = DIRENT64_RECLEN(offset + 1);
2751 3462 if (uio->uio_resid < reclen)
2752 3463 goto out;
2753 3464 bzero(dp, reclen);
2754 3465 dp->d_reclen = reclen;
2755 3466 dp->d_name[0] = '.';
2756 3467 dp->d_name[1] = '.';
2757 3468 dp->d_name[offset + 1] = '\0';
2758 3469 /*
2759 3470 * Want the real I-numbers for the "." and ".."
2760 3471 * entries. For these two names, we know that
2761 3472 * smbfslookup can get the nodes efficiently.
2762 3473 */
2763 3474 error = smbfslookup(vp, dp->d_name, &newvp, cr, 1, ct);
2764 3475 if (error) {
2765 3476 dp->d_ino = np->n_ino + offset; /* fiction */
2766 3477 } else {
2767 3478 dp->d_ino = VTOSMB(newvp)->n_ino;
2768 3479 VN_RELE(newvp);
2769 3480 }
2770 3481 /*
2771 3482 * Note: d_off is the offset that a user-level program
2772 3483 * should seek to for reading the NEXT directory entry.
2773 3484 * See libc: readdir, telldir, seekdir
2774 3485 */
2775 3486 dp->d_off = offset + 1;
2776 3487 error = uiomove(dp, reclen, UIO_READ, uio);
2777 3488 if (error)
2778 3489 goto out;
2779 3490 /*
2780 3491 * Note: uiomove updates uio->uio_offset,
2781 3492 * but we want it to be our "cookie" value,
2782 3493 * which just counts dirents ignoring size.
2783 3494 */
2784 3495 uio->uio_offset = ++offset;
2785 3496 }
2786 3497
2787 3498 /*
2788 3499 * If there was a backward seek, we have to reopen.
2789 3500 */
2790 3501 if (offset < np->n_dirofs) {
2791 3502 SMBVDEBUG("Reopening search %d:%d\n",
2792 3503 offset, np->n_dirofs);
2793 3504 error = smbfs_smb_findopen(np, "*", 1,
2794 3505 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
2795 3506 &scred, &ctx);
2796 3507 if (error) {
2797 3508 SMBVDEBUG("can not open search, error = %d", error);
2798 3509 goto out;
2799 3510 }
2800 3511 /* free the old one */
2801 3512 (void) smbfs_smb_findclose(np->n_dirseq, &scred);
2802 3513 /* save the new one */
2803 3514 np->n_dirseq = ctx;
2804 3515 np->n_dirofs = FIRST_DIROFS;
2805 3516 } else {
2806 3517 ctx = np->n_dirseq;
2807 3518 }
2808 3519
2809 3520 /*
2810 3521 * Skip entries before the requested offset.
2811 3522 */
2812 3523 while (np->n_dirofs < offset) {
2813 3524 error = smbfs_smb_findnext(ctx, limit, &scred);
2814 3525 if (error != 0)
2815 3526 goto out;
2816 3527 np->n_dirofs++;
2817 3528 }
2818 3529
2819 3530 /*
2820 3531 * While there's room in the caller's buffer:
2821 3532 * get a directory entry from SMB,
2822 3533 * convert to a dirent, copyout.
2823 3534 * We stop when there is no longer room for a
2824 3535 * maximum sized dirent because we must decide
2825 3536 * before we know anything about the next entry.
2826 3537 */
2827 3538 while (uio->uio_resid >= dbufsiz) {
2828 3539 error = smbfs_smb_findnext(ctx, limit, &scred);
2829 3540 if (error != 0)
2830 3541 goto out;
2831 3542 np->n_dirofs++;
2832 3543
2833 3544 /* Sanity check the name length. */
2834 3545 nmlen = ctx->f_nmlen;
2835 3546 if (nmlen > SMB_MAXFNAMELEN) {
2836 3547 nmlen = SMB_MAXFNAMELEN;
2837 3548 SMBVDEBUG("Truncating name: %s\n", ctx->f_name);
2838 3549 }
2839 3550 if (smbfs_fastlookup) {
2840 3551 /* See comment at smbfs_fastlookup above. */
2841 3552 if (smbfs_nget(vp, ctx->f_name, nmlen,
2842 3553 &ctx->f_attr, &newvp) == 0)
2843 3554 VN_RELE(newvp);
2844 3555 }
2845 3556
2846 3557 reclen = DIRENT64_RECLEN(nmlen);
2847 3558 bzero(dp, reclen);
2848 3559 dp->d_reclen = reclen;
2849 3560 bcopy(ctx->f_name, dp->d_name, nmlen);
2850 3561 dp->d_name[nmlen] = '\0';
2851 3562 dp->d_ino = ctx->f_inum;
2852 3563 dp->d_off = offset + 1; /* See d_off comment above */
2853 3564 error = uiomove(dp, reclen, UIO_READ, uio);
2854 3565 if (error)
2855 3566 goto out;
2856 3567 /* See comment re. uio_offset above. */
2857 3568 uio->uio_offset = ++offset;
2858 3569 }
2859 3570
2860 3571 out:
2861 3572 /*
2862 3573 * When we come to the end of a directory, the
2863 3574 * SMB-level functions return ENOENT, but the
2864 3575 * caller is not expecting an error return.
2865 3576 *
2866 3577 * Also note that we must delay the call to
2867 3578 * smbfs_smb_findclose(np->n_dirseq, ...)
2868 3579 * until smbfs_close so that all reads at the
2869 3580 * end of the directory will return no data.
2870 3581 */
2871 3582 if (error == ENOENT) {
2872 3583 error = 0;
2873 3584 if (eofp)
2874 3585 *eofp = 1;
2875 3586 }
2876 3587 /*
2877 3588 * If we encountered an error (i.e. "access denied")
2878 3589 * from the FindFirst call, we will have copied out
2879 3590 * the "." and ".." entries leaving offset == 2.
2880 3591 * In that case, restore the original offset/resid
2881 3592 * so the caller gets no data with the error.
2882 3593 */
2883 3594 if (error != 0 && offset == FIRST_DIROFS) {
2884 3595 uio->uio_loffset = save_offset;
↓ open down ↓ |
213 lines elided |
↑ open up ↑ |
2885 3596 uio->uio_resid = save_resid;
2886 3597 }
2887 3598 SMBVDEBUG("out: offset=%d, resid=%d\n",
2888 3599 (int)uio->uio_offset, (int)uio->uio_resid);
2889 3600
2890 3601 kmem_free(dp, dbufsiz);
2891 3602 smb_credrele(&scred);
2892 3603 return (error);
2893 3604 }
2894 3605
3606 +/*
3607 + * Here NFS has: nfs3_bio
3608 + * See smbfs_bio above.
3609 + */
2895 3610
3611 +/* ARGSUSED */
3612 +static int
3613 +smbfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
3614 +{
3615 + return (ENOSYS);
3616 +}
3617 +
3618 +
2896 3619 /*
2897 3620 * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK
2898 3621 * are optional functions that are called by:
2899 3622 * getdents, before/after VOP_READDIR
2900 3623 * pread, before/after ... VOP_READ
2901 3624 * pwrite, before/after ... VOP_WRITE
2902 3625 * (other places)
2903 3626 *
2904 3627 * Careful here: None of the above check for any
2905 3628 * error returns from VOP_RWLOCK / VOP_RWUNLOCK!
2906 3629 * In fact, the return value from _rwlock is NOT
2907 3630 * an error code, but V_WRITELOCK_TRUE / _FALSE.
2908 3631 *
2909 3632 * Therefore, it's up to _this_ code to make sure
2910 3633 * the lock state remains balanced, which means
2911 3634 * we can't "bail out" on interrupts, etc.
2912 3635 */
2913 3636
2914 3637 /* ARGSUSED2 */
2915 3638 static int
2916 3639 smbfs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2917 3640 {
2918 3641 smbnode_t *np = VTOSMB(vp);
2919 3642
2920 3643 if (!write_lock) {
2921 3644 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_READER, FALSE);
2922 3645 return (V_WRITELOCK_FALSE);
2923 3646 }
2924 3647
2925 3648
2926 3649 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, FALSE);
2927 3650 return (V_WRITELOCK_TRUE);
2928 3651 }
2929 3652
2930 3653 /* ARGSUSED */
2931 3654 static void
2932 3655 smbfs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2933 3656 {
2934 3657 smbnode_t *np = VTOSMB(vp);
2935 3658
2936 3659 smbfs_rw_exit(&np->r_rwlock);
2937 3660 }
2938 3661
2939 3662
2940 3663 /* ARGSUSED */
2941 3664 static int
2942 3665 smbfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
2943 3666 {
2944 3667 smbmntinfo_t *smi;
2945 3668
2946 3669 smi = VTOSMI(vp);
2947 3670
2948 3671 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2949 3672 return (EPERM);
2950 3673
2951 3674 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2952 3675 return (EIO);
2953 3676
2954 3677 /*
2955 3678 * Because we stuff the readdir cookie into the offset field
2956 3679 * someone may attempt to do an lseek with the cookie which
2957 3680 * we want to succeed.
2958 3681 */
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
2959 3682 if (vp->v_type == VDIR)
2960 3683 return (0);
2961 3684
2962 3685 /* Like NFS3, just check for 63-bit overflow. */
2963 3686 if (*noffp < 0)
2964 3687 return (EINVAL);
2965 3688
2966 3689 return (0);
2967 3690 }
2968 3691
3692 +/* mmap support ******************************************************** */
2969 3693
3694 +#ifdef DEBUG
3695 +static int smbfs_lostpage = 0; /* number of times we lost original page */
3696 +#endif
3697 +
2970 3698 /*
3699 + * Return all the pages from [off..off+len) in file
3700 + * Like nfs3_getpage
3701 + */
3702 +/* ARGSUSED */
3703 +static int
3704 +smbfs_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
3705 + page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
3706 + enum seg_rw rw, cred_t *cr, caller_context_t *ct)
3707 +{
3708 + smbnode_t *np;
3709 + smbmntinfo_t *smi;
3710 + int error;
3711 +
3712 + np = VTOSMB(vp);
3713 + smi = VTOSMI(vp);
3714 +
3715 + if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3716 + return (EIO);
3717 +
3718 + if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3719 + return (EIO);
3720 +
3721 + if (vp->v_flag & VNOMAP)
3722 + return (ENOSYS);
3723 +
3724 + if (protp != NULL)
3725 + *protp = PROT_ALL;
3726 +
3727 + /*
3728 + * Now valididate that the caches are up to date.
3729 + */
3730 + error = smbfs_validate_caches(vp, cr);
3731 + if (error)
3732 + return (error);
3733 +
3734 +retry:
3735 + mutex_enter(&np->r_statelock);
3736 +
3737 + /*
3738 + * Don't create dirty pages faster than they
3739 + * can be cleaned ... (etc. see nfs)
3740 + *
3741 + * Here NFS also tests:
3742 + * (mi->mi_max_threads != 0 &&
3743 + * rp->r_awcount > 2 * mi->mi_max_threads)
3744 + */
3745 + if (rw == S_CREATE) {
3746 + while (np->r_gcount > 0)
3747 + cv_wait(&np->r_cv, &np->r_statelock);
3748 + }
3749 +
3750 + /*
3751 + * If we are getting called as a side effect of a write
3752 + * operation the local file size might not be extended yet.
3753 + * In this case we want to be able to return pages of zeroes.
3754 + */
3755 + if (off + len > np->r_size + PAGEOFFSET && seg != segkmap) {
3756 + mutex_exit(&np->r_statelock);
3757 + return (EFAULT); /* beyond EOF */
3758 + }
3759 +
3760 + mutex_exit(&np->r_statelock);
3761 +
3762 + error = pvn_getpages(smbfs_getapage, vp, off, len, protp,
3763 + pl, plsz, seg, addr, rw, cr);
3764 +
3765 + switch (error) {
3766 + case SMBFS_EOF:
3767 + smbfs_purge_caches(vp, cr);
3768 + goto retry;
3769 + case ESTALE:
3770 + /*
3771 + * Here NFS has: PURGE_STALE_FH(error, vp, cr);
3772 + * In-line here as we only use it once.
3773 + */
3774 + mutex_enter(&np->r_statelock);
3775 + np->r_flags |= RSTALE;
3776 + if (!np->r_error)
3777 + np->r_error = (error);
3778 + mutex_exit(&np->r_statelock);
3779 + if (vn_has_cached_data(vp))
3780 + smbfs_invalidate_pages(vp, (u_offset_t)0, cr);
3781 + smbfs_purge_caches(vp, cr);
3782 + break;
3783 + default:
3784 + break;
3785 + }
3786 +
3787 + return (error);
3788 +}
3789 +
3790 +/*
3791 + * Called from pvn_getpages to get a particular page.
3792 + * Like nfs3_getapage
3793 + */
3794 +/* ARGSUSED */
3795 +static int
3796 +smbfs_getapage(vnode_t *vp, u_offset_t off, size_t len, uint_t *protp,
3797 + page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
3798 + enum seg_rw rw, cred_t *cr)
3799 +{
3800 + smbnode_t *np;
3801 + smbmntinfo_t *smi;
3802 +
3803 + uint_t bsize;
3804 + struct buf *bp;
3805 + page_t *pp;
3806 + u_offset_t lbn;
3807 + u_offset_t io_off;
3808 + u_offset_t blkoff;
3809 + size_t io_len;
3810 + uint_t blksize;
3811 + int error;
3812 + /* int readahead; */
3813 + int readahead_issued = 0;
3814 + /* int ra_window; * readahead window */
3815 + page_t *pagefound;
3816 +
3817 + np = VTOSMB(vp);
3818 + smi = VTOSMI(vp);
3819 +
3820 + if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3821 + return (EIO);
3822 +
3823 + if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3824 + return (EIO);
3825 +
3826 + bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE);
3827 +
3828 +reread:
3829 + bp = NULL;
3830 + pp = NULL;
3831 + pagefound = NULL;
3832 +
3833 + if (pl != NULL)
3834 + pl[0] = NULL;
3835 +
3836 + error = 0;
3837 + lbn = off / bsize;
3838 + blkoff = lbn * bsize;
3839 +
3840 + /*
3841 + * NFS queues up readahead work here.
3842 + */
3843 +
3844 +again:
3845 + if ((pagefound = page_exists(vp, off)) == NULL) {
3846 + if (pl == NULL) {
3847 + (void) 0; /* Todo: smbfs_async_readahead(); */
3848 + } else if (rw == S_CREATE) {
3849 + /*
3850 + * Block for this page is not allocated, or the offset
3851 + * is beyond the current allocation size, or we're
3852 + * allocating a swap slot and the page was not found,
3853 + * so allocate it and return a zero page.
3854 + */
3855 + if ((pp = page_create_va(vp, off,
3856 + PAGESIZE, PG_WAIT, seg, addr)) == NULL)
3857 + cmn_err(CE_PANIC, "smbfs_getapage: page_create");
3858 + io_len = PAGESIZE;
3859 + mutex_enter(&np->r_statelock);
3860 + np->r_nextr = off + PAGESIZE;
3861 + mutex_exit(&np->r_statelock);
3862 + } else {
3863 + /*
3864 + * Need to go to server to get a BLOCK, exception to
3865 + * that being while reading at offset = 0 or doing
3866 + * random i/o, in that case read only a PAGE.
3867 + */
3868 + mutex_enter(&np->r_statelock);
3869 + if (blkoff < np->r_size &&
3870 + blkoff + bsize >= np->r_size) {
3871 + /*
3872 + * If only a block or less is left in
3873 + * the file, read all that is remaining.
3874 + */
3875 + if (np->r_size <= off) {
3876 + /*
3877 + * Trying to access beyond EOF,
3878 + * set up to get at least one page.
3879 + */
3880 + blksize = off + PAGESIZE - blkoff;
3881 + } else
3882 + blksize = np->r_size - blkoff;
3883 + } else if ((off == 0) ||
3884 + (off != np->r_nextr && !readahead_issued)) {
3885 + blksize = PAGESIZE;
3886 + blkoff = off; /* block = page here */
3887 + } else
3888 + blksize = bsize;
3889 + mutex_exit(&np->r_statelock);
3890 +
3891 + pp = pvn_read_kluster(vp, off, seg, addr, &io_off,
3892 + &io_len, blkoff, blksize, 0);
3893 +
3894 + /*
3895 + * Some other thread has entered the page,
3896 + * so just use it.
3897 + */
3898 + if (pp == NULL)
3899 + goto again;
3900 +
3901 + /*
3902 + * Now round the request size up to page boundaries.
3903 + * This ensures that the entire page will be
3904 + * initialized to zeroes if EOF is encountered.
3905 + */
3906 + io_len = ptob(btopr(io_len));
3907 +
3908 + bp = pageio_setup(pp, io_len, vp, B_READ);
3909 + ASSERT(bp != NULL);
3910 +
3911 + /*
3912 + * pageio_setup should have set b_addr to 0. This
3913 + * is correct since we want to do I/O on a page
3914 + * boundary. bp_mapin will use this addr to calculate
3915 + * an offset, and then set b_addr to the kernel virtual
3916 + * address it allocated for us.
3917 + */
3918 + ASSERT(bp->b_un.b_addr == 0);
3919 +
3920 + bp->b_edev = 0;
3921 + bp->b_dev = 0;
3922 + bp->b_lblkno = lbtodb(io_off);
3923 + bp->b_file = vp;
3924 + bp->b_offset = (offset_t)off;
3925 + bp_mapin(bp);
3926 +
3927 + /*
3928 + * If doing a write beyond what we believe is EOF,
3929 + * don't bother trying to read the pages from the
3930 + * server, we'll just zero the pages here. We
3931 + * don't check that the rw flag is S_WRITE here
3932 + * because some implementations may attempt a
3933 + * read access to the buffer before copying data.
3934 + */
3935 + mutex_enter(&np->r_statelock);
3936 + if (io_off >= np->r_size && seg == segkmap) {
3937 + mutex_exit(&np->r_statelock);
3938 + bzero(bp->b_un.b_addr, io_len);
3939 + } else {
3940 + mutex_exit(&np->r_statelock);
3941 + error = smbfs_bio(bp, 0, cr);
3942 + }
3943 +
3944 + /*
3945 + * Unmap the buffer before freeing it.
3946 + */
3947 + bp_mapout(bp);
3948 + pageio_done(bp);
3949 +
3950 + /* Here NFS3 updates all pp->p_fsdata */
3951 +
3952 + if (error == SMBFS_EOF) {
3953 + /*
3954 + * If doing a write system call just return
3955 + * zeroed pages, else user tried to get pages
3956 + * beyond EOF, return error. We don't check
3957 + * that the rw flag is S_WRITE here because
3958 + * some implementations may attempt a read
3959 + * access to the buffer before copying data.
3960 + */
3961 + if (seg == segkmap)
3962 + error = 0;
3963 + else
3964 + error = EFAULT;
3965 + }
3966 +
3967 + if (!readahead_issued && !error) {
3968 + mutex_enter(&np->r_statelock);
3969 + np->r_nextr = io_off + io_len;
3970 + mutex_exit(&np->r_statelock);
3971 + }
3972 + }
3973 + }
3974 +
3975 + if (pl == NULL)
3976 + return (error);
3977 +
3978 + if (error) {
3979 + if (pp != NULL)
3980 + pvn_read_done(pp, B_ERROR);
3981 + return (error);
3982 + }
3983 +
3984 + if (pagefound) {
3985 + se_t se = (rw == S_CREATE ? SE_EXCL : SE_SHARED);
3986 +
3987 + /*
3988 + * Page exists in the cache, acquire the appropriate lock.
3989 + * If this fails, start all over again.
3990 + */
3991 + if ((pp = page_lookup(vp, off, se)) == NULL) {
3992 +#ifdef DEBUG
3993 + smbfs_lostpage++;
3994 +#endif
3995 + goto reread;
3996 + }
3997 + pl[0] = pp;
3998 + pl[1] = NULL;
3999 + return (0);
4000 + }
4001 +
4002 + if (pp != NULL)
4003 + pvn_plist_init(pp, pl, plsz, off, io_len, rw);
4004 +
4005 + return (error);
4006 +}
4007 +
4008 +/*
4009 + * Here NFS has: nfs3_readahead
4010 + * No read-ahead in smbfs yet.
4011 + */
4012 +
4013 +/*
4014 + * Flags are composed of {B_INVAL, B_FREE, B_DONTNEED, B_FORCE}
4015 + * If len == 0, do from off to EOF.
4016 + *
4017 + * The normal cases should be len == 0 && off == 0 (entire vp list),
4018 + * len == MAXBSIZE (from segmap_release actions), and len == PAGESIZE
4019 + * (from pageout).
4020 + *
4021 + * Like nfs3_putpage + nfs_putpages
4022 + */
4023 +/* ARGSUSED */
4024 +static int
4025 +smbfs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
4026 + caller_context_t *ct)
4027 +{
4028 + smbnode_t *np;
4029 + smbmntinfo_t *smi;
4030 + page_t *pp;
4031 + u_offset_t eoff;
4032 + u_offset_t io_off;
4033 + size_t io_len;
4034 + int error;
4035 + int rdirty;
4036 + int err;
4037 +
4038 + np = VTOSMB(vp);
4039 + smi = VTOSMI(vp);
4040 +
4041 + if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
4042 + return (EIO);
4043 +
4044 + if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
4045 + return (EIO);
4046 +
4047 + if (vp->v_flag & VNOMAP)
4048 + return (ENOSYS);
4049 +
4050 + /* Here NFS does rp->r_count (++/--) stuff. */
4051 +
4052 + /* Beginning of code from nfs_putpages. */
4053 +
4054 + if (!vn_has_cached_data(vp))
4055 + return (0);
4056 +
4057 + /*
4058 + * If ROUTOFSPACE is set, then all writes turn into B_INVAL
4059 + * writes. B_FORCE is set to force the VM system to actually
4060 + * invalidate the pages, even if the i/o failed. The pages
4061 + * need to get invalidated because they can't be written out
4062 + * because there isn't any space left on either the server's
4063 + * file system or in the user's disk quota. The B_FREE bit
4064 + * is cleared to avoid confusion as to whether this is a
4065 + * request to place the page on the freelist or to destroy
4066 + * it.
4067 + */
4068 + if ((np->r_flags & ROUTOFSPACE) ||
4069 + (vp->v_vfsp->vfs_flag & VFS_UNMOUNTED))
4070 + flags = (flags & ~B_FREE) | B_INVAL | B_FORCE;
4071 +
4072 + if (len == 0) {
4073 + /*
4074 + * If doing a full file synchronous operation, then clear
4075 + * the RDIRTY bit. If a page gets dirtied while the flush
4076 + * is happening, then RDIRTY will get set again. The
4077 + * RDIRTY bit must get cleared before the flush so that
4078 + * we don't lose this information.
4079 + *
4080 + * NFS has B_ASYNC vs sync stuff here.
4081 + */
4082 + if (off == (u_offset_t)0 &&
4083 + (np->r_flags & RDIRTY)) {
4084 + mutex_enter(&np->r_statelock);
4085 + rdirty = (np->r_flags & RDIRTY);
4086 + np->r_flags &= ~RDIRTY;
4087 + mutex_exit(&np->r_statelock);
4088 + } else
4089 + rdirty = 0;
4090 +
4091 + /*
4092 + * Search the entire vp list for pages >= off, and flush
4093 + * the dirty pages.
4094 + */
4095 + error = pvn_vplist_dirty(vp, off, smbfs_putapage,
4096 + flags, cr);
4097 +
4098 + /*
4099 + * If an error occurred and the file was marked as dirty
4100 + * before and we aren't forcibly invalidating pages, then
4101 + * reset the RDIRTY flag.
4102 + */
4103 + if (error && rdirty &&
4104 + (flags & (B_INVAL | B_FORCE)) != (B_INVAL | B_FORCE)) {
4105 + mutex_enter(&np->r_statelock);
4106 + np->r_flags |= RDIRTY;
4107 + mutex_exit(&np->r_statelock);
4108 + }
4109 + } else {
4110 + /*
4111 + * Do a range from [off...off + len) looking for pages
4112 + * to deal with.
4113 + */
4114 + error = 0;
4115 + io_len = 1; /* quiet warnings */
4116 + eoff = off + len;
4117 +
4118 + for (io_off = off; io_off < eoff; io_off += io_len) {
4119 + mutex_enter(&np->r_statelock);
4120 + if (io_off >= np->r_size) {
4121 + mutex_exit(&np->r_statelock);
4122 + break;
4123 + }
4124 + mutex_exit(&np->r_statelock);
4125 + /*
4126 + * If we are not invalidating, synchronously
4127 + * freeing or writing pages use the routine
4128 + * page_lookup_nowait() to prevent reclaiming
4129 + * them from the free list.
4130 + */
4131 + if ((flags & B_INVAL) || !(flags & B_ASYNC)) {
4132 + pp = page_lookup(vp, io_off,
4133 + (flags & (B_INVAL | B_FREE)) ?
4134 + SE_EXCL : SE_SHARED);
4135 + } else {
4136 + pp = page_lookup_nowait(vp, io_off,
4137 + (flags & B_FREE) ? SE_EXCL : SE_SHARED);
4138 + }
4139 +
4140 + if (pp == NULL || !pvn_getdirty(pp, flags))
4141 + io_len = PAGESIZE;
4142 + else {
4143 + err = smbfs_putapage(vp, pp, &io_off,
4144 + &io_len, flags, cr);
4145 + if (!error)
4146 + error = err;
4147 + /*
4148 + * "io_off" and "io_len" are returned as
4149 + * the range of pages we actually wrote.
4150 + * This allows us to skip ahead more quickly
4151 + * since several pages may've been dealt
4152 + * with by this iteration of the loop.
4153 + */
4154 + }
4155 + }
4156 + }
4157 +
4158 + return (error);
4159 +}
4160 +
4161 +/*
4162 + * Write out a single page, possibly klustering adjacent dirty pages.
4163 + *
4164 + * Like nfs3_putapage / nfs3_sync_putapage
4165 + */
4166 +static int
4167 +smbfs_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
4168 + int flags, cred_t *cr)
4169 +{
4170 + smbnode_t *np;
4171 + u_offset_t io_off;
4172 + u_offset_t lbn_off;
4173 + u_offset_t lbn;
4174 + size_t io_len;
4175 + uint_t bsize;
4176 + int error;
4177 +
4178 + np = VTOSMB(vp);
4179 +
4180 + ASSERT(!vn_is_readonly(vp));
4181 +
4182 + bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE);
4183 + lbn = pp->p_offset / bsize;
4184 + lbn_off = lbn * bsize;
4185 +
4186 + /*
4187 + * Find a kluster that fits in one block, or in
4188 + * one page if pages are bigger than blocks. If
4189 + * there is less file space allocated than a whole
4190 + * page, we'll shorten the i/o request below.
4191 + */
4192 + pp = pvn_write_kluster(vp, pp, &io_off, &io_len, lbn_off,
4193 + roundup(bsize, PAGESIZE), flags);
4194 +
4195 + /*
4196 + * pvn_write_kluster shouldn't have returned a page with offset
4197 + * behind the original page we were given. Verify that.
4198 + */
4199 + ASSERT((pp->p_offset / bsize) >= lbn);
4200 +
4201 + /*
4202 + * Now pp will have the list of kept dirty pages marked for
4203 + * write back. It will also handle invalidation and freeing
4204 + * of pages that are not dirty. Check for page length rounding
4205 + * problems.
4206 + */
4207 + if (io_off + io_len > lbn_off + bsize) {
4208 + ASSERT((io_off + io_len) - (lbn_off + bsize) < PAGESIZE);
4209 + io_len = lbn_off + bsize - io_off;
4210 + }
4211 + /*
4212 + * The RMODINPROGRESS flag makes sure that smbfs_bio() sees a
4213 + * consistent value of r_size. RMODINPROGRESS is set in writerp().
4214 + * When RMODINPROGRESS is set it indicates that a uiomove() is in
4215 + * progress and the r_size has not been made consistent with the
4216 + * new size of the file. When the uiomove() completes the r_size is
4217 + * updated and the RMODINPROGRESS flag is cleared.
4218 + *
4219 + * The RMODINPROGRESS flag makes sure that smbfs_bio() sees a
4220 + * consistent value of r_size. Without this handshaking, it is
4221 + * possible that smbfs_bio() picks up the old value of r_size
4222 + * before the uiomove() in writerp() completes. This will result
4223 + * in the write through smbfs_bio() being dropped.
4224 + *
4225 + * More precisely, there is a window between the time the uiomove()
4226 + * completes and the time the r_size is updated. If a VOP_PUTPAGE()
4227 + * operation intervenes in this window, the page will be picked up,
4228 + * because it is dirty (it will be unlocked, unless it was
4229 + * pagecreate'd). When the page is picked up as dirty, the dirty
4230 + * bit is reset (pvn_getdirty()). In smbfs_write(), r_size is
4231 + * checked. This will still be the old size. Therefore the page will
4232 + * not be written out. When segmap_release() calls VOP_PUTPAGE(),
4233 + * the page will be found to be clean and the write will be dropped.
4234 + */
4235 + if (np->r_flags & RMODINPROGRESS) {
4236 + mutex_enter(&np->r_statelock);
4237 + if ((np->r_flags & RMODINPROGRESS) &&
4238 + np->r_modaddr + MAXBSIZE > io_off &&
4239 + np->r_modaddr < io_off + io_len) {
4240 + page_t *plist;
4241 + /*
4242 + * A write is in progress for this region of the file.
4243 + * If we did not detect RMODINPROGRESS here then this
4244 + * path through smbfs_putapage() would eventually go to
4245 + * smbfs_bio() and may not write out all of the data
4246 + * in the pages. We end up losing data. So we decide
4247 + * to set the modified bit on each page in the page
4248 + * list and mark the rnode with RDIRTY. This write
4249 + * will be restarted at some later time.
4250 + */
4251 + plist = pp;
4252 + while (plist != NULL) {
4253 + pp = plist;
4254 + page_sub(&plist, pp);
4255 + hat_setmod(pp);
4256 + page_io_unlock(pp);
4257 + page_unlock(pp);
4258 + }
4259 + np->r_flags |= RDIRTY;
4260 + mutex_exit(&np->r_statelock);
4261 + if (offp)
4262 + *offp = io_off;
4263 + if (lenp)
4264 + *lenp = io_len;
4265 + return (0);
4266 + }
4267 + mutex_exit(&np->r_statelock);
4268 + }
4269 +
4270 + /*
4271 + * NFS handles (flags & B_ASYNC) here...
4272 + * (See nfs_async_putapage())
4273 + *
4274 + * This code section from: nfs3_sync_putapage()
4275 + */
4276 +
4277 + flags |= B_WRITE;
4278 +
4279 + error = smbfs_rdwrlbn(vp, pp, io_off, io_len, flags, cr);
4280 +
4281 + if ((error == ENOSPC || error == EDQUOT || error == EFBIG ||
4282 + error == EACCES) &&
4283 + (flags & (B_INVAL|B_FORCE)) != (B_INVAL|B_FORCE)) {
4284 + if (!(np->r_flags & ROUTOFSPACE)) {
4285 + mutex_enter(&np->r_statelock);
4286 + np->r_flags |= ROUTOFSPACE;
4287 + mutex_exit(&np->r_statelock);
4288 + }
4289 + flags |= B_ERROR;
4290 + pvn_write_done(pp, flags);
4291 + /*
4292 + * If this was not an async thread, then try again to
4293 + * write out the pages, but this time, also destroy
4294 + * them whether or not the write is successful. This
4295 + * will prevent memory from filling up with these
4296 + * pages and destroying them is the only alternative
4297 + * if they can't be written out.
4298 + *
4299 + * Don't do this if this is an async thread because
4300 + * when the pages are unlocked in pvn_write_done,
4301 + * some other thread could have come along, locked
4302 + * them, and queued for an async thread. It would be
4303 + * possible for all of the async threads to be tied
4304 + * up waiting to lock the pages again and they would
4305 + * all already be locked and waiting for an async
4306 + * thread to handle them. Deadlock.
4307 + */
4308 + if (!(flags & B_ASYNC)) {
4309 + error = smbfs_putpage(vp, io_off, io_len,
4310 + B_INVAL | B_FORCE, cr, NULL);
4311 + }
4312 + } else {
4313 + if (error)
4314 + flags |= B_ERROR;
4315 + else if (np->r_flags & ROUTOFSPACE) {
4316 + mutex_enter(&np->r_statelock);
4317 + np->r_flags &= ~ROUTOFSPACE;
4318 + mutex_exit(&np->r_statelock);
4319 + }
4320 + pvn_write_done(pp, flags);
4321 + }
4322 +
4323 + /* Now more code from: nfs3_putapage */
4324 +
4325 + if (offp)
4326 + *offp = io_off;
4327 + if (lenp)
4328 + *lenp = io_len;
4329 +
4330 + return (error);
4331 +}
4332 +
4333 +/*
4334 + * NFS has this in nfs_client.c (shared by v2,v3,...)
4335 + * We have it here so smbfs_putapage can be file scope.
4336 + */
4337 +void
4338 +smbfs_invalidate_pages(vnode_t *vp, u_offset_t off, cred_t *cr)
4339 +{
4340 + smbnode_t *np;
4341 +
4342 + np = VTOSMB(vp);
4343 +
4344 + mutex_enter(&np->r_statelock);
4345 + while (np->r_flags & RTRUNCATE)
4346 + cv_wait(&np->r_cv, &np->r_statelock);
4347 + np->r_flags |= RTRUNCATE;
4348 +
4349 + if (off == (u_offset_t)0) {
4350 + np->r_flags &= ~RDIRTY;
4351 + if (!(np->r_flags & RSTALE))
4352 + np->r_error = 0;
4353 + }
4354 + /* Here NFSv3 has np->r_truncaddr = off; */
4355 + mutex_exit(&np->r_statelock);
4356 +
4357 + (void) pvn_vplist_dirty(vp, off, smbfs_putapage,
4358 + B_INVAL | B_TRUNC, cr);
4359 +
4360 + mutex_enter(&np->r_statelock);
4361 + np->r_flags &= ~RTRUNCATE;
4362 + cv_broadcast(&np->r_cv);
4363 + mutex_exit(&np->r_statelock);
4364 +}
4365 +
4366 +/* Like nfs3_map */
4367 +
4368 +/* ARGSUSED */
4369 +static int
4370 +smbfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp,
4371 + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
4372 + cred_t *cr, caller_context_t *ct)
4373 +{
4374 + segvn_crargs_t vn_a;
4375 + struct vattr va;
4376 + smbnode_t *np;
4377 + smbmntinfo_t *smi;
4378 + int error;
4379 +
4380 + np = VTOSMB(vp);
4381 + smi = VTOSMI(vp);
4382 +
4383 + if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
4384 + return (EIO);
4385 +
4386 + if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
4387 + return (EIO);
4388 +
4389 + if (vp->v_flag & VNOMAP)
4390 + return (ENOSYS);
4391 +
4392 + if (off < 0 || off + (ssize_t)len < 0)
4393 + return (ENXIO);
4394 +
4395 + if (vp->v_type != VREG)
4396 + return (ENODEV);
4397 +
4398 + /*
4399 + * NFS does close-to-open consistency stuff here.
4400 + * Just get (possibly cached) attributes.
4401 + */
4402 + va.va_mask = AT_ALL;
4403 + if ((error = smbfsgetattr(vp, &va, cr)) != 0)
4404 + return (error);
4405 +
4406 + /*
4407 + * Check to see if the vnode is currently marked as not cachable.
4408 + * This means portions of the file are locked (through VOP_FRLOCK).
4409 + * In this case the map request must be refused. We use
4410 + * rp->r_lkserlock to avoid a race with concurrent lock requests.
4411 + */
4412 + /*
4413 + * Atomically increment r_inmap after acquiring r_rwlock. The
4414 + * idea here is to acquire r_rwlock to block read/write and
4415 + * not to protect r_inmap. r_inmap will inform smbfs_read/write()
4416 + * that we are in smbfs_map(). Now, r_rwlock is acquired in order
4417 + * and we can prevent the deadlock that would have occurred
4418 + * when smbfs_addmap() would have acquired it out of order.
4419 + *
4420 + * Since we are not protecting r_inmap by any lock, we do not
4421 + * hold any lock when we decrement it. We atomically decrement
4422 + * r_inmap after we release r_lkserlock. Note that rwlock is
4423 + * re-entered as writer in smbfs_addmap (called via as_map).
4424 + */
4425 +
4426 + if (smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, SMBINTR(vp)))
4427 + return (EINTR);
4428 + atomic_inc_uint(&np->r_inmap);
4429 + smbfs_rw_exit(&np->r_rwlock);
4430 +
4431 + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) {
4432 + atomic_dec_uint(&np->r_inmap);
4433 + return (EINTR);
4434 + }
4435 +
4436 + if (vp->v_flag & VNOCACHE) {
4437 + error = EAGAIN;
4438 + goto done;
4439 + }
4440 +
4441 + /*
4442 + * Don't allow concurrent locks and mapping if mandatory locking is
4443 + * enabled.
4444 + */
4445 + if ((flk_has_remote_locks(vp) || smbfs_lm_has_sleep(vp)) &&
4446 + MANDLOCK(vp, va.va_mode)) {
4447 + error = EAGAIN;
4448 + goto done;
4449 + }
4450 +
4451 + as_rangelock(as);
4452 + error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
4453 + if (error != 0) {
4454 + as_rangeunlock(as);
4455 + goto done;
4456 + }
4457 +
4458 + vn_a.vp = vp;
4459 + vn_a.offset = off;
4460 + vn_a.type = (flags & MAP_TYPE);
4461 + vn_a.prot = (uchar_t)prot;
4462 + vn_a.maxprot = (uchar_t)maxprot;
4463 + vn_a.flags = (flags & ~MAP_TYPE);
4464 + vn_a.cred = cr;
4465 + vn_a.amp = NULL;
4466 + vn_a.szc = 0;
4467 + vn_a.lgrp_mem_policy_flags = 0;
4468 +
4469 + error = as_map(as, *addrp, len, segvn_create, &vn_a);
4470 + as_rangeunlock(as);
4471 +
4472 +done:
4473 + smbfs_rw_exit(&np->r_lkserlock);
4474 + atomic_dec_uint(&np->r_inmap);
4475 + return (error);
4476 +}
4477 +
4478 +/* ARGSUSED */
4479 +static int
4480 +smbfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
4481 + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
4482 + cred_t *cr, caller_context_t *ct)
4483 +{
4484 + smbnode_t *np = VTOSMB(vp);
4485 + boolean_t inc_fidrefs = B_FALSE;
4486 +
4487 + /*
4488 + * When r_mapcnt goes from zero to non-zero,
4489 + * increment n_fidrefs
4490 + */
4491 + mutex_enter(&np->r_statelock);
4492 + if (np->r_mapcnt == 0)
4493 + inc_fidrefs = B_TRUE;
4494 + np->r_mapcnt += btopr(len);
4495 + mutex_exit(&np->r_statelock);
4496 +
4497 + if (inc_fidrefs) {
4498 + (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
4499 + np->n_fidrefs++;
4500 + smbfs_rw_exit(&np->r_lkserlock);
4501 + }
4502 +
4503 + return (0);
4504 +}
4505 +
4506 +/*
4507 + * Use an address space callback to flush pages dirty pages after unmap,
4508 + * which we can't do directly in smbfs_delmap due to locking issues.
4509 + */
4510 +typedef struct smbfs_delmap_args {
4511 + vnode_t *vp;
4512 + cred_t *cr;
4513 + offset_t off;
4514 + caddr_t addr;
4515 + size_t len;
4516 + uint_t prot;
4517 + uint_t maxprot;
4518 + uint_t flags;
4519 + boolean_t dec_fidrefs;
4520 +} smbfs_delmap_args_t;
4521 +
4522 +/* ARGSUSED */
4523 +static int
4524 +smbfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
4525 + size_t len, uint_t prot, uint_t maxprot, uint_t flags,
4526 + cred_t *cr, caller_context_t *ct)
4527 +{
4528 + smbnode_t *np = VTOSMB(vp);
4529 + smbfs_delmap_args_t *dmapp;
4530 + int error;
4531 +
4532 + dmapp = kmem_zalloc(sizeof (*dmapp), KM_SLEEP);
4533 +
4534 + dmapp->vp = vp;
4535 + dmapp->off = off;
4536 + dmapp->addr = addr;
4537 + dmapp->len = len;
4538 + dmapp->prot = prot;
4539 + dmapp->maxprot = maxprot;
4540 + dmapp->flags = flags;
4541 + dmapp->cr = cr;
4542 + dmapp->dec_fidrefs = B_FALSE;
4543 +
4544 + /*
4545 + * When r_mapcnt returns to zero, arrange for the
4546 + * callback to decrement n_fidrefs
4547 + */
4548 + mutex_enter(&np->r_statelock);
4549 + np->r_mapcnt -= btopr(len);
4550 + ASSERT(np->r_mapcnt >= 0);
4551 + if (np->r_mapcnt == 0)
4552 + dmapp->dec_fidrefs = B_TRUE;
4553 + mutex_exit(&np->r_statelock);
4554 +
4555 + error = as_add_callback(as, smbfs_delmap_callback, dmapp,
4556 + AS_UNMAP_EVENT, addr, len, KM_SLEEP);
4557 + if (error != 0) {
4558 + /*
4559 + * So sad, no callback is coming. Can't flush pages
4560 + * in delmap (as locks). Just handle n_fidrefs.
4561 + */
4562 + cmn_err(CE_NOTE, "smbfs_delmap(%p) "
4563 + "as_add_callback err=%d",
4564 + (void *)vp, error);
4565 +
4566 + if (dmapp->dec_fidrefs) {
4567 + struct smb_cred scred;
4568 +
4569 + (void) smbfs_rw_enter_sig(&np->r_lkserlock,
4570 + RW_WRITER, 0);
4571 + smb_credinit(&scred, dmapp->cr);
4572 +
4573 + smbfs_rele_fid(np, &scred);
4574 +
4575 + smb_credrele(&scred);
4576 + smbfs_rw_exit(&np->r_lkserlock);
4577 + }
4578 + kmem_free(dmapp, sizeof (*dmapp));
4579 + }
4580 +
4581 + return (0);
4582 +}
4583 +
4584 +/*
4585 + * Remove some pages from an mmap'd vnode. Flush any
4586 + * dirty pages in the unmapped range.
4587 + */
4588 +/* ARGSUSED */
4589 +static void
4590 +smbfs_delmap_callback(struct as *as, void *arg, uint_t event)
4591 +{
4592 + vnode_t *vp;
4593 + smbnode_t *np;
4594 + smbmntinfo_t *smi;
4595 + smbfs_delmap_args_t *dmapp = arg;
4596 +
4597 + vp = dmapp->vp;
4598 + np = VTOSMB(vp);
4599 + smi = VTOSMI(vp);
4600 +
4601 + /* Decremented r_mapcnt in smbfs_delmap */
4602 +
4603 + /*
4604 + * Initiate a page flush and potential commit if there are
4605 + * pages, the file system was not mounted readonly, the segment
4606 + * was mapped shared, and the pages themselves were writeable.
4607 + *
4608 + * mark RDIRTY here, will be used to check if a file is dirty when
4609 + * unmount smbfs
4610 + */
4611 + if (vn_has_cached_data(vp) && !vn_is_readonly(vp) &&
4612 + dmapp->flags == MAP_SHARED && (dmapp->maxprot & PROT_WRITE)) {
4613 + mutex_enter(&np->r_statelock);
4614 + np->r_flags |= RDIRTY;
4615 + mutex_exit(&np->r_statelock);
4616 +
4617 + /*
4618 + * Need to finish the putpage before we
4619 + * close the OtW FID needed for I/O.
4620 + */
4621 + (void) smbfs_putpage(vp, dmapp->off, dmapp->len, 0,
4622 + dmapp->cr, NULL);
4623 + }
4624 +
4625 + if ((np->r_flags & RDIRECTIO) || (smi->smi_flags & SMI_DIRECTIO))
4626 + (void) smbfs_putpage(vp, dmapp->off, dmapp->len,
4627 + B_INVAL, dmapp->cr, NULL);
4628 +
4629 + /*
4630 + * If r_mapcnt went to zero, drop our FID ref now.
4631 + * On the last fidref, this does an OtW close.
4632 + */
4633 + if (dmapp->dec_fidrefs) {
4634 + struct smb_cred scred;
4635 +
4636 + (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
4637 + smb_credinit(&scred, dmapp->cr);
4638 +
4639 + smbfs_rele_fid(np, &scred);
4640 +
4641 + smb_credrele(&scred);
4642 + smbfs_rw_exit(&np->r_lkserlock);
4643 + }
4644 +
4645 + (void) as_delete_callback(as, arg);
4646 + kmem_free(dmapp, sizeof (*dmapp));
4647 +}
4648 +
4649 +/* No smbfs_pageio() or smbfs_dispose() ops. */
4650 +
4651 +/* misc. ******************************************************** */
4652 +
4653 +
4654 +/*
2971 4655 * XXX
2972 4656 * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service.
2973 4657 */
2974 4658 static int
2975 4659 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2976 4660 offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
2977 4661 caller_context_t *ct)
2978 4662 {
2979 4663 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
2980 4664 return (EIO);
2981 4665
2982 4666 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
2983 4667 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
2984 4668 else
2985 4669 return (ENOSYS);
2986 4670 }
2987 4671
2988 4672 /*
2989 4673 * Free storage space associated with the specified vnode. The portion
2990 4674 * to be freed is specified by bfp->l_start and bfp->l_len (already
2991 4675 * normalized to a "whence" of 0).
2992 4676 *
2993 4677 * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc.
2994 4678 */
2995 4679 /* ARGSUSED */
2996 4680 static int
2997 4681 smbfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2998 4682 offset_t offset, cred_t *cr, caller_context_t *ct)
2999 4683 {
3000 4684 int error;
3001 4685 smbmntinfo_t *smi;
3002 4686
3003 4687 smi = VTOSMI(vp);
3004 4688
3005 4689 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3006 4690 return (EIO);
3007 4691
3008 4692 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3009 4693 return (EIO);
3010 4694
3011 4695 /* Caller (fcntl) has checked v_type */
3012 4696 ASSERT(vp->v_type == VREG);
3013 4697 if (cmd != F_FREESP)
3014 4698 return (EINVAL);
3015 4699
3016 4700 /*
3017 4701 * Like NFS3, no 32-bit offset checks here.
3018 4702 * Our SMB layer takes care to return EFBIG
3019 4703 * when it has to fallback to a 32-bit call.
3020 4704 */
3021 4705
3022 4706 error = convoff(vp, bfp, 0, offset);
3023 4707 if (!error) {
3024 4708 ASSERT(bfp->l_start >= 0);
3025 4709 if (bfp->l_len == 0) {
3026 4710 struct vattr va;
3027 4711
3028 4712 /*
3029 4713 * ftruncate should not change the ctime and
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
3030 4714 * mtime if we truncate the file to its
3031 4715 * previous size.
3032 4716 */
3033 4717 va.va_mask = AT_SIZE;
3034 4718 error = smbfsgetattr(vp, &va, cr);
3035 4719 if (error || va.va_size == bfp->l_start)
3036 4720 return (error);
3037 4721 va.va_mask = AT_SIZE;
3038 4722 va.va_size = bfp->l_start;
3039 4723 error = smbfssetattr(vp, &va, 0, cr);
4724 + /* SMBFS_VNEVENT... */
3040 4725 } else
3041 4726 error = EINVAL;
3042 4727 }
3043 4728
3044 4729 return (error);
3045 4730 }
3046 4731
4732 +
3047 4733 /* ARGSUSED */
3048 4734 static int
4735 +smbfs_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
4736 +{
4737 +
4738 + return (ENOSYS);
4739 +}
4740 +
4741 +
4742 +/* ARGSUSED */
4743 +static int
3049 4744 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
3050 4745 caller_context_t *ct)
3051 4746 {
3052 4747 vfs_t *vfs;
3053 4748 smbmntinfo_t *smi;
3054 4749 struct smb_share *ssp;
3055 4750
3056 4751 vfs = vp->v_vfsp;
3057 4752 smi = VFTOSMI(vfs);
3058 4753
3059 4754 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3060 4755 return (EIO);
3061 4756
3062 4757 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3063 4758 return (EIO);
3064 4759
3065 4760 switch (cmd) {
3066 4761 case _PC_FILESIZEBITS:
3067 4762 ssp = smi->smi_share;
3068 4763 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)
3069 4764 *valp = 64;
3070 4765 else
3071 4766 *valp = 32;
3072 4767 break;
3073 4768
3074 4769 case _PC_LINK_MAX:
3075 4770 /* We only ever report one link to an object */
3076 4771 *valp = 1;
3077 4772 break;
3078 4773
3079 4774 case _PC_ACL_ENABLED:
3080 4775 /*
3081 4776 * Always indicate that ACLs are enabled and
3082 4777 * that we support ACE_T format, otherwise
3083 4778 * libsec will ask for ACLENT_T format data
3084 4779 * which we don't support.
3085 4780 */
3086 4781 *valp = _ACL_ACE_ENABLED;
3087 4782 break;
3088 4783
3089 4784 case _PC_SYMLINK_MAX: /* No symlinks until we do Unix extensions */
3090 4785 *valp = 0;
3091 4786 break;
3092 4787
3093 4788 case _PC_XATTR_EXISTS:
3094 4789 if (vfs->vfs_flag & VFS_XATTR) {
3095 4790 *valp = smbfs_xa_exists(vp, cr);
3096 4791 break;
3097 4792 }
3098 4793 return (EINVAL);
3099 4794
3100 4795 case _PC_SATTR_ENABLED:
3101 4796 case _PC_SATTR_EXISTS:
3102 4797 *valp = 1;
3103 4798 break;
3104 4799
3105 4800 case _PC_TIMESTAMP_RESOLUTION:
3106 4801 /*
3107 4802 * Windows times are tenths of microseconds
3108 4803 * (multiples of 100 nanoseconds).
3109 4804 */
3110 4805 *valp = 100L;
3111 4806 break;
3112 4807
3113 4808 default:
3114 4809 return (fs_pathconf(vp, cmd, valp, cr, ct));
3115 4810 }
3116 4811 return (0);
3117 4812 }
3118 4813
3119 4814 /* ARGSUSED */
3120 4815 static int
3121 4816 smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3122 4817 caller_context_t *ct)
3123 4818 {
3124 4819 vfs_t *vfsp;
3125 4820 smbmntinfo_t *smi;
3126 4821 int error;
3127 4822 uint_t mask;
3128 4823
3129 4824 vfsp = vp->v_vfsp;
3130 4825 smi = VFTOSMI(vfsp);
3131 4826
3132 4827 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3133 4828 return (EIO);
3134 4829
3135 4830 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3136 4831 return (EIO);
3137 4832
3138 4833 /*
3139 4834 * Our _pathconf indicates _ACL_ACE_ENABLED,
3140 4835 * so we should only see VSA_ACE, etc here.
3141 4836 * Note: vn_create asks for VSA_DFACLCNT,
3142 4837 * and it expects ENOSYS and empty data.
3143 4838 */
3144 4839 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT |
3145 4840 VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES);
3146 4841 if (mask == 0)
3147 4842 return (ENOSYS);
3148 4843
3149 4844 if (smi->smi_flags & SMI_ACL)
3150 4845 error = smbfs_acl_getvsa(vp, vsa, flag, cr);
3151 4846 else
3152 4847 error = ENOSYS;
3153 4848
3154 4849 if (error == ENOSYS)
3155 4850 error = fs_fab_acl(vp, vsa, flag, cr, ct);
3156 4851
3157 4852 return (error);
3158 4853 }
3159 4854
3160 4855 /* ARGSUSED */
3161 4856 static int
3162 4857 smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3163 4858 caller_context_t *ct)
3164 4859 {
3165 4860 vfs_t *vfsp;
3166 4861 smbmntinfo_t *smi;
3167 4862 int error;
3168 4863 uint_t mask;
3169 4864
3170 4865 vfsp = vp->v_vfsp;
3171 4866 smi = VFTOSMI(vfsp);
3172 4867
3173 4868 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3174 4869 return (EIO);
3175 4870
3176 4871 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3177 4872 return (EIO);
3178 4873
3179 4874 /*
3180 4875 * Our _pathconf indicates _ACL_ACE_ENABLED,
3181 4876 * so we should only see VSA_ACE, etc here.
3182 4877 */
3183 4878 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT);
3184 4879 if (mask == 0)
3185 4880 return (ENOSYS);
3186 4881
3187 4882 if (vfsp->vfs_flag & VFS_RDONLY)
3188 4883 return (EROFS);
3189 4884
3190 4885 /*
3191 4886 * Allow only the mount owner to do this.
3192 4887 * See comments at smbfs_access_rwx.
3193 4888 */
3194 4889 error = secpolicy_vnode_setdac(cr, smi->smi_uid);
3195 4890 if (error != 0)
3196 4891 return (error);
3197 4892
3198 4893 if (smi->smi_flags & SMI_ACL)
3199 4894 error = smbfs_acl_setvsa(vp, vsa, flag, cr);
3200 4895 else
3201 4896 error = ENOSYS;
3202 4897
3203 4898 return (error);
3204 4899 }
3205 4900
3206 4901
3207 4902 /*
3208 4903 * XXX
3209 4904 * This op should eventually support PSARC 2007/268.
3210 4905 */
3211 4906 static int
3212 4907 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
↓ open down ↓ |
154 lines elided |
↑ open up ↑ |
3213 4908 caller_context_t *ct)
3214 4909 {
3215 4910 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
3216 4911 return (EIO);
3217 4912
3218 4913 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
3219 4914 return (fs_shrlock(vp, cmd, shr, flag, cr, ct));
3220 4915 else
3221 4916 return (ENOSYS);
3222 4917 }
4918 +
4919 +
4920 +/*
4921 + * Most unimplemented ops will return ENOSYS because of fs_nosys().
4922 + * The only ops where that won't work are ACCESS (due to open(2)
4923 + * failures) and ... (anything else left?)
4924 + */
4925 +const fs_operation_def_t smbfs_vnodeops_template[] = {
4926 + VOPNAME_OPEN, { .vop_open = smbfs_open },
4927 + VOPNAME_CLOSE, { .vop_close = smbfs_close },
4928 + VOPNAME_READ, { .vop_read = smbfs_read },
4929 + VOPNAME_WRITE, { .vop_write = smbfs_write },
4930 + VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl },
4931 + VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr },
4932 + VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr },
4933 + VOPNAME_ACCESS, { .vop_access = smbfs_access },
4934 + VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup },
4935 + VOPNAME_CREATE, { .vop_create = smbfs_create },
4936 + VOPNAME_REMOVE, { .vop_remove = smbfs_remove },
4937 + VOPNAME_LINK, { .vop_link = smbfs_link },
4938 + VOPNAME_RENAME, { .vop_rename = smbfs_rename },
4939 + VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir },
4940 + VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir },
4941 + VOPNAME_READDIR, { .vop_readdir = smbfs_readdir },
4942 + VOPNAME_SYMLINK, { .vop_symlink = smbfs_symlink },
4943 + VOPNAME_READLINK, { .vop_readlink = smbfs_readlink },
4944 + VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync },
4945 + VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive },
4946 + VOPNAME_FID, { .vop_fid = smbfs_fid },
4947 + VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock },
4948 + VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock },
4949 + VOPNAME_SEEK, { .vop_seek = smbfs_seek },
4950 + VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock },
4951 + VOPNAME_SPACE, { .vop_space = smbfs_space },
4952 + VOPNAME_REALVP, { .vop_realvp = smbfs_realvp },
4953 + VOPNAME_GETPAGE, { .vop_getpage = smbfs_getpage },
4954 + VOPNAME_PUTPAGE, { .vop_putpage = smbfs_putpage },
4955 + VOPNAME_MAP, { .vop_map = smbfs_map },
4956 + VOPNAME_ADDMAP, { .vop_addmap = smbfs_addmap },
4957 + VOPNAME_DELMAP, { .vop_delmap = smbfs_delmap },
4958 + VOPNAME_DUMP, { .error = fs_nosys }, /* smbfs_dump, */
4959 + VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf },
4960 + VOPNAME_PAGEIO, { .error = fs_nosys }, /* smbfs_pageio, */
4961 + VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr },
4962 + VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr },
4963 + VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock },
4964 +#ifdef SMBFS_VNEVENT
4965 + VOPNAME_VNEVENT, { .vop_vnevent = fs_vnevent_support },
4966 +#endif
4967 + { NULL, NULL }
4968 +};
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX