Print this page
6879933 Let SMBFS support extensible attributes per. PSARC 2007/315
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
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 39 #include <sys/systm.h>
40 40 #include <sys/cred.h>
41 41 #include <sys/vnode.h>
42 42 #include <sys/vfs.h>
43 43 #include <sys/filio.h>
44 44 #include <sys/uio.h>
45 45 #include <sys/dirent.h>
46 46 #include <sys/errno.h>
47 47 #include <sys/sunddi.h>
48 48 #include <sys/sysmacros.h>
49 49 #include <sys/kmem.h>
50 50 #include <sys/cmn_err.h>
51 51 #include <sys/vfs_opreg.h>
52 52 #include <sys/policy.h>
53 53
54 54 #include <netsmb/smb_osdep.h>
55 55 #include <netsmb/smb.h>
56 56 #include <netsmb/smb_conn.h>
57 57 #include <netsmb/smb_subr.h>
58 58
59 59 #include <smbfs/smbfs.h>
60 60 #include <smbfs/smbfs_node.h>
61 61 #include <smbfs/smbfs_subr.h>
62 62
63 63 #include <sys/fs/smbfs_ioctl.h>
64 64 #include <fs/fs_subr.h>
65 65
66 66 /*
67 67 * We assign directory offsets like the NFS client, where the
68 68 * offset increments by _one_ after each directory entry.
69 69 * Further, the entries "." and ".." are always at offsets
70 70 * zero and one (respectively) and the "real" entries from
71 71 * the server appear at offsets starting with two. This
72 72 * macro is used to initialize the n_dirofs field after
73 73 * setting n_dirseq with a _findopen call.
74 74 */
75 75 #define FIRST_DIROFS 2
76 76
77 77 /*
78 78 * These characters are illegal in NTFS file names.
79 79 * ref: http://support.microsoft.com/kb/147438
80 80 *
81 81 * Careful! The check in the XATTR case skips the
82 82 * first character to allow colon in XATTR names.
83 83 */
84 84 static const char illegal_chars[] = {
85 85 ':', /* colon - keep this first! */
86 86 '\\', /* back slash */
87 87 '/', /* slash */
88 88 '*', /* asterisk */
89 89 '?', /* question mark */
90 90 '"', /* double quote */
91 91 '<', /* less than sign */
92 92 '>', /* greater than sign */
93 93 '|', /* vertical bar */
94 94 0
95 95 };
96 96
97 97 /*
98 98 * Turning this on causes nodes to be created in the cache
99 99 * during directory listings, normally avoiding a second
100 100 * OtW attribute fetch just after a readdir.
101 101 */
102 102 int smbfs_fastlookup = 1;
103 103
104 104 /* local static function defines */
105 105
106 106 static int smbfslookup_cache(vnode_t *, char *, int, vnode_t **,
↓ open down ↓ |
106 lines elided |
↑ open up ↑ |
107 107 cred_t *);
108 108 static int smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
109 109 int cache_ok, caller_context_t *);
110 110 static int smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm,
111 111 cred_t *cr, caller_context_t *);
112 112 static int smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
113 113 static int smbfs_accessx(void *, int, cred_t *);
114 114 static int smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
115 115 caller_context_t *);
116 116 static void smbfs_rele_fid(smbnode_t *, struct smb_cred *);
117 +static uint32_t xvattr_to_dosattr(smbnode_t *, struct vattr *);
117 118
118 119 /*
119 120 * These are the vnode ops routines which implement the vnode interface to
120 121 * the networked file system. These routines just take their parameters,
121 122 * make them look networkish by putting the right info into interface structs,
122 123 * and then calling the appropriate remote routine(s) to do the work.
123 124 *
124 125 * Note on directory name lookup cacheing: If we detect a stale fhandle,
125 126 * we purge the directory cache relative to that vnode. This way, the
126 127 * user won't get burned by the cache repeatedly. See <smbfs/smbnode.h> for
127 128 * more details on smbnode locking.
128 129 */
129 130
130 131 static int smbfs_open(vnode_t **, int, cred_t *, caller_context_t *);
131 132 static int smbfs_close(vnode_t *, int, int, offset_t, cred_t *,
132 133 caller_context_t *);
133 134 static int smbfs_read(vnode_t *, struct uio *, int, cred_t *,
134 135 caller_context_t *);
135 136 static int smbfs_write(vnode_t *, struct uio *, int, cred_t *,
136 137 caller_context_t *);
137 138 static int smbfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
138 139 caller_context_t *);
139 140 static int smbfs_getattr(vnode_t *, struct vattr *, int, cred_t *,
140 141 caller_context_t *);
141 142 static int smbfs_setattr(vnode_t *, struct vattr *, int, cred_t *,
142 143 caller_context_t *);
143 144 static int smbfs_access(vnode_t *, int, int, cred_t *, caller_context_t *);
144 145 static int smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *);
145 146 static void smbfs_inactive(vnode_t *, cred_t *, caller_context_t *);
146 147 static int smbfs_lookup(vnode_t *, char *, vnode_t **, struct pathname *,
147 148 int, vnode_t *, cred_t *, caller_context_t *,
148 149 int *, pathname_t *);
149 150 static int smbfs_create(vnode_t *, char *, struct vattr *, enum vcexcl,
150 151 int, vnode_t **, cred_t *, int, caller_context_t *,
151 152 vsecattr_t *);
152 153 static int smbfs_remove(vnode_t *, char *, cred_t *, caller_context_t *,
153 154 int);
154 155 static int smbfs_rename(vnode_t *, char *, vnode_t *, char *, cred_t *,
155 156 caller_context_t *, int);
156 157 static int smbfs_mkdir(vnode_t *, char *, struct vattr *, vnode_t **,
157 158 cred_t *, caller_context_t *, int, vsecattr_t *);
158 159 static int smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
159 160 caller_context_t *, int);
160 161 static int smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *,
161 162 caller_context_t *, int);
162 163 static int smbfs_rwlock(vnode_t *, int, caller_context_t *);
163 164 static void smbfs_rwunlock(vnode_t *, int, caller_context_t *);
164 165 static int smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
165 166 static int smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t,
166 167 struct flk_callback *, cred_t *, caller_context_t *);
167 168 static int smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t,
168 169 cred_t *, caller_context_t *);
169 170 static int smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *,
170 171 caller_context_t *);
171 172 static int smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
172 173 caller_context_t *);
173 174 static int smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
174 175 caller_context_t *);
175 176 static int smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *,
176 177 caller_context_t *);
177 178
178 179 /* Dummy function to use until correct function is ported in */
179 180 int noop_vnodeop() {
180 181 return (0);
181 182 }
182 183
183 184 struct vnodeops *smbfs_vnodeops = NULL;
184 185
185 186 /*
186 187 * Most unimplemented ops will return ENOSYS because of fs_nosys().
187 188 * The only ops where that won't work are ACCESS (due to open(2)
188 189 * failures) and ... (anything else left?)
189 190 */
190 191 const fs_operation_def_t smbfs_vnodeops_template[] = {
191 192 { VOPNAME_OPEN, { .vop_open = smbfs_open } },
192 193 { VOPNAME_CLOSE, { .vop_close = smbfs_close } },
193 194 { VOPNAME_READ, { .vop_read = smbfs_read } },
194 195 { VOPNAME_WRITE, { .vop_write = smbfs_write } },
195 196 { VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl } },
196 197 { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } },
197 198 { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } },
198 199 { VOPNAME_ACCESS, { .vop_access = smbfs_access } },
199 200 { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } },
200 201 { VOPNAME_CREATE, { .vop_create = smbfs_create } },
201 202 { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } },
202 203 { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */
203 204 { VOPNAME_RENAME, { .vop_rename = smbfs_rename } },
204 205 { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } },
205 206 { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } },
206 207 { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } },
207 208 { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */
208 209 { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */
209 210 { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } },
210 211 { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } },
211 212 { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */
212 213 { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } },
213 214 { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } },
214 215 { VOPNAME_SEEK, { .vop_seek = smbfs_seek } },
215 216 { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } },
216 217 { VOPNAME_SPACE, { .vop_space = smbfs_space } },
217 218 { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */
218 219 { VOPNAME_GETPAGE, { .error = fs_nosys } }, /* smbfs_getpage, */
219 220 { VOPNAME_PUTPAGE, { .error = fs_nosys } }, /* smbfs_putpage, */
220 221 { VOPNAME_MAP, { .error = fs_nosys } }, /* smbfs_map, */
221 222 { VOPNAME_ADDMAP, { .error = fs_nosys } }, /* smbfs_addmap, */
222 223 { VOPNAME_DELMAP, { .error = fs_nosys } }, /* smbfs_delmap, */
223 224 { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */
224 225 { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } },
225 226 { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */
226 227 { VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr } },
227 228 { VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr } },
228 229 { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } },
229 230 { NULL, NULL }
230 231 };
231 232
232 233 /*
233 234 * XXX
234 235 * When new and relevant functionality is enabled, we should be
235 236 * calling vfs_set_feature() to inform callers that pieces of
236 237 * functionality are available, per PSARC 2007/227.
237 238 */
238 239 /* ARGSUSED */
239 240 static int
240 241 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
241 242 {
242 243 smbnode_t *np;
243 244 vnode_t *vp;
244 245 smbfattr_t fa;
245 246 u_int32_t rights, rightsrcvd;
246 247 u_int16_t fid, oldfid;
247 248 int oldgenid;
248 249 struct smb_cred scred;
249 250 smbmntinfo_t *smi;
250 251 smb_share_t *ssp;
251 252 cred_t *oldcr;
252 253 int tmperror;
253 254 int error = 0;
254 255
255 256 vp = *vpp;
256 257 np = VTOSMB(vp);
257 258 smi = VTOSMI(vp);
258 259 ssp = smi->smi_share;
259 260
260 261 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
261 262 return (EIO);
262 263
263 264 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
264 265 return (EIO);
265 266
266 267 if (vp->v_type != VREG && vp->v_type != VDIR) { /* XXX VLNK? */
267 268 SMBVDEBUG("open eacces vtype=%d\n", vp->v_type);
268 269 return (EACCES);
269 270 }
270 271
271 272 /*
272 273 * Get exclusive access to n_fid and related stuff.
273 274 * No returns after this until out.
274 275 */
275 276 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
276 277 return (EINTR);
277 278 smb_credinit(&scred, cr);
278 279
279 280 /*
280 281 * Keep track of the vnode type at first open.
281 282 * It may change later, and we need close to do
282 283 * cleanup for the type we opened. Also deny
283 284 * open of new types until old type is closed.
284 285 * XXX: Per-open instance nodes whould help.
285 286 */
286 287 if (np->n_ovtype == VNON) {
287 288 ASSERT(np->n_dirrefs == 0);
288 289 ASSERT(np->n_fidrefs == 0);
289 290 } else if (np->n_ovtype != vp->v_type) {
290 291 SMBVDEBUG("open n_ovtype=%d v_type=%d\n",
291 292 np->n_ovtype, vp->v_type);
292 293 error = EACCES;
293 294 goto out;
294 295 }
295 296
296 297 /*
297 298 * Directory open. See smbfs_readvdir()
298 299 */
299 300 if (vp->v_type == VDIR) {
300 301 if (np->n_dirseq == NULL) {
301 302 /* first open */
302 303 error = smbfs_smb_findopen(np, "*", 1,
303 304 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
304 305 &scred, &np->n_dirseq);
305 306 if (error != 0)
306 307 goto out;
307 308 }
308 309 np->n_dirofs = FIRST_DIROFS;
309 310 np->n_dirrefs++;
310 311 goto have_fid;
311 312 }
312 313
313 314 /*
314 315 * If caller specified O_TRUNC/FTRUNC, then be sure to set
315 316 * FWRITE (to drive successful setattr(size=0) after open)
316 317 */
317 318 if (flag & FTRUNC)
318 319 flag |= FWRITE;
319 320
320 321 /*
321 322 * If we already have it open, and the FID is still valid,
322 323 * check whether the rights are sufficient for FID reuse.
323 324 */
324 325 if (np->n_fidrefs > 0 &&
325 326 np->n_vcgenid == ssp->ss_vcgenid) {
326 327 int upgrade = 0;
327 328
328 329 if ((flag & FWRITE) &&
329 330 !(np->n_rights & SA_RIGHT_FILE_WRITE_DATA))
330 331 upgrade = 1;
331 332 if ((flag & FREAD) &&
332 333 !(np->n_rights & SA_RIGHT_FILE_READ_DATA))
333 334 upgrade = 1;
334 335 if (!upgrade) {
335 336 /*
336 337 * the existing open is good enough
337 338 */
338 339 np->n_fidrefs++;
339 340 goto have_fid;
340 341 }
341 342 }
342 343 rights = np->n_fidrefs ? np->n_rights : 0;
343 344
344 345 /*
345 346 * we always ask for READ_CONTROL so we can always get the
346 347 * owner/group IDs to satisfy a stat. Ditto attributes.
347 348 */
348 349 rights |= (STD_RIGHT_READ_CONTROL_ACCESS |
349 350 SA_RIGHT_FILE_READ_ATTRIBUTES);
350 351 if ((flag & FREAD))
351 352 rights |= SA_RIGHT_FILE_READ_DATA;
352 353 if ((flag & FWRITE))
353 354 rights |= SA_RIGHT_FILE_WRITE_DATA |
354 355 SA_RIGHT_FILE_APPEND_DATA |
355 356 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
356 357
357 358 bzero(&fa, sizeof (fa));
358 359 error = smbfs_smb_open(np,
359 360 NULL, 0, 0, /* name nmlen xattr */
360 361 rights, &scred,
361 362 &fid, &rightsrcvd, &fa);
362 363 if (error)
363 364 goto out;
364 365 smbfs_attrcache_fa(vp, &fa);
365 366
366 367 /*
367 368 * We have a new FID and access rights.
368 369 */
369 370 oldfid = np->n_fid;
370 371 oldgenid = np->n_vcgenid;
371 372 np->n_fid = fid;
372 373 np->n_vcgenid = ssp->ss_vcgenid;
373 374 np->n_rights = rightsrcvd;
374 375 np->n_fidrefs++;
375 376 if (np->n_fidrefs > 1 &&
376 377 oldgenid == ssp->ss_vcgenid) {
377 378 /*
378 379 * We already had it open (presumably because
379 380 * it was open with insufficient rights.)
380 381 * Close old wire-open.
381 382 */
382 383 tmperror = smbfs_smb_close(ssp,
383 384 oldfid, NULL, &scred);
384 385 if (tmperror)
385 386 SMBVDEBUG("error %d closing %s\n",
386 387 tmperror, np->n_rpath);
387 388 }
388 389
389 390 /*
390 391 * This thread did the open.
391 392 * Save our credentials too.
392 393 */
393 394 mutex_enter(&np->r_statelock);
394 395 oldcr = np->r_cred;
395 396 np->r_cred = cr;
396 397 crhold(cr);
397 398 if (oldcr)
398 399 crfree(oldcr);
399 400 mutex_exit(&np->r_statelock);
400 401
401 402 have_fid:
402 403 /*
403 404 * Keep track of the vnode type at first open.
404 405 * (see comments above)
405 406 */
406 407 if (np->n_ovtype == VNON)
407 408 np->n_ovtype = vp->v_type;
408 409
409 410 out:
410 411 smb_credrele(&scred);
411 412 smbfs_rw_exit(&np->r_lkserlock);
412 413 return (error);
413 414 }
414 415
415 416 /*ARGSUSED*/
416 417 static int
417 418 smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
418 419 caller_context_t *ct)
419 420 {
420 421 smbnode_t *np;
421 422 smbmntinfo_t *smi;
422 423 struct smb_cred scred;
423 424
424 425 np = VTOSMB(vp);
425 426 smi = VTOSMI(vp);
426 427
427 428 /*
428 429 * Don't "bail out" for VFS_UNMOUNTED here,
429 430 * as we want to do cleanup, etc.
430 431 */
431 432
432 433 /*
433 434 * zone_enter(2) prevents processes from changing zones with SMBFS files
434 435 * open; if we happen to get here from the wrong zone we can't do
435 436 * anything over the wire.
436 437 */
437 438 if (smi->smi_zone_ref.zref_zone != curproc->p_zone) {
438 439 /*
439 440 * We could attempt to clean up locks, except we're sure
440 441 * that the current process didn't acquire any locks on
441 442 * the file: any attempt to lock a file belong to another zone
442 443 * will fail, and one can't lock an SMBFS file and then change
443 444 * zones, as that fails too.
444 445 *
445 446 * Returning an error here is the sane thing to do. A
446 447 * subsequent call to VN_RELE() which translates to a
447 448 * smbfs_inactive() will clean up state: if the zone of the
448 449 * vnode's origin is still alive and kicking, an async worker
449 450 * thread will handle the request (from the correct zone), and
450 451 * everything (minus the final smbfs_getattr_otw() call) should
451 452 * be OK. If the zone is going away smbfs_async_inactive() will
452 453 * throw away cached pages inline.
453 454 */
454 455 return (EIO);
455 456 }
456 457
457 458 /*
458 459 * If we are using local locking for this filesystem, then
459 460 * release all of the SYSV style record locks. Otherwise,
460 461 * we are doing network locking and we need to release all
461 462 * of the network locks. All of the locks held by this
462 463 * process on this file are released no matter what the
463 464 * incoming reference count is.
464 465 */
465 466 if (smi->smi_flags & SMI_LLOCK) {
466 467 pid_t pid = ddi_get_pid();
467 468 cleanlocks(vp, pid, 0);
468 469 cleanshares(vp, pid);
469 470 }
470 471
471 472 /*
472 473 * This (passed in) count is the ref. count from the
473 474 * user's file_t before the closef call (fio.c).
474 475 * We only care when the reference goes away.
475 476 */
476 477 if (count > 1)
477 478 return (0);
478 479
479 480 /*
480 481 * Decrement the reference count for the FID
481 482 * and possibly do the OtW close.
482 483 *
483 484 * Exclusive lock for modifying n_fid stuff.
484 485 * Don't want this one ever interruptible.
485 486 */
486 487 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
487 488 smb_credinit(&scred, cr);
488 489
489 490 smbfs_rele_fid(np, &scred);
490 491
491 492 smb_credrele(&scred);
492 493 smbfs_rw_exit(&np->r_lkserlock);
493 494
494 495 return (0);
495 496 }
496 497
497 498 /*
498 499 * Helper for smbfs_close. Decrement the reference count
499 500 * for an SMB-level file or directory ID, and when the last
500 501 * reference for the fid goes away, do the OtW close.
501 502 * Also called in smbfs_inactive (defensive cleanup).
502 503 */
503 504 static void
504 505 smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred)
505 506 {
506 507 smb_share_t *ssp;
507 508 cred_t *oldcr;
508 509 struct smbfs_fctx *fctx;
509 510 int error;
510 511 uint16_t ofid;
511 512
512 513 ssp = np->n_mount->smi_share;
513 514 error = 0;
514 515
515 516 /* Make sure we serialize for n_dirseq use. */
516 517 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
517 518
518 519 /*
519 520 * Note that vp->v_type may change if a remote node
520 521 * is deleted and recreated as a different type, and
521 522 * our getattr may change v_type accordingly.
522 523 * Now use n_ovtype to keep track of the v_type
523 524 * we had during open (see comments above).
524 525 */
525 526 switch (np->n_ovtype) {
526 527 case VDIR:
527 528 ASSERT(np->n_dirrefs > 0);
528 529 if (--np->n_dirrefs)
529 530 return;
530 531 if ((fctx = np->n_dirseq) != NULL) {
531 532 np->n_dirseq = NULL;
532 533 np->n_dirofs = 0;
533 534 error = smbfs_smb_findclose(fctx, scred);
534 535 }
535 536 break;
536 537
537 538 case VREG:
538 539 ASSERT(np->n_fidrefs > 0);
539 540 if (--np->n_fidrefs)
540 541 return;
541 542 if ((ofid = np->n_fid) != SMB_FID_UNUSED) {
542 543 np->n_fid = SMB_FID_UNUSED;
543 544 /* After reconnect, n_fid is invalid */
544 545 if (np->n_vcgenid == ssp->ss_vcgenid) {
545 546 error = smbfs_smb_close(
546 547 ssp, ofid, NULL, scred);
547 548 }
548 549 }
549 550 break;
550 551
551 552 default:
552 553 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
553 554 break;
554 555 }
555 556 if (error) {
556 557 SMBVDEBUG("error %d closing %s\n",
557 558 error, np->n_rpath);
558 559 }
559 560
560 561 /* Allow next open to use any v_type. */
561 562 np->n_ovtype = VNON;
562 563
563 564 /*
564 565 * Other "last close" stuff.
565 566 */
566 567 mutex_enter(&np->r_statelock);
567 568 if (np->n_flag & NATTRCHANGED)
568 569 smbfs_attrcache_rm_locked(np);
569 570 oldcr = np->r_cred;
570 571 np->r_cred = NULL;
571 572 mutex_exit(&np->r_statelock);
572 573 if (oldcr != NULL)
573 574 crfree(oldcr);
574 575 }
575 576
576 577 /* ARGSUSED */
577 578 static int
578 579 smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
579 580 caller_context_t *ct)
580 581 {
581 582 struct smb_cred scred;
582 583 struct vattr va;
583 584 smbnode_t *np;
584 585 smbmntinfo_t *smi;
585 586 smb_share_t *ssp;
586 587 offset_t endoff;
587 588 ssize_t past_eof;
588 589 int error;
589 590
590 591 np = VTOSMB(vp);
591 592 smi = VTOSMI(vp);
592 593 ssp = smi->smi_share;
593 594
594 595 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
595 596 return (EIO);
596 597
597 598 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
598 599 return (EIO);
599 600
600 601 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
601 602
602 603 if (vp->v_type != VREG)
603 604 return (EISDIR);
604 605
605 606 if (uiop->uio_resid == 0)
606 607 return (0);
607 608
608 609 /*
609 610 * Like NFS3, just check for 63-bit overflow.
610 611 * Our SMB layer takes care to return EFBIG
611 612 * when it has to fallback to a 32-bit call.
612 613 */
613 614 endoff = uiop->uio_loffset + uiop->uio_resid;
614 615 if (uiop->uio_loffset < 0 || endoff < 0)
615 616 return (EINVAL);
616 617
617 618 /* get vnode attributes from server */
618 619 va.va_mask = AT_SIZE | AT_MTIME;
619 620 if (error = smbfsgetattr(vp, &va, cr))
620 621 return (error);
621 622
622 623 /* Update mtime with mtime from server here? */
623 624
624 625 /* if offset is beyond EOF, read nothing */
625 626 if (uiop->uio_loffset >= va.va_size)
626 627 return (0);
627 628
628 629 /*
629 630 * Limit the read to the remaining file size.
630 631 * Do this by temporarily reducing uio_resid
631 632 * by the amount the lies beyoned the EOF.
632 633 */
633 634 if (endoff > va.va_size) {
634 635 past_eof = (ssize_t)(endoff - va.va_size);
635 636 uiop->uio_resid -= past_eof;
636 637 } else
637 638 past_eof = 0;
638 639
639 640 /* Shared lock for n_fid use in smb_rwuio */
640 641 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
641 642 return (EINTR);
642 643 smb_credinit(&scred, cr);
643 644
644 645 /* After reconnect, n_fid is invalid */
645 646 if (np->n_vcgenid != ssp->ss_vcgenid)
646 647 error = ESTALE;
647 648 else
648 649 error = smb_rwuio(ssp, np->n_fid, UIO_READ,
649 650 uiop, &scred, smb_timo_read);
650 651
651 652 smb_credrele(&scred);
652 653 smbfs_rw_exit(&np->r_lkserlock);
653 654
654 655 /* undo adjustment of resid */
655 656 uiop->uio_resid += past_eof;
656 657
657 658 return (error);
658 659 }
659 660
660 661
661 662 /* ARGSUSED */
662 663 static int
663 664 smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
664 665 caller_context_t *ct)
665 666 {
666 667 struct smb_cred scred;
667 668 struct vattr va;
668 669 smbnode_t *np;
669 670 smbmntinfo_t *smi;
670 671 smb_share_t *ssp;
671 672 offset_t endoff, limit;
672 673 ssize_t past_limit;
673 674 int error, timo;
674 675
675 676 np = VTOSMB(vp);
676 677 smi = VTOSMI(vp);
677 678 ssp = smi->smi_share;
678 679
679 680 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
680 681 return (EIO);
681 682
682 683 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
683 684 return (EIO);
684 685
685 686 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
686 687
687 688 if (vp->v_type != VREG)
688 689 return (EISDIR);
689 690
690 691 if (uiop->uio_resid == 0)
691 692 return (0);
692 693
693 694 /*
694 695 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
695 696 */
696 697 if (ioflag & (FAPPEND | FSYNC)) {
697 698 if (np->n_flag & NMODIFIED) {
698 699 smbfs_attrcache_remove(np);
699 700 /* XXX: smbfs_vinvalbuf? */
700 701 }
701 702 }
702 703 if (ioflag & FAPPEND) {
703 704 /*
704 705 * File size can be changed by another client
705 706 */
706 707 va.va_mask = AT_SIZE;
707 708 if (error = smbfsgetattr(vp, &va, cr))
708 709 return (error);
709 710 uiop->uio_loffset = va.va_size;
710 711 }
711 712
712 713 /*
713 714 * Like NFS3, just check for 63-bit overflow.
714 715 */
715 716 endoff = uiop->uio_loffset + uiop->uio_resid;
716 717 if (uiop->uio_loffset < 0 || endoff < 0)
717 718 return (EINVAL);
718 719
719 720 /*
720 721 * Check to make sure that the process will not exceed
721 722 * its limit on file size. It is okay to write up to
722 723 * the limit, but not beyond. Thus, the write which
723 724 * reaches the limit will be short and the next write
724 725 * will return an error.
725 726 *
726 727 * So if we're starting at or beyond the limit, EFBIG.
727 728 * Otherwise, temporarily reduce resid to the amount
728 729 * the falls after the limit.
729 730 */
730 731 limit = uiop->uio_llimit;
731 732 if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
732 733 limit = MAXOFFSET_T;
733 734 if (uiop->uio_loffset >= limit)
734 735 return (EFBIG);
735 736 if (endoff > limit) {
736 737 past_limit = (ssize_t)(endoff - limit);
737 738 uiop->uio_resid -= past_limit;
738 739 } else
739 740 past_limit = 0;
740 741
741 742 /* Timeout: longer for append. */
742 743 timo = smb_timo_write;
743 744 if (endoff > np->r_size)
744 745 timo = smb_timo_append;
745 746
746 747 /* Shared lock for n_fid use in smb_rwuio */
747 748 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
748 749 return (EINTR);
749 750 smb_credinit(&scred, cr);
750 751
751 752 /* After reconnect, n_fid is invalid */
752 753 if (np->n_vcgenid != ssp->ss_vcgenid)
753 754 error = ESTALE;
754 755 else
755 756 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
756 757 uiop, &scred, timo);
757 758
758 759 if (error == 0) {
759 760 mutex_enter(&np->r_statelock);
760 761 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
761 762 if (uiop->uio_loffset > (offset_t)np->r_size)
762 763 np->r_size = (len_t)uiop->uio_loffset;
763 764 mutex_exit(&np->r_statelock);
764 765 if (ioflag & (FSYNC|FDSYNC)) {
765 766 /* Don't error the I/O if this fails. */
766 767 (void) smbfs_smb_flush(np, &scred);
767 768 }
768 769 }
769 770
770 771 smb_credrele(&scred);
771 772 smbfs_rw_exit(&np->r_lkserlock);
772 773
773 774 /* undo adjustment of resid */
774 775 uiop->uio_resid += past_limit;
775 776
776 777 return (error);
777 778 }
778 779
779 780
780 781 /* ARGSUSED */
781 782 static int
782 783 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag,
783 784 cred_t *cr, int *rvalp, caller_context_t *ct)
784 785 {
785 786 int error;
786 787 smbmntinfo_t *smi;
787 788
788 789 smi = VTOSMI(vp);
789 790
790 791 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
791 792 return (EIO);
792 793
793 794 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
794 795 return (EIO);
795 796
796 797 switch (cmd) {
797 798 /* First three from ZFS. XXX - need these? */
798 799
799 800 case _FIOFFS:
800 801 error = smbfs_fsync(vp, 0, cr, ct);
801 802 break;
802 803
803 804 /*
804 805 * The following two ioctls are used by bfu.
805 806 * Silently ignore to avoid bfu errors.
806 807 */
807 808 case _FIOGDIO:
808 809 case _FIOSDIO:
809 810 error = 0;
810 811 break;
811 812
812 813 #ifdef NOT_YET /* XXX - from the NFS code. */
813 814 case _FIODIRECTIO:
814 815 error = smbfs_directio(vp, (int)arg, cr);
815 816 #endif
816 817
817 818 /*
818 819 * Allow get/set with "raw" security descriptor (SD) data.
819 820 * Useful for testing, diagnosing idmap problems, etc.
820 821 */
821 822 case SMBFSIO_GETSD:
822 823 error = smbfs_acl_iocget(vp, arg, flag, cr);
823 824 break;
824 825
825 826 case SMBFSIO_SETSD:
826 827 error = smbfs_acl_iocset(vp, arg, flag, cr);
827 828 break;
828 829
829 830 default:
830 831 error = ENOTTY;
↓ open down ↓ |
704 lines elided |
↑ open up ↑ |
831 832 break;
832 833 }
833 834
834 835 return (error);
835 836 }
836 837
837 838
838 839 /*
839 840 * Return either cached or remote attributes. If get remote attr
840 841 * use them to check and invalidate caches, then cache the new attributes.
841 - *
842 - * XXX
843 - * This op should eventually support PSARC 2007/315, Extensible Attribute
844 - * Interfaces, for richer metadata.
845 842 */
846 843 /* ARGSUSED */
847 844 static int
848 845 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
849 846 caller_context_t *ct)
850 847 {
851 848 smbnode_t *np;
852 849 smbmntinfo_t *smi;
853 850
854 851 smi = VTOSMI(vp);
855 852
856 853 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
857 854 return (EIO);
858 855
859 856 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
860 857 return (EIO);
861 858
862 859 /*
863 860 * If it has been specified that the return value will
864 861 * just be used as a hint, and we are only being asked
865 862 * for size, fsid or rdevid, then return the client's
866 863 * notion of these values without checking to make sure
867 864 * that the attribute cache is up to date.
868 865 * The whole point is to avoid an over the wire GETATTR
869 866 * call.
870 867 */
871 868 np = VTOSMB(vp);
872 869 if (flags & ATTR_HINT) {
873 870 if (vap->va_mask ==
874 871 (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) {
875 872 mutex_enter(&np->r_statelock);
876 873 if (vap->va_mask | AT_SIZE)
877 874 vap->va_size = np->r_size;
878 875 if (vap->va_mask | AT_FSID)
879 876 vap->va_fsid = vp->v_vfsp->vfs_dev;
880 877 if (vap->va_mask | AT_RDEV)
881 878 vap->va_rdev = vp->v_rdev;
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
882 879 mutex_exit(&np->r_statelock);
883 880 return (0);
884 881 }
885 882 }
886 883
887 884 return (smbfsgetattr(vp, vap, cr));
888 885 }
889 886
890 887 /* smbfsgetattr() in smbfs_client.c */
891 888
892 -/*
893 - * XXX
894 - * This op should eventually support PSARC 2007/315, Extensible Attribute
895 - * Interfaces, for richer metadata.
896 - */
897 889 /*ARGSUSED4*/
898 890 static int
899 891 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
900 892 caller_context_t *ct)
901 893 {
902 894 vfs_t *vfsp;
903 895 smbmntinfo_t *smi;
904 896 int error;
905 897 uint_t mask;
906 898 struct vattr oldva;
907 899
908 900 vfsp = vp->v_vfsp;
909 901 smi = VFTOSMI(vfsp);
910 902
911 903 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
912 904 return (EIO);
913 905
914 906 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
915 907 return (EIO);
916 908
917 909 mask = vap->va_mask;
918 910 if (mask & AT_NOSET)
919 911 return (EINVAL);
920 912
921 913 if (vfsp->vfs_flag & VFS_RDONLY)
922 914 return (EROFS);
923 915
924 916 /*
925 917 * This is a _local_ access check so that only the owner of
926 918 * this mount can set attributes. With ACLs enabled, the
927 919 * file owner can be different from the mount owner, and we
928 920 * need to check the _mount_ owner here. See _access_rwx
929 921 */
930 922 bzero(&oldva, sizeof (oldva));
931 923 oldva.va_mask = AT_TYPE | AT_MODE;
932 924 error = smbfsgetattr(vp, &oldva, cr);
933 925 if (error)
934 926 return (error);
935 927 oldva.va_mask |= AT_UID | AT_GID;
936 928 oldva.va_uid = smi->smi_uid;
937 929 oldva.va_gid = smi->smi_gid;
938 930
939 931 error = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
940 932 smbfs_accessx, vp);
941 933 if (error)
942 934 return (error);
943 935
944 936 if (mask & (AT_UID | AT_GID)) {
945 937 if (smi->smi_flags & SMI_ACL)
946 938 error = smbfs_acl_setids(vp, vap, cr);
947 939 else
948 940 error = ENOSYS;
949 941 if (error != 0) {
950 942 SMBVDEBUG("error %d seting UID/GID on %s",
951 943 error, VTOSMB(vp)->n_rpath);
952 944 /*
953 945 * It might be more correct to return the
954 946 * error here, but that causes complaints
955 947 * when root extracts a cpio archive, etc.
956 948 * So ignore this error, and go ahead with
957 949 * the rest of the setattr work.
958 950 */
959 951 }
960 952 }
961 953
962 954 return (smbfssetattr(vp, vap, flags, cr));
963 955 }
964 956
965 957 /*
966 958 * Mostly from Darwin smbfs_setattr()
967 959 * but then modified a lot.
968 960 */
969 961 /* ARGSUSED */
970 962 static int
971 963 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
972 964 {
973 965 int error = 0;
974 966 smbnode_t *np = VTOSMB(vp);
975 967 uint_t mask = vap->va_mask;
976 968 struct timespec *mtime, *atime;
977 969 struct smb_cred scred;
978 970 int cerror, modified = 0;
979 971 unsigned short fid;
980 972 int have_fid = 0;
981 973 uint32_t rights = 0;
974 + uint32_t dosattr = 0;
982 975
983 976 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
984 977
985 978 /*
986 979 * There are no settable attributes on the XATTR dir,
987 980 * so just silently ignore these. On XATTR files,
988 981 * you can set the size but nothing else.
989 982 */
990 983 if (vp->v_flag & V_XATTRDIR)
991 984 return (0);
992 985 if (np->n_flag & N_XATTR) {
993 986 if (mask & AT_TIMES)
994 987 SMBVDEBUG("ignore set time on xattr\n");
995 988 mask &= AT_SIZE;
996 989 }
997 990
998 991 /*
999 992 * If our caller is trying to set multiple attributes, they
1000 993 * can make no assumption about what order they are done in.
1001 994 * Here we try to do them in order of decreasing likelihood
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
1002 995 * of failure, just to minimize the chance we'll wind up
1003 996 * with a partially complete request.
1004 997 */
1005 998
1006 999 /* Shared lock for (possible) n_fid use. */
1007 1000 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1008 1001 return (EINTR);
1009 1002 smb_credinit(&scred, cr);
1010 1003
1011 1004 /*
1005 + * If the caller has provided extensible attributes,
1006 + * map those into DOS attributes supported by SMB.
1007 + * Note: zero means "no change".
1008 + */
1009 + if (mask & AT_XVATTR)
1010 + dosattr = xvattr_to_dosattr(np, vap);
1011 +
1012 + /*
1012 1013 * Will we need an open handle for this setattr?
1013 1014 * If so, what rights will we need?
1014 1015 */
1015 - if (mask & (AT_ATIME | AT_MTIME)) {
1016 + if (dosattr || (mask & (AT_ATIME | AT_MTIME))) {
1016 1017 rights |=
1017 1018 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
1018 1019 }
1019 1020 if (mask & AT_SIZE) {
1020 1021 rights |=
1021 1022 SA_RIGHT_FILE_WRITE_DATA |
1022 1023 SA_RIGHT_FILE_APPEND_DATA;
1023 1024 }
1024 1025
1025 1026 /*
1026 1027 * Only SIZE really requires a handle, but it's
1027 1028 * simpler and more reliable to set via a handle.
1028 1029 * Some servers like NT4 won't set times by path.
1029 1030 * Also, we're usually setting everything anyway.
1030 1031 */
1031 - if (mask & (AT_SIZE | AT_ATIME | AT_MTIME)) {
1032 + if (rights != 0) {
1032 1033 error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
1033 1034 if (error) {
1034 1035 SMBVDEBUG("error %d opening %s\n",
1035 1036 error, np->n_rpath);
1036 1037 goto out;
1037 1038 }
1038 1039 have_fid = 1;
1039 1040 }
1040 1041
1041 1042 /*
1042 1043 * If the server supports the UNIX extensions, right here is where
1043 1044 * we'd support changes to uid, gid, mode, and possibly va_flags.
1044 1045 * For now we claim to have made any such changes.
1045 1046 */
1046 1047
1047 1048 if (mask & AT_SIZE) {
1048 1049 /*
1049 1050 * If the new file size is less than what the client sees as
1050 1051 * the file size, then just change the size and invalidate
1051 1052 * the pages.
1052 1053 * I am commenting this code at present because the function
1053 1054 * smbfs_putapage() is not yet implemented.
1054 1055 */
1055 1056
1056 1057 /*
1057 1058 * Set the file size to vap->va_size.
1058 1059 */
1059 1060 ASSERT(have_fid);
1060 1061 error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred);
1061 1062 if (error) {
1062 1063 SMBVDEBUG("setsize error %d file %s\n",
1063 1064 error, np->n_rpath);
1064 1065 } else {
1065 1066 /*
1066 1067 * Darwin had code here to zero-extend.
1067 1068 * Tests indicate the server will zero-fill,
1068 1069 * so looks like we don't need to do this.
1069 1070 * Good thing, as this could take forever.
1070 1071 *
1071 1072 * XXX: Reportedly, writing one byte of zero
1072 1073 * at the end offset avoids problems here.
1073 1074 */
1074 1075 mutex_enter(&np->r_statelock);
1075 1076 np->r_size = vap->va_size;
1076 1077 mutex_exit(&np->r_statelock);
1077 1078 modified = 1;
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
1078 1079 }
1079 1080 }
1080 1081
1081 1082 /*
1082 1083 * XXX: When Solaris has create_time, set that too.
1083 1084 * Note: create_time is different from ctime.
1084 1085 */
1085 1086 mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0);
1086 1087 atime = ((mask & AT_ATIME) ? &vap->va_atime : 0);
1087 1088
1088 - if (mtime || atime) {
1089 + if (dosattr || mtime || atime) {
1089 1090 /*
1090 1091 * Always use the handle-based set attr call now.
1091 1092 * Not trying to set DOS attributes here so pass zero.
1092 1093 */
1093 1094 ASSERT(have_fid);
1094 1095 error = smbfs_smb_setfattr(np, fid,
1095 - 0, mtime, atime, &scred);
1096 + dosattr, mtime, atime, &scred);
1096 1097 if (error) {
1097 1098 SMBVDEBUG("set times error %d file %s\n",
1098 1099 error, np->n_rpath);
1099 1100 } else {
1100 1101 modified = 1;
1101 1102 }
1102 1103 }
1103 1104
1104 1105 out:
1105 1106 if (modified) {
1106 1107 /*
1107 1108 * Invalidate attribute cache in case the server
1108 1109 * doesn't set exactly the attributes we asked.
1109 1110 */
1110 1111 smbfs_attrcache_remove(np);
1111 1112 }
1112 1113
1113 1114 if (have_fid) {
1114 1115 cerror = smbfs_smb_tmpclose(np, fid, &scred);
1115 1116 if (cerror)
1116 1117 SMBVDEBUG("error %d closing %s\n",
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
1117 1118 cerror, np->n_rpath);
1118 1119 }
1119 1120
1120 1121 smb_credrele(&scred);
1121 1122 smbfs_rw_exit(&np->r_lkserlock);
1122 1123
1123 1124 return (error);
1124 1125 }
1125 1126
1126 1127 /*
1128 + * Helper function for extensible system attributes (PSARC 2007/315)
1129 + * Compute the DOS attribute word to pass to _setfattr (see above).
1130 + * This returns zero IFF no change is being made to attributes.
1131 + * Otherwise return the new attributes or SMB_EFA_NORMAL.
1132 + */
1133 +static uint32_t
1134 +xvattr_to_dosattr(smbnode_t *np, struct vattr *vap)
1135 +{
1136 + xvattr_t *xvap = (xvattr_t *)vap;
1137 + xoptattr_t *xoap = NULL;
1138 + uint32_t attr = np->r_attr.fa_attr;
1139 + boolean_t anyset = B_FALSE;
1140 +
1141 + if ((xoap = xva_getxoptattr(xvap)) == NULL)
1142 + return (0);
1143 +
1144 + if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
1145 + if (xoap->xoa_archive)
1146 + attr |= SMB_FA_ARCHIVE;
1147 + else
1148 + attr &= ~SMB_FA_ARCHIVE;
1149 + XVA_SET_RTN(xvap, XAT_ARCHIVE);
1150 + anyset = B_TRUE;
1151 + }
1152 + if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
1153 + if (xoap->xoa_system)
1154 + attr |= SMB_FA_SYSTEM;
1155 + else
1156 + attr &= ~SMB_FA_SYSTEM;
1157 + XVA_SET_RTN(xvap, XAT_SYSTEM);
1158 + anyset = B_TRUE;
1159 + }
1160 + if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
1161 + if (xoap->xoa_readonly)
1162 + attr |= SMB_FA_RDONLY;
1163 + else
1164 + attr &= ~SMB_FA_RDONLY;
1165 + XVA_SET_RTN(xvap, XAT_READONLY);
1166 + anyset = B_TRUE;
1167 + }
1168 + if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
1169 + if (xoap->xoa_hidden)
1170 + attr |= SMB_FA_HIDDEN;
1171 + else
1172 + attr &= ~SMB_FA_HIDDEN;
1173 + XVA_SET_RTN(xvap, XAT_HIDDEN);
1174 + anyset = B_TRUE;
1175 + }
1176 +
1177 + if (anyset == B_FALSE)
1178 + return (0); /* no change */
1179 + if (attr == 0)
1180 + attr = SMB_EFA_NORMAL;
1181 +
1182 + return (attr);
1183 +}
1184 +
1185 +/*
1127 1186 * smbfs_access_rwx()
1128 1187 * Common function for smbfs_access, etc.
1129 1188 *
1130 1189 * The security model implemented by the FS is unusual
1131 1190 * due to the current "single user mounts" restriction:
1132 1191 * All access under a given mount point uses the CIFS
1133 1192 * credentials established by the owner of the mount.
1134 1193 *
1135 1194 * Most access checking is handled by the CIFS server,
1136 1195 * but we need sufficient Unix access checks here to
1137 1196 * prevent other local Unix users from having access
1138 1197 * to objects under this mount that the uid/gid/mode
1139 1198 * settings in the mount would not allow.
1140 1199 *
1141 1200 * With this model, there is a case where we need the
1142 1201 * ability to do an access check before we have the
1143 1202 * vnode for an object. This function takes advantage
1144 1203 * of the fact that the uid/gid/mode is per mount, and
1145 1204 * avoids the need for a vnode.
1146 1205 *
1147 1206 * We still (sort of) need a vnode when we call
1148 1207 * secpolicy_vnode_access, but that only uses
1149 1208 * the vtype field, so we can use a pair of fake
1150 1209 * vnodes that have only v_type filled in.
1151 1210 *
1152 1211 * XXX: Later, add a new secpolicy_vtype_access()
1153 1212 * that takes the vtype instead of a vnode, and
1154 1213 * get rid of the tmpl_vxxx fake vnodes below.
1155 1214 */
1156 1215 static int
1157 1216 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
1158 1217 {
1159 1218 /* See the secpolicy call below. */
1160 1219 static const vnode_t tmpl_vdir = { .v_type = VDIR };
1161 1220 static const vnode_t tmpl_vreg = { .v_type = VREG };
1162 1221 vattr_t va;
1163 1222 vnode_t *tvp;
1164 1223 struct smbmntinfo *smi = VFTOSMI(vfsp);
1165 1224 int shift = 0;
1166 1225
1167 1226 /*
1168 1227 * Build our (fabricated) vnode attributes.
1169 1228 * XXX: Could make these templates in the
1170 1229 * per-mount struct and use them here.
1171 1230 */
1172 1231 bzero(&va, sizeof (va));
1173 1232 va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1174 1233 va.va_type = vtype;
1175 1234 va.va_mode = (vtype == VDIR) ?
1176 1235 smi->smi_dmode : smi->smi_fmode;
1177 1236 va.va_uid = smi->smi_uid;
1178 1237 va.va_gid = smi->smi_gid;
1179 1238
1180 1239 /*
1181 1240 * Disallow write attempts on read-only file systems,
1182 1241 * unless the file is a device or fifo node. Note:
1183 1242 * Inline vn_is_readonly and IS_DEVVP here because
1184 1243 * we may not have a vnode ptr. Original expr. was:
1185 1244 * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp))
1186 1245 */
1187 1246 if ((mode & VWRITE) &&
1188 1247 (vfsp->vfs_flag & VFS_RDONLY) &&
1189 1248 !(vtype == VCHR || vtype == VBLK || vtype == VFIFO))
1190 1249 return (EROFS);
1191 1250
1192 1251 /*
1193 1252 * Disallow attempts to access mandatory lock files.
1194 1253 * Similarly, expand MANDLOCK here.
1195 1254 * XXX: not sure we need this.
1196 1255 */
1197 1256 if ((mode & (VWRITE | VREAD | VEXEC)) &&
1198 1257 va.va_type == VREG && MANDMODE(va.va_mode))
1199 1258 return (EACCES);
1200 1259
1201 1260 /*
1202 1261 * Access check is based on only
1203 1262 * one of owner, group, public.
1204 1263 * If not owner, then check group.
1205 1264 * If not a member of the group,
1206 1265 * then check public access.
1207 1266 */
1208 1267 if (crgetuid(cr) != va.va_uid) {
1209 1268 shift += 3;
1210 1269 if (!groupmember(va.va_gid, cr))
1211 1270 shift += 3;
1212 1271 }
1213 1272
1214 1273 /*
1215 1274 * We need a vnode for secpolicy_vnode_access,
1216 1275 * but the only thing it looks at is v_type,
1217 1276 * so pass one of the templates above.
1218 1277 */
1219 1278 tvp = (va.va_type == VDIR) ?
1220 1279 (vnode_t *)&tmpl_vdir :
1221 1280 (vnode_t *)&tmpl_vreg;
1222 1281
1223 1282 return (secpolicy_vnode_access2(cr, tvp, va.va_uid,
1224 1283 va.va_mode << shift, mode));
1225 1284 }
1226 1285
1227 1286 /*
1228 1287 * See smbfs_setattr
1229 1288 */
1230 1289 static int
1231 1290 smbfs_accessx(void *arg, int mode, cred_t *cr)
1232 1291 {
1233 1292 vnode_t *vp = arg;
1234 1293 /*
1235 1294 * Note: The caller has checked the current zone,
1236 1295 * the SMI_DEAD and VFS_UNMOUNTED flags, etc.
1237 1296 */
1238 1297 return (smbfs_access_rwx(vp->v_vfsp, vp->v_type, mode, cr));
1239 1298 }
1240 1299
1241 1300 /*
1242 1301 * XXX
1243 1302 * This op should support PSARC 2007/403, Modified Access Checks for CIFS
1244 1303 */
1245 1304 /* ARGSUSED */
1246 1305 static int
1247 1306 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
1248 1307 {
1249 1308 vfs_t *vfsp;
1250 1309 smbmntinfo_t *smi;
1251 1310
1252 1311 vfsp = vp->v_vfsp;
1253 1312 smi = VFTOSMI(vfsp);
1254 1313
1255 1314 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1256 1315 return (EIO);
1257 1316
1258 1317 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1259 1318 return (EIO);
1260 1319
1261 1320 return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr));
1262 1321 }
1263 1322
1264 1323
1265 1324 /*
1266 1325 * Flush local dirty pages to stable storage on the server.
1267 1326 *
1268 1327 * If FNODSYNC is specified, then there is nothing to do because
1269 1328 * metadata changes are not cached on the client before being
1270 1329 * sent to the server.
1271 1330 */
1272 1331 /* ARGSUSED */
1273 1332 static int
1274 1333 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
1275 1334 {
1276 1335 int error = 0;
1277 1336 smbmntinfo_t *smi;
1278 1337 smbnode_t *np;
1279 1338 struct smb_cred scred;
1280 1339
1281 1340 np = VTOSMB(vp);
1282 1341 smi = VTOSMI(vp);
1283 1342
1284 1343 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1285 1344 return (EIO);
1286 1345
1287 1346 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1288 1347 return (EIO);
1289 1348
1290 1349 if ((syncflag & FNODSYNC) || IS_SWAPVP(vp))
1291 1350 return (0);
1292 1351
1293 1352 if ((syncflag & (FSYNC|FDSYNC)) == 0)
1294 1353 return (0);
1295 1354
1296 1355 /* Shared lock for n_fid use in _flush */
1297 1356 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1298 1357 return (EINTR);
1299 1358 smb_credinit(&scred, cr);
1300 1359
1301 1360 error = smbfs_smb_flush(np, &scred);
1302 1361
1303 1362 smb_credrele(&scred);
1304 1363 smbfs_rw_exit(&np->r_lkserlock);
1305 1364
1306 1365 return (error);
1307 1366 }
1308 1367
1309 1368 /*
1310 1369 * Last reference to vnode went away.
1311 1370 */
1312 1371 /* ARGSUSED */
1313 1372 static void
1314 1373 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
1315 1374 {
1316 1375 smbnode_t *np;
1317 1376 struct smb_cred scred;
1318 1377
1319 1378 /*
1320 1379 * Don't "bail out" for VFS_UNMOUNTED here,
1321 1380 * as we want to do cleanup, etc.
1322 1381 * See also pcfs_inactive
1323 1382 */
1324 1383
1325 1384 np = VTOSMB(vp);
1326 1385
1327 1386 /*
1328 1387 * If this is coming from the wrong zone, we let someone in the right
1329 1388 * zone take care of it asynchronously. We can get here due to
1330 1389 * VN_RELE() being called from pageout() or fsflush(). This call may
1331 1390 * potentially turn into an expensive no-op if, for instance, v_count
1332 1391 * gets incremented in the meantime, but it's still correct.
1333 1392 */
1334 1393
1335 1394 /*
1336 1395 * Defend against the possibility that higher-level callers
1337 1396 * might not correctly balance open and close calls. If we
1338 1397 * get here with open references remaining, it means there
1339 1398 * was a missing VOP_CLOSE somewhere. If that happens, do
1340 1399 * the close here so we don't "leak" FIDs on the server.
1341 1400 *
1342 1401 * Exclusive lock for modifying n_fid stuff.
1343 1402 * Don't want this one ever interruptible.
1344 1403 */
1345 1404 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
1346 1405 smb_credinit(&scred, cr);
1347 1406
1348 1407 switch (np->n_ovtype) {
1349 1408 case VNON:
1350 1409 /* not open (OK) */
1351 1410 break;
1352 1411
1353 1412 case VDIR:
1354 1413 if (np->n_dirrefs == 0)
1355 1414 break;
1356 1415 SMBVDEBUG("open dir: refs %d path %s\n",
1357 1416 np->n_dirrefs, np->n_rpath);
1358 1417 /* Force last close. */
1359 1418 np->n_dirrefs = 1;
1360 1419 smbfs_rele_fid(np, &scred);
1361 1420 break;
1362 1421
1363 1422 case VREG:
1364 1423 if (np->n_fidrefs == 0)
1365 1424 break;
1366 1425 SMBVDEBUG("open file: refs %d id 0x%x path %s\n",
1367 1426 np->n_fidrefs, np->n_fid, np->n_rpath);
1368 1427 /* Force last close. */
1369 1428 np->n_fidrefs = 1;
1370 1429 smbfs_rele_fid(np, &scred);
1371 1430 break;
1372 1431
1373 1432 default:
1374 1433 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
1375 1434 np->n_ovtype = VNON;
1376 1435 break;
1377 1436 }
1378 1437
1379 1438 smb_credrele(&scred);
1380 1439 smbfs_rw_exit(&np->r_lkserlock);
1381 1440
1382 1441 smbfs_addfree(np);
1383 1442 }
1384 1443
1385 1444 /*
1386 1445 * Remote file system operations having to do with directory manipulation.
1387 1446 */
1388 1447 /* ARGSUSED */
1389 1448 static int
1390 1449 smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
1391 1450 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
1392 1451 int *direntflags, pathname_t *realpnp)
1393 1452 {
1394 1453 vfs_t *vfs;
1395 1454 smbmntinfo_t *smi;
1396 1455 smbnode_t *dnp;
1397 1456 int error;
1398 1457
1399 1458 vfs = dvp->v_vfsp;
1400 1459 smi = VFTOSMI(vfs);
1401 1460
1402 1461 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1403 1462 return (EPERM);
1404 1463
1405 1464 if (smi->smi_flags & SMI_DEAD || vfs->vfs_flag & VFS_UNMOUNTED)
1406 1465 return (EIO);
1407 1466
1408 1467 dnp = VTOSMB(dvp);
1409 1468
1410 1469 /*
1411 1470 * Are we looking up extended attributes? If so, "dvp" is
1412 1471 * the file or directory for which we want attributes, and
1413 1472 * we need a lookup of the (faked up) attribute directory
1414 1473 * before we lookup the rest of the path.
1415 1474 */
1416 1475 if (flags & LOOKUP_XATTR) {
1417 1476 /*
1418 1477 * Require the xattr mount option.
1419 1478 */
1420 1479 if ((vfs->vfs_flag & VFS_XATTR) == 0)
1421 1480 return (EINVAL);
1422 1481
1423 1482 error = smbfs_get_xattrdir(dvp, vpp, cr, flags);
1424 1483 return (error);
1425 1484 }
1426 1485
1427 1486 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp)))
1428 1487 return (EINTR);
1429 1488
1430 1489 error = smbfslookup(dvp, nm, vpp, cr, 1, ct);
1431 1490
1432 1491 smbfs_rw_exit(&dnp->r_rwlock);
1433 1492
1434 1493 return (error);
1435 1494 }
1436 1495
1437 1496 /* ARGSUSED */
1438 1497 static int
1439 1498 smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
1440 1499 int cache_ok, caller_context_t *ct)
1441 1500 {
1442 1501 int error;
1443 1502 int supplen; /* supported length */
1444 1503 vnode_t *vp;
1445 1504 smbnode_t *np;
1446 1505 smbnode_t *dnp;
1447 1506 smbmntinfo_t *smi;
1448 1507 /* struct smb_vc *vcp; */
1449 1508 const char *ill;
1450 1509 const char *name = (const char *)nm;
1451 1510 int nmlen = strlen(nm);
1452 1511 int rplen;
1453 1512 struct smb_cred scred;
1454 1513 struct smbfattr fa;
1455 1514
1456 1515 smi = VTOSMI(dvp);
1457 1516 dnp = VTOSMB(dvp);
1458 1517
1459 1518 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
1460 1519
1461 1520 #ifdef NOT_YET
1462 1521 vcp = SSTOVC(smi->smi_share);
1463 1522
1464 1523 /* XXX: Should compute this once and store it in smbmntinfo_t */
1465 1524 supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12;
1466 1525 #else
1467 1526 supplen = 255;
1468 1527 #endif
1469 1528
1470 1529 /*
1471 1530 * RWlock must be held, either reader or writer.
1472 1531 * XXX: Can we check without looking directly
1473 1532 * inside the struct smbfs_rwlock_t?
1474 1533 */
1475 1534 ASSERT(dnp->r_rwlock.count != 0);
1476 1535
1477 1536 /*
1478 1537 * If lookup is for "", just return dvp.
1479 1538 * No need to perform any access checks.
1480 1539 */
1481 1540 if (nmlen == 0) {
1482 1541 VN_HOLD(dvp);
1483 1542 *vpp = dvp;
1484 1543 return (0);
1485 1544 }
1486 1545
1487 1546 /*
1488 1547 * Can't do lookups in non-directories.
1489 1548 */
1490 1549 if (dvp->v_type != VDIR)
1491 1550 return (ENOTDIR);
1492 1551
1493 1552 /*
1494 1553 * Need search permission in the directory.
1495 1554 */
1496 1555 error = smbfs_access(dvp, VEXEC, 0, cr, ct);
1497 1556 if (error)
1498 1557 return (error);
1499 1558
1500 1559 /*
1501 1560 * If lookup is for ".", just return dvp.
1502 1561 * Access check was done above.
1503 1562 */
1504 1563 if (nmlen == 1 && name[0] == '.') {
1505 1564 VN_HOLD(dvp);
1506 1565 *vpp = dvp;
1507 1566 return (0);
1508 1567 }
1509 1568
1510 1569 /*
1511 1570 * Now some sanity checks on the name.
1512 1571 * First check the length.
1513 1572 */
1514 1573 if (nmlen > supplen)
1515 1574 return (ENAMETOOLONG);
1516 1575
1517 1576 /*
1518 1577 * Avoid surprises with characters that are
1519 1578 * illegal in Windows file names.
1520 1579 * Todo: CATIA mappings XXX
1521 1580 */
1522 1581 ill = illegal_chars;
1523 1582 if (dnp->n_flag & N_XATTR)
1524 1583 ill++; /* allow colon */
1525 1584 if (strpbrk(nm, ill))
1526 1585 return (EINVAL);
1527 1586
1528 1587 /*
1529 1588 * Special handling for lookup of ".."
1530 1589 *
1531 1590 * We keep full pathnames (as seen on the server)
1532 1591 * so we can just trim off the last component to
1533 1592 * get the full pathname of the parent. Note:
1534 1593 * We don't actually copy and modify, but just
1535 1594 * compute the trimmed length and pass that with
1536 1595 * the current dir path (not null terminated).
1537 1596 *
1538 1597 * We don't go over-the-wire to get attributes
1539 1598 * for ".." because we know it's a directory,
1540 1599 * and we can just leave the rest "stale"
1541 1600 * until someone does a getattr.
1542 1601 */
1543 1602 if (nmlen == 2 && name[0] == '.' && name[1] == '.') {
1544 1603 if (dvp->v_flag & VROOT) {
1545 1604 /*
1546 1605 * Already at the root. This can happen
1547 1606 * with directory listings at the root,
1548 1607 * which lookup "." and ".." to get the
1549 1608 * inode numbers. Let ".." be the same
1550 1609 * as "." in the FS root.
1551 1610 */
1552 1611 VN_HOLD(dvp);
1553 1612 *vpp = dvp;
1554 1613 return (0);
1555 1614 }
1556 1615
1557 1616 /*
1558 1617 * Special case for XATTR directory
1559 1618 */
1560 1619 if (dvp->v_flag & V_XATTRDIR) {
1561 1620 error = smbfs_xa_parent(dvp, vpp);
1562 1621 return (error);
1563 1622 }
1564 1623
1565 1624 /*
1566 1625 * Find the parent path length.
1567 1626 */
1568 1627 rplen = dnp->n_rplen;
1569 1628 ASSERT(rplen > 0);
1570 1629 while (--rplen >= 0) {
1571 1630 if (dnp->n_rpath[rplen] == '\\')
1572 1631 break;
1573 1632 }
1574 1633 if (rplen <= 0) {
1575 1634 /* Found our way to the root. */
1576 1635 vp = SMBTOV(smi->smi_root);
1577 1636 VN_HOLD(vp);
1578 1637 *vpp = vp;
1579 1638 return (0);
1580 1639 }
1581 1640 np = smbfs_node_findcreate(smi,
1582 1641 dnp->n_rpath, rplen, NULL, 0, 0,
1583 1642 &smbfs_fattr0); /* force create */
1584 1643 ASSERT(np != NULL);
1585 1644 vp = SMBTOV(np);
1586 1645 vp->v_type = VDIR;
1587 1646
1588 1647 /* Success! */
1589 1648 *vpp = vp;
1590 1649 return (0);
1591 1650 }
1592 1651
1593 1652 /*
1594 1653 * Normal lookup of a name under this directory.
1595 1654 * Note we handled "", ".", ".." above.
1596 1655 */
1597 1656 if (cache_ok) {
1598 1657 /*
1599 1658 * The caller indicated that it's OK to use a
1600 1659 * cached result for this lookup, so try to
1601 1660 * reclaim a node from the smbfs node cache.
1602 1661 */
1603 1662 error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr);
1604 1663 if (error)
1605 1664 return (error);
1606 1665 if (vp != NULL) {
1607 1666 /* hold taken in lookup_cache */
1608 1667 *vpp = vp;
1609 1668 return (0);
1610 1669 }
1611 1670 }
1612 1671
1613 1672 /*
1614 1673 * OK, go over-the-wire to get the attributes,
1615 1674 * then create the node.
1616 1675 */
1617 1676 smb_credinit(&scred, cr);
1618 1677 /* Note: this can allocate a new "name" */
1619 1678 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred);
1620 1679 smb_credrele(&scred);
1621 1680 if (error == ENOTDIR) {
1622 1681 /*
1623 1682 * Lookup failed because this directory was
1624 1683 * removed or renamed by another client.
1625 1684 * Remove any cached attributes under it.
1626 1685 */
1627 1686 smbfs_attrcache_remove(dnp);
1628 1687 smbfs_attrcache_prune(dnp);
1629 1688 }
1630 1689 if (error)
1631 1690 goto out;
1632 1691
1633 1692 error = smbfs_nget(dvp, name, nmlen, &fa, &vp);
1634 1693 if (error)
1635 1694 goto out;
1636 1695
1637 1696 /* Success! */
1638 1697 *vpp = vp;
1639 1698
1640 1699 out:
1641 1700 /* smbfs_smb_lookup may have allocated name. */
1642 1701 if (name != nm)
1643 1702 smbfs_name_free(name, nmlen);
1644 1703
1645 1704 return (error);
1646 1705 }
1647 1706
1648 1707 /*
1649 1708 * smbfslookup_cache
1650 1709 *
1651 1710 * Try to reclaim a node from the smbfs node cache.
1652 1711 * Some statistics for DEBUG.
1653 1712 *
1654 1713 * This mechanism lets us avoid many of the five (or more)
1655 1714 * OtW lookup calls per file seen with "ls -l" if we search
1656 1715 * the smbfs node cache for recently inactive(ated) nodes.
1657 1716 */
1658 1717 #ifdef DEBUG
1659 1718 int smbfs_lookup_cache_calls = 0;
1660 1719 int smbfs_lookup_cache_error = 0;
1661 1720 int smbfs_lookup_cache_miss = 0;
1662 1721 int smbfs_lookup_cache_stale = 0;
1663 1722 int smbfs_lookup_cache_hits = 0;
1664 1723 #endif /* DEBUG */
1665 1724
1666 1725 /* ARGSUSED */
1667 1726 static int
1668 1727 smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen,
1669 1728 vnode_t **vpp, cred_t *cr)
1670 1729 {
1671 1730 struct vattr va;
1672 1731 smbnode_t *dnp;
1673 1732 smbnode_t *np;
1674 1733 vnode_t *vp;
1675 1734 int error;
1676 1735 char sep;
1677 1736
1678 1737 dnp = VTOSMB(dvp);
1679 1738 *vpp = NULL;
1680 1739
1681 1740 #ifdef DEBUG
1682 1741 smbfs_lookup_cache_calls++;
1683 1742 #endif
1684 1743
1685 1744 /*
1686 1745 * First make sure we can get attributes for the
1687 1746 * directory. Cached attributes are OK here.
1688 1747 * If we removed or renamed the directory, this
1689 1748 * will return ENOENT. If someone else removed
1690 1749 * this directory or file, we'll find out when we
1691 1750 * try to open or get attributes.
1692 1751 */
1693 1752 va.va_mask = AT_TYPE | AT_MODE;
1694 1753 error = smbfsgetattr(dvp, &va, cr);
1695 1754 if (error) {
1696 1755 #ifdef DEBUG
1697 1756 smbfs_lookup_cache_error++;
1698 1757 #endif
1699 1758 return (error);
1700 1759 }
1701 1760
1702 1761 /*
1703 1762 * Passing NULL smbfattr here so we will
1704 1763 * just look, not create.
1705 1764 */
1706 1765 sep = SMBFS_DNP_SEP(dnp);
1707 1766 np = smbfs_node_findcreate(dnp->n_mount,
1708 1767 dnp->n_rpath, dnp->n_rplen,
1709 1768 nm, nmlen, sep, NULL);
1710 1769 if (np == NULL) {
1711 1770 #ifdef DEBUG
1712 1771 smbfs_lookup_cache_miss++;
1713 1772 #endif
1714 1773 return (0);
1715 1774 }
1716 1775
1717 1776 /*
1718 1777 * Found it. Attributes still valid?
1719 1778 */
1720 1779 vp = SMBTOV(np);
1721 1780 if (np->r_attrtime <= gethrtime()) {
1722 1781 /* stale */
1723 1782 #ifdef DEBUG
1724 1783 smbfs_lookup_cache_stale++;
1725 1784 #endif
1726 1785 VN_RELE(vp);
1727 1786 return (0);
1728 1787 }
1729 1788
1730 1789 /*
1731 1790 * Success!
1732 1791 * Caller gets hold from smbfs_node_findcreate
1733 1792 */
1734 1793 #ifdef DEBUG
1735 1794 smbfs_lookup_cache_hits++;
1736 1795 #endif
1737 1796 *vpp = vp;
1738 1797 return (0);
1739 1798 }
1740 1799
1741 1800 /*
1742 1801 * XXX
1743 1802 * vsecattr_t is new to build 77, and we need to eventually support
1744 1803 * it in order to create an ACL when an object is created.
1745 1804 *
1746 1805 * This op should support the new FIGNORECASE flag for case-insensitive
1747 1806 * lookups, per PSARC 2007/244.
1748 1807 */
1749 1808 /* ARGSUSED */
1750 1809 static int
1751 1810 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
1752 1811 int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct,
1753 1812 vsecattr_t *vsecp)
1754 1813 {
1755 1814 int error;
1756 1815 int cerror;
1757 1816 vfs_t *vfsp;
1758 1817 vnode_t *vp;
1759 1818 #ifdef NOT_YET
1760 1819 smbnode_t *np;
1761 1820 #endif
1762 1821 smbnode_t *dnp;
1763 1822 smbmntinfo_t *smi;
1764 1823 struct vattr vattr;
1765 1824 struct smbfattr fattr;
1766 1825 struct smb_cred scred;
1767 1826 const char *name = (const char *)nm;
1768 1827 int nmlen = strlen(nm);
1769 1828 uint32_t disp;
1770 1829 uint16_t fid;
1771 1830 int xattr;
1772 1831
1773 1832 vfsp = dvp->v_vfsp;
1774 1833 smi = VFTOSMI(vfsp);
1775 1834 dnp = VTOSMB(dvp);
1776 1835 vp = NULL;
1777 1836
1778 1837 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1779 1838 return (EPERM);
1780 1839
1781 1840 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1782 1841 return (EIO);
1783 1842
1784 1843 /*
1785 1844 * Note: this may break mknod(2) calls to create a directory,
1786 1845 * but that's obscure use. Some other filesystems do this.
1787 1846 * XXX: Later, redirect VDIR type here to _mkdir.
1788 1847 */
1789 1848 if (va->va_type != VREG)
1790 1849 return (EINVAL);
1791 1850
1792 1851 /*
1793 1852 * If the pathname is "", just use dvp, no checks.
1794 1853 * Do this outside of the rwlock (like zfs).
1795 1854 */
1796 1855 if (nmlen == 0) {
1797 1856 VN_HOLD(dvp);
1798 1857 *vpp = dvp;
1799 1858 return (0);
1800 1859 }
1801 1860
1802 1861 /* Don't allow "." or ".." through here. */
1803 1862 if ((nmlen == 1 && name[0] == '.') ||
1804 1863 (nmlen == 2 && name[0] == '.' && name[1] == '.'))
1805 1864 return (EISDIR);
1806 1865
1807 1866 /*
1808 1867 * We make a copy of the attributes because the caller does not
1809 1868 * expect us to change what va points to.
1810 1869 */
1811 1870 vattr = *va;
1812 1871
1813 1872 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
1814 1873 return (EINTR);
1815 1874 smb_credinit(&scred, cr);
1816 1875
1817 1876 /*
1818 1877 * XXX: Do we need r_lkserlock too?
1819 1878 * No use of any shared fid or fctx...
1820 1879 */
1821 1880
1822 1881 /*
1823 1882 * NFS needs to go over the wire, just to be sure whether the
1824 1883 * file exists or not. Using a cached result is dangerous in
1825 1884 * this case when making a decision regarding existence.
1826 1885 *
1827 1886 * The SMB protocol does NOT really need to go OTW here
1828 1887 * thanks to the expressive NTCREATE disposition values.
1829 1888 * Unfortunately, to do Unix access checks correctly,
1830 1889 * we need to know if the object already exists.
1831 1890 * When the object does not exist, we need VWRITE on
1832 1891 * the directory. Note: smbfslookup() checks VEXEC.
1833 1892 */
1834 1893 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
1835 1894 if (error == 0) {
1836 1895 /*
1837 1896 * The file already exists. Error?
1838 1897 * NB: have a hold from smbfslookup
1839 1898 */
1840 1899 if (exclusive == EXCL) {
1841 1900 error = EEXIST;
1842 1901 VN_RELE(vp);
1843 1902 goto out;
1844 1903 }
1845 1904 /*
1846 1905 * Verify requested access.
1847 1906 */
1848 1907 error = smbfs_access(vp, mode, 0, cr, ct);
1849 1908 if (error) {
1850 1909 VN_RELE(vp);
1851 1910 goto out;
1852 1911 }
1853 1912
1854 1913 /*
1855 1914 * Truncate (if requested).
1856 1915 */
1857 1916 if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) {
1858 1917 vattr.va_mask = AT_SIZE;
1859 1918 error = smbfssetattr(vp, &vattr, 0, cr);
1860 1919 if (error) {
1861 1920 VN_RELE(vp);
1862 1921 goto out;
1863 1922 }
1864 1923 }
1865 1924 /* Success! */
1866 1925 #ifdef NOT_YET
1867 1926 vnevent_create(vp, ct);
1868 1927 #endif
1869 1928 *vpp = vp;
1870 1929 goto out;
1871 1930 }
1872 1931
1873 1932 /*
1874 1933 * The file did not exist. Need VWRITE in the directory.
1875 1934 */
1876 1935 error = smbfs_access(dvp, VWRITE, 0, cr, ct);
1877 1936 if (error)
1878 1937 goto out;
1879 1938
1880 1939 /*
1881 1940 * Now things get tricky. We also need to check the
1882 1941 * requested open mode against the file we may create.
1883 1942 * See comments at smbfs_access_rwx
1884 1943 */
1885 1944 error = smbfs_access_rwx(vfsp, VREG, mode, cr);
1886 1945 if (error)
1887 1946 goto out;
1888 1947
1889 1948 /*
1890 1949 * Now the code derived from Darwin,
1891 1950 * but with greater use of NT_CREATE
1892 1951 * disposition options. Much changed.
1893 1952 *
1894 1953 * Create (or open) a new child node.
1895 1954 * Note we handled "." and ".." above.
1896 1955 */
1897 1956
1898 1957 if (exclusive == EXCL)
1899 1958 disp = NTCREATEX_DISP_CREATE;
1900 1959 else {
1901 1960 /* Truncate regular files if requested. */
1902 1961 if ((va->va_type == VREG) &&
1903 1962 (va->va_mask & AT_SIZE) &&
1904 1963 (va->va_size == 0))
1905 1964 disp = NTCREATEX_DISP_OVERWRITE_IF;
1906 1965 else
1907 1966 disp = NTCREATEX_DISP_OPEN_IF;
1908 1967 }
1909 1968 xattr = (dnp->n_flag & N_XATTR) ? 1 : 0;
1910 1969 error = smbfs_smb_create(dnp,
1911 1970 name, nmlen, xattr,
1912 1971 disp, &scred, &fid);
1913 1972 if (error)
1914 1973 goto out;
1915 1974
1916 1975 /*
1917 1976 * XXX: Missing some code here to deal with
1918 1977 * the case where we opened an existing file,
1919 1978 * it's size is larger than 32-bits, and we're
1920 1979 * setting the size from a process that's not
1921 1980 * aware of large file offsets. i.e.
1922 1981 * from the NFS3 code:
1923 1982 */
1924 1983 #if NOT_YET /* XXX */
1925 1984 if ((vattr.va_mask & AT_SIZE) &&
1926 1985 vp->v_type == VREG) {
1927 1986 np = VTOSMB(vp);
1928 1987 /*
1929 1988 * Check here for large file handled
1930 1989 * by LF-unaware process (as
1931 1990 * ufs_create() does)
1932 1991 */
1933 1992 if (!(lfaware & FOFFMAX)) {
1934 1993 mutex_enter(&np->r_statelock);
1935 1994 if (np->r_size > MAXOFF32_T)
1936 1995 error = EOVERFLOW;
1937 1996 mutex_exit(&np->r_statelock);
1938 1997 }
1939 1998 if (!error) {
1940 1999 vattr.va_mask = AT_SIZE;
1941 2000 error = smbfssetattr(vp,
1942 2001 &vattr, 0, cr);
1943 2002 }
1944 2003 }
1945 2004 #endif /* XXX */
1946 2005 /*
1947 2006 * Should use the fid to get/set the size
1948 2007 * while we have it opened here. See above.
1949 2008 */
1950 2009
1951 2010 cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred);
1952 2011 if (cerror)
1953 2012 SMBVDEBUG("error %d closing %s\\%s\n",
1954 2013 cerror, dnp->n_rpath, name);
1955 2014
1956 2015 /*
1957 2016 * In the open case, the name may differ a little
1958 2017 * from what we passed to create (case, etc.)
1959 2018 * so call lookup to get the (opened) name.
1960 2019 *
1961 2020 * XXX: Could avoid this extra lookup if the
1962 2021 * "createact" result from NT_CREATE says we
1963 2022 * created the object.
1964 2023 */
1965 2024 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
1966 2025 if (error)
1967 2026 goto out;
1968 2027
1969 2028 /* update attr and directory cache */
1970 2029 smbfs_attr_touchdir(dnp);
1971 2030
1972 2031 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
1973 2032 if (error)
1974 2033 goto out;
1975 2034
1976 2035 /* XXX invalidate pages if we truncated? */
1977 2036
1978 2037 /* Success! */
1979 2038 *vpp = vp;
1980 2039 error = 0;
1981 2040
1982 2041 out:
1983 2042 smb_credrele(&scred);
1984 2043 smbfs_rw_exit(&dnp->r_rwlock);
1985 2044 if (name != nm)
1986 2045 smbfs_name_free(name, nmlen);
1987 2046 return (error);
1988 2047 }
1989 2048
1990 2049 /*
1991 2050 * XXX
1992 2051 * This op should support the new FIGNORECASE flag for case-insensitive
1993 2052 * lookups, per PSARC 2007/244.
1994 2053 */
1995 2054 /* ARGSUSED */
1996 2055 static int
1997 2056 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
1998 2057 int flags)
1999 2058 {
2000 2059 int error;
2001 2060 vnode_t *vp;
2002 2061 smbnode_t *np;
2003 2062 smbnode_t *dnp;
2004 2063 struct smb_cred scred;
2005 2064 /* enum smbfsstat status; */
2006 2065 smbmntinfo_t *smi;
2007 2066
2008 2067 smi = VTOSMI(dvp);
2009 2068
2010 2069 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2011 2070 return (EPERM);
2012 2071
2013 2072 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2014 2073 return (EIO);
2015 2074
2016 2075 dnp = VTOSMB(dvp);
2017 2076 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2018 2077 return (EINTR);
2019 2078 smb_credinit(&scred, cr);
2020 2079
2021 2080 /*
2022 2081 * Verify access to the dirctory.
2023 2082 */
2024 2083 error = smbfs_access(dvp, VWRITE|VEXEC, 0, cr, ct);
2025 2084 if (error)
2026 2085 goto out;
2027 2086
2028 2087 /*
2029 2088 * NOTE: the darwin code gets the "vp" passed in so it looks
2030 2089 * like the "vp" has probably been "lookup"ed by the VFS layer.
2031 2090 * It looks like we will need to lookup the vp to check the
2032 2091 * caches and check if the object being deleted is a directory.
2033 2092 */
2034 2093 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2035 2094 if (error)
2036 2095 goto out;
2037 2096
2038 2097 /* Never allow link/unlink directories on CIFS. */
2039 2098 if (vp->v_type == VDIR) {
2040 2099 VN_RELE(vp);
2041 2100 error = EPERM;
2042 2101 goto out;
2043 2102 }
2044 2103
2045 2104 /*
2046 2105 * Now we have the real reference count on the vnode
2047 2106 * Do we have the file open?
2048 2107 */
2049 2108 np = VTOSMB(vp);
2050 2109 mutex_enter(&np->r_statelock);
2051 2110 if ((vp->v_count > 1) && (np->n_fidrefs > 0)) {
2052 2111 /*
2053 2112 * NFS does a rename on remove here.
2054 2113 * Probably not applicable for SMB.
2055 2114 * Like Darwin, just return EBUSY.
2056 2115 *
2057 2116 * XXX: Todo - Use Trans2rename, and
2058 2117 * if that fails, ask the server to
2059 2118 * set the delete-on-close flag.
2060 2119 */
2061 2120 mutex_exit(&np->r_statelock);
2062 2121 error = EBUSY;
2063 2122 } else {
2064 2123 smbfs_attrcache_rm_locked(np);
2065 2124 mutex_exit(&np->r_statelock);
2066 2125
2067 2126 error = smbfs_smb_delete(np, &scred, NULL, 0, 0);
2068 2127
2069 2128 /*
2070 2129 * If the file should no longer exist, discard
2071 2130 * any cached attributes under this node.
2072 2131 */
2073 2132 switch (error) {
2074 2133 case 0:
2075 2134 case ENOENT:
2076 2135 case ENOTDIR:
2077 2136 smbfs_attrcache_prune(np);
2078 2137 break;
2079 2138 }
2080 2139 }
2081 2140
2082 2141 VN_RELE(vp);
2083 2142
2084 2143 out:
2085 2144 smb_credrele(&scred);
2086 2145 smbfs_rw_exit(&dnp->r_rwlock);
2087 2146
2088 2147 return (error);
2089 2148 }
2090 2149
2091 2150
2092 2151 /*
2093 2152 * XXX
2094 2153 * This op should support the new FIGNORECASE flag for case-insensitive
2095 2154 * lookups, per PSARC 2007/244.
2096 2155 */
2097 2156 /* ARGSUSED */
2098 2157 static int
2099 2158 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2100 2159 caller_context_t *ct, int flags)
2101 2160 {
2102 2161 /* vnode_t *realvp; */
2103 2162
2104 2163 if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone ||
2105 2164 curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone)
2106 2165 return (EPERM);
2107 2166
2108 2167 if (VTOSMI(odvp)->smi_flags & SMI_DEAD ||
2109 2168 VTOSMI(ndvp)->smi_flags & SMI_DEAD ||
2110 2169 odvp->v_vfsp->vfs_flag & VFS_UNMOUNTED ||
2111 2170 ndvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2112 2171 return (EIO);
2113 2172
2114 2173 return (smbfsrename(odvp, onm, ndvp, nnm, cr, ct));
2115 2174 }
2116 2175
2117 2176 /*
2118 2177 * smbfsrename does the real work of renaming in SMBFS
2119 2178 */
2120 2179 /* ARGSUSED */
2121 2180 static int
2122 2181 smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2123 2182 caller_context_t *ct)
2124 2183 {
2125 2184 int error;
2126 2185 int nvp_locked = 0;
2127 2186 vnode_t *nvp = NULL;
2128 2187 vnode_t *ovp = NULL;
2129 2188 smbnode_t *onp;
2130 2189 smbnode_t *nnp;
2131 2190 smbnode_t *odnp;
2132 2191 smbnode_t *ndnp;
2133 2192 struct smb_cred scred;
2134 2193 /* enum smbfsstat status; */
2135 2194
2136 2195 ASSERT(curproc->p_zone == VTOSMI(odvp)->smi_zone_ref.zref_zone);
2137 2196
2138 2197 if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 ||
2139 2198 strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0)
2140 2199 return (EINVAL);
2141 2200
2142 2201 /*
2143 2202 * Check that everything is on the same filesystem.
2144 2203 * vn_rename checks the fsid's, but in case we don't
2145 2204 * fill those in correctly, check here too.
2146 2205 */
2147 2206 if (odvp->v_vfsp != ndvp->v_vfsp)
2148 2207 return (EXDEV);
2149 2208
2150 2209 odnp = VTOSMB(odvp);
2151 2210 ndnp = VTOSMB(ndvp);
2152 2211
2153 2212 /*
2154 2213 * Avoid deadlock here on old vs new directory nodes
2155 2214 * by always taking the locks in order of address.
2156 2215 * The order is arbitrary, but must be consistent.
2157 2216 */
2158 2217 if (odnp < ndnp) {
2159 2218 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2160 2219 SMBINTR(odvp)))
2161 2220 return (EINTR);
2162 2221 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2163 2222 SMBINTR(ndvp))) {
2164 2223 smbfs_rw_exit(&odnp->r_rwlock);
2165 2224 return (EINTR);
2166 2225 }
2167 2226 } else {
2168 2227 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2169 2228 SMBINTR(ndvp)))
2170 2229 return (EINTR);
2171 2230 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2172 2231 SMBINTR(odvp))) {
2173 2232 smbfs_rw_exit(&ndnp->r_rwlock);
2174 2233 return (EINTR);
2175 2234 }
2176 2235 }
2177 2236 smb_credinit(&scred, cr);
2178 2237 /*
2179 2238 * No returns after this point (goto out)
2180 2239 */
2181 2240
2182 2241 /*
2183 2242 * Need write access on source and target.
2184 2243 * Server takes care of most checks.
2185 2244 */
2186 2245 error = smbfs_access(odvp, VWRITE|VEXEC, 0, cr, ct);
2187 2246 if (error)
2188 2247 goto out;
2189 2248 if (odvp != ndvp) {
2190 2249 error = smbfs_access(ndvp, VWRITE, 0, cr, ct);
2191 2250 if (error)
2192 2251 goto out;
2193 2252 }
2194 2253
2195 2254 /*
2196 2255 * Lookup the source name. Must already exist.
2197 2256 */
2198 2257 error = smbfslookup(odvp, onm, &ovp, cr, 0, ct);
2199 2258 if (error)
2200 2259 goto out;
2201 2260
2202 2261 /*
2203 2262 * Lookup the target file. If it exists, it needs to be
2204 2263 * checked to see whether it is a mount point and whether
2205 2264 * it is active (open).
2206 2265 */
2207 2266 error = smbfslookup(ndvp, nnm, &nvp, cr, 0, ct);
2208 2267 if (!error) {
2209 2268 /*
2210 2269 * Target (nvp) already exists. Check that it
2211 2270 * has the same type as the source. The server
2212 2271 * will check this also, (and more reliably) but
2213 2272 * this lets us return the correct error codes.
2214 2273 */
2215 2274 if (ovp->v_type == VDIR) {
2216 2275 if (nvp->v_type != VDIR) {
2217 2276 error = ENOTDIR;
2218 2277 goto out;
2219 2278 }
2220 2279 } else {
2221 2280 if (nvp->v_type == VDIR) {
2222 2281 error = EISDIR;
2223 2282 goto out;
2224 2283 }
2225 2284 }
2226 2285
2227 2286 /*
2228 2287 * POSIX dictates that when the source and target
2229 2288 * entries refer to the same file object, rename
2230 2289 * must do nothing and exit without error.
2231 2290 */
2232 2291 if (ovp == nvp) {
2233 2292 error = 0;
2234 2293 goto out;
2235 2294 }
2236 2295
2237 2296 /*
2238 2297 * Also must ensure the target is not a mount point,
2239 2298 * and keep mount/umount away until we're done.
2240 2299 */
2241 2300 if (vn_vfsrlock(nvp)) {
2242 2301 error = EBUSY;
2243 2302 goto out;
2244 2303 }
2245 2304 nvp_locked = 1;
2246 2305 if (vn_mountedvfs(nvp) != NULL) {
2247 2306 error = EBUSY;
2248 2307 goto out;
2249 2308 }
2250 2309
2251 2310 /*
2252 2311 * CIFS gives a SHARING_VIOLATION error when
2253 2312 * trying to rename onto an exising object,
2254 2313 * so try to remove the target first.
2255 2314 * (Only for files, not directories.)
2256 2315 */
2257 2316 if (nvp->v_type == VDIR) {
2258 2317 error = EEXIST;
2259 2318 goto out;
2260 2319 }
2261 2320
2262 2321 /*
2263 2322 * Nodes that are "not active" here have v_count=2
2264 2323 * because vn_renameat (our caller) did a lookup on
2265 2324 * both the source and target before this call.
2266 2325 * Otherwise this similar to smbfs_remove.
2267 2326 */
2268 2327 nnp = VTOSMB(nvp);
2269 2328 mutex_enter(&nnp->r_statelock);
2270 2329 if ((nvp->v_count > 2) && (nnp->n_fidrefs > 0)) {
2271 2330 /*
2272 2331 * The target file exists, is not the same as
2273 2332 * the source file, and is active. Other FS
2274 2333 * implementations unlink the target here.
2275 2334 * For SMB, we don't assume we can remove an
2276 2335 * open file. Return an error instead.
2277 2336 */
2278 2337 mutex_exit(&nnp->r_statelock);
2279 2338 error = EBUSY;
2280 2339 goto out;
2281 2340 }
2282 2341
2283 2342 /*
2284 2343 * Target file is not active. Try to remove it.
2285 2344 */
2286 2345 smbfs_attrcache_rm_locked(nnp);
2287 2346 mutex_exit(&nnp->r_statelock);
2288 2347
2289 2348 error = smbfs_smb_delete(nnp, &scred, NULL, 0, 0);
2290 2349
2291 2350 /*
2292 2351 * Similar to smbfs_remove
2293 2352 */
2294 2353 switch (error) {
2295 2354 case 0:
2296 2355 case ENOENT:
2297 2356 case ENOTDIR:
2298 2357 smbfs_attrcache_prune(nnp);
2299 2358 break;
2300 2359 }
2301 2360
2302 2361 if (error)
2303 2362 goto out;
2304 2363 /*
2305 2364 * OK, removed the target file. Continue as if
2306 2365 * lookup target had failed (nvp == NULL).
2307 2366 */
2308 2367 vn_vfsunlock(nvp);
2309 2368 nvp_locked = 0;
2310 2369 VN_RELE(nvp);
2311 2370 nvp = NULL;
2312 2371 } /* nvp */
2313 2372
2314 2373 onp = VTOSMB(ovp);
2315 2374 smbfs_attrcache_remove(onp);
2316 2375
2317 2376 error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), &scred);
2318 2377
2319 2378 /*
2320 2379 * If the old name should no longer exist,
2321 2380 * discard any cached attributes under it.
2322 2381 */
2323 2382 if (error == 0)
2324 2383 smbfs_attrcache_prune(onp);
2325 2384
2326 2385 out:
2327 2386 if (nvp) {
2328 2387 if (nvp_locked)
2329 2388 vn_vfsunlock(nvp);
2330 2389 VN_RELE(nvp);
2331 2390 }
2332 2391 if (ovp)
2333 2392 VN_RELE(ovp);
2334 2393
2335 2394 smb_credrele(&scred);
2336 2395 smbfs_rw_exit(&odnp->r_rwlock);
2337 2396 smbfs_rw_exit(&ndnp->r_rwlock);
2338 2397
2339 2398 return (error);
2340 2399 }
2341 2400
2342 2401 /*
2343 2402 * XXX
2344 2403 * vsecattr_t is new to build 77, and we need to eventually support
2345 2404 * it in order to create an ACL when an object is created.
2346 2405 *
2347 2406 * This op should support the new FIGNORECASE flag for case-insensitive
2348 2407 * lookups, per PSARC 2007/244.
2349 2408 */
2350 2409 /* ARGSUSED */
2351 2410 static int
2352 2411 smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp,
2353 2412 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
2354 2413 {
2355 2414 vnode_t *vp;
2356 2415 struct smbnode *dnp = VTOSMB(dvp);
2357 2416 struct smbmntinfo *smi = VTOSMI(dvp);
2358 2417 struct smb_cred scred;
2359 2418 struct smbfattr fattr;
2360 2419 const char *name = (const char *) nm;
2361 2420 int nmlen = strlen(name);
2362 2421 int error, hiderr;
2363 2422
2364 2423 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2365 2424 return (EPERM);
2366 2425
2367 2426 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2368 2427 return (EIO);
2369 2428
2370 2429 if ((nmlen == 1 && name[0] == '.') ||
2371 2430 (nmlen == 2 && name[0] == '.' && name[1] == '.'))
2372 2431 return (EEXIST);
2373 2432
2374 2433 /* Only plain files are allowed in V_XATTRDIR. */
2375 2434 if (dvp->v_flag & V_XATTRDIR)
2376 2435 return (EINVAL);
2377 2436
2378 2437 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2379 2438 return (EINTR);
2380 2439 smb_credinit(&scred, cr);
2381 2440
2382 2441 /*
2383 2442 * XXX: Do we need r_lkserlock too?
2384 2443 * No use of any shared fid or fctx...
2385 2444 */
2386 2445
2387 2446 /*
2388 2447 * Require write access in the containing directory.
2389 2448 */
2390 2449 error = smbfs_access(dvp, VWRITE, 0, cr, ct);
2391 2450 if (error)
2392 2451 goto out;
2393 2452
2394 2453 error = smbfs_smb_mkdir(dnp, name, nmlen, &scred);
2395 2454 if (error)
2396 2455 goto out;
2397 2456
2398 2457 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2399 2458 if (error)
2400 2459 goto out;
2401 2460
2402 2461 smbfs_attr_touchdir(dnp);
2403 2462
2404 2463 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2405 2464 if (error)
2406 2465 goto out;
2407 2466
2408 2467 if (name[0] == '.')
2409 2468 if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred)))
2410 2469 SMBVDEBUG("hide failure %d\n", hiderr);
2411 2470
2412 2471 /* Success! */
2413 2472 *vpp = vp;
2414 2473 error = 0;
2415 2474 out:
2416 2475 smb_credrele(&scred);
2417 2476 smbfs_rw_exit(&dnp->r_rwlock);
2418 2477
2419 2478 if (name != nm)
2420 2479 smbfs_name_free(name, nmlen);
2421 2480
2422 2481 return (error);
2423 2482 }
2424 2483
2425 2484 /*
2426 2485 * XXX
2427 2486 * This op should support the new FIGNORECASE flag for case-insensitive
2428 2487 * lookups, per PSARC 2007/244.
2429 2488 */
2430 2489 /* ARGSUSED */
2431 2490 static int
2432 2491 smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
2433 2492 caller_context_t *ct, int flags)
2434 2493 {
2435 2494 vnode_t *vp = NULL;
2436 2495 int vp_locked = 0;
2437 2496 struct smbmntinfo *smi = VTOSMI(dvp);
2438 2497 struct smbnode *dnp = VTOSMB(dvp);
2439 2498 struct smbnode *np;
2440 2499 struct smb_cred scred;
2441 2500 int error;
2442 2501
2443 2502 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2444 2503 return (EPERM);
2445 2504
2446 2505 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2447 2506 return (EIO);
2448 2507
2449 2508 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2450 2509 return (EINTR);
2451 2510 smb_credinit(&scred, cr);
2452 2511
2453 2512 /*
2454 2513 * Require w/x access in the containing directory.
2455 2514 * Server handles all other access checks.
2456 2515 */
2457 2516 error = smbfs_access(dvp, VEXEC|VWRITE, 0, cr, ct);
2458 2517 if (error)
2459 2518 goto out;
2460 2519
2461 2520 /*
2462 2521 * First lookup the entry to be removed.
2463 2522 */
2464 2523 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2465 2524 if (error)
2466 2525 goto out;
2467 2526 np = VTOSMB(vp);
2468 2527
2469 2528 /*
2470 2529 * Disallow rmdir of "." or current dir, or the FS root.
2471 2530 * Also make sure it's a directory, not a mount point,
2472 2531 * and lock to keep mount/umount away until we're done.
2473 2532 */
2474 2533 if ((vp == dvp) || (vp == cdir) || (vp->v_flag & VROOT)) {
2475 2534 error = EINVAL;
2476 2535 goto out;
2477 2536 }
2478 2537 if (vp->v_type != VDIR) {
2479 2538 error = ENOTDIR;
2480 2539 goto out;
2481 2540 }
2482 2541 if (vn_vfsrlock(vp)) {
2483 2542 error = EBUSY;
2484 2543 goto out;
2485 2544 }
2486 2545 vp_locked = 1;
2487 2546 if (vn_mountedvfs(vp) != NULL) {
2488 2547 error = EBUSY;
2489 2548 goto out;
2490 2549 }
2491 2550
2492 2551 smbfs_attrcache_remove(np);
2493 2552 error = smbfs_smb_rmdir(np, &scred);
2494 2553
2495 2554 /*
2496 2555 * Similar to smbfs_remove
2497 2556 */
2498 2557 switch (error) {
2499 2558 case 0:
2500 2559 case ENOENT:
2501 2560 case ENOTDIR:
2502 2561 smbfs_attrcache_prune(np);
2503 2562 break;
2504 2563 }
2505 2564
2506 2565 if (error)
2507 2566 goto out;
2508 2567
2509 2568 mutex_enter(&np->r_statelock);
2510 2569 dnp->n_flag |= NMODIFIED;
2511 2570 mutex_exit(&np->r_statelock);
2512 2571 smbfs_attr_touchdir(dnp);
2513 2572 smbfs_rmhash(np);
2514 2573
2515 2574 out:
2516 2575 if (vp) {
2517 2576 if (vp_locked)
2518 2577 vn_vfsunlock(vp);
2519 2578 VN_RELE(vp);
2520 2579 }
2521 2580 smb_credrele(&scred);
2522 2581 smbfs_rw_exit(&dnp->r_rwlock);
2523 2582
2524 2583 return (error);
2525 2584 }
2526 2585
2527 2586
2528 2587 /* ARGSUSED */
2529 2588 static int
2530 2589 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp,
2531 2590 caller_context_t *ct, int flags)
2532 2591 {
2533 2592 struct smbnode *np = VTOSMB(vp);
2534 2593 int error = 0;
2535 2594 smbmntinfo_t *smi;
2536 2595
2537 2596 smi = VTOSMI(vp);
2538 2597
2539 2598 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2540 2599 return (EIO);
2541 2600
2542 2601 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2543 2602 return (EIO);
2544 2603
2545 2604 /*
2546 2605 * Require read access in the directory.
2547 2606 */
2548 2607 error = smbfs_access(vp, VREAD, 0, cr, ct);
2549 2608 if (error)
2550 2609 return (error);
2551 2610
2552 2611 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
2553 2612
2554 2613 /*
2555 2614 * XXX: Todo readdir cache here
2556 2615 * Note: NFS code is just below this.
2557 2616 *
2558 2617 * I am serializing the entire readdir opreation
2559 2618 * now since we have not yet implemented readdir
2560 2619 * cache. This fix needs to be revisited once
2561 2620 * we implement readdir cache.
2562 2621 */
2563 2622 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
2564 2623 return (EINTR);
2565 2624
2566 2625 error = smbfs_readvdir(vp, uiop, cr, eofp, ct);
2567 2626
2568 2627 smbfs_rw_exit(&np->r_lkserlock);
2569 2628
2570 2629 return (error);
2571 2630 }
2572 2631
2573 2632 /* ARGSUSED */
2574 2633 static int
2575 2634 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
2576 2635 caller_context_t *ct)
2577 2636 {
2578 2637 /*
2579 2638 * Note: "limit" tells the SMB-level FindFirst/FindNext
2580 2639 * functions how many directory entries to request in
2581 2640 * each OtW call. It needs to be large enough so that
2582 2641 * we don't make lots of tiny OtW requests, but there's
2583 2642 * no point making it larger than the maximum number of
2584 2643 * OtW entries that would fit in a maximum sized trans2
2585 2644 * response (64k / 48). Beyond that, it's just tuning.
2586 2645 * WinNT used 512, Win2k used 1366. We use 1000.
2587 2646 */
2588 2647 static const int limit = 1000;
2589 2648 /* Largest possible dirent size. */
2590 2649 static const size_t dbufsiz = DIRENT64_RECLEN(SMB_MAXFNAMELEN);
2591 2650 struct smb_cred scred;
2592 2651 vnode_t *newvp;
2593 2652 struct smbnode *np = VTOSMB(vp);
2594 2653 struct smbfs_fctx *ctx;
2595 2654 struct dirent64 *dp;
2596 2655 ssize_t save_resid;
2597 2656 offset_t save_offset; /* 64 bits */
2598 2657 int offset; /* yes, 32 bits */
2599 2658 int nmlen, error;
2600 2659 ushort_t reclen;
2601 2660
2602 2661 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
2603 2662
2604 2663 /* Make sure we serialize for n_dirseq use. */
2605 2664 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
2606 2665
2607 2666 /*
2608 2667 * Make sure smbfs_open filled in n_dirseq
2609 2668 */
2610 2669 if (np->n_dirseq == NULL)
2611 2670 return (EBADF);
2612 2671
2613 2672 /* Check for overflow of (32-bit) directory offset. */
2614 2673 if (uio->uio_loffset < 0 || uio->uio_loffset > INT32_MAX ||
2615 2674 (uio->uio_loffset + uio->uio_resid) > INT32_MAX)
2616 2675 return (EINVAL);
2617 2676
2618 2677 /* Require space for at least one dirent. */
2619 2678 if (uio->uio_resid < dbufsiz)
2620 2679 return (EINVAL);
2621 2680
2622 2681 SMBVDEBUG("dirname='%s'\n", np->n_rpath);
2623 2682 smb_credinit(&scred, cr);
2624 2683 dp = kmem_alloc(dbufsiz, KM_SLEEP);
2625 2684
2626 2685 save_resid = uio->uio_resid;
2627 2686 save_offset = uio->uio_loffset;
2628 2687 offset = uio->uio_offset;
2629 2688 SMBVDEBUG("in: offset=%d, resid=%d\n",
2630 2689 (int)uio->uio_offset, (int)uio->uio_resid);
2631 2690 error = 0;
2632 2691
2633 2692 /*
2634 2693 * Generate the "." and ".." entries here so we can
2635 2694 * (1) make sure they appear (but only once), and
2636 2695 * (2) deal with getting their I numbers which the
2637 2696 * findnext below does only for normal names.
2638 2697 */
2639 2698 while (offset < FIRST_DIROFS) {
2640 2699 /*
2641 2700 * Tricky bit filling in the first two:
2642 2701 * offset 0 is ".", offset 1 is ".."
2643 2702 * so strlen of these is offset+1.
2644 2703 */
2645 2704 reclen = DIRENT64_RECLEN(offset + 1);
2646 2705 if (uio->uio_resid < reclen)
2647 2706 goto out;
2648 2707 bzero(dp, reclen);
2649 2708 dp->d_reclen = reclen;
2650 2709 dp->d_name[0] = '.';
2651 2710 dp->d_name[1] = '.';
2652 2711 dp->d_name[offset + 1] = '\0';
2653 2712 /*
2654 2713 * Want the real I-numbers for the "." and ".."
2655 2714 * entries. For these two names, we know that
2656 2715 * smbfslookup can get the nodes efficiently.
2657 2716 */
2658 2717 error = smbfslookup(vp, dp->d_name, &newvp, cr, 1, ct);
2659 2718 if (error) {
2660 2719 dp->d_ino = np->n_ino + offset; /* fiction */
2661 2720 } else {
2662 2721 dp->d_ino = VTOSMB(newvp)->n_ino;
2663 2722 VN_RELE(newvp);
2664 2723 }
2665 2724 /*
2666 2725 * Note: d_off is the offset that a user-level program
2667 2726 * should seek to for reading the NEXT directory entry.
2668 2727 * See libc: readdir, telldir, seekdir
2669 2728 */
2670 2729 dp->d_off = offset + 1;
2671 2730 error = uiomove(dp, reclen, UIO_READ, uio);
2672 2731 if (error)
2673 2732 goto out;
2674 2733 /*
2675 2734 * Note: uiomove updates uio->uio_offset,
2676 2735 * but we want it to be our "cookie" value,
2677 2736 * which just counts dirents ignoring size.
2678 2737 */
2679 2738 uio->uio_offset = ++offset;
2680 2739 }
2681 2740
2682 2741 /*
2683 2742 * If there was a backward seek, we have to reopen.
2684 2743 */
2685 2744 if (offset < np->n_dirofs) {
2686 2745 SMBVDEBUG("Reopening search %d:%d\n",
2687 2746 offset, np->n_dirofs);
2688 2747 error = smbfs_smb_findopen(np, "*", 1,
2689 2748 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
2690 2749 &scred, &ctx);
2691 2750 if (error) {
2692 2751 SMBVDEBUG("can not open search, error = %d", error);
2693 2752 goto out;
2694 2753 }
2695 2754 /* free the old one */
2696 2755 (void) smbfs_smb_findclose(np->n_dirseq, &scred);
2697 2756 /* save the new one */
2698 2757 np->n_dirseq = ctx;
2699 2758 np->n_dirofs = FIRST_DIROFS;
2700 2759 } else {
2701 2760 ctx = np->n_dirseq;
2702 2761 }
2703 2762
2704 2763 /*
2705 2764 * Skip entries before the requested offset.
2706 2765 */
2707 2766 while (np->n_dirofs < offset) {
2708 2767 error = smbfs_smb_findnext(ctx, limit, &scred);
2709 2768 if (error != 0)
2710 2769 goto out;
2711 2770 np->n_dirofs++;
2712 2771 }
2713 2772
2714 2773 /*
2715 2774 * While there's room in the caller's buffer:
2716 2775 * get a directory entry from SMB,
2717 2776 * convert to a dirent, copyout.
2718 2777 * We stop when there is no longer room for a
2719 2778 * maximum sized dirent because we must decide
2720 2779 * before we know anything about the next entry.
2721 2780 */
2722 2781 while (uio->uio_resid >= dbufsiz) {
2723 2782 error = smbfs_smb_findnext(ctx, limit, &scred);
2724 2783 if (error != 0)
2725 2784 goto out;
2726 2785 np->n_dirofs++;
2727 2786
2728 2787 /* Sanity check the name length. */
2729 2788 nmlen = ctx->f_nmlen;
2730 2789 if (nmlen > SMB_MAXFNAMELEN) {
2731 2790 nmlen = SMB_MAXFNAMELEN;
2732 2791 SMBVDEBUG("Truncating name: %s\n", ctx->f_name);
2733 2792 }
2734 2793 if (smbfs_fastlookup) {
2735 2794 /* See comment at smbfs_fastlookup above. */
2736 2795 if (smbfs_nget(vp, ctx->f_name, nmlen,
2737 2796 &ctx->f_attr, &newvp) == 0)
2738 2797 VN_RELE(newvp);
2739 2798 }
2740 2799
2741 2800 reclen = DIRENT64_RECLEN(nmlen);
2742 2801 bzero(dp, reclen);
2743 2802 dp->d_reclen = reclen;
2744 2803 bcopy(ctx->f_name, dp->d_name, nmlen);
2745 2804 dp->d_name[nmlen] = '\0';
2746 2805 dp->d_ino = ctx->f_inum;
2747 2806 dp->d_off = offset + 1; /* See d_off comment above */
2748 2807 error = uiomove(dp, reclen, UIO_READ, uio);
2749 2808 if (error)
2750 2809 goto out;
2751 2810 /* See comment re. uio_offset above. */
2752 2811 uio->uio_offset = ++offset;
2753 2812 }
2754 2813
2755 2814 out:
2756 2815 /*
2757 2816 * When we come to the end of a directory, the
2758 2817 * SMB-level functions return ENOENT, but the
2759 2818 * caller is not expecting an error return.
2760 2819 *
2761 2820 * Also note that we must delay the call to
2762 2821 * smbfs_smb_findclose(np->n_dirseq, ...)
2763 2822 * until smbfs_close so that all reads at the
2764 2823 * end of the directory will return no data.
2765 2824 */
2766 2825 if (error == ENOENT) {
2767 2826 error = 0;
2768 2827 if (eofp)
2769 2828 *eofp = 1;
2770 2829 }
2771 2830 /*
2772 2831 * If we encountered an error (i.e. "access denied")
2773 2832 * from the FindFirst call, we will have copied out
2774 2833 * the "." and ".." entries leaving offset == 2.
2775 2834 * In that case, restore the original offset/resid
2776 2835 * so the caller gets no data with the error.
2777 2836 */
2778 2837 if (error != 0 && offset == FIRST_DIROFS) {
2779 2838 uio->uio_loffset = save_offset;
2780 2839 uio->uio_resid = save_resid;
2781 2840 }
2782 2841 SMBVDEBUG("out: offset=%d, resid=%d\n",
2783 2842 (int)uio->uio_offset, (int)uio->uio_resid);
2784 2843
2785 2844 kmem_free(dp, dbufsiz);
2786 2845 smb_credrele(&scred);
2787 2846 return (error);
2788 2847 }
2789 2848
2790 2849
2791 2850 /*
2792 2851 * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK
2793 2852 * are optional functions that are called by:
2794 2853 * getdents, before/after VOP_READDIR
2795 2854 * pread, before/after ... VOP_READ
2796 2855 * pwrite, before/after ... VOP_WRITE
2797 2856 * (other places)
2798 2857 *
2799 2858 * Careful here: None of the above check for any
2800 2859 * error returns from VOP_RWLOCK / VOP_RWUNLOCK!
2801 2860 * In fact, the return value from _rwlock is NOT
2802 2861 * an error code, but V_WRITELOCK_TRUE / _FALSE.
2803 2862 *
2804 2863 * Therefore, it's up to _this_ code to make sure
2805 2864 * the lock state remains balanced, which means
2806 2865 * we can't "bail out" on interrupts, etc.
2807 2866 */
2808 2867
2809 2868 /* ARGSUSED2 */
2810 2869 static int
2811 2870 smbfs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2812 2871 {
2813 2872 smbnode_t *np = VTOSMB(vp);
2814 2873
2815 2874 if (!write_lock) {
2816 2875 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_READER, FALSE);
2817 2876 return (V_WRITELOCK_FALSE);
2818 2877 }
2819 2878
2820 2879
2821 2880 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, FALSE);
2822 2881 return (V_WRITELOCK_TRUE);
2823 2882 }
2824 2883
2825 2884 /* ARGSUSED */
2826 2885 static void
2827 2886 smbfs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2828 2887 {
2829 2888 smbnode_t *np = VTOSMB(vp);
2830 2889
2831 2890 smbfs_rw_exit(&np->r_rwlock);
2832 2891 }
2833 2892
2834 2893
2835 2894 /* ARGSUSED */
2836 2895 static int
2837 2896 smbfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
2838 2897 {
2839 2898 smbmntinfo_t *smi;
2840 2899
2841 2900 smi = VTOSMI(vp);
2842 2901
2843 2902 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2844 2903 return (EPERM);
2845 2904
2846 2905 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2847 2906 return (EIO);
2848 2907
2849 2908 /*
2850 2909 * Because we stuff the readdir cookie into the offset field
2851 2910 * someone may attempt to do an lseek with the cookie which
2852 2911 * we want to succeed.
2853 2912 */
2854 2913 if (vp->v_type == VDIR)
2855 2914 return (0);
2856 2915
2857 2916 /* Like NFS3, just check for 63-bit overflow. */
2858 2917 if (*noffp < 0)
2859 2918 return (EINVAL);
2860 2919
2861 2920 return (0);
2862 2921 }
2863 2922
2864 2923
2865 2924 /*
2866 2925 * XXX
2867 2926 * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service.
2868 2927 */
2869 2928 static int
2870 2929 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2871 2930 offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
2872 2931 caller_context_t *ct)
2873 2932 {
2874 2933 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
2875 2934 return (EIO);
2876 2935
2877 2936 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
2878 2937 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
2879 2938 else
2880 2939 return (ENOSYS);
2881 2940 }
2882 2941
2883 2942 /*
2884 2943 * Free storage space associated with the specified vnode. The portion
2885 2944 * to be freed is specified by bfp->l_start and bfp->l_len (already
2886 2945 * normalized to a "whence" of 0).
2887 2946 *
2888 2947 * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc.
2889 2948 */
2890 2949 /* ARGSUSED */
2891 2950 static int
2892 2951 smbfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2893 2952 offset_t offset, cred_t *cr, caller_context_t *ct)
2894 2953 {
2895 2954 int error;
2896 2955 smbmntinfo_t *smi;
2897 2956
2898 2957 smi = VTOSMI(vp);
2899 2958
2900 2959 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2901 2960 return (EIO);
2902 2961
2903 2962 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2904 2963 return (EIO);
2905 2964
2906 2965 /* Caller (fcntl) has checked v_type */
2907 2966 ASSERT(vp->v_type == VREG);
2908 2967 if (cmd != F_FREESP)
2909 2968 return (EINVAL);
2910 2969
2911 2970 /*
2912 2971 * Like NFS3, no 32-bit offset checks here.
2913 2972 * Our SMB layer takes care to return EFBIG
2914 2973 * when it has to fallback to a 32-bit call.
2915 2974 */
2916 2975
2917 2976 error = convoff(vp, bfp, 0, offset);
2918 2977 if (!error) {
2919 2978 ASSERT(bfp->l_start >= 0);
2920 2979 if (bfp->l_len == 0) {
2921 2980 struct vattr va;
2922 2981
2923 2982 /*
2924 2983 * ftruncate should not change the ctime and
2925 2984 * mtime if we truncate the file to its
2926 2985 * previous size.
2927 2986 */
2928 2987 va.va_mask = AT_SIZE;
2929 2988 error = smbfsgetattr(vp, &va, cr);
2930 2989 if (error || va.va_size == bfp->l_start)
2931 2990 return (error);
2932 2991 va.va_mask = AT_SIZE;
2933 2992 va.va_size = bfp->l_start;
2934 2993 error = smbfssetattr(vp, &va, 0, cr);
2935 2994 } else
2936 2995 error = EINVAL;
2937 2996 }
2938 2997
2939 2998 return (error);
2940 2999 }
2941 3000
2942 3001 /* ARGSUSED */
2943 3002 static int
2944 3003 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
2945 3004 caller_context_t *ct)
2946 3005 {
2947 3006 vfs_t *vfs;
2948 3007 smbmntinfo_t *smi;
2949 3008 struct smb_share *ssp;
2950 3009
2951 3010 vfs = vp->v_vfsp;
2952 3011 smi = VFTOSMI(vfs);
2953 3012
2954 3013 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2955 3014 return (EIO);
2956 3015
2957 3016 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2958 3017 return (EIO);
2959 3018
2960 3019 switch (cmd) {
2961 3020 case _PC_FILESIZEBITS:
2962 3021 ssp = smi->smi_share;
2963 3022 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)
2964 3023 *valp = 64;
2965 3024 else
2966 3025 *valp = 32;
2967 3026 break;
2968 3027
2969 3028 case _PC_LINK_MAX:
2970 3029 /* We only ever report one link to an object */
2971 3030 *valp = 1;
2972 3031 break;
2973 3032
2974 3033 case _PC_ACL_ENABLED:
2975 3034 /*
2976 3035 * Always indicate that ACLs are enabled and
2977 3036 * that we support ACE_T format, otherwise
2978 3037 * libsec will ask for ACLENT_T format data
2979 3038 * which we don't support.
2980 3039 */
2981 3040 *valp = _ACL_ACE_ENABLED;
2982 3041 break;
2983 3042
2984 3043 case _PC_SYMLINK_MAX: /* No symlinks until we do Unix extensions */
↓ open down ↓ |
1848 lines elided |
↑ open up ↑ |
2985 3044 *valp = 0;
2986 3045 break;
2987 3046
2988 3047 case _PC_XATTR_EXISTS:
2989 3048 if (vfs->vfs_flag & VFS_XATTR) {
2990 3049 *valp = smbfs_xa_exists(vp, cr);
2991 3050 break;
2992 3051 }
2993 3052 return (EINVAL);
2994 3053
3054 + case _PC_SATTR_ENABLED:
3055 + case _PC_SATTR_EXISTS:
3056 + *valp = 1;
3057 + break;
3058 +
2995 3059 case _PC_TIMESTAMP_RESOLUTION:
2996 3060 /*
2997 3061 * Windows times are tenths of microseconds
2998 3062 * (multiples of 100 nanoseconds).
2999 3063 */
3000 3064 *valp = 100L;
3001 3065 break;
3002 3066
3003 3067 default:
3004 3068 return (fs_pathconf(vp, cmd, valp, cr, ct));
3005 3069 }
3006 3070 return (0);
3007 3071 }
3008 3072
3009 3073 /* ARGSUSED */
3010 3074 static int
3011 3075 smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3012 3076 caller_context_t *ct)
3013 3077 {
3014 3078 vfs_t *vfsp;
3015 3079 smbmntinfo_t *smi;
3016 3080 int error;
3017 3081 uint_t mask;
3018 3082
3019 3083 vfsp = vp->v_vfsp;
3020 3084 smi = VFTOSMI(vfsp);
3021 3085
3022 3086 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3023 3087 return (EIO);
3024 3088
3025 3089 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3026 3090 return (EIO);
3027 3091
3028 3092 /*
3029 3093 * Our _pathconf indicates _ACL_ACE_ENABLED,
3030 3094 * so we should only see VSA_ACE, etc here.
3031 3095 * Note: vn_create asks for VSA_DFACLCNT,
3032 3096 * and it expects ENOSYS and empty data.
3033 3097 */
3034 3098 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT |
3035 3099 VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES);
3036 3100 if (mask == 0)
3037 3101 return (ENOSYS);
3038 3102
3039 3103 if (smi->smi_flags & SMI_ACL)
3040 3104 error = smbfs_acl_getvsa(vp, vsa, flag, cr);
3041 3105 else
3042 3106 error = ENOSYS;
3043 3107
3044 3108 if (error == ENOSYS)
3045 3109 error = fs_fab_acl(vp, vsa, flag, cr, ct);
3046 3110
3047 3111 return (error);
3048 3112 }
3049 3113
3050 3114 /* ARGSUSED */
3051 3115 static int
3052 3116 smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3053 3117 caller_context_t *ct)
3054 3118 {
3055 3119 vfs_t *vfsp;
3056 3120 smbmntinfo_t *smi;
3057 3121 int error;
3058 3122 uint_t mask;
3059 3123
3060 3124 vfsp = vp->v_vfsp;
3061 3125 smi = VFTOSMI(vfsp);
3062 3126
3063 3127 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3064 3128 return (EIO);
3065 3129
3066 3130 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3067 3131 return (EIO);
3068 3132
3069 3133 /*
3070 3134 * Our _pathconf indicates _ACL_ACE_ENABLED,
3071 3135 * so we should only see VSA_ACE, etc here.
3072 3136 */
3073 3137 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT);
3074 3138 if (mask == 0)
3075 3139 return (ENOSYS);
3076 3140
3077 3141 if (vfsp->vfs_flag & VFS_RDONLY)
3078 3142 return (EROFS);
3079 3143
3080 3144 /*
3081 3145 * Allow only the mount owner to do this.
3082 3146 * See comments at smbfs_access_rwx.
3083 3147 */
3084 3148 error = secpolicy_vnode_setdac(cr, smi->smi_uid);
3085 3149 if (error != 0)
3086 3150 return (error);
3087 3151
3088 3152 if (smi->smi_flags & SMI_ACL)
3089 3153 error = smbfs_acl_setvsa(vp, vsa, flag, cr);
3090 3154 else
3091 3155 error = ENOSYS;
3092 3156
3093 3157 return (error);
3094 3158 }
3095 3159
3096 3160
3097 3161 /*
3098 3162 * XXX
3099 3163 * This op should eventually support PSARC 2007/268.
3100 3164 */
3101 3165 static int
3102 3166 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
3103 3167 caller_context_t *ct)
3104 3168 {
3105 3169 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
3106 3170 return (EIO);
3107 3171
3108 3172 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
3109 3173 return (fs_shrlock(vp, cmd, shr, flag, cr, ct));
3110 3174 else
3111 3175 return (ENOSYS);
3112 3176 }
↓ open down ↓ |
108 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX