Print this page
*** NO COMMENTS ***
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>
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
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 +#include <sys/param.h>
55 +#include <sys/vm.h>
56 +#include <vm/seg_vn.h>
57 +#include <vm/pvn.h>
58 +#include <vm/as.h>
59 +#include <vm/hat.h>
60 +#include <vm/page.h>
61 +#include <vm/seg.h>
62 +#include <vm/seg_map.h>
63 +#include <vm/seg_kmem.h>
64 +#include <vm/seg_kpm.h>
65 +
54 66 #include <netsmb/smb_osdep.h>
55 67 #include <netsmb/smb.h>
56 68 #include <netsmb/smb_conn.h>
57 69 #include <netsmb/smb_subr.h>
58 70
59 71 #include <smbfs/smbfs.h>
60 72 #include <smbfs/smbfs_node.h>
61 73 #include <smbfs/smbfs_subr.h>
62 74
63 75 #include <sys/fs/smbfs_ioctl.h>
64 76 #include <fs/fs_subr.h>
65 77
66 78 /*
67 79 * We assign directory offsets like the NFS client, where the
68 80 * offset increments by _one_ after each directory entry.
69 81 * Further, the entries "." and ".." are always at offsets
70 82 * zero and one (respectively) and the "real" entries from
71 83 * the server appear at offsets starting with two. This
72 84 * macro is used to initialize the n_dirofs field after
73 85 * setting n_dirseq with a _findopen call.
74 86 */
75 87 #define FIRST_DIROFS 2
76 88
77 89 /*
78 90 * These characters are illegal in NTFS file names.
79 91 * ref: http://support.microsoft.com/kb/147438
80 92 *
81 93 * Careful! The check in the XATTR case skips the
82 94 * first character to allow colon in XATTR names.
83 95 */
84 96 static const char illegal_chars[] = {
85 97 ':', /* colon - keep this first! */
86 98 '\\', /* back slash */
87 99 '/', /* slash */
88 100 '*', /* asterisk */
89 101 '?', /* question mark */
90 102 '"', /* double quote */
91 103 '<', /* less than sign */
92 104 '>', /* greater than sign */
93 105 '|', /* vertical bar */
94 106 0
95 107 };
96 108
97 109 /*
98 110 * Turning this on causes nodes to be created in the cache
99 111 * during directory listings, normally avoiding a second
100 112 * OtW attribute fetch just after a readdir.
101 113 */
102 114 int smbfs_fastlookup = 1;
103 115
104 116 /* local static function defines */
105 117
106 118 static int smbfslookup_cache(vnode_t *, char *, int, vnode_t **,
107 119 cred_t *);
108 120 static int smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
109 121 int cache_ok, caller_context_t *);
110 122 static int smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm,
111 123 cred_t *cr, caller_context_t *);
112 124 static int smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
113 125 static int smbfs_accessx(void *, int, cred_t *);
114 126 static int smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
115 127 caller_context_t *);
116 128 static void smbfs_rele_fid(smbnode_t *, struct smb_cred *);
117 129
118 130 /*
119 131 * These are the vnode ops routines which implement the vnode interface to
120 132 * the networked file system. These routines just take their parameters,
121 133 * make them look networkish by putting the right info into interface structs,
122 134 * and then calling the appropriate remote routine(s) to do the work.
123 135 *
124 136 * Note on directory name lookup cacheing: If we detect a stale fhandle,
125 137 * we purge the directory cache relative to that vnode. This way, the
126 138 * user won't get burned by the cache repeatedly. See <smbfs/smbnode.h> for
127 139 * more details on smbnode locking.
128 140 */
129 141
130 142 static int smbfs_open(vnode_t **, int, cred_t *, caller_context_t *);
131 143 static int smbfs_close(vnode_t *, int, int, offset_t, cred_t *,
132 144 caller_context_t *);
133 145 static int smbfs_read(vnode_t *, struct uio *, int, cred_t *,
134 146 caller_context_t *);
135 147 static int smbfs_write(vnode_t *, struct uio *, int, cred_t *,
136 148 caller_context_t *);
137 149 static int smbfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
138 150 caller_context_t *);
139 151 static int smbfs_getattr(vnode_t *, struct vattr *, int, cred_t *,
140 152 caller_context_t *);
141 153 static int smbfs_setattr(vnode_t *, struct vattr *, int, cred_t *,
142 154 caller_context_t *);
143 155 static int smbfs_access(vnode_t *, int, int, cred_t *, caller_context_t *);
144 156 static int smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *);
145 157 static void smbfs_inactive(vnode_t *, cred_t *, caller_context_t *);
146 158 static int smbfs_lookup(vnode_t *, char *, vnode_t **, struct pathname *,
147 159 int, vnode_t *, cred_t *, caller_context_t *,
148 160 int *, pathname_t *);
149 161 static int smbfs_create(vnode_t *, char *, struct vattr *, enum vcexcl,
150 162 int, vnode_t **, cred_t *, int, caller_context_t *,
151 163 vsecattr_t *);
152 164 static int smbfs_remove(vnode_t *, char *, cred_t *, caller_context_t *,
153 165 int);
154 166 static int smbfs_rename(vnode_t *, char *, vnode_t *, char *, cred_t *,
155 167 caller_context_t *, int);
156 168 static int smbfs_mkdir(vnode_t *, char *, struct vattr *, vnode_t **,
157 169 cred_t *, caller_context_t *, int, vsecattr_t *);
158 170 static int smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
159 171 caller_context_t *, int);
160 172 static int smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *,
161 173 caller_context_t *, int);
162 174 static int smbfs_rwlock(vnode_t *, int, caller_context_t *);
163 175 static void smbfs_rwunlock(vnode_t *, int, caller_context_t *);
164 176 static int smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
165 177 static int smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t,
166 178 struct flk_callback *, cred_t *, caller_context_t *);
167 179 static int smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t,
↓ open down ↓ |
104 lines elided |
↑ open up ↑ |
168 180 cred_t *, caller_context_t *);
169 181 static int smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *,
170 182 caller_context_t *);
171 183 static int smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
172 184 caller_context_t *);
173 185 static int smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
174 186 caller_context_t *);
175 187 static int smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *,
176 188 caller_context_t *);
177 189
190 +static int uio_page_mapin(uio_t *uiop, page_t *pp);
191 +
192 +static void uio_page_mapout(uio_t *uiop, page_t *pp);
193 +
194 +static int smbfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp,
195 + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr,
196 + caller_context_t *ct);
197 +
198 +static int smbfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
199 + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr,
200 + caller_context_t *ct);
201 +
202 +static int smbfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
203 + size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr,
204 + caller_context_t *ct);
205 +
206 +static int smbfs_putpage(vnode_t *vp, offset_t off, size_t len, int flags,
207 + cred_t *cr, caller_context_t *ct);
208 +
209 +static int smbfs_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
210 + int flags, cred_t *cr);
211 +
212 +static int smbfs_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
213 + page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
214 + enum seg_rw rw, cred_t *cr, caller_context_t *ct);
215 +
216 +static int smbfs_getapage(vnode_t *vp, u_offset_t off, size_t len,
217 + uint_t *protp, page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
218 + enum seg_rw rw, cred_t *cr);
219 +
220 +static int writenp(smbnode_t *np, caddr_t base, int tcount, struct uio *uiop, int pgcreated);
221 +
178 222 /* Dummy function to use until correct function is ported in */
179 223 int noop_vnodeop() {
180 224 return (0);
181 225 }
182 226
183 227 struct vnodeops *smbfs_vnodeops = NULL;
184 228
185 229 /*
186 230 * Most unimplemented ops will return ENOSYS because of fs_nosys().
187 231 * The only ops where that won't work are ACCESS (due to open(2)
188 232 * failures) and ... (anything else left?)
189 233 */
190 234 const fs_operation_def_t smbfs_vnodeops_template[] = {
191 235 { VOPNAME_OPEN, { .vop_open = smbfs_open } },
192 236 { VOPNAME_CLOSE, { .vop_close = smbfs_close } },
193 237 { VOPNAME_READ, { .vop_read = smbfs_read } },
194 238 { VOPNAME_WRITE, { .vop_write = smbfs_write } },
195 239 { VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl } },
196 240 { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } },
197 241 { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } },
198 242 { VOPNAME_ACCESS, { .vop_access = smbfs_access } },
199 243 { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } },
200 244 { VOPNAME_CREATE, { .vop_create = smbfs_create } },
201 245 { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } },
202 246 { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */
203 247 { VOPNAME_RENAME, { .vop_rename = smbfs_rename } },
204 248 { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } },
205 249 { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } },
206 250 { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } },
207 251 { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
208 252 { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */
209 253 { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } },
210 254 { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } },
211 255 { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */
212 256 { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } },
213 257 { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } },
214 258 { VOPNAME_SEEK, { .vop_seek = smbfs_seek } },
215 259 { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } },
216 260 { VOPNAME_SPACE, { .vop_space = smbfs_space } },
217 261 { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */
218 - { VOPNAME_GETPAGE, { .error = fs_nosys } }, /* smbfs_getpage, */
219 - { VOPNAME_PUTPAGE, { .error = fs_nosys } }, /* smbfs_putpage, */
220 - { VOPNAME_MAP, { .error = fs_nosys } }, /* smbfs_map, */
221 - { VOPNAME_ADDMAP, { .error = fs_nosys } }, /* smbfs_addmap, */
222 - { VOPNAME_DELMAP, { .error = fs_nosys } }, /* smbfs_delmap, */
262 + { VOPNAME_GETPAGE, { .vop_getpage = smbfs_getpage } }, /* smbfs_getpage, */
263 + { VOPNAME_PUTPAGE, { .vop_putpage = smbfs_putpage } }, /* smbfs_putpage, */
264 + { VOPNAME_MAP, { .vop_map = smbfs_map } }, /* smbfs_map, */
265 + { VOPNAME_ADDMAP, { .vop_addmap = smbfs_addmap } }, /* smbfs_addmap, */
266 + { VOPNAME_DELMAP, { .vop_delmap = smbfs_delmap } }, /* smbfs_delmap, */
267 + { VOPNAME_DISPOSE, { .vop_dispose = fs_dispose}},
223 268 { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */
224 269 { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } },
225 270 { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */
226 271 { VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr } },
227 272 { VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr } },
228 273 { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } },
229 274 { NULL, NULL }
230 275 };
231 276
232 277 /*
233 278 * XXX
234 279 * When new and relevant functionality is enabled, we should be
235 280 * calling vfs_set_feature() to inform callers that pieces of
236 281 * functionality are available, per PSARC 2007/227.
237 282 */
238 283 /* ARGSUSED */
239 284 static int
240 285 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
241 286 {
242 287 smbnode_t *np;
243 288 vnode_t *vp;
244 289 smbfattr_t fa;
245 290 u_int32_t rights, rightsrcvd;
246 291 u_int16_t fid, oldfid;
247 292 int oldgenid;
248 293 struct smb_cred scred;
249 294 smbmntinfo_t *smi;
250 295 smb_share_t *ssp;
251 296 cred_t *oldcr;
252 297 int tmperror;
253 298 int error = 0;
254 299
255 300 vp = *vpp;
256 301 np = VTOSMB(vp);
257 302 smi = VTOSMI(vp);
258 303 ssp = smi->smi_share;
259 304
260 305 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
261 306 return (EIO);
262 307
263 308 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
264 309 return (EIO);
265 310
266 311 if (vp->v_type != VREG && vp->v_type != VDIR) { /* XXX VLNK? */
267 312 SMBVDEBUG("open eacces vtype=%d\n", vp->v_type);
268 313 return (EACCES);
269 314 }
270 315
271 316 /*
272 317 * Get exclusive access to n_fid and related stuff.
273 318 * No returns after this until out.
274 319 */
275 320 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
276 321 return (EINTR);
277 322 smb_credinit(&scred, cr);
278 323
279 324 /*
280 325 * Keep track of the vnode type at first open.
281 326 * It may change later, and we need close to do
282 327 * cleanup for the type we opened. Also deny
283 328 * open of new types until old type is closed.
284 329 * XXX: Per-open instance nodes whould help.
285 330 */
286 331 if (np->n_ovtype == VNON) {
287 332 ASSERT(np->n_dirrefs == 0);
288 333 ASSERT(np->n_fidrefs == 0);
289 334 } else if (np->n_ovtype != vp->v_type) {
290 335 SMBVDEBUG("open n_ovtype=%d v_type=%d\n",
291 336 np->n_ovtype, vp->v_type);
292 337 error = EACCES;
293 338 goto out;
294 339 }
295 340
296 341 /*
297 342 * Directory open. See smbfs_readvdir()
298 343 */
299 344 if (vp->v_type == VDIR) {
300 345 if (np->n_dirseq == NULL) {
301 346 /* first open */
302 347 error = smbfs_smb_findopen(np, "*", 1,
303 348 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
304 349 &scred, &np->n_dirseq);
305 350 if (error != 0)
306 351 goto out;
307 352 }
308 353 np->n_dirofs = FIRST_DIROFS;
309 354 np->n_dirrefs++;
310 355 goto have_fid;
311 356 }
312 357
313 358 /*
314 359 * If caller specified O_TRUNC/FTRUNC, then be sure to set
315 360 * FWRITE (to drive successful setattr(size=0) after open)
316 361 */
317 362 if (flag & FTRUNC)
318 363 flag |= FWRITE;
319 364
320 365 /*
321 366 * If we already have it open, and the FID is still valid,
322 367 * check whether the rights are sufficient for FID reuse.
323 368 */
324 369 if (np->n_fidrefs > 0 &&
325 370 np->n_vcgenid == ssp->ss_vcgenid) {
326 371 int upgrade = 0;
327 372
328 373 if ((flag & FWRITE) &&
329 374 !(np->n_rights & SA_RIGHT_FILE_WRITE_DATA))
330 375 upgrade = 1;
331 376 if ((flag & FREAD) &&
332 377 !(np->n_rights & SA_RIGHT_FILE_READ_DATA))
333 378 upgrade = 1;
334 379 if (!upgrade) {
335 380 /*
336 381 * the existing open is good enough
337 382 */
338 383 np->n_fidrefs++;
339 384 goto have_fid;
340 385 }
341 386 }
342 387 rights = np->n_fidrefs ? np->n_rights : 0;
343 388
344 389 /*
345 390 * we always ask for READ_CONTROL so we can always get the
346 391 * owner/group IDs to satisfy a stat. Ditto attributes.
347 392 */
348 393 rights |= (STD_RIGHT_READ_CONTROL_ACCESS |
349 394 SA_RIGHT_FILE_READ_ATTRIBUTES);
350 395 if ((flag & FREAD))
351 396 rights |= SA_RIGHT_FILE_READ_DATA;
352 397 if ((flag & FWRITE))
353 398 rights |= SA_RIGHT_FILE_WRITE_DATA |
354 399 SA_RIGHT_FILE_APPEND_DATA |
355 400 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
356 401
357 402 bzero(&fa, sizeof (fa));
358 403 error = smbfs_smb_open(np,
359 404 NULL, 0, 0, /* name nmlen xattr */
360 405 rights, &scred,
361 406 &fid, &rightsrcvd, &fa);
362 407 if (error)
363 408 goto out;
364 409 smbfs_attrcache_fa(vp, &fa);
365 410
366 411 /*
367 412 * We have a new FID and access rights.
368 413 */
369 414 oldfid = np->n_fid;
370 415 oldgenid = np->n_vcgenid;
371 416 np->n_fid = fid;
372 417 np->n_vcgenid = ssp->ss_vcgenid;
373 418 np->n_rights = rightsrcvd;
374 419 np->n_fidrefs++;
375 420 if (np->n_fidrefs > 1 &&
376 421 oldgenid == ssp->ss_vcgenid) {
377 422 /*
378 423 * We already had it open (presumably because
379 424 * it was open with insufficient rights.)
380 425 * Close old wire-open.
381 426 */
382 427 tmperror = smbfs_smb_close(ssp,
383 428 oldfid, NULL, &scred);
384 429 if (tmperror)
385 430 SMBVDEBUG("error %d closing %s\n",
386 431 tmperror, np->n_rpath);
387 432 }
388 433
389 434 /*
390 435 * This thread did the open.
391 436 * Save our credentials too.
392 437 */
393 438 mutex_enter(&np->r_statelock);
394 439 oldcr = np->r_cred;
395 440 np->r_cred = cr;
396 441 crhold(cr);
397 442 if (oldcr)
398 443 crfree(oldcr);
399 444 mutex_exit(&np->r_statelock);
400 445
401 446 have_fid:
402 447 /*
403 448 * Keep track of the vnode type at first open.
404 449 * (see comments above)
405 450 */
406 451 if (np->n_ovtype == VNON)
407 452 np->n_ovtype = vp->v_type;
408 453
409 454 out:
410 455 smb_credrele(&scred);
411 456 smbfs_rw_exit(&np->r_lkserlock);
412 457 return (error);
413 458 }
414 459
415 460 /*ARGSUSED*/
416 461 static int
417 462 smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
418 463 caller_context_t *ct)
419 464 {
420 465 smbnode_t *np;
421 466 smbmntinfo_t *smi;
422 467 struct smb_cred scred;
423 468
424 469 np = VTOSMB(vp);
425 470 smi = VTOSMI(vp);
426 471
427 472 /*
428 473 * Don't "bail out" for VFS_UNMOUNTED here,
429 474 * as we want to do cleanup, etc.
430 475 */
431 476
432 477 /*
433 478 * zone_enter(2) prevents processes from changing zones with SMBFS files
434 479 * open; if we happen to get here from the wrong zone we can't do
435 480 * anything over the wire.
436 481 */
437 482 if (smi->smi_zone_ref.zref_zone != curproc->p_zone) {
438 483 /*
439 484 * We could attempt to clean up locks, except we're sure
440 485 * that the current process didn't acquire any locks on
441 486 * the file: any attempt to lock a file belong to another zone
442 487 * will fail, and one can't lock an SMBFS file and then change
443 488 * zones, as that fails too.
444 489 *
445 490 * Returning an error here is the sane thing to do. A
446 491 * subsequent call to VN_RELE() which translates to a
447 492 * smbfs_inactive() will clean up state: if the zone of the
448 493 * vnode's origin is still alive and kicking, an async worker
449 494 * thread will handle the request (from the correct zone), and
450 495 * everything (minus the final smbfs_getattr_otw() call) should
451 496 * be OK. If the zone is going away smbfs_async_inactive() will
452 497 * throw away cached pages inline.
453 498 */
454 499 return (EIO);
455 500 }
456 501
457 502 /*
458 503 * If we are using local locking for this filesystem, then
459 504 * release all of the SYSV style record locks. Otherwise,
460 505 * we are doing network locking and we need to release all
461 506 * of the network locks. All of the locks held by this
462 507 * process on this file are released no matter what the
463 508 * incoming reference count is.
464 509 */
465 510 if (smi->smi_flags & SMI_LLOCK) {
466 511 pid_t pid = ddi_get_pid();
467 512 cleanlocks(vp, pid, 0);
468 513 cleanshares(vp, pid);
469 514 }
470 515
471 516 /*
472 517 * This (passed in) count is the ref. count from the
473 518 * user's file_t before the closef call (fio.c).
474 519 * We only care when the reference goes away.
475 520 */
476 521 if (count > 1)
477 522 return (0);
478 523
↓ open down ↓ |
246 lines elided |
↑ open up ↑ |
479 524 /*
480 525 * Decrement the reference count for the FID
481 526 * and possibly do the OtW close.
482 527 *
483 528 * Exclusive lock for modifying n_fid stuff.
484 529 * Don't want this one ever interruptible.
485 530 */
486 531 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
487 532 smb_credinit(&scred, cr);
488 533
489 - smbfs_rele_fid(np, &scred);
534 + /*
535 + * If FID ref. count is 1 and count of mmaped pages isn't 0,
536 + * we won't call smbfs_rele_fid(), because it will result in the otW close.
537 + * The count of mapped pages isn't 0, which means the mapped pages
538 + * possibly will be accessed after close(), we should keep the FID valid,
539 + * i.e., dont do the otW close.
540 + * Dont worry that FID will be leaked, because when the
541 + * vnode's count becomes 0, smbfs_inactive() will
542 + * help us release FID and eventually do the otW close.
543 + */
544 + if (np->n_fidrefs > 1) {
545 + smbfs_rele_fid(np, &scred);
546 + } else if (np->r_mapcnt == 0) {
547 + /*
548 + * Before otW close, make sure dirty pages written back.
549 + */
550 + if ((flag & FWRITE) && vn_has_cached_data(vp)) {
551 + /* smbfs_putapage() will acquire shared lock, so release
552 + * exclusive lock temporally.
553 + */
554 + smbfs_rw_exit(&np->r_lkserlock);
555 +
556 + (void) smbfs_putpage(vp, (offset_t) 0, 0, B_INVAL | B_ASYNC, cr, ct);
557 +
558 + /* acquire exclusive lock again. */
559 + (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
560 + }
561 + smbfs_rele_fid(np, &scred);
562 + }
490 563
491 564 smb_credrele(&scred);
492 565 smbfs_rw_exit(&np->r_lkserlock);
493 566
494 567 return (0);
495 568 }
496 569
497 570 /*
498 571 * Helper for smbfs_close. Decrement the reference count
499 572 * for an SMB-level file or directory ID, and when the last
500 573 * reference for the fid goes away, do the OtW close.
501 574 * Also called in smbfs_inactive (defensive cleanup).
502 575 */
503 576 static void
504 577 smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred)
505 578 {
506 579 smb_share_t *ssp;
507 580 cred_t *oldcr;
508 581 struct smbfs_fctx *fctx;
509 582 int error;
510 583 uint16_t ofid;
511 584
512 585 ssp = np->n_mount->smi_share;
513 586 error = 0;
514 587
515 588 /* Make sure we serialize for n_dirseq use. */
516 589 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
517 590
518 591 /*
519 592 * Note that vp->v_type may change if a remote node
520 593 * is deleted and recreated as a different type, and
521 594 * our getattr may change v_type accordingly.
522 595 * Now use n_ovtype to keep track of the v_type
523 596 * we had during open (see comments above).
524 597 */
525 598 switch (np->n_ovtype) {
526 599 case VDIR:
527 600 ASSERT(np->n_dirrefs > 0);
528 601 if (--np->n_dirrefs)
529 602 return;
530 603 if ((fctx = np->n_dirseq) != NULL) {
531 604 np->n_dirseq = NULL;
532 605 np->n_dirofs = 0;
533 606 error = smbfs_smb_findclose(fctx, scred);
534 607 }
535 608 break;
536 609
537 610 case VREG:
538 611 ASSERT(np->n_fidrefs > 0);
539 612 if (--np->n_fidrefs)
540 613 return;
541 614 if ((ofid = np->n_fid) != SMB_FID_UNUSED) {
542 615 np->n_fid = SMB_FID_UNUSED;
543 616 /* After reconnect, n_fid is invalid */
544 617 if (np->n_vcgenid == ssp->ss_vcgenid) {
545 618 error = smbfs_smb_close(
546 619 ssp, ofid, NULL, scred);
547 620 }
548 621 }
549 622 break;
550 623
551 624 default:
552 625 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
553 626 break;
554 627 }
555 628 if (error) {
556 629 SMBVDEBUG("error %d closing %s\n",
557 630 error, np->n_rpath);
558 631 }
559 632
560 633 /* Allow next open to use any v_type. */
561 634 np->n_ovtype = VNON;
562 635
563 636 /*
564 637 * Other "last close" stuff.
565 638 */
566 639 mutex_enter(&np->r_statelock);
567 640 if (np->n_flag & NATTRCHANGED)
↓ open down ↓ |
68 lines elided |
↑ open up ↑ |
568 641 smbfs_attrcache_rm_locked(np);
569 642 oldcr = np->r_cred;
570 643 np->r_cred = NULL;
571 644 mutex_exit(&np->r_statelock);
572 645 if (oldcr != NULL)
573 646 crfree(oldcr);
574 647 }
575 648
576 649 /* ARGSUSED */
577 650 static int
578 -smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
579 - caller_context_t *ct)
651 +smbfs_read(vnode_t * vp, struct uio * uiop, int ioflag, cred_t * cr,
652 + caller_context_t * ct)
580 653 {
581 654 struct smb_cred scred;
582 - struct vattr va;
583 - smbnode_t *np;
584 - smbmntinfo_t *smi;
585 - smb_share_t *ssp;
586 - offset_t endoff;
587 - ssize_t past_eof;
588 - int error;
655 + struct vattr va;
656 + smbnode_t *np;
657 + smbmntinfo_t *smi;
658 + smb_share_t *ssp;
659 + offset_t endoff;
660 + ssize_t past_eof;
661 + int error;
662 +
663 + caddr_t base;
664 + u_offset_t blk;
665 + u_offset_t boff;
666 + size_t blen;
667 + uint_t flags;
589 668
590 669 np = VTOSMB(vp);
591 670 smi = VTOSMI(vp);
592 671 ssp = smi->smi_share;
593 672
594 673 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
595 674 return (EIO);
596 675
597 676 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
598 677 return (EIO);
599 678
600 679 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
601 680
602 681 if (vp->v_type != VREG)
603 682 return (EISDIR);
604 683
605 684 if (uiop->uio_resid == 0)
606 685 return (0);
607 686
608 687 /*
609 - * Like NFS3, just check for 63-bit overflow.
610 - * Our SMB layer takes care to return EFBIG
611 - * when it has to fallback to a 32-bit call.
688 + * Like NFS3, just check for 63-bit overflow. Our SMB layer takes
689 + * care to return EFBIG when it has to fallback to a 32-bit call.
612 690 */
613 691 endoff = uiop->uio_loffset + uiop->uio_resid;
614 692 if (uiop->uio_loffset < 0 || endoff < 0)
615 693 return (EINVAL);
616 694
617 695 /* get vnode attributes from server */
618 696 va.va_mask = AT_SIZE | AT_MTIME;
619 697 if (error = smbfsgetattr(vp, &va, cr))
620 698 return (error);
621 699
622 700 /* Update mtime with mtime from server here? */
623 701
624 702 /* if offset is beyond EOF, read nothing */
625 703 if (uiop->uio_loffset >= va.va_size)
626 704 return (0);
627 705
628 706 /*
629 - * Limit the read to the remaining file size.
630 - * Do this by temporarily reducing uio_resid
631 - * by the amount the lies beyoned the EOF.
707 + * Limit the read to the remaining file size. Do this by temporarily
708 + * reducing uio_resid by the amount the lies beyoned the EOF.
632 709 */
633 710 if (endoff > va.va_size) {
634 - past_eof = (ssize_t)(endoff - va.va_size);
711 + past_eof = (ssize_t) (endoff - va.va_size);
635 712 uiop->uio_resid -= past_eof;
636 713 } else
637 714 past_eof = 0;
638 715
639 - /* Shared lock for n_fid use in smb_rwuio */
640 - if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
641 - return (EINTR);
642 - smb_credinit(&scred, cr);
716 + /* Bypass the VM if vnode is non-cacheable. */
717 + if ((vp->v_flag & VNOCACHE) ||
718 + ((np->r_flags & RDIRECTIO) &&
719 + np->r_mapcnt == 0 &&
720 + !(vn_has_cached_data(vp)))) {
643 721
644 - /* After reconnect, n_fid is invalid */
645 - if (np->n_vcgenid != ssp->ss_vcgenid)
646 - error = ESTALE;
647 - else
648 - error = smb_rwuio(ssp, np->n_fid, UIO_READ,
649 - uiop, &scred, smb_timo_read);
722 + /* Shared lock for n_fid use in smb_rwuio */
723 + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
724 + return (EINTR);
725 + smb_credinit(&scred, cr);
650 726
651 - smb_credrele(&scred);
652 - smbfs_rw_exit(&np->r_lkserlock);
727 + /* After reconnect, n_fid is invalid */
728 + if (np->n_vcgenid != ssp->ss_vcgenid)
729 + error = ESTALE;
730 + else
731 + error = smb_rwuio(ssp, np->n_fid, UIO_READ,
732 + uiop, &scred, smb_timo_read);
733 +
734 + smb_credrele(&scred);
735 + smbfs_rw_exit(&np->r_lkserlock);
736 +
737 + } else {
738 +
739 + /* Do I/O through segmap. */
740 + do {
741 + blk = uiop->uio_loffset & MAXBMASK;
742 + boff = uiop->uio_loffset & MAXBOFFSET;
743 + blen = MIN(MAXBSIZE - boff, uiop->uio_resid);
744 +
745 + if (vpm_enable) {
746 +
747 + error = vpm_data_copy(vp, blk + boff, blen, uiop, 1, NULL, 0, S_READ);
748 +
749 + } else {
750 +
751 + base = segmap_getmapflt(segkmap, vp, blk + boff, blen, 1, S_READ);
752 +
753 + error = uiomove(base + boff, blen, UIO_READ, uiop);
754 + }
755 +
756 + if (!error) {
757 + mutex_enter(&np->r_statelock);
758 + if ((blen + boff == MAXBSIZE) || (uiop->uio_loffset == np->r_size)) {
759 + flags = SM_DONTNEED;
760 + } else {
761 + flags = 0;
762 + }
763 + mutex_exit(&np->r_statelock);
764 + } else {
765 + flags = 0;
766 + }
767 + if (vpm_enable) {
768 + (void) vpm_sync_pages(vp, blk + boff, blen, flags);
769 + } else {
770 + (void) segmap_release(segkmap, base, flags);
771 + }
772 + } while (!error && uiop->uio_resid > 0);
773 + }
653 774
654 775 /* undo adjustment of resid */
655 776 uiop->uio_resid += past_eof;
656 777
657 778 return (error);
658 779 }
659 780
660 -
661 781 /* ARGSUSED */
662 782 static int
663 -smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
664 - caller_context_t *ct)
783 +smbfs_write(vnode_t * vp, struct uio * uiop, int ioflag, cred_t * cr,
784 + caller_context_t * ct)
665 785 {
666 786 struct smb_cred scred;
667 - struct vattr va;
668 - smbnode_t *np;
669 - smbmntinfo_t *smi;
670 - smb_share_t *ssp;
671 - offset_t endoff, limit;
672 - ssize_t past_limit;
673 - int error, timo;
787 + struct vattr va;
788 + smbnode_t *np;
789 + smbmntinfo_t *smi;
790 + smb_share_t *ssp;
791 + offset_t endoff, limit;
792 + ssize_t past_limit;
793 + int error, timo;
794 +
795 + caddr_t base;
796 + u_offset_t blk;
797 + u_offset_t boff;
798 + size_t blen;
799 + uint_t flags;
800 +
801 + u_offset_t last_off;
802 + size_t last_resid;
674 803
675 804 np = VTOSMB(vp);
676 805 smi = VTOSMI(vp);
677 806 ssp = smi->smi_share;
678 807
679 808 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
680 809 return (EIO);
681 810
682 811 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
683 812 return (EIO);
684 813
685 814 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
686 815
687 816 if (vp->v_type != VREG)
688 817 return (EISDIR);
689 818
690 819 if (uiop->uio_resid == 0)
691 820 return (0);
692 821
693 822 /*
694 823 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
695 824 */
696 825 if (ioflag & (FAPPEND | FSYNC)) {
697 826 if (np->n_flag & NMODIFIED) {
698 827 smbfs_attrcache_remove(np);
699 828 /* XXX: smbfs_vinvalbuf? */
700 829 }
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
701 830 }
702 831 if (ioflag & FAPPEND) {
703 832 /*
704 833 * File size can be changed by another client
705 834 */
706 835 va.va_mask = AT_SIZE;
707 836 if (error = smbfsgetattr(vp, &va, cr))
708 837 return (error);
709 838 uiop->uio_loffset = va.va_size;
710 839 }
711 -
712 840 /*
713 841 * Like NFS3, just check for 63-bit overflow.
714 842 */
715 843 endoff = uiop->uio_loffset + uiop->uio_resid;
716 844 if (uiop->uio_loffset < 0 || endoff < 0)
717 845 return (EINVAL);
718 846
719 847 /*
720 - * Check to make sure that the process will not exceed
721 - * its limit on file size. It is okay to write up to
722 - * the limit, but not beyond. Thus, the write which
723 - * reaches the limit will be short and the next write
724 - * will return an error.
725 - *
726 - * So if we're starting at or beyond the limit, EFBIG.
727 - * Otherwise, temporarily reduce resid to the amount
728 - * the falls after the limit.
848 + * Check to make sure that the process will not exceed its limit on
849 + * file size. It is okay to write up to the limit, but not beyond.
850 + * Thus, the write which reaches the limit will be short and the next
851 + * write will return an error.
852 + *
853 + * So if we're starting at or beyond the limit, EFBIG. Otherwise,
854 + * temporarily reduce resid to the amount the falls after the limit.
729 855 */
730 856 limit = uiop->uio_llimit;
731 857 if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
732 858 limit = MAXOFFSET_T;
733 859 if (uiop->uio_loffset >= limit)
734 860 return (EFBIG);
735 861 if (endoff > limit) {
736 - past_limit = (ssize_t)(endoff - limit);
862 + past_limit = (ssize_t) (endoff - limit);
737 863 uiop->uio_resid -= past_limit;
738 864 } else
739 865 past_limit = 0;
740 866
741 - /* Timeout: longer for append. */
742 - timo = smb_timo_write;
743 - if (endoff > np->r_size)
744 - timo = smb_timo_append;
867 + /* Bypass the VM if vnode is non-cacheable. */
868 + if ((vp->v_flag & VNOCACHE) ||
869 + ((np->r_flags & RDIRECTIO) &&
870 + np->r_mapcnt == 0 &&
871 + !(vn_has_cached_data(vp)))) {
872 +
873 + /* Timeout: longer for append. */
874 + timo = smb_timo_write;
875 + if (endoff > np->r_size)
876 + timo = smb_timo_append;
745 877
746 - /* Shared lock for n_fid use in smb_rwuio */
747 - if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
748 - return (EINTR);
749 - smb_credinit(&scred, cr);
878 + /* Shared lock for n_fid use in smb_rwuio */
879 + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
880 + return (EINTR);
881 + smb_credinit(&scred, cr);
750 882
751 - /* After reconnect, n_fid is invalid */
752 - if (np->n_vcgenid != ssp->ss_vcgenid)
753 - error = ESTALE;
754 - else
755 - error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
756 - uiop, &scred, timo);
883 + /* After reconnect, n_fid is invalid */
884 + if (np->n_vcgenid != ssp->ss_vcgenid)
885 + error = ESTALE;
886 + else
887 + error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
888 + uiop, &scred, timo);
757 889
758 - if (error == 0) {
759 - mutex_enter(&np->r_statelock);
760 - np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
761 - if (uiop->uio_loffset > (offset_t)np->r_size)
762 - np->r_size = (len_t)uiop->uio_loffset;
763 - mutex_exit(&np->r_statelock);
764 - if (ioflag & (FSYNC|FDSYNC)) {
765 - /* Don't error the I/O if this fails. */
766 - (void) smbfs_smb_flush(np, &scred);
890 + if (error == 0) {
891 + mutex_enter(&np->r_statelock);
892 + np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
893 + if (uiop->uio_loffset > (offset_t) np->r_size)
894 + np->r_size = (len_t) uiop->uio_loffset;
895 + mutex_exit(&np->r_statelock);
896 + if (ioflag & (FSYNC | FDSYNC)) {
897 + /* Don't error the I/O if this fails. */
898 + (void) smbfs_smb_flush(np, &scred);
899 + }
767 900 }
768 - }
901 + smb_credrele(&scred);
902 + smbfs_rw_exit(&np->r_lkserlock);
769 903
770 - smb_credrele(&scred);
771 - smbfs_rw_exit(&np->r_lkserlock);
904 + } else {
905 +
906 + /* Do I/O through segmap. */
907 + size_t bsize = vp->v_vfsp->vfs_bsize;
908 +
909 + do {
910 + blk = uiop->uio_loffset & MAXBMASK;
911 + boff = uiop->uio_loffset & MAXBOFFSET;
912 + blen = MIN(MAXBSIZE - boff, uiop->uio_resid);
913 +
914 + last_off = uiop->uio_loffset;
915 + last_resid = uiop->uio_resid;
916 +
917 + uio_prefaultpages((ssize_t) blen, uiop);
918 +
919 + if (vpm_enable) {
920 +
921 + error = writenp(np, NULL, blen, uiop, 0);
922 +
923 + } else {
924 +
925 + if (segmap_kpm) {
926 + u_offset_t poff = uiop->uio_loffset & PAGEOFFSET;
927 + size_t plen = MIN(PAGESIZE - poff, uiop->uio_resid);
928 +
929 + int pagecreate;
930 +
931 + mutex_enter(&np->r_statelock);
932 + pagecreate = (poff == 0) &&
933 + ((plen == PAGESIZE) ||
934 + (uiop->uio_loffset + plen >= np->r_size));
935 + mutex_exit(&np->r_statelock);
936 +
937 + base = segmap_getmapflt(segkmap, vp, blk + boff, plen, !pagecreate, S_WRITE);
938 + error = writenp(np, base + poff, blen, uiop, pagecreate);
939 +
940 + } else {
941 + base = segmap_getmapflt(segkmap, vp, blk + boff, blen, 0, S_READ);
942 + error = writenp(np, base + boff, blen, uiop, 0);
943 + }
944 + }
945 +
946 + if (!error) {
947 + if (uiop->uio_loffset % bsize == 0) {
948 + flags = SM_WRITE | SM_DONTNEED;
949 + } else {
950 + flags = 0;
951 + }
952 +
953 + if (ioflag & (FSYNC | FDSYNC)) {
954 + flags &= ~SM_ASYNC;
955 + flags |= SM_WRITE;
956 + }
957 + if (vpm_enable) {
958 + error = vpm_sync_pages(vp, blk, blen, flags);
959 + } else {
960 + error = segmap_release(segkmap, base, flags);
961 + }
962 + } else {
963 + if (vpm_enable) {
964 + (void) vpm_sync_pages(vp, blk, blen, 0);
965 + } else {
966 + (void) segmap_release(segkmap, base, 0);
967 + }
968 + }
969 + } while (!error && uiop->uio_resid > 0);
970 + }
772 971
773 972 /* undo adjustment of resid */
774 - uiop->uio_resid += past_limit;
973 + if (error) {
974 + uiop->uio_resid = last_resid + past_limit;
975 + uiop->uio_loffset = last_off;
976 + } else {
977 + uiop->uio_resid += past_limit;
978 + }
775 979
776 980 return (error);
777 981 }
778 982
983 +/* correspond to writerp() in nfs_client.c */
984 +static int
985 +writenp(smbnode_t * np, caddr_t base, int tcount, struct uio * uiop, int pgcreated)
986 +{
987 + int pagecreate;
988 + int n;
989 + int saved_n;
990 + caddr_t saved_base;
991 + u_offset_t offset;
992 + int error;
993 + int sm_error;
994 +
995 + vnode_t *vp = SMBTOV(np);
996 +
997 + ASSERT(tcount <= MAXBSIZE && tcount <= uiop->uio_resid);
998 + ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
999 + if (!vpm_enable) {
1000 + ASSERT(((uintptr_t) base & MAXBOFFSET) + tcount <= MAXBSIZE);
1001 + }
1002 + /*
1003 + * Move bytes in at most PAGESIZE chunks. We must avoid spanning
1004 + * pages in uiomove() because page faults may cause the cache to be
1005 + * invalidated out from under us. The r_size is not updated until
1006 + * after the uiomove. If we push the last page of a file before
1007 + * r_size is correct, we will lose the data written past the current
1008 + * (and invalid) r_size.
1009 + */
1010 + do {
1011 + offset = uiop->uio_loffset;
1012 + pagecreate = 0;
1013 +
1014 + /*
1015 + * n is the number of bytes required to satisfy the request
1016 + * or the number of bytes to fill out the page.
1017 + */
1018 + n = (int) MIN((PAGESIZE - (offset & PAGEOFFSET)), tcount);
1019 +
1020 + /*
1021 + * Check to see if we can skip reading in the page and just
1022 + * allocate the memory. We can do this if we are going to
1023 + * rewrite the entire mapping or if we are going to write to
1024 + * or beyond the current end of file from the beginning of
1025 + * the mapping.
1026 + *
1027 + * The read of r_size is now protected by r_statelock.
1028 + */
1029 + mutex_enter(&np->r_statelock);
1030 + /*
1031 + * When pgcreated is nonzero the caller has already done a
1032 + * segmap_getmapflt with forcefault 0 and S_WRITE. With
1033 + * segkpm this means we already have at least one page
1034 + * created and mapped at base.
1035 + */
1036 + pagecreate = pgcreated ||
1037 + ((offset & PAGEOFFSET) == 0 &&
1038 + (n == PAGESIZE || ((offset + n) >= np->r_size)));
1039 +
1040 + mutex_exit(&np->r_statelock);
1041 +
1042 + if (!vpm_enable && pagecreate) {
1043 + /*
1044 + * The last argument tells segmap_pagecreate() to
1045 + * always lock the page, as opposed to sometimes
1046 + * returning with the page locked. This way we avoid
1047 + * a fault on the ensuing uiomove(), but also more
1048 + * importantly (to fix bug 1094402) we can call
1049 + * segmap_fault() to unlock the page in all cases. An
1050 + * alternative would be to modify segmap_pagecreate()
1051 + * to tell us when it is locking a page, but that's a
1052 + * fairly major interface change.
1053 + */
1054 + if (pgcreated == 0)
1055 + (void) segmap_pagecreate(segkmap, base,
1056 + (uint_t) n, 1);
1057 + saved_base = base;
1058 + saved_n = n;
1059 + }
1060 + /*
1061 + * The number of bytes of data in the last page can not be
1062 + * accurately be determined while page is being uiomove'd to
1063 + * and the size of the file being updated. Thus, inform
1064 + * threads which need to know accurately how much data is in
1065 + * the last page of the file. They will not do the i/o
1066 + * immediately, but will arrange for the i/o to happen later
1067 + * when this modify operation will have finished.
1068 + */
1069 + ASSERT(!(np->r_flags & RMODINPROGRESS));
1070 + mutex_enter(&np->r_statelock);
1071 + np->r_flags |= RMODINPROGRESS;
1072 + np->r_modaddr = (offset & MAXBMASK);
1073 + mutex_exit(&np->r_statelock);
1074 +
1075 + if (vpm_enable) {
1076 + /*
1077 + * Copy data. If new pages are created, part of the
1078 + * page that is not written will be initizliazed with
1079 + * zeros.
1080 + */
1081 + error = vpm_data_copy(vp, offset, n, uiop,
1082 + !pagecreate, NULL, 0, S_WRITE);
1083 + } else {
1084 + error = uiomove(base, n, UIO_WRITE, uiop);
1085 + }
1086 +
1087 + /*
1088 + * r_size is the maximum number of bytes known to be in the
1089 + * file. Make sure it is at least as high as the first
1090 + * unwritten byte pointed to by uio_loffset.
1091 + */
1092 + mutex_enter(&np->r_statelock);
1093 + if (np->r_size < uiop->uio_loffset)
1094 + np->r_size = uiop->uio_loffset;
1095 + np->r_flags &= ~RMODINPROGRESS;
1096 + np->r_flags |= RDIRTY;
1097 + mutex_exit(&np->r_statelock);
1098 +
1099 + /* n = # of bytes written */
1100 + n = (int) (uiop->uio_loffset - offset);
1101 +
1102 + if (!vpm_enable) {
1103 + base += n;
1104 + }
1105 + tcount -= n;
1106 + /*
1107 + * If we created pages w/o initializing them completely, we
1108 + * need to zero the part that wasn't set up. This happens on
1109 + * a most EOF write cases and if we had some sort of error
1110 + * during the uiomove.
1111 + */
1112 + if (!vpm_enable && pagecreate) {
1113 + if ((uiop->uio_loffset & PAGEOFFSET) || n == 0)
1114 + (void) kzero(base, PAGESIZE - n);
1115 +
1116 + if (pgcreated) {
1117 + /*
1118 + * Caller is responsible for this page, it
1119 + * was not created in this loop.
1120 + */
1121 + pgcreated = 0;
1122 + } else {
1123 + /*
1124 + * For bug 1094402: segmap_pagecreate locks
1125 + * page. Unlock it. This also unlocks the
1126 + * pages allocated by page_create_va() in
1127 + * segmap_pagecreate().
1128 + */
1129 + sm_error = segmap_fault(kas.a_hat, segkmap,
1130 + saved_base, saved_n,
1131 + F_SOFTUNLOCK, S_WRITE);
1132 + if (error == 0)
1133 + error = sm_error;
1134 + }
1135 + }
1136 + } while (tcount > 0 && error == 0);
1137 +
1138 + return (error);
1139 +}
779 1140
780 1141 /* ARGSUSED */
781 1142 static int
782 1143 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag,
783 1144 cred_t *cr, int *rvalp, caller_context_t *ct)
784 1145 {
785 1146 int error;
786 1147 smbmntinfo_t *smi;
787 1148
788 1149 smi = VTOSMI(vp);
789 1150
790 1151 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
791 1152 return (EIO);
792 1153
793 1154 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
794 1155 return (EIO);
795 1156
796 1157 switch (cmd) {
797 1158 /* First three from ZFS. XXX - need these? */
798 1159
799 1160 case _FIOFFS:
800 1161 error = smbfs_fsync(vp, 0, cr, ct);
801 1162 break;
802 1163
803 1164 /*
804 1165 * The following two ioctls are used by bfu.
805 1166 * Silently ignore to avoid bfu errors.
806 1167 */
807 1168 case _FIOGDIO:
808 1169 case _FIOSDIO:
809 1170 error = 0;
810 1171 break;
811 1172
812 1173 #ifdef NOT_YET /* XXX - from the NFS code. */
813 1174 case _FIODIRECTIO:
814 1175 error = smbfs_directio(vp, (int)arg, cr);
815 1176 #endif
816 1177
817 1178 /*
818 1179 * Allow get/set with "raw" security descriptor (SD) data.
819 1180 * Useful for testing, diagnosing idmap problems, etc.
820 1181 */
821 1182 case SMBFSIO_GETSD:
822 1183 error = smbfs_acl_iocget(vp, arg, flag, cr);
823 1184 break;
824 1185
825 1186 case SMBFSIO_SETSD:
826 1187 error = smbfs_acl_iocset(vp, arg, flag, cr);
827 1188 break;
828 1189
829 1190 default:
830 1191 error = ENOTTY;
831 1192 break;
832 1193 }
833 1194
834 1195 return (error);
835 1196 }
836 1197
837 1198
838 1199 /*
839 1200 * Return either cached or remote attributes. If get remote attr
840 1201 * use them to check and invalidate caches, then cache the new attributes.
841 1202 *
842 1203 * XXX
843 1204 * This op should eventually support PSARC 2007/315, Extensible Attribute
844 1205 * Interfaces, for richer metadata.
845 1206 */
846 1207 /* ARGSUSED */
847 1208 static int
848 1209 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
849 1210 caller_context_t *ct)
850 1211 {
851 1212 smbnode_t *np;
852 1213 smbmntinfo_t *smi;
853 1214
854 1215 smi = VTOSMI(vp);
855 1216
856 1217 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
857 1218 return (EIO);
858 1219
859 1220 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
860 1221 return (EIO);
861 1222
862 1223 /*
863 1224 * If it has been specified that the return value will
864 1225 * just be used as a hint, and we are only being asked
865 1226 * for size, fsid or rdevid, then return the client's
866 1227 * notion of these values without checking to make sure
867 1228 * that the attribute cache is up to date.
868 1229 * The whole point is to avoid an over the wire GETATTR
869 1230 * call.
870 1231 */
871 1232 np = VTOSMB(vp);
872 1233 if (flags & ATTR_HINT) {
873 1234 if (vap->va_mask ==
874 1235 (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) {
875 1236 mutex_enter(&np->r_statelock);
876 1237 if (vap->va_mask | AT_SIZE)
877 1238 vap->va_size = np->r_size;
878 1239 if (vap->va_mask | AT_FSID)
879 1240 vap->va_fsid = vp->v_vfsp->vfs_dev;
880 1241 if (vap->va_mask | AT_RDEV)
881 1242 vap->va_rdev = vp->v_rdev;
882 1243 mutex_exit(&np->r_statelock);
883 1244 return (0);
884 1245 }
885 1246 }
886 1247
887 1248 return (smbfsgetattr(vp, vap, cr));
888 1249 }
889 1250
890 1251 /* smbfsgetattr() in smbfs_client.c */
891 1252
892 1253 /*
893 1254 * XXX
894 1255 * This op should eventually support PSARC 2007/315, Extensible Attribute
895 1256 * Interfaces, for richer metadata.
896 1257 */
897 1258 /*ARGSUSED4*/
898 1259 static int
899 1260 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
900 1261 caller_context_t *ct)
901 1262 {
902 1263 vfs_t *vfsp;
903 1264 smbmntinfo_t *smi;
904 1265 int error;
905 1266 uint_t mask;
906 1267 struct vattr oldva;
907 1268
908 1269 vfsp = vp->v_vfsp;
909 1270 smi = VFTOSMI(vfsp);
910 1271
911 1272 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
912 1273 return (EIO);
913 1274
914 1275 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
915 1276 return (EIO);
916 1277
917 1278 mask = vap->va_mask;
918 1279 if (mask & AT_NOSET)
919 1280 return (EINVAL);
920 1281
921 1282 if (vfsp->vfs_flag & VFS_RDONLY)
922 1283 return (EROFS);
923 1284
924 1285 /*
925 1286 * This is a _local_ access check so that only the owner of
926 1287 * this mount can set attributes. With ACLs enabled, the
927 1288 * file owner can be different from the mount owner, and we
928 1289 * need to check the _mount_ owner here. See _access_rwx
929 1290 */
930 1291 bzero(&oldva, sizeof (oldva));
931 1292 oldva.va_mask = AT_TYPE | AT_MODE;
932 1293 error = smbfsgetattr(vp, &oldva, cr);
933 1294 if (error)
934 1295 return (error);
935 1296 oldva.va_mask |= AT_UID | AT_GID;
936 1297 oldva.va_uid = smi->smi_uid;
937 1298 oldva.va_gid = smi->smi_gid;
938 1299
939 1300 error = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
940 1301 smbfs_accessx, vp);
941 1302 if (error)
942 1303 return (error);
943 1304
944 1305 if (mask & (AT_UID | AT_GID)) {
945 1306 if (smi->smi_flags & SMI_ACL)
946 1307 error = smbfs_acl_setids(vp, vap, cr);
947 1308 else
948 1309 error = ENOSYS;
949 1310 if (error != 0) {
950 1311 SMBVDEBUG("error %d seting UID/GID on %s",
951 1312 error, VTOSMB(vp)->n_rpath);
952 1313 /*
953 1314 * It might be more correct to return the
954 1315 * error here, but that causes complaints
955 1316 * when root extracts a cpio archive, etc.
956 1317 * So ignore this error, and go ahead with
957 1318 * the rest of the setattr work.
958 1319 */
959 1320 }
960 1321 }
961 1322
962 1323 return (smbfssetattr(vp, vap, flags, cr));
963 1324 }
964 1325
965 1326 /*
966 1327 * Mostly from Darwin smbfs_setattr()
967 1328 * but then modified a lot.
968 1329 */
969 1330 /* ARGSUSED */
970 1331 static int
971 1332 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
972 1333 {
973 1334 int error = 0;
974 1335 smbnode_t *np = VTOSMB(vp);
975 1336 uint_t mask = vap->va_mask;
976 1337 struct timespec *mtime, *atime;
977 1338 struct smb_cred scred;
978 1339 int cerror, modified = 0;
979 1340 unsigned short fid;
980 1341 int have_fid = 0;
981 1342 uint32_t rights = 0;
982 1343
983 1344 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
984 1345
985 1346 /*
986 1347 * There are no settable attributes on the XATTR dir,
987 1348 * so just silently ignore these. On XATTR files,
988 1349 * you can set the size but nothing else.
989 1350 */
990 1351 if (vp->v_flag & V_XATTRDIR)
991 1352 return (0);
992 1353 if (np->n_flag & N_XATTR) {
993 1354 if (mask & AT_TIMES)
994 1355 SMBVDEBUG("ignore set time on xattr\n");
995 1356 mask &= AT_SIZE;
996 1357 }
997 1358
998 1359 /*
999 1360 * If our caller is trying to set multiple attributes, they
1000 1361 * can make no assumption about what order they are done in.
1001 1362 * Here we try to do them in order of decreasing likelihood
1002 1363 * of failure, just to minimize the chance we'll wind up
1003 1364 * with a partially complete request.
1004 1365 */
1005 1366
1006 1367 /* Shared lock for (possible) n_fid use. */
1007 1368 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1008 1369 return (EINTR);
1009 1370 smb_credinit(&scred, cr);
1010 1371
1011 1372 /*
1012 1373 * Will we need an open handle for this setattr?
1013 1374 * If so, what rights will we need?
1014 1375 */
1015 1376 if (mask & (AT_ATIME | AT_MTIME)) {
1016 1377 rights |=
1017 1378 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
1018 1379 }
1019 1380 if (mask & AT_SIZE) {
1020 1381 rights |=
1021 1382 SA_RIGHT_FILE_WRITE_DATA |
1022 1383 SA_RIGHT_FILE_APPEND_DATA;
1023 1384 }
1024 1385
1025 1386 /*
1026 1387 * Only SIZE really requires a handle, but it's
1027 1388 * simpler and more reliable to set via a handle.
1028 1389 * Some servers like NT4 won't set times by path.
1029 1390 * Also, we're usually setting everything anyway.
1030 1391 */
1031 1392 if (mask & (AT_SIZE | AT_ATIME | AT_MTIME)) {
1032 1393 error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
1033 1394 if (error) {
1034 1395 SMBVDEBUG("error %d opening %s\n",
1035 1396 error, np->n_rpath);
1036 1397 goto out;
1037 1398 }
1038 1399 have_fid = 1;
1039 1400 }
1040 1401
1041 1402 /*
1042 1403 * If the server supports the UNIX extensions, right here is where
1043 1404 * we'd support changes to uid, gid, mode, and possibly va_flags.
1044 1405 * For now we claim to have made any such changes.
1045 1406 */
1046 1407
1047 1408 if (mask & AT_SIZE) {
1048 1409 /*
1049 1410 * If the new file size is less than what the client sees as
1050 1411 * the file size, then just change the size and invalidate
1051 1412 * the pages.
1052 1413 * I am commenting this code at present because the function
1053 1414 * smbfs_putapage() is not yet implemented.
1054 1415 */
1055 1416
1056 1417 /*
1057 1418 * Set the file size to vap->va_size.
1058 1419 */
1059 1420 ASSERT(have_fid);
1060 1421 error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred);
1061 1422 if (error) {
1062 1423 SMBVDEBUG("setsize error %d file %s\n",
1063 1424 error, np->n_rpath);
1064 1425 } else {
1065 1426 /*
1066 1427 * Darwin had code here to zero-extend.
1067 1428 * Tests indicate the server will zero-fill,
1068 1429 * so looks like we don't need to do this.
1069 1430 * Good thing, as this could take forever.
1070 1431 *
1071 1432 * XXX: Reportedly, writing one byte of zero
1072 1433 * at the end offset avoids problems here.
1073 1434 */
1074 1435 mutex_enter(&np->r_statelock);
1075 1436 np->r_size = vap->va_size;
1076 1437 mutex_exit(&np->r_statelock);
1077 1438 modified = 1;
1078 1439 }
1079 1440 }
1080 1441
1081 1442 /*
1082 1443 * XXX: When Solaris has create_time, set that too.
1083 1444 * Note: create_time is different from ctime.
1084 1445 */
1085 1446 mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0);
1086 1447 atime = ((mask & AT_ATIME) ? &vap->va_atime : 0);
1087 1448
1088 1449 if (mtime || atime) {
1089 1450 /*
1090 1451 * Always use the handle-based set attr call now.
1091 1452 * Not trying to set DOS attributes here so pass zero.
1092 1453 */
1093 1454 ASSERT(have_fid);
1094 1455 error = smbfs_smb_setfattr(np, fid,
1095 1456 0, mtime, atime, &scred);
1096 1457 if (error) {
1097 1458 SMBVDEBUG("set times error %d file %s\n",
1098 1459 error, np->n_rpath);
1099 1460 } else {
1100 1461 modified = 1;
1101 1462 }
1102 1463 }
1103 1464
1104 1465 out:
1105 1466 if (modified) {
1106 1467 /*
1107 1468 * Invalidate attribute cache in case the server
1108 1469 * doesn't set exactly the attributes we asked.
1109 1470 */
1110 1471 smbfs_attrcache_remove(np);
1111 1472 }
1112 1473
1113 1474 if (have_fid) {
1114 1475 cerror = smbfs_smb_tmpclose(np, fid, &scred);
1115 1476 if (cerror)
1116 1477 SMBVDEBUG("error %d closing %s\n",
1117 1478 cerror, np->n_rpath);
1118 1479 }
1119 1480
1120 1481 smb_credrele(&scred);
1121 1482 smbfs_rw_exit(&np->r_lkserlock);
1122 1483
1123 1484 return (error);
1124 1485 }
1125 1486
1126 1487 /*
1127 1488 * smbfs_access_rwx()
1128 1489 * Common function for smbfs_access, etc.
1129 1490 *
1130 1491 * The security model implemented by the FS is unusual
1131 1492 * due to the current "single user mounts" restriction:
1132 1493 * All access under a given mount point uses the CIFS
1133 1494 * credentials established by the owner of the mount.
1134 1495 *
1135 1496 * Most access checking is handled by the CIFS server,
1136 1497 * but we need sufficient Unix access checks here to
1137 1498 * prevent other local Unix users from having access
1138 1499 * to objects under this mount that the uid/gid/mode
1139 1500 * settings in the mount would not allow.
1140 1501 *
1141 1502 * With this model, there is a case where we need the
1142 1503 * ability to do an access check before we have the
1143 1504 * vnode for an object. This function takes advantage
1144 1505 * of the fact that the uid/gid/mode is per mount, and
1145 1506 * avoids the need for a vnode.
1146 1507 *
1147 1508 * We still (sort of) need a vnode when we call
1148 1509 * secpolicy_vnode_access, but that only uses
1149 1510 * the vtype field, so we can use a pair of fake
1150 1511 * vnodes that have only v_type filled in.
1151 1512 *
1152 1513 * XXX: Later, add a new secpolicy_vtype_access()
1153 1514 * that takes the vtype instead of a vnode, and
1154 1515 * get rid of the tmpl_vxxx fake vnodes below.
1155 1516 */
1156 1517 static int
1157 1518 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
1158 1519 {
1159 1520 /* See the secpolicy call below. */
1160 1521 static const vnode_t tmpl_vdir = { .v_type = VDIR };
1161 1522 static const vnode_t tmpl_vreg = { .v_type = VREG };
1162 1523 vattr_t va;
1163 1524 vnode_t *tvp;
1164 1525 struct smbmntinfo *smi = VFTOSMI(vfsp);
1165 1526 int shift = 0;
1166 1527
1167 1528 /*
1168 1529 * Build our (fabricated) vnode attributes.
1169 1530 * XXX: Could make these templates in the
1170 1531 * per-mount struct and use them here.
1171 1532 */
1172 1533 bzero(&va, sizeof (va));
1173 1534 va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1174 1535 va.va_type = vtype;
1175 1536 va.va_mode = (vtype == VDIR) ?
1176 1537 smi->smi_dmode : smi->smi_fmode;
1177 1538 va.va_uid = smi->smi_uid;
1178 1539 va.va_gid = smi->smi_gid;
1179 1540
1180 1541 /*
1181 1542 * Disallow write attempts on read-only file systems,
1182 1543 * unless the file is a device or fifo node. Note:
1183 1544 * Inline vn_is_readonly and IS_DEVVP here because
1184 1545 * we may not have a vnode ptr. Original expr. was:
1185 1546 * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp))
1186 1547 */
1187 1548 if ((mode & VWRITE) &&
1188 1549 (vfsp->vfs_flag & VFS_RDONLY) &&
1189 1550 !(vtype == VCHR || vtype == VBLK || vtype == VFIFO))
1190 1551 return (EROFS);
1191 1552
1192 1553 /*
1193 1554 * Disallow attempts to access mandatory lock files.
1194 1555 * Similarly, expand MANDLOCK here.
1195 1556 * XXX: not sure we need this.
1196 1557 */
1197 1558 if ((mode & (VWRITE | VREAD | VEXEC)) &&
1198 1559 va.va_type == VREG && MANDMODE(va.va_mode))
1199 1560 return (EACCES);
1200 1561
1201 1562 /*
1202 1563 * Access check is based on only
1203 1564 * one of owner, group, public.
1204 1565 * If not owner, then check group.
1205 1566 * If not a member of the group,
1206 1567 * then check public access.
1207 1568 */
1208 1569 if (crgetuid(cr) != va.va_uid) {
1209 1570 shift += 3;
1210 1571 if (!groupmember(va.va_gid, cr))
1211 1572 shift += 3;
1212 1573 }
1213 1574
1214 1575 /*
1215 1576 * We need a vnode for secpolicy_vnode_access,
1216 1577 * but the only thing it looks at is v_type,
1217 1578 * so pass one of the templates above.
1218 1579 */
1219 1580 tvp = (va.va_type == VDIR) ?
1220 1581 (vnode_t *)&tmpl_vdir :
1221 1582 (vnode_t *)&tmpl_vreg;
1222 1583
1223 1584 return (secpolicy_vnode_access2(cr, tvp, va.va_uid,
1224 1585 va.va_mode << shift, mode));
1225 1586 }
1226 1587
1227 1588 /*
1228 1589 * See smbfs_setattr
1229 1590 */
1230 1591 static int
1231 1592 smbfs_accessx(void *arg, int mode, cred_t *cr)
1232 1593 {
1233 1594 vnode_t *vp = arg;
1234 1595 /*
1235 1596 * Note: The caller has checked the current zone,
1236 1597 * the SMI_DEAD and VFS_UNMOUNTED flags, etc.
1237 1598 */
1238 1599 return (smbfs_access_rwx(vp->v_vfsp, vp->v_type, mode, cr));
1239 1600 }
1240 1601
1241 1602 /*
1242 1603 * XXX
1243 1604 * This op should support PSARC 2007/403, Modified Access Checks for CIFS
1244 1605 */
1245 1606 /* ARGSUSED */
1246 1607 static int
1247 1608 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
1248 1609 {
1249 1610 vfs_t *vfsp;
1250 1611 smbmntinfo_t *smi;
1251 1612
1252 1613 vfsp = vp->v_vfsp;
1253 1614 smi = VFTOSMI(vfsp);
1254 1615
1255 1616 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1256 1617 return (EIO);
1257 1618
1258 1619 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1259 1620 return (EIO);
1260 1621
1261 1622 return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr));
1262 1623 }
1263 1624
1264 1625
1265 1626 /*
1266 1627 * Flush local dirty pages to stable storage on the server.
1267 1628 *
1268 1629 * If FNODSYNC is specified, then there is nothing to do because
1269 1630 * metadata changes are not cached on the client before being
1270 1631 * sent to the server.
1271 1632 */
1272 1633 /* ARGSUSED */
1273 1634 static int
1274 1635 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
1275 1636 {
1276 1637 int error = 0;
1277 1638 smbmntinfo_t *smi;
1278 1639 smbnode_t *np;
1279 1640 struct smb_cred scred;
1280 1641
1281 1642 np = VTOSMB(vp);
1282 1643 smi = VTOSMI(vp);
1283 1644
1284 1645 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1285 1646 return (EIO);
1286 1647
1287 1648 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1288 1649 return (EIO);
1289 1650
1290 1651 if ((syncflag & FNODSYNC) || IS_SWAPVP(vp))
1291 1652 return (0);
1292 1653
1293 1654 if ((syncflag & (FSYNC|FDSYNC)) == 0)
1294 1655 return (0);
1295 1656
1296 1657 /* Shared lock for n_fid use in _flush */
1297 1658 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1298 1659 return (EINTR);
1299 1660 smb_credinit(&scred, cr);
1300 1661
1301 1662 error = smbfs_smb_flush(np, &scred);
1302 1663
1303 1664 smb_credrele(&scred);
1304 1665 smbfs_rw_exit(&np->r_lkserlock);
1305 1666
1306 1667 return (error);
1307 1668 }
1308 1669
1309 1670 /*
1310 1671 * Last reference to vnode went away.
1311 1672 */
1312 1673 /* ARGSUSED */
1313 1674 static void
1314 1675 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
1315 1676 {
1316 1677 smbnode_t *np;
1317 1678 struct smb_cred scred;
1318 1679
1319 1680 /*
1320 1681 * Don't "bail out" for VFS_UNMOUNTED here,
1321 1682 * as we want to do cleanup, etc.
1322 1683 * See also pcfs_inactive
1323 1684 */
1324 1685
1325 1686 np = VTOSMB(vp);
1326 1687
1327 1688 /*
1328 1689 * If this is coming from the wrong zone, we let someone in the right
1329 1690 * zone take care of it asynchronously. We can get here due to
1330 1691 * VN_RELE() being called from pageout() or fsflush(). This call may
1331 1692 * potentially turn into an expensive no-op if, for instance, v_count
1332 1693 * gets incremented in the meantime, but it's still correct.
1333 1694 */
1334 1695
1335 1696 /*
1336 1697 * Defend against the possibility that higher-level callers
1337 1698 * might not correctly balance open and close calls. If we
1338 1699 * get here with open references remaining, it means there
1339 1700 * was a missing VOP_CLOSE somewhere. If that happens, do
1340 1701 * the close here so we don't "leak" FIDs on the server.
1341 1702 *
1342 1703 * Exclusive lock for modifying n_fid stuff.
1343 1704 * Don't want this one ever interruptible.
1344 1705 */
1345 1706 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
1346 1707 smb_credinit(&scred, cr);
1347 1708
1348 1709 switch (np->n_ovtype) {
1349 1710 case VNON:
1350 1711 /* not open (OK) */
1351 1712 break;
1352 1713
1353 1714 case VDIR:
1354 1715 if (np->n_dirrefs == 0)
1355 1716 break;
1356 1717 SMBVDEBUG("open dir: refs %d path %s\n",
1357 1718 np->n_dirrefs, np->n_rpath);
↓ open down ↓ |
569 lines elided |
↑ open up ↑ |
1358 1719 /* Force last close. */
1359 1720 np->n_dirrefs = 1;
1360 1721 smbfs_rele_fid(np, &scred);
1361 1722 break;
1362 1723
1363 1724 case VREG:
1364 1725 if (np->n_fidrefs == 0)
1365 1726 break;
1366 1727 SMBVDEBUG("open file: refs %d id 0x%x path %s\n",
1367 1728 np->n_fidrefs, np->n_fid, np->n_rpath);
1729 + /*
1730 + * Before otW close, make sure dirty pages written back.
1731 + */
1732 + if (vn_has_cached_data(vp)) {
1733 + /* smbfs_putapage() will acquire shared lock, so release
1734 + * exclusive lock temporally.
1735 + */
1736 + smbfs_rw_exit(&np->r_lkserlock);
1737 +
1738 + (void) smbfs_putpage(vp, (offset_t) 0, 0, B_INVAL | B_ASYNC, cr, ct);
1739 +
1740 + /* acquire exclusive lock again. */
1741 + (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
1742 + }
1368 1743 /* Force last close. */
1369 1744 np->n_fidrefs = 1;
1370 1745 smbfs_rele_fid(np, &scred);
1371 1746 break;
1372 1747
1373 1748 default:
1374 1749 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
1375 1750 np->n_ovtype = VNON;
1376 1751 break;
1377 1752 }
1378 1753
1379 1754 smb_credrele(&scred);
1380 1755 smbfs_rw_exit(&np->r_lkserlock);
1381 1756
1382 1757 smbfs_addfree(np);
1383 1758 }
1384 1759
1385 1760 /*
1386 1761 * Remote file system operations having to do with directory manipulation.
1387 1762 */
1388 1763 /* ARGSUSED */
1389 1764 static int
1390 1765 smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
1391 1766 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
1392 1767 int *direntflags, pathname_t *realpnp)
1393 1768 {
1394 1769 vfs_t *vfs;
1395 1770 smbmntinfo_t *smi;
1396 1771 smbnode_t *dnp;
1397 1772 int error;
1398 1773
1399 1774 vfs = dvp->v_vfsp;
1400 1775 smi = VFTOSMI(vfs);
1401 1776
1402 1777 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1403 1778 return (EPERM);
1404 1779
1405 1780 if (smi->smi_flags & SMI_DEAD || vfs->vfs_flag & VFS_UNMOUNTED)
1406 1781 return (EIO);
1407 1782
1408 1783 dnp = VTOSMB(dvp);
1409 1784
1410 1785 /*
1411 1786 * Are we looking up extended attributes? If so, "dvp" is
1412 1787 * the file or directory for which we want attributes, and
1413 1788 * we need a lookup of the (faked up) attribute directory
1414 1789 * before we lookup the rest of the path.
1415 1790 */
1416 1791 if (flags & LOOKUP_XATTR) {
1417 1792 /*
1418 1793 * Require the xattr mount option.
1419 1794 */
1420 1795 if ((vfs->vfs_flag & VFS_XATTR) == 0)
1421 1796 return (EINVAL);
1422 1797
1423 1798 error = smbfs_get_xattrdir(dvp, vpp, cr, flags);
1424 1799 return (error);
1425 1800 }
1426 1801
1427 1802 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp)))
1428 1803 return (EINTR);
1429 1804
1430 1805 error = smbfslookup(dvp, nm, vpp, cr, 1, ct);
1431 1806
1432 1807 smbfs_rw_exit(&dnp->r_rwlock);
1433 1808
1434 1809 return (error);
1435 1810 }
1436 1811
1437 1812 /* ARGSUSED */
1438 1813 static int
1439 1814 smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
1440 1815 int cache_ok, caller_context_t *ct)
1441 1816 {
1442 1817 int error;
1443 1818 int supplen; /* supported length */
1444 1819 vnode_t *vp;
1445 1820 smbnode_t *np;
1446 1821 smbnode_t *dnp;
1447 1822 smbmntinfo_t *smi;
1448 1823 /* struct smb_vc *vcp; */
1449 1824 const char *ill;
1450 1825 const char *name = (const char *)nm;
1451 1826 int nmlen = strlen(nm);
1452 1827 int rplen;
1453 1828 struct smb_cred scred;
1454 1829 struct smbfattr fa;
1455 1830
1456 1831 smi = VTOSMI(dvp);
1457 1832 dnp = VTOSMB(dvp);
1458 1833
1459 1834 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
1460 1835
1461 1836 #ifdef NOT_YET
1462 1837 vcp = SSTOVC(smi->smi_share);
1463 1838
1464 1839 /* XXX: Should compute this once and store it in smbmntinfo_t */
1465 1840 supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12;
1466 1841 #else
1467 1842 supplen = 255;
1468 1843 #endif
1469 1844
1470 1845 /*
1471 1846 * RWlock must be held, either reader or writer.
1472 1847 * XXX: Can we check without looking directly
1473 1848 * inside the struct smbfs_rwlock_t?
1474 1849 */
1475 1850 ASSERT(dnp->r_rwlock.count != 0);
1476 1851
1477 1852 /*
1478 1853 * If lookup is for "", just return dvp.
1479 1854 * No need to perform any access checks.
1480 1855 */
1481 1856 if (nmlen == 0) {
1482 1857 VN_HOLD(dvp);
1483 1858 *vpp = dvp;
1484 1859 return (0);
1485 1860 }
1486 1861
1487 1862 /*
1488 1863 * Can't do lookups in non-directories.
1489 1864 */
1490 1865 if (dvp->v_type != VDIR)
1491 1866 return (ENOTDIR);
1492 1867
1493 1868 /*
1494 1869 * Need search permission in the directory.
1495 1870 */
1496 1871 error = smbfs_access(dvp, VEXEC, 0, cr, ct);
1497 1872 if (error)
1498 1873 return (error);
1499 1874
1500 1875 /*
1501 1876 * If lookup is for ".", just return dvp.
1502 1877 * Access check was done above.
1503 1878 */
1504 1879 if (nmlen == 1 && name[0] == '.') {
1505 1880 VN_HOLD(dvp);
1506 1881 *vpp = dvp;
1507 1882 return (0);
1508 1883 }
1509 1884
1510 1885 /*
1511 1886 * Now some sanity checks on the name.
1512 1887 * First check the length.
1513 1888 */
1514 1889 if (nmlen > supplen)
1515 1890 return (ENAMETOOLONG);
1516 1891
1517 1892 /*
1518 1893 * Avoid surprises with characters that are
1519 1894 * illegal in Windows file names.
1520 1895 * Todo: CATIA mappings XXX
1521 1896 */
1522 1897 ill = illegal_chars;
1523 1898 if (dnp->n_flag & N_XATTR)
1524 1899 ill++; /* allow colon */
1525 1900 if (strpbrk(nm, ill))
1526 1901 return (EINVAL);
1527 1902
1528 1903 /*
1529 1904 * Special handling for lookup of ".."
1530 1905 *
1531 1906 * We keep full pathnames (as seen on the server)
1532 1907 * so we can just trim off the last component to
1533 1908 * get the full pathname of the parent. Note:
1534 1909 * We don't actually copy and modify, but just
1535 1910 * compute the trimmed length and pass that with
1536 1911 * the current dir path (not null terminated).
1537 1912 *
1538 1913 * We don't go over-the-wire to get attributes
1539 1914 * for ".." because we know it's a directory,
1540 1915 * and we can just leave the rest "stale"
1541 1916 * until someone does a getattr.
1542 1917 */
1543 1918 if (nmlen == 2 && name[0] == '.' && name[1] == '.') {
1544 1919 if (dvp->v_flag & VROOT) {
1545 1920 /*
1546 1921 * Already at the root. This can happen
1547 1922 * with directory listings at the root,
1548 1923 * which lookup "." and ".." to get the
1549 1924 * inode numbers. Let ".." be the same
1550 1925 * as "." in the FS root.
1551 1926 */
1552 1927 VN_HOLD(dvp);
1553 1928 *vpp = dvp;
1554 1929 return (0);
1555 1930 }
1556 1931
1557 1932 /*
1558 1933 * Special case for XATTR directory
1559 1934 */
1560 1935 if (dvp->v_flag & V_XATTRDIR) {
1561 1936 error = smbfs_xa_parent(dvp, vpp);
1562 1937 return (error);
1563 1938 }
1564 1939
1565 1940 /*
1566 1941 * Find the parent path length.
1567 1942 */
1568 1943 rplen = dnp->n_rplen;
1569 1944 ASSERT(rplen > 0);
1570 1945 while (--rplen >= 0) {
1571 1946 if (dnp->n_rpath[rplen] == '\\')
1572 1947 break;
1573 1948 }
1574 1949 if (rplen <= 0) {
1575 1950 /* Found our way to the root. */
1576 1951 vp = SMBTOV(smi->smi_root);
1577 1952 VN_HOLD(vp);
1578 1953 *vpp = vp;
1579 1954 return (0);
1580 1955 }
1581 1956 np = smbfs_node_findcreate(smi,
1582 1957 dnp->n_rpath, rplen, NULL, 0, 0,
1583 1958 &smbfs_fattr0); /* force create */
1584 1959 ASSERT(np != NULL);
1585 1960 vp = SMBTOV(np);
1586 1961 vp->v_type = VDIR;
1587 1962
1588 1963 /* Success! */
1589 1964 *vpp = vp;
1590 1965 return (0);
1591 1966 }
1592 1967
1593 1968 /*
1594 1969 * Normal lookup of a name under this directory.
1595 1970 * Note we handled "", ".", ".." above.
1596 1971 */
1597 1972 if (cache_ok) {
1598 1973 /*
1599 1974 * The caller indicated that it's OK to use a
1600 1975 * cached result for this lookup, so try to
1601 1976 * reclaim a node from the smbfs node cache.
1602 1977 */
1603 1978 error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr);
1604 1979 if (error)
1605 1980 return (error);
1606 1981 if (vp != NULL) {
1607 1982 /* hold taken in lookup_cache */
1608 1983 *vpp = vp;
1609 1984 return (0);
1610 1985 }
1611 1986 }
1612 1987
1613 1988 /*
1614 1989 * OK, go over-the-wire to get the attributes,
1615 1990 * then create the node.
1616 1991 */
1617 1992 smb_credinit(&scred, cr);
1618 1993 /* Note: this can allocate a new "name" */
1619 1994 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred);
1620 1995 smb_credrele(&scred);
1621 1996 if (error == ENOTDIR) {
1622 1997 /*
1623 1998 * Lookup failed because this directory was
1624 1999 * removed or renamed by another client.
1625 2000 * Remove any cached attributes under it.
1626 2001 */
1627 2002 smbfs_attrcache_remove(dnp);
1628 2003 smbfs_attrcache_prune(dnp);
1629 2004 }
1630 2005 if (error)
1631 2006 goto out;
1632 2007
1633 2008 error = smbfs_nget(dvp, name, nmlen, &fa, &vp);
1634 2009 if (error)
1635 2010 goto out;
1636 2011
1637 2012 /* Success! */
1638 2013 *vpp = vp;
1639 2014
1640 2015 out:
1641 2016 /* smbfs_smb_lookup may have allocated name. */
1642 2017 if (name != nm)
1643 2018 smbfs_name_free(name, nmlen);
1644 2019
1645 2020 return (error);
1646 2021 }
1647 2022
1648 2023 /*
1649 2024 * smbfslookup_cache
1650 2025 *
1651 2026 * Try to reclaim a node from the smbfs node cache.
1652 2027 * Some statistics for DEBUG.
1653 2028 *
1654 2029 * This mechanism lets us avoid many of the five (or more)
1655 2030 * OtW lookup calls per file seen with "ls -l" if we search
1656 2031 * the smbfs node cache for recently inactive(ated) nodes.
1657 2032 */
1658 2033 #ifdef DEBUG
1659 2034 int smbfs_lookup_cache_calls = 0;
1660 2035 int smbfs_lookup_cache_error = 0;
1661 2036 int smbfs_lookup_cache_miss = 0;
1662 2037 int smbfs_lookup_cache_stale = 0;
1663 2038 int smbfs_lookup_cache_hits = 0;
1664 2039 #endif /* DEBUG */
1665 2040
1666 2041 /* ARGSUSED */
1667 2042 static int
1668 2043 smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen,
1669 2044 vnode_t **vpp, cred_t *cr)
1670 2045 {
1671 2046 struct vattr va;
1672 2047 smbnode_t *dnp;
1673 2048 smbnode_t *np;
1674 2049 vnode_t *vp;
1675 2050 int error;
1676 2051 char sep;
1677 2052
1678 2053 dnp = VTOSMB(dvp);
1679 2054 *vpp = NULL;
1680 2055
1681 2056 #ifdef DEBUG
1682 2057 smbfs_lookup_cache_calls++;
1683 2058 #endif
1684 2059
1685 2060 /*
1686 2061 * First make sure we can get attributes for the
1687 2062 * directory. Cached attributes are OK here.
1688 2063 * If we removed or renamed the directory, this
1689 2064 * will return ENOENT. If someone else removed
1690 2065 * this directory or file, we'll find out when we
1691 2066 * try to open or get attributes.
1692 2067 */
1693 2068 va.va_mask = AT_TYPE | AT_MODE;
1694 2069 error = smbfsgetattr(dvp, &va, cr);
1695 2070 if (error) {
1696 2071 #ifdef DEBUG
1697 2072 smbfs_lookup_cache_error++;
1698 2073 #endif
1699 2074 return (error);
1700 2075 }
1701 2076
1702 2077 /*
1703 2078 * Passing NULL smbfattr here so we will
1704 2079 * just look, not create.
1705 2080 */
1706 2081 sep = SMBFS_DNP_SEP(dnp);
1707 2082 np = smbfs_node_findcreate(dnp->n_mount,
1708 2083 dnp->n_rpath, dnp->n_rplen,
1709 2084 nm, nmlen, sep, NULL);
1710 2085 if (np == NULL) {
1711 2086 #ifdef DEBUG
1712 2087 smbfs_lookup_cache_miss++;
1713 2088 #endif
1714 2089 return (0);
1715 2090 }
1716 2091
1717 2092 /*
1718 2093 * Found it. Attributes still valid?
1719 2094 */
1720 2095 vp = SMBTOV(np);
1721 2096 if (np->r_attrtime <= gethrtime()) {
1722 2097 /* stale */
1723 2098 #ifdef DEBUG
1724 2099 smbfs_lookup_cache_stale++;
1725 2100 #endif
1726 2101 VN_RELE(vp);
1727 2102 return (0);
1728 2103 }
1729 2104
1730 2105 /*
1731 2106 * Success!
1732 2107 * Caller gets hold from smbfs_node_findcreate
1733 2108 */
1734 2109 #ifdef DEBUG
1735 2110 smbfs_lookup_cache_hits++;
1736 2111 #endif
1737 2112 *vpp = vp;
1738 2113 return (0);
1739 2114 }
1740 2115
1741 2116 /*
1742 2117 * XXX
1743 2118 * vsecattr_t is new to build 77, and we need to eventually support
1744 2119 * it in order to create an ACL when an object is created.
1745 2120 *
1746 2121 * This op should support the new FIGNORECASE flag for case-insensitive
1747 2122 * lookups, per PSARC 2007/244.
1748 2123 */
1749 2124 /* ARGSUSED */
1750 2125 static int
1751 2126 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
1752 2127 int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct,
1753 2128 vsecattr_t *vsecp)
1754 2129 {
1755 2130 int error;
1756 2131 int cerror;
1757 2132 vfs_t *vfsp;
1758 2133 vnode_t *vp;
1759 2134 #ifdef NOT_YET
1760 2135 smbnode_t *np;
1761 2136 #endif
1762 2137 smbnode_t *dnp;
1763 2138 smbmntinfo_t *smi;
1764 2139 struct vattr vattr;
1765 2140 struct smbfattr fattr;
1766 2141 struct smb_cred scred;
1767 2142 const char *name = (const char *)nm;
1768 2143 int nmlen = strlen(nm);
1769 2144 uint32_t disp;
1770 2145 uint16_t fid;
1771 2146 int xattr;
1772 2147
1773 2148 vfsp = dvp->v_vfsp;
1774 2149 smi = VFTOSMI(vfsp);
1775 2150 dnp = VTOSMB(dvp);
1776 2151 vp = NULL;
1777 2152
1778 2153 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1779 2154 return (EPERM);
1780 2155
1781 2156 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1782 2157 return (EIO);
1783 2158
1784 2159 /*
1785 2160 * Note: this may break mknod(2) calls to create a directory,
1786 2161 * but that's obscure use. Some other filesystems do this.
1787 2162 * XXX: Later, redirect VDIR type here to _mkdir.
1788 2163 */
1789 2164 if (va->va_type != VREG)
1790 2165 return (EINVAL);
1791 2166
1792 2167 /*
1793 2168 * If the pathname is "", just use dvp, no checks.
1794 2169 * Do this outside of the rwlock (like zfs).
1795 2170 */
1796 2171 if (nmlen == 0) {
1797 2172 VN_HOLD(dvp);
1798 2173 *vpp = dvp;
1799 2174 return (0);
1800 2175 }
1801 2176
1802 2177 /* Don't allow "." or ".." through here. */
1803 2178 if ((nmlen == 1 && name[0] == '.') ||
1804 2179 (nmlen == 2 && name[0] == '.' && name[1] == '.'))
1805 2180 return (EISDIR);
1806 2181
1807 2182 /*
1808 2183 * We make a copy of the attributes because the caller does not
1809 2184 * expect us to change what va points to.
1810 2185 */
1811 2186 vattr = *va;
1812 2187
1813 2188 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
1814 2189 return (EINTR);
1815 2190 smb_credinit(&scred, cr);
1816 2191
1817 2192 /*
1818 2193 * XXX: Do we need r_lkserlock too?
1819 2194 * No use of any shared fid or fctx...
1820 2195 */
1821 2196
1822 2197 /*
1823 2198 * NFS needs to go over the wire, just to be sure whether the
1824 2199 * file exists or not. Using a cached result is dangerous in
1825 2200 * this case when making a decision regarding existence.
1826 2201 *
1827 2202 * The SMB protocol does NOT really need to go OTW here
1828 2203 * thanks to the expressive NTCREATE disposition values.
1829 2204 * Unfortunately, to do Unix access checks correctly,
1830 2205 * we need to know if the object already exists.
1831 2206 * When the object does not exist, we need VWRITE on
1832 2207 * the directory. Note: smbfslookup() checks VEXEC.
1833 2208 */
1834 2209 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
1835 2210 if (error == 0) {
1836 2211 /*
1837 2212 * The file already exists. Error?
1838 2213 * NB: have a hold from smbfslookup
1839 2214 */
1840 2215 if (exclusive == EXCL) {
1841 2216 error = EEXIST;
1842 2217 VN_RELE(vp);
1843 2218 goto out;
1844 2219 }
1845 2220 /*
1846 2221 * Verify requested access.
1847 2222 */
1848 2223 error = smbfs_access(vp, mode, 0, cr, ct);
1849 2224 if (error) {
1850 2225 VN_RELE(vp);
1851 2226 goto out;
1852 2227 }
1853 2228
1854 2229 /*
1855 2230 * Truncate (if requested).
1856 2231 */
1857 2232 if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) {
1858 2233 vattr.va_mask = AT_SIZE;
1859 2234 error = smbfssetattr(vp, &vattr, 0, cr);
1860 2235 if (error) {
1861 2236 VN_RELE(vp);
1862 2237 goto out;
1863 2238 }
1864 2239 }
1865 2240 /* Success! */
1866 2241 #ifdef NOT_YET
1867 2242 vnevent_create(vp, ct);
1868 2243 #endif
1869 2244 *vpp = vp;
1870 2245 goto out;
1871 2246 }
1872 2247
1873 2248 /*
1874 2249 * The file did not exist. Need VWRITE in the directory.
1875 2250 */
1876 2251 error = smbfs_access(dvp, VWRITE, 0, cr, ct);
1877 2252 if (error)
1878 2253 goto out;
1879 2254
1880 2255 /*
1881 2256 * Now things get tricky. We also need to check the
1882 2257 * requested open mode against the file we may create.
1883 2258 * See comments at smbfs_access_rwx
1884 2259 */
1885 2260 error = smbfs_access_rwx(vfsp, VREG, mode, cr);
1886 2261 if (error)
1887 2262 goto out;
1888 2263
1889 2264 /*
1890 2265 * Now the code derived from Darwin,
1891 2266 * but with greater use of NT_CREATE
1892 2267 * disposition options. Much changed.
1893 2268 *
1894 2269 * Create (or open) a new child node.
1895 2270 * Note we handled "." and ".." above.
1896 2271 */
1897 2272
1898 2273 if (exclusive == EXCL)
1899 2274 disp = NTCREATEX_DISP_CREATE;
1900 2275 else {
1901 2276 /* Truncate regular files if requested. */
1902 2277 if ((va->va_type == VREG) &&
1903 2278 (va->va_mask & AT_SIZE) &&
1904 2279 (va->va_size == 0))
1905 2280 disp = NTCREATEX_DISP_OVERWRITE_IF;
1906 2281 else
1907 2282 disp = NTCREATEX_DISP_OPEN_IF;
1908 2283 }
1909 2284 xattr = (dnp->n_flag & N_XATTR) ? 1 : 0;
1910 2285 error = smbfs_smb_create(dnp,
1911 2286 name, nmlen, xattr,
1912 2287 disp, &scred, &fid);
1913 2288 if (error)
1914 2289 goto out;
1915 2290
1916 2291 /*
1917 2292 * XXX: Missing some code here to deal with
1918 2293 * the case where we opened an existing file,
1919 2294 * it's size is larger than 32-bits, and we're
1920 2295 * setting the size from a process that's not
1921 2296 * aware of large file offsets. i.e.
1922 2297 * from the NFS3 code:
1923 2298 */
1924 2299 #if NOT_YET /* XXX */
1925 2300 if ((vattr.va_mask & AT_SIZE) &&
1926 2301 vp->v_type == VREG) {
1927 2302 np = VTOSMB(vp);
1928 2303 /*
1929 2304 * Check here for large file handled
1930 2305 * by LF-unaware process (as
1931 2306 * ufs_create() does)
1932 2307 */
1933 2308 if (!(lfaware & FOFFMAX)) {
1934 2309 mutex_enter(&np->r_statelock);
1935 2310 if (np->r_size > MAXOFF32_T)
1936 2311 error = EOVERFLOW;
1937 2312 mutex_exit(&np->r_statelock);
1938 2313 }
1939 2314 if (!error) {
1940 2315 vattr.va_mask = AT_SIZE;
1941 2316 error = smbfssetattr(vp,
1942 2317 &vattr, 0, cr);
1943 2318 }
1944 2319 }
1945 2320 #endif /* XXX */
1946 2321 /*
1947 2322 * Should use the fid to get/set the size
1948 2323 * while we have it opened here. See above.
1949 2324 */
1950 2325
1951 2326 cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred);
1952 2327 if (cerror)
1953 2328 SMBVDEBUG("error %d closing %s\\%s\n",
1954 2329 cerror, dnp->n_rpath, name);
1955 2330
1956 2331 /*
1957 2332 * In the open case, the name may differ a little
1958 2333 * from what we passed to create (case, etc.)
1959 2334 * so call lookup to get the (opened) name.
1960 2335 *
1961 2336 * XXX: Could avoid this extra lookup if the
1962 2337 * "createact" result from NT_CREATE says we
1963 2338 * created the object.
1964 2339 */
1965 2340 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
1966 2341 if (error)
1967 2342 goto out;
1968 2343
1969 2344 /* update attr and directory cache */
1970 2345 smbfs_attr_touchdir(dnp);
1971 2346
1972 2347 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
1973 2348 if (error)
1974 2349 goto out;
1975 2350
1976 2351 /* XXX invalidate pages if we truncated? */
1977 2352
1978 2353 /* Success! */
1979 2354 *vpp = vp;
1980 2355 error = 0;
1981 2356
1982 2357 out:
1983 2358 smb_credrele(&scred);
1984 2359 smbfs_rw_exit(&dnp->r_rwlock);
1985 2360 if (name != nm)
1986 2361 smbfs_name_free(name, nmlen);
1987 2362 return (error);
1988 2363 }
1989 2364
1990 2365 /*
1991 2366 * XXX
1992 2367 * This op should support the new FIGNORECASE flag for case-insensitive
1993 2368 * lookups, per PSARC 2007/244.
1994 2369 */
1995 2370 /* ARGSUSED */
1996 2371 static int
1997 2372 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
1998 2373 int flags)
1999 2374 {
2000 2375 int error;
2001 2376 vnode_t *vp;
2002 2377 smbnode_t *np;
2003 2378 smbnode_t *dnp;
2004 2379 struct smb_cred scred;
2005 2380 /* enum smbfsstat status; */
2006 2381 smbmntinfo_t *smi;
2007 2382
2008 2383 smi = VTOSMI(dvp);
2009 2384
2010 2385 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2011 2386 return (EPERM);
2012 2387
2013 2388 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2014 2389 return (EIO);
2015 2390
2016 2391 dnp = VTOSMB(dvp);
2017 2392 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2018 2393 return (EINTR);
2019 2394 smb_credinit(&scred, cr);
2020 2395
2021 2396 /*
2022 2397 * Verify access to the dirctory.
2023 2398 */
2024 2399 error = smbfs_access(dvp, VWRITE|VEXEC, 0, cr, ct);
2025 2400 if (error)
2026 2401 goto out;
2027 2402
2028 2403 /*
2029 2404 * NOTE: the darwin code gets the "vp" passed in so it looks
2030 2405 * like the "vp" has probably been "lookup"ed by the VFS layer.
2031 2406 * It looks like we will need to lookup the vp to check the
2032 2407 * caches and check if the object being deleted is a directory.
2033 2408 */
2034 2409 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2035 2410 if (error)
2036 2411 goto out;
2037 2412
2038 2413 /* Never allow link/unlink directories on CIFS. */
2039 2414 if (vp->v_type == VDIR) {
2040 2415 VN_RELE(vp);
2041 2416 error = EPERM;
2042 2417 goto out;
2043 2418 }
2044 2419
2045 2420 /*
2046 2421 * Now we have the real reference count on the vnode
2047 2422 * Do we have the file open?
2048 2423 */
2049 2424 np = VTOSMB(vp);
2050 2425 mutex_enter(&np->r_statelock);
2051 2426 if ((vp->v_count > 1) && (np->n_fidrefs > 0)) {
2052 2427 /*
2053 2428 * NFS does a rename on remove here.
2054 2429 * Probably not applicable for SMB.
2055 2430 * Like Darwin, just return EBUSY.
2056 2431 *
2057 2432 * XXX: Todo - Use Trans2rename, and
2058 2433 * if that fails, ask the server to
2059 2434 * set the delete-on-close flag.
2060 2435 */
2061 2436 mutex_exit(&np->r_statelock);
2062 2437 error = EBUSY;
2063 2438 } else {
2064 2439 smbfs_attrcache_rm_locked(np);
2065 2440 mutex_exit(&np->r_statelock);
2066 2441
2067 2442 error = smbfs_smb_delete(np, &scred, NULL, 0, 0);
2068 2443
2069 2444 /*
2070 2445 * If the file should no longer exist, discard
2071 2446 * any cached attributes under this node.
2072 2447 */
2073 2448 switch (error) {
2074 2449 case 0:
2075 2450 case ENOENT:
2076 2451 case ENOTDIR:
2077 2452 smbfs_attrcache_prune(np);
2078 2453 break;
2079 2454 }
2080 2455 }
2081 2456
2082 2457 VN_RELE(vp);
2083 2458
2084 2459 out:
2085 2460 smb_credrele(&scred);
2086 2461 smbfs_rw_exit(&dnp->r_rwlock);
2087 2462
2088 2463 return (error);
2089 2464 }
2090 2465
2091 2466
2092 2467 /*
2093 2468 * XXX
2094 2469 * This op should support the new FIGNORECASE flag for case-insensitive
2095 2470 * lookups, per PSARC 2007/244.
2096 2471 */
2097 2472 /* ARGSUSED */
2098 2473 static int
2099 2474 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2100 2475 caller_context_t *ct, int flags)
2101 2476 {
2102 2477 /* vnode_t *realvp; */
2103 2478
2104 2479 if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone ||
2105 2480 curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone)
2106 2481 return (EPERM);
2107 2482
2108 2483 if (VTOSMI(odvp)->smi_flags & SMI_DEAD ||
2109 2484 VTOSMI(ndvp)->smi_flags & SMI_DEAD ||
2110 2485 odvp->v_vfsp->vfs_flag & VFS_UNMOUNTED ||
2111 2486 ndvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2112 2487 return (EIO);
2113 2488
2114 2489 return (smbfsrename(odvp, onm, ndvp, nnm, cr, ct));
2115 2490 }
2116 2491
2117 2492 /*
2118 2493 * smbfsrename does the real work of renaming in SMBFS
2119 2494 */
2120 2495 /* ARGSUSED */
2121 2496 static int
2122 2497 smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2123 2498 caller_context_t *ct)
2124 2499 {
2125 2500 int error;
2126 2501 int nvp_locked = 0;
2127 2502 vnode_t *nvp = NULL;
2128 2503 vnode_t *ovp = NULL;
2129 2504 smbnode_t *onp;
2130 2505 smbnode_t *nnp;
2131 2506 smbnode_t *odnp;
2132 2507 smbnode_t *ndnp;
2133 2508 struct smb_cred scred;
2134 2509 /* enum smbfsstat status; */
2135 2510
2136 2511 ASSERT(curproc->p_zone == VTOSMI(odvp)->smi_zone_ref.zref_zone);
2137 2512
2138 2513 if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 ||
2139 2514 strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0)
2140 2515 return (EINVAL);
2141 2516
2142 2517 /*
2143 2518 * Check that everything is on the same filesystem.
2144 2519 * vn_rename checks the fsid's, but in case we don't
2145 2520 * fill those in correctly, check here too.
2146 2521 */
2147 2522 if (odvp->v_vfsp != ndvp->v_vfsp)
2148 2523 return (EXDEV);
2149 2524
2150 2525 odnp = VTOSMB(odvp);
2151 2526 ndnp = VTOSMB(ndvp);
2152 2527
2153 2528 /*
2154 2529 * Avoid deadlock here on old vs new directory nodes
2155 2530 * by always taking the locks in order of address.
2156 2531 * The order is arbitrary, but must be consistent.
2157 2532 */
2158 2533 if (odnp < ndnp) {
2159 2534 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2160 2535 SMBINTR(odvp)))
2161 2536 return (EINTR);
2162 2537 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2163 2538 SMBINTR(ndvp))) {
2164 2539 smbfs_rw_exit(&odnp->r_rwlock);
2165 2540 return (EINTR);
2166 2541 }
2167 2542 } else {
2168 2543 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2169 2544 SMBINTR(ndvp)))
2170 2545 return (EINTR);
2171 2546 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2172 2547 SMBINTR(odvp))) {
2173 2548 smbfs_rw_exit(&ndnp->r_rwlock);
2174 2549 return (EINTR);
2175 2550 }
2176 2551 }
2177 2552 smb_credinit(&scred, cr);
2178 2553 /*
2179 2554 * No returns after this point (goto out)
2180 2555 */
2181 2556
2182 2557 /*
2183 2558 * Need write access on source and target.
2184 2559 * Server takes care of most checks.
2185 2560 */
2186 2561 error = smbfs_access(odvp, VWRITE|VEXEC, 0, cr, ct);
2187 2562 if (error)
2188 2563 goto out;
2189 2564 if (odvp != ndvp) {
2190 2565 error = smbfs_access(ndvp, VWRITE, 0, cr, ct);
2191 2566 if (error)
2192 2567 goto out;
2193 2568 }
2194 2569
2195 2570 /*
2196 2571 * Lookup the source name. Must already exist.
2197 2572 */
2198 2573 error = smbfslookup(odvp, onm, &ovp, cr, 0, ct);
2199 2574 if (error)
2200 2575 goto out;
2201 2576
2202 2577 /*
2203 2578 * Lookup the target file. If it exists, it needs to be
2204 2579 * checked to see whether it is a mount point and whether
2205 2580 * it is active (open).
2206 2581 */
2207 2582 error = smbfslookup(ndvp, nnm, &nvp, cr, 0, ct);
2208 2583 if (!error) {
2209 2584 /*
2210 2585 * Target (nvp) already exists. Check that it
2211 2586 * has the same type as the source. The server
2212 2587 * will check this also, (and more reliably) but
2213 2588 * this lets us return the correct error codes.
2214 2589 */
2215 2590 if (ovp->v_type == VDIR) {
2216 2591 if (nvp->v_type != VDIR) {
2217 2592 error = ENOTDIR;
2218 2593 goto out;
2219 2594 }
2220 2595 } else {
2221 2596 if (nvp->v_type == VDIR) {
2222 2597 error = EISDIR;
2223 2598 goto out;
2224 2599 }
2225 2600 }
2226 2601
2227 2602 /*
2228 2603 * POSIX dictates that when the source and target
2229 2604 * entries refer to the same file object, rename
2230 2605 * must do nothing and exit without error.
2231 2606 */
2232 2607 if (ovp == nvp) {
2233 2608 error = 0;
2234 2609 goto out;
2235 2610 }
2236 2611
2237 2612 /*
2238 2613 * Also must ensure the target is not a mount point,
2239 2614 * and keep mount/umount away until we're done.
2240 2615 */
2241 2616 if (vn_vfsrlock(nvp)) {
2242 2617 error = EBUSY;
2243 2618 goto out;
2244 2619 }
2245 2620 nvp_locked = 1;
2246 2621 if (vn_mountedvfs(nvp) != NULL) {
2247 2622 error = EBUSY;
2248 2623 goto out;
2249 2624 }
2250 2625
2251 2626 /*
2252 2627 * CIFS gives a SHARING_VIOLATION error when
2253 2628 * trying to rename onto an exising object,
2254 2629 * so try to remove the target first.
2255 2630 * (Only for files, not directories.)
2256 2631 */
2257 2632 if (nvp->v_type == VDIR) {
2258 2633 error = EEXIST;
2259 2634 goto out;
2260 2635 }
2261 2636
2262 2637 /*
2263 2638 * Nodes that are "not active" here have v_count=2
2264 2639 * because vn_renameat (our caller) did a lookup on
2265 2640 * both the source and target before this call.
2266 2641 * Otherwise this similar to smbfs_remove.
2267 2642 */
2268 2643 nnp = VTOSMB(nvp);
2269 2644 mutex_enter(&nnp->r_statelock);
2270 2645 if ((nvp->v_count > 2) && (nnp->n_fidrefs > 0)) {
2271 2646 /*
2272 2647 * The target file exists, is not the same as
2273 2648 * the source file, and is active. Other FS
2274 2649 * implementations unlink the target here.
2275 2650 * For SMB, we don't assume we can remove an
2276 2651 * open file. Return an error instead.
2277 2652 */
2278 2653 mutex_exit(&nnp->r_statelock);
2279 2654 error = EBUSY;
2280 2655 goto out;
2281 2656 }
2282 2657
2283 2658 /*
2284 2659 * Target file is not active. Try to remove it.
2285 2660 */
2286 2661 smbfs_attrcache_rm_locked(nnp);
2287 2662 mutex_exit(&nnp->r_statelock);
2288 2663
2289 2664 error = smbfs_smb_delete(nnp, &scred, NULL, 0, 0);
2290 2665
2291 2666 /*
2292 2667 * Similar to smbfs_remove
2293 2668 */
2294 2669 switch (error) {
2295 2670 case 0:
2296 2671 case ENOENT:
2297 2672 case ENOTDIR:
2298 2673 smbfs_attrcache_prune(nnp);
2299 2674 break;
2300 2675 }
2301 2676
2302 2677 if (error)
2303 2678 goto out;
2304 2679 /*
2305 2680 * OK, removed the target file. Continue as if
2306 2681 * lookup target had failed (nvp == NULL).
2307 2682 */
2308 2683 vn_vfsunlock(nvp);
2309 2684 nvp_locked = 0;
2310 2685 VN_RELE(nvp);
2311 2686 nvp = NULL;
2312 2687 } /* nvp */
2313 2688
2314 2689 onp = VTOSMB(ovp);
2315 2690 smbfs_attrcache_remove(onp);
2316 2691
2317 2692 error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), &scred);
2318 2693
2319 2694 /*
2320 2695 * If the old name should no longer exist,
2321 2696 * discard any cached attributes under it.
2322 2697 */
2323 2698 if (error == 0)
2324 2699 smbfs_attrcache_prune(onp);
2325 2700
2326 2701 out:
2327 2702 if (nvp) {
2328 2703 if (nvp_locked)
2329 2704 vn_vfsunlock(nvp);
2330 2705 VN_RELE(nvp);
2331 2706 }
2332 2707 if (ovp)
2333 2708 VN_RELE(ovp);
2334 2709
2335 2710 smb_credrele(&scred);
2336 2711 smbfs_rw_exit(&odnp->r_rwlock);
2337 2712 smbfs_rw_exit(&ndnp->r_rwlock);
2338 2713
2339 2714 return (error);
2340 2715 }
2341 2716
2342 2717 /*
2343 2718 * XXX
2344 2719 * vsecattr_t is new to build 77, and we need to eventually support
2345 2720 * it in order to create an ACL when an object is created.
2346 2721 *
2347 2722 * This op should support the new FIGNORECASE flag for case-insensitive
2348 2723 * lookups, per PSARC 2007/244.
2349 2724 */
2350 2725 /* ARGSUSED */
2351 2726 static int
2352 2727 smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp,
2353 2728 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
2354 2729 {
2355 2730 vnode_t *vp;
2356 2731 struct smbnode *dnp = VTOSMB(dvp);
2357 2732 struct smbmntinfo *smi = VTOSMI(dvp);
2358 2733 struct smb_cred scred;
2359 2734 struct smbfattr fattr;
2360 2735 const char *name = (const char *) nm;
2361 2736 int nmlen = strlen(name);
2362 2737 int error, hiderr;
2363 2738
2364 2739 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2365 2740 return (EPERM);
2366 2741
2367 2742 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2368 2743 return (EIO);
2369 2744
2370 2745 if ((nmlen == 1 && name[0] == '.') ||
2371 2746 (nmlen == 2 && name[0] == '.' && name[1] == '.'))
2372 2747 return (EEXIST);
2373 2748
2374 2749 /* Only plain files are allowed in V_XATTRDIR. */
2375 2750 if (dvp->v_flag & V_XATTRDIR)
2376 2751 return (EINVAL);
2377 2752
2378 2753 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2379 2754 return (EINTR);
2380 2755 smb_credinit(&scred, cr);
2381 2756
2382 2757 /*
2383 2758 * XXX: Do we need r_lkserlock too?
2384 2759 * No use of any shared fid or fctx...
2385 2760 */
2386 2761
2387 2762 /*
2388 2763 * Require write access in the containing directory.
2389 2764 */
2390 2765 error = smbfs_access(dvp, VWRITE, 0, cr, ct);
2391 2766 if (error)
2392 2767 goto out;
2393 2768
2394 2769 error = smbfs_smb_mkdir(dnp, name, nmlen, &scred);
2395 2770 if (error)
2396 2771 goto out;
2397 2772
2398 2773 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2399 2774 if (error)
2400 2775 goto out;
2401 2776
2402 2777 smbfs_attr_touchdir(dnp);
2403 2778
2404 2779 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2405 2780 if (error)
2406 2781 goto out;
2407 2782
2408 2783 if (name[0] == '.')
2409 2784 if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred)))
2410 2785 SMBVDEBUG("hide failure %d\n", hiderr);
2411 2786
2412 2787 /* Success! */
2413 2788 *vpp = vp;
2414 2789 error = 0;
2415 2790 out:
2416 2791 smb_credrele(&scred);
2417 2792 smbfs_rw_exit(&dnp->r_rwlock);
2418 2793
2419 2794 if (name != nm)
2420 2795 smbfs_name_free(name, nmlen);
2421 2796
2422 2797 return (error);
2423 2798 }
2424 2799
2425 2800 /*
2426 2801 * XXX
2427 2802 * This op should support the new FIGNORECASE flag for case-insensitive
2428 2803 * lookups, per PSARC 2007/244.
2429 2804 */
2430 2805 /* ARGSUSED */
2431 2806 static int
2432 2807 smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
2433 2808 caller_context_t *ct, int flags)
2434 2809 {
2435 2810 vnode_t *vp = NULL;
2436 2811 int vp_locked = 0;
2437 2812 struct smbmntinfo *smi = VTOSMI(dvp);
2438 2813 struct smbnode *dnp = VTOSMB(dvp);
2439 2814 struct smbnode *np;
2440 2815 struct smb_cred scred;
2441 2816 int error;
2442 2817
2443 2818 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2444 2819 return (EPERM);
2445 2820
2446 2821 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2447 2822 return (EIO);
2448 2823
2449 2824 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2450 2825 return (EINTR);
2451 2826 smb_credinit(&scred, cr);
2452 2827
2453 2828 /*
2454 2829 * Require w/x access in the containing directory.
2455 2830 * Server handles all other access checks.
2456 2831 */
2457 2832 error = smbfs_access(dvp, VEXEC|VWRITE, 0, cr, ct);
2458 2833 if (error)
2459 2834 goto out;
2460 2835
2461 2836 /*
2462 2837 * First lookup the entry to be removed.
2463 2838 */
2464 2839 error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2465 2840 if (error)
2466 2841 goto out;
2467 2842 np = VTOSMB(vp);
2468 2843
2469 2844 /*
2470 2845 * Disallow rmdir of "." or current dir, or the FS root.
2471 2846 * Also make sure it's a directory, not a mount point,
2472 2847 * and lock to keep mount/umount away until we're done.
2473 2848 */
2474 2849 if ((vp == dvp) || (vp == cdir) || (vp->v_flag & VROOT)) {
2475 2850 error = EINVAL;
2476 2851 goto out;
2477 2852 }
2478 2853 if (vp->v_type != VDIR) {
2479 2854 error = ENOTDIR;
2480 2855 goto out;
2481 2856 }
2482 2857 if (vn_vfsrlock(vp)) {
2483 2858 error = EBUSY;
2484 2859 goto out;
2485 2860 }
2486 2861 vp_locked = 1;
2487 2862 if (vn_mountedvfs(vp) != NULL) {
2488 2863 error = EBUSY;
2489 2864 goto out;
2490 2865 }
2491 2866
2492 2867 smbfs_attrcache_remove(np);
2493 2868 error = smbfs_smb_rmdir(np, &scred);
2494 2869
2495 2870 /*
2496 2871 * Similar to smbfs_remove
2497 2872 */
2498 2873 switch (error) {
2499 2874 case 0:
2500 2875 case ENOENT:
2501 2876 case ENOTDIR:
2502 2877 smbfs_attrcache_prune(np);
2503 2878 break;
2504 2879 }
2505 2880
2506 2881 if (error)
2507 2882 goto out;
2508 2883
2509 2884 mutex_enter(&np->r_statelock);
2510 2885 dnp->n_flag |= NMODIFIED;
2511 2886 mutex_exit(&np->r_statelock);
2512 2887 smbfs_attr_touchdir(dnp);
2513 2888 smbfs_rmhash(np);
2514 2889
2515 2890 out:
2516 2891 if (vp) {
2517 2892 if (vp_locked)
2518 2893 vn_vfsunlock(vp);
2519 2894 VN_RELE(vp);
2520 2895 }
2521 2896 smb_credrele(&scred);
2522 2897 smbfs_rw_exit(&dnp->r_rwlock);
2523 2898
2524 2899 return (error);
2525 2900 }
2526 2901
2527 2902
2528 2903 /* ARGSUSED */
2529 2904 static int
2530 2905 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp,
2531 2906 caller_context_t *ct, int flags)
2532 2907 {
2533 2908 struct smbnode *np = VTOSMB(vp);
2534 2909 int error = 0;
2535 2910 smbmntinfo_t *smi;
2536 2911
2537 2912 smi = VTOSMI(vp);
2538 2913
2539 2914 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2540 2915 return (EIO);
2541 2916
2542 2917 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2543 2918 return (EIO);
2544 2919
2545 2920 /*
2546 2921 * Require read access in the directory.
2547 2922 */
2548 2923 error = smbfs_access(vp, VREAD, 0, cr, ct);
2549 2924 if (error)
2550 2925 return (error);
2551 2926
2552 2927 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
2553 2928
2554 2929 /*
2555 2930 * XXX: Todo readdir cache here
2556 2931 * Note: NFS code is just below this.
2557 2932 *
2558 2933 * I am serializing the entire readdir opreation
2559 2934 * now since we have not yet implemented readdir
2560 2935 * cache. This fix needs to be revisited once
2561 2936 * we implement readdir cache.
2562 2937 */
2563 2938 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
2564 2939 return (EINTR);
2565 2940
2566 2941 error = smbfs_readvdir(vp, uiop, cr, eofp, ct);
2567 2942
2568 2943 smbfs_rw_exit(&np->r_lkserlock);
2569 2944
2570 2945 return (error);
2571 2946 }
2572 2947
2573 2948 /* ARGSUSED */
2574 2949 static int
2575 2950 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
2576 2951 caller_context_t *ct)
2577 2952 {
2578 2953 /*
2579 2954 * Note: "limit" tells the SMB-level FindFirst/FindNext
2580 2955 * functions how many directory entries to request in
2581 2956 * each OtW call. It needs to be large enough so that
2582 2957 * we don't make lots of tiny OtW requests, but there's
2583 2958 * no point making it larger than the maximum number of
2584 2959 * OtW entries that would fit in a maximum sized trans2
2585 2960 * response (64k / 48). Beyond that, it's just tuning.
2586 2961 * WinNT used 512, Win2k used 1366. We use 1000.
2587 2962 */
2588 2963 static const int limit = 1000;
2589 2964 /* Largest possible dirent size. */
2590 2965 static const size_t dbufsiz = DIRENT64_RECLEN(SMB_MAXFNAMELEN);
2591 2966 struct smb_cred scred;
2592 2967 vnode_t *newvp;
2593 2968 struct smbnode *np = VTOSMB(vp);
2594 2969 struct smbfs_fctx *ctx;
2595 2970 struct dirent64 *dp;
2596 2971 ssize_t save_resid;
2597 2972 offset_t save_offset; /* 64 bits */
2598 2973 int offset; /* yes, 32 bits */
2599 2974 int nmlen, error;
2600 2975 ushort_t reclen;
2601 2976
2602 2977 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
2603 2978
2604 2979 /* Make sure we serialize for n_dirseq use. */
2605 2980 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
2606 2981
2607 2982 /*
2608 2983 * Make sure smbfs_open filled in n_dirseq
2609 2984 */
2610 2985 if (np->n_dirseq == NULL)
2611 2986 return (EBADF);
2612 2987
2613 2988 /* Check for overflow of (32-bit) directory offset. */
2614 2989 if (uio->uio_loffset < 0 || uio->uio_loffset > INT32_MAX ||
2615 2990 (uio->uio_loffset + uio->uio_resid) > INT32_MAX)
2616 2991 return (EINVAL);
2617 2992
2618 2993 /* Require space for at least one dirent. */
2619 2994 if (uio->uio_resid < dbufsiz)
2620 2995 return (EINVAL);
2621 2996
2622 2997 SMBVDEBUG("dirname='%s'\n", np->n_rpath);
2623 2998 smb_credinit(&scred, cr);
2624 2999 dp = kmem_alloc(dbufsiz, KM_SLEEP);
2625 3000
2626 3001 save_resid = uio->uio_resid;
2627 3002 save_offset = uio->uio_loffset;
2628 3003 offset = uio->uio_offset;
2629 3004 SMBVDEBUG("in: offset=%d, resid=%d\n",
2630 3005 (int)uio->uio_offset, (int)uio->uio_resid);
2631 3006 error = 0;
2632 3007
2633 3008 /*
2634 3009 * Generate the "." and ".." entries here so we can
2635 3010 * (1) make sure they appear (but only once), and
2636 3011 * (2) deal with getting their I numbers which the
2637 3012 * findnext below does only for normal names.
2638 3013 */
2639 3014 while (offset < FIRST_DIROFS) {
2640 3015 /*
2641 3016 * Tricky bit filling in the first two:
2642 3017 * offset 0 is ".", offset 1 is ".."
2643 3018 * so strlen of these is offset+1.
2644 3019 */
2645 3020 reclen = DIRENT64_RECLEN(offset + 1);
2646 3021 if (uio->uio_resid < reclen)
2647 3022 goto out;
2648 3023 bzero(dp, reclen);
2649 3024 dp->d_reclen = reclen;
2650 3025 dp->d_name[0] = '.';
2651 3026 dp->d_name[1] = '.';
2652 3027 dp->d_name[offset + 1] = '\0';
2653 3028 /*
2654 3029 * Want the real I-numbers for the "." and ".."
2655 3030 * entries. For these two names, we know that
2656 3031 * smbfslookup can get the nodes efficiently.
2657 3032 */
2658 3033 error = smbfslookup(vp, dp->d_name, &newvp, cr, 1, ct);
2659 3034 if (error) {
2660 3035 dp->d_ino = np->n_ino + offset; /* fiction */
2661 3036 } else {
2662 3037 dp->d_ino = VTOSMB(newvp)->n_ino;
2663 3038 VN_RELE(newvp);
2664 3039 }
2665 3040 /*
2666 3041 * Note: d_off is the offset that a user-level program
2667 3042 * should seek to for reading the NEXT directory entry.
2668 3043 * See libc: readdir, telldir, seekdir
2669 3044 */
2670 3045 dp->d_off = offset + 1;
2671 3046 error = uiomove(dp, reclen, UIO_READ, uio);
2672 3047 if (error)
2673 3048 goto out;
2674 3049 /*
2675 3050 * Note: uiomove updates uio->uio_offset,
2676 3051 * but we want it to be our "cookie" value,
2677 3052 * which just counts dirents ignoring size.
2678 3053 */
2679 3054 uio->uio_offset = ++offset;
2680 3055 }
2681 3056
2682 3057 /*
2683 3058 * If there was a backward seek, we have to reopen.
2684 3059 */
2685 3060 if (offset < np->n_dirofs) {
2686 3061 SMBVDEBUG("Reopening search %d:%d\n",
2687 3062 offset, np->n_dirofs);
2688 3063 error = smbfs_smb_findopen(np, "*", 1,
2689 3064 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
2690 3065 &scred, &ctx);
2691 3066 if (error) {
2692 3067 SMBVDEBUG("can not open search, error = %d", error);
2693 3068 goto out;
2694 3069 }
2695 3070 /* free the old one */
2696 3071 (void) smbfs_smb_findclose(np->n_dirseq, &scred);
2697 3072 /* save the new one */
2698 3073 np->n_dirseq = ctx;
2699 3074 np->n_dirofs = FIRST_DIROFS;
2700 3075 } else {
2701 3076 ctx = np->n_dirseq;
2702 3077 }
2703 3078
2704 3079 /*
2705 3080 * Skip entries before the requested offset.
2706 3081 */
2707 3082 while (np->n_dirofs < offset) {
2708 3083 error = smbfs_smb_findnext(ctx, limit, &scred);
2709 3084 if (error != 0)
2710 3085 goto out;
2711 3086 np->n_dirofs++;
2712 3087 }
2713 3088
2714 3089 /*
2715 3090 * While there's room in the caller's buffer:
2716 3091 * get a directory entry from SMB,
2717 3092 * convert to a dirent, copyout.
2718 3093 * We stop when there is no longer room for a
2719 3094 * maximum sized dirent because we must decide
2720 3095 * before we know anything about the next entry.
2721 3096 */
2722 3097 while (uio->uio_resid >= dbufsiz) {
2723 3098 error = smbfs_smb_findnext(ctx, limit, &scred);
2724 3099 if (error != 0)
2725 3100 goto out;
2726 3101 np->n_dirofs++;
2727 3102
2728 3103 /* Sanity check the name length. */
2729 3104 nmlen = ctx->f_nmlen;
2730 3105 if (nmlen > SMB_MAXFNAMELEN) {
2731 3106 nmlen = SMB_MAXFNAMELEN;
2732 3107 SMBVDEBUG("Truncating name: %s\n", ctx->f_name);
2733 3108 }
2734 3109 if (smbfs_fastlookup) {
2735 3110 /* See comment at smbfs_fastlookup above. */
2736 3111 if (smbfs_nget(vp, ctx->f_name, nmlen,
2737 3112 &ctx->f_attr, &newvp) == 0)
2738 3113 VN_RELE(newvp);
2739 3114 }
2740 3115
2741 3116 reclen = DIRENT64_RECLEN(nmlen);
2742 3117 bzero(dp, reclen);
2743 3118 dp->d_reclen = reclen;
2744 3119 bcopy(ctx->f_name, dp->d_name, nmlen);
2745 3120 dp->d_name[nmlen] = '\0';
2746 3121 dp->d_ino = ctx->f_inum;
2747 3122 dp->d_off = offset + 1; /* See d_off comment above */
2748 3123 error = uiomove(dp, reclen, UIO_READ, uio);
2749 3124 if (error)
2750 3125 goto out;
2751 3126 /* See comment re. uio_offset above. */
2752 3127 uio->uio_offset = ++offset;
2753 3128 }
2754 3129
2755 3130 out:
2756 3131 /*
2757 3132 * When we come to the end of a directory, the
2758 3133 * SMB-level functions return ENOENT, but the
2759 3134 * caller is not expecting an error return.
2760 3135 *
2761 3136 * Also note that we must delay the call to
2762 3137 * smbfs_smb_findclose(np->n_dirseq, ...)
2763 3138 * until smbfs_close so that all reads at the
2764 3139 * end of the directory will return no data.
2765 3140 */
2766 3141 if (error == ENOENT) {
2767 3142 error = 0;
2768 3143 if (eofp)
2769 3144 *eofp = 1;
2770 3145 }
2771 3146 /*
2772 3147 * If we encountered an error (i.e. "access denied")
2773 3148 * from the FindFirst call, we will have copied out
2774 3149 * the "." and ".." entries leaving offset == 2.
2775 3150 * In that case, restore the original offset/resid
2776 3151 * so the caller gets no data with the error.
2777 3152 */
2778 3153 if (error != 0 && offset == FIRST_DIROFS) {
2779 3154 uio->uio_loffset = save_offset;
2780 3155 uio->uio_resid = save_resid;
2781 3156 }
2782 3157 SMBVDEBUG("out: offset=%d, resid=%d\n",
2783 3158 (int)uio->uio_offset, (int)uio->uio_resid);
2784 3159
2785 3160 kmem_free(dp, dbufsiz);
2786 3161 smb_credrele(&scred);
2787 3162 return (error);
2788 3163 }
2789 3164
2790 3165
2791 3166 /*
2792 3167 * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK
2793 3168 * are optional functions that are called by:
2794 3169 * getdents, before/after VOP_READDIR
2795 3170 * pread, before/after ... VOP_READ
2796 3171 * pwrite, before/after ... VOP_WRITE
2797 3172 * (other places)
2798 3173 *
2799 3174 * Careful here: None of the above check for any
2800 3175 * error returns from VOP_RWLOCK / VOP_RWUNLOCK!
2801 3176 * In fact, the return value from _rwlock is NOT
2802 3177 * an error code, but V_WRITELOCK_TRUE / _FALSE.
2803 3178 *
2804 3179 * Therefore, it's up to _this_ code to make sure
2805 3180 * the lock state remains balanced, which means
2806 3181 * we can't "bail out" on interrupts, etc.
2807 3182 */
2808 3183
2809 3184 /* ARGSUSED2 */
2810 3185 static int
2811 3186 smbfs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2812 3187 {
2813 3188 smbnode_t *np = VTOSMB(vp);
2814 3189
2815 3190 if (!write_lock) {
2816 3191 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_READER, FALSE);
2817 3192 return (V_WRITELOCK_FALSE);
2818 3193 }
2819 3194
2820 3195
2821 3196 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, FALSE);
2822 3197 return (V_WRITELOCK_TRUE);
2823 3198 }
2824 3199
2825 3200 /* ARGSUSED */
2826 3201 static void
2827 3202 smbfs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2828 3203 {
2829 3204 smbnode_t *np = VTOSMB(vp);
2830 3205
2831 3206 smbfs_rw_exit(&np->r_rwlock);
2832 3207 }
2833 3208
2834 3209
2835 3210 /* ARGSUSED */
2836 3211 static int
2837 3212 smbfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
2838 3213 {
2839 3214 smbmntinfo_t *smi;
2840 3215
2841 3216 smi = VTOSMI(vp);
2842 3217
2843 3218 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2844 3219 return (EPERM);
2845 3220
2846 3221 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2847 3222 return (EIO);
2848 3223
2849 3224 /*
2850 3225 * Because we stuff the readdir cookie into the offset field
2851 3226 * someone may attempt to do an lseek with the cookie which
2852 3227 * we want to succeed.
2853 3228 */
2854 3229 if (vp->v_type == VDIR)
2855 3230 return (0);
2856 3231
2857 3232 /* Like NFS3, just check for 63-bit overflow. */
2858 3233 if (*noffp < 0)
2859 3234 return (EINVAL);
2860 3235
2861 3236 return (0);
2862 3237 }
2863 3238
2864 3239
2865 3240 /*
2866 3241 * XXX
2867 3242 * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service.
2868 3243 */
2869 3244 static int
2870 3245 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2871 3246 offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
2872 3247 caller_context_t *ct)
2873 3248 {
2874 3249 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
2875 3250 return (EIO);
2876 3251
2877 3252 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
2878 3253 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
2879 3254 else
2880 3255 return (ENOSYS);
2881 3256 }
2882 3257
2883 3258 /*
2884 3259 * Free storage space associated with the specified vnode. The portion
2885 3260 * to be freed is specified by bfp->l_start and bfp->l_len (already
2886 3261 * normalized to a "whence" of 0).
2887 3262 *
2888 3263 * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc.
2889 3264 */
2890 3265 /* ARGSUSED */
2891 3266 static int
2892 3267 smbfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2893 3268 offset_t offset, cred_t *cr, caller_context_t *ct)
2894 3269 {
2895 3270 int error;
2896 3271 smbmntinfo_t *smi;
2897 3272
2898 3273 smi = VTOSMI(vp);
2899 3274
2900 3275 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2901 3276 return (EIO);
2902 3277
2903 3278 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2904 3279 return (EIO);
2905 3280
2906 3281 /* Caller (fcntl) has checked v_type */
2907 3282 ASSERT(vp->v_type == VREG);
2908 3283 if (cmd != F_FREESP)
2909 3284 return (EINVAL);
2910 3285
2911 3286 /*
2912 3287 * Like NFS3, no 32-bit offset checks here.
2913 3288 * Our SMB layer takes care to return EFBIG
2914 3289 * when it has to fallback to a 32-bit call.
2915 3290 */
2916 3291
2917 3292 error = convoff(vp, bfp, 0, offset);
2918 3293 if (!error) {
2919 3294 ASSERT(bfp->l_start >= 0);
2920 3295 if (bfp->l_len == 0) {
2921 3296 struct vattr va;
2922 3297
2923 3298 /*
2924 3299 * ftruncate should not change the ctime and
2925 3300 * mtime if we truncate the file to its
2926 3301 * previous size.
2927 3302 */
2928 3303 va.va_mask = AT_SIZE;
2929 3304 error = smbfsgetattr(vp, &va, cr);
2930 3305 if (error || va.va_size == bfp->l_start)
2931 3306 return (error);
2932 3307 va.va_mask = AT_SIZE;
2933 3308 va.va_size = bfp->l_start;
2934 3309 error = smbfssetattr(vp, &va, 0, cr);
2935 3310 } else
2936 3311 error = EINVAL;
2937 3312 }
2938 3313
2939 3314 return (error);
2940 3315 }
2941 3316
2942 3317 /* ARGSUSED */
2943 3318 static int
2944 3319 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
2945 3320 caller_context_t *ct)
2946 3321 {
2947 3322 vfs_t *vfs;
2948 3323 smbmntinfo_t *smi;
2949 3324 struct smb_share *ssp;
2950 3325
2951 3326 vfs = vp->v_vfsp;
2952 3327 smi = VFTOSMI(vfs);
2953 3328
2954 3329 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2955 3330 return (EIO);
2956 3331
2957 3332 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2958 3333 return (EIO);
2959 3334
2960 3335 switch (cmd) {
2961 3336 case _PC_FILESIZEBITS:
2962 3337 ssp = smi->smi_share;
2963 3338 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)
2964 3339 *valp = 64;
2965 3340 else
2966 3341 *valp = 32;
2967 3342 break;
2968 3343
2969 3344 case _PC_LINK_MAX:
2970 3345 /* We only ever report one link to an object */
2971 3346 *valp = 1;
2972 3347 break;
2973 3348
2974 3349 case _PC_ACL_ENABLED:
2975 3350 /*
2976 3351 * Always indicate that ACLs are enabled and
2977 3352 * that we support ACE_T format, otherwise
2978 3353 * libsec will ask for ACLENT_T format data
2979 3354 * which we don't support.
2980 3355 */
2981 3356 *valp = _ACL_ACE_ENABLED;
2982 3357 break;
2983 3358
2984 3359 case _PC_SYMLINK_MAX: /* No symlinks until we do Unix extensions */
2985 3360 *valp = 0;
2986 3361 break;
2987 3362
2988 3363 case _PC_XATTR_EXISTS:
2989 3364 if (vfs->vfs_flag & VFS_XATTR) {
2990 3365 *valp = smbfs_xa_exists(vp, cr);
2991 3366 break;
2992 3367 }
2993 3368 return (EINVAL);
2994 3369
2995 3370 case _PC_TIMESTAMP_RESOLUTION:
2996 3371 /*
2997 3372 * Windows times are tenths of microseconds
2998 3373 * (multiples of 100 nanoseconds).
2999 3374 */
3000 3375 *valp = 100L;
3001 3376 break;
3002 3377
3003 3378 default:
3004 3379 return (fs_pathconf(vp, cmd, valp, cr, ct));
3005 3380 }
3006 3381 return (0);
3007 3382 }
3008 3383
3009 3384 /* ARGSUSED */
3010 3385 static int
3011 3386 smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3012 3387 caller_context_t *ct)
3013 3388 {
3014 3389 vfs_t *vfsp;
3015 3390 smbmntinfo_t *smi;
3016 3391 int error;
3017 3392 uint_t mask;
3018 3393
3019 3394 vfsp = vp->v_vfsp;
3020 3395 smi = VFTOSMI(vfsp);
3021 3396
3022 3397 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3023 3398 return (EIO);
3024 3399
3025 3400 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3026 3401 return (EIO);
3027 3402
3028 3403 /*
3029 3404 * Our _pathconf indicates _ACL_ACE_ENABLED,
3030 3405 * so we should only see VSA_ACE, etc here.
3031 3406 * Note: vn_create asks for VSA_DFACLCNT,
3032 3407 * and it expects ENOSYS and empty data.
3033 3408 */
3034 3409 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT |
3035 3410 VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES);
3036 3411 if (mask == 0)
3037 3412 return (ENOSYS);
3038 3413
3039 3414 if (smi->smi_flags & SMI_ACL)
3040 3415 error = smbfs_acl_getvsa(vp, vsa, flag, cr);
3041 3416 else
3042 3417 error = ENOSYS;
3043 3418
3044 3419 if (error == ENOSYS)
3045 3420 error = fs_fab_acl(vp, vsa, flag, cr, ct);
3046 3421
3047 3422 return (error);
3048 3423 }
3049 3424
3050 3425 /* ARGSUSED */
3051 3426 static int
3052 3427 smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3053 3428 caller_context_t *ct)
3054 3429 {
3055 3430 vfs_t *vfsp;
3056 3431 smbmntinfo_t *smi;
3057 3432 int error;
3058 3433 uint_t mask;
3059 3434
3060 3435 vfsp = vp->v_vfsp;
3061 3436 smi = VFTOSMI(vfsp);
3062 3437
3063 3438 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3064 3439 return (EIO);
3065 3440
3066 3441 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3067 3442 return (EIO);
3068 3443
3069 3444 /*
3070 3445 * Our _pathconf indicates _ACL_ACE_ENABLED,
3071 3446 * so we should only see VSA_ACE, etc here.
3072 3447 */
3073 3448 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT);
3074 3449 if (mask == 0)
3075 3450 return (ENOSYS);
3076 3451
3077 3452 if (vfsp->vfs_flag & VFS_RDONLY)
3078 3453 return (EROFS);
3079 3454
3080 3455 /*
3081 3456 * Allow only the mount owner to do this.
3082 3457 * See comments at smbfs_access_rwx.
3083 3458 */
3084 3459 error = secpolicy_vnode_setdac(cr, smi->smi_uid);
3085 3460 if (error != 0)
3086 3461 return (error);
3087 3462
3088 3463 if (smi->smi_flags & SMI_ACL)
3089 3464 error = smbfs_acl_setvsa(vp, vsa, flag, cr);
3090 3465 else
3091 3466 error = ENOSYS;
3092 3467
3093 3468 return (error);
3094 3469 }
3095 3470
3096 3471
3097 3472 /*
3098 3473 * XXX
3099 3474 * This op should eventually support PSARC 2007/268.
3100 3475 */
3101 3476 static int
3102 3477 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
↓ open down ↓ |
1725 lines elided |
↑ open up ↑ |
3103 3478 caller_context_t *ct)
3104 3479 {
3105 3480 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
3106 3481 return (EIO);
3107 3482
3108 3483 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
3109 3484 return (fs_shrlock(vp, cmd, shr, flag, cr, ct));
3110 3485 else
3111 3486 return (ENOSYS);
3112 3487 }
3488 +
3489 +/* correspond to bp_mapin() in bp_map.c */
3490 +static int
3491 +uio_page_mapin(uio_t * uiop, page_t * pp)
3492 +{
3493 + u_offset_t off;
3494 + size_t size;
3495 + pgcnt_t npages;
3496 + caddr_t kaddr;
3497 + pfn_t pfnum;
3498 +
3499 + off = (uintptr_t) uiop->uio_loffset & PAGEOFFSET;
3500 + size = P2ROUNDUP(uiop->uio_resid + off, PAGESIZE);
3501 + npages = btop(size);
3502 +
3503 + ASSERT(pp != NULL);
3504 +
3505 + if (npages == 1 && kpm_enable) {
3506 + kaddr = hat_kpm_mapin(pp, NULL);
3507 + if (kaddr == NULL)
3508 + return (EFAULT);
3509 +
3510 + uiop->uio_iov->iov_base = kaddr + off;
3511 + uiop->uio_iov->iov_len = PAGESIZE - off;
3512 +
3513 + } else {
3514 + kaddr = vmem_xalloc(heap_arena, size, PAGESIZE, 0, 0, NULL, NULL, VM_SLEEP);
3515 + if (kaddr == NULL)
3516 + return (EFAULT);
3517 +
3518 + uiop->uio_iov->iov_base = kaddr + off;
3519 + uiop->uio_iov->iov_len = size - off;
3520 +
3521 + /* map pages into kaddr */
3522 + uint_t attr = PROT_READ | PROT_WRITE | HAT_NOSYNC;
3523 + while (npages-- > 0) {
3524 + pfnum = pp->p_pagenum;
3525 + pp = pp->p_next;
3526 +
3527 + hat_devload(kas.a_hat, kaddr, PAGESIZE, pfnum, attr, HAT_LOAD_LOCK);
3528 + kaddr += PAGESIZE;
3529 + }
3530 + }
3531 + return (0);
3532 +}
3533 +
3534 +/* correspond to bp_mapout() in bp_map.c */
3535 +static void
3536 +uio_page_mapout(uio_t * uiop, page_t * pp)
3537 +{
3538 + u_offset_t off;
3539 + size_t size;
3540 + pgcnt_t npages;
3541 + caddr_t kaddr;
3542 +
3543 + kaddr = uiop->uio_iov->iov_base;
3544 + off = (uintptr_t) kaddr & PAGEOFFSET;
3545 + size = P2ROUNDUP(uiop->uio_iov->iov_len + off, PAGESIZE);
3546 + npages = btop(size);
3547 +
3548 + ASSERT(pp != NULL);
3549 +
3550 + kaddr = (caddr_t) ((uintptr_t) kaddr & MMU_PAGEMASK);
3551 +
3552 + if (npages == 1 && kpm_enable) {
3553 + hat_kpm_mapout(pp, NULL, kaddr);
3554 +
3555 + } else {
3556 + hat_unload(kas.a_hat, (void *) kaddr, size,
3557 + HAT_UNLOAD_NOSYNC | HAT_UNLOAD_UNLOCK);
3558 + vmem_free(heap_arena, (void *) kaddr, size);
3559 + }
3560 + uiop->uio_iov->iov_base = 0;
3561 + uiop->uio_iov->iov_len = 0;
3562 +}
3563 +
3564 +static int
3565 +smbfs_map(vnode_t * vp, offset_t off, struct as * as, caddr_t * addrp,
3566 + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t * cr,
3567 + caller_context_t * ct)
3568 +{
3569 + smbnode_t *np;
3570 + smbmntinfo_t *smi;
3571 + struct vattr va;
3572 + segvn_crargs_t vn_a;
3573 + int error;
3574 +
3575 + np = VTOSMB(vp);
3576 + smi = VTOSMI(vp);
3577 +
3578 + if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3579 + return (EIO);
3580 +
3581 + if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3582 + return (EIO);
3583 +
3584 + if (vp->v_flag & VNOMAP || vp->v_flag & VNOCACHE)
3585 + return (EAGAIN);
3586 +
3587 + if (vp->v_type != VREG)
3588 + return (ENODEV);
3589 +
3590 + va.va_mask = AT_ALL;
3591 + if (error = smbfsgetattr(vp, &va, cr))
3592 + return (error);
3593 +
3594 + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
3595 + return (EINTR);
3596 +
3597 + if (MANDLOCK(vp, va.va_mode)) {
3598 + error = EAGAIN;
3599 + goto out;
3600 + }
3601 + as_rangelock(as);
3602 + error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
3603 +
3604 + if (error != 0) {
3605 + as_rangeunlock(as);
3606 + goto out;
3607 + }
3608 + vn_a.vp = vp;
3609 + vn_a.offset = off;
3610 + vn_a.type = flags & MAP_TYPE;
3611 + vn_a.prot = prot;
3612 + vn_a.maxprot = maxprot;
3613 + vn_a.flags = flags & ~MAP_TYPE;
3614 + vn_a.cred = cr;
3615 + vn_a.amp = NULL;
3616 + vn_a.szc = 0;
3617 + vn_a.lgrp_mem_policy_flags = 0;
3618 +
3619 + error = as_map(as, *addrp, len, segvn_create, &vn_a);
3620 +
3621 + as_rangeunlock(as);
3622 +
3623 +out:
3624 + smbfs_rw_exit(&np->r_lkserlock);
3625 +
3626 + return (error);
3627 +}
3628 +
3629 +static int
3630 +smbfs_addmap(vnode_t * vp, offset_t off, struct as * as, caddr_t addr,
3631 + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t * cr,
3632 + caller_context_t * ct)
3633 +{
3634 + atomic_add_long((ulong_t *) & VTOSMB(vp)->r_mapcnt, btopr(len));
3635 + return (0);
3636 +}
3637 +
3638 +static int
3639 +smbfs_delmap(vnode_t * vp, offset_t off, struct as * as, caddr_t addr,
3640 + size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t * cr,
3641 + caller_context_t * ct)
3642 +{
3643 +
3644 + smbnode_t *np;
3645 +
3646 + atomic_add_long((ulong_t *) & VTOSMB(vp)->r_mapcnt, -btopr(len));
3647 +
3648 + /*
3649 + * mark RDIRTY here, will be used to check if a file is dirty when
3650 + * unmount smbfs
3651 + */
3652 + if (vn_has_cached_data(vp) && !vn_is_readonly(vp) && (maxprot & PROT_WRITE)
3653 + && (flags == MAP_SHARED)) {
3654 + np = VTOSMB(vp);
3655 + mutex_enter(&np->r_statelock);
3656 + np->r_flags |= RDIRTY;
3657 + mutex_exit(&np->r_statelock);
3658 + }
3659 + return (0);
3660 +}
3661 +
3662 +static int
3663 +smbfs_putpage(vnode_t * vp, offset_t off, size_t len, int flags,
3664 + cred_t * cr, caller_context_t * ct)
3665 +{
3666 +
3667 + smbnode_t *np;
3668 + size_t io_len;
3669 + u_offset_t io_off;
3670 + u_offset_t eoff;
3671 + int error = 0;
3672 + page_t *pp;
3673 + int rdirty;
3674 +
3675 + np = VTOSMB(vp);
3676 +
3677 + if (len == 0) {
3678 +
3679 + /* will flush the whole file, so clear RDIRTY */
3680 + if (off == (u_offset_t) 0 && (np->r_flags & RDIRTY)) {
3681 + mutex_enter(&np->r_statelock);
3682 + rdirty = np->r_flags & RDIRTY;
3683 + np->r_flags &= ~RDIRTY;
3684 + mutex_exit(&np->r_statelock);
3685 + } else
3686 + rdirty = 0;
3687 +
3688 + error = pvn_vplist_dirty(vp, off, smbfs_putapage, flags, cr);
3689 +
3690 + /*
3691 + * if failed and the vnode was dirty before and we aren't
3692 + * forcibly invalidating pages, then mark RDIRTY again.
3693 + */
3694 + if (error && rdirty &&
3695 + (flags & (B_INVAL | B_FORCE)) != (B_INVAL | B_FORCE)) {
3696 + mutex_enter(&np->r_statelock);
3697 + np->r_flags |= RDIRTY;
3698 + mutex_exit(&np->r_statelock);
3699 + }
3700 + } else {
3701 +
3702 + eoff = off + len;
3703 +
3704 + mutex_enter(&np->r_statelock);
3705 + if (eoff > np->r_size)
3706 + eoff = np->r_size;
3707 + mutex_exit(&np->r_statelock);
3708 +
3709 + for (io_off = off; io_off < eoff; io_off += io_len) {
3710 + if ((flags & B_INVAL) || (flags & B_ASYNC) == 0) {
3711 + pp = page_lookup(vp, io_off,
3712 + (flags & (B_INVAL | B_FREE) ? SE_EXCL : SE_SHARED));
3713 + } else {
3714 + pp = page_lookup_nowait(vp, io_off,
3715 + (flags & B_FREE) ? SE_EXCL : SE_SHARED);
3716 + }
3717 +
3718 + if (pp == NULL || !pvn_getdirty(pp, flags))
3719 + io_len = PAGESIZE;
3720 + else {
3721 + error = smbfs_putapage(vp, pp, &io_off, &io_len, flags, cr);
3722 + }
3723 + }
3724 +
3725 + }
3726 +
3727 + return (error);
3728 +}
3729 +
3730 +static int
3731 +smbfs_putapage(vnode_t * vp, page_t * pp, u_offset_t * offp, size_t * lenp,
3732 + int flags, cred_t * cr)
3733 +{
3734 +
3735 + struct smb_cred scred;
3736 + smbnode_t *np;
3737 + smbmntinfo_t *smi;
3738 + smb_share_t *ssp;
3739 + uio_t uio;
3740 + iovec_t uiov, uiov_bak;
3741 +
3742 + size_t io_len;
3743 + u_offset_t io_off;
3744 + size_t limit;
3745 + size_t bsize;
3746 + size_t blksize;
3747 + u_offset_t blkoff;
3748 + int error;
3749 +
3750 + np = VTOSMB(vp);
3751 + smi = VTOSMI(vp);
3752 + ssp = smi->smi_share;
3753 +
3754 + /* do block io, get a kluster of dirty pages in a block. */
3755 + bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE);
3756 + blkoff = pp->p_offset / bsize;
3757 + blkoff *= bsize;
3758 + blksize = roundup(bsize, PAGESIZE);
3759 +
3760 + pp = pvn_write_kluster(vp, pp, &io_off, &io_len, blkoff, blksize, flags);
3761 +
3762 + ASSERT(pp->p_offset >= blkoff);
3763 +
3764 + if (io_off + io_len > blkoff + blksize) {
3765 + ASSERT((io_off + io_len) - (blkoff + blksize) < PAGESIZE);
3766 + }
3767 +
3768 + /* Don't allow put pages beyond EOF */
3769 + mutex_enter(&np->r_statelock);
3770 + limit=MIN(np->r_size, blkoff + blksize);
3771 + mutex_exit(&np->r_statelock);
3772 +
3773 + if (io_off >= limit) {
3774 + error = 0;
3775 + goto out;
3776 + } else if (io_off + io_len > limit) {
3777 + int npages = btopr(limit - io_off);
3778 + page_t *trunc;
3779 + page_list_break(&pp, &trunc, npages);
3780 + if (trunc)
3781 + pvn_write_done(trunc, flags);
3782 + io_len = limit - io_off;
3783 + }
3784 +
3785 + /*
3786 + * Taken from NFS4. The RMODINPROGRESS flag makes sure that
3787 + * smbfs_putapage() sees a consistent value of r_size. RMODINPROGRESS
3788 + * is set in writenp(). When RMODINPROGRESS is set it indicates that
3789 + * a uiomove() is in progress and the r_size has not been made
3790 + * consistent with the new size of the file. When the uiomove()
3791 + * completes the r_size is updated and the RMODINPROGRESS flag is
3792 + * cleared.
3793 + *
3794 + * The RMODINPROGRESS flag makes sure that smbfs_putapage() sees a
3795 + * consistent value of r_size. Without this handshaking, it is
3796 + * possible that smbfs_putapage() picks up the old value of r_size
3797 + * before the uiomove() in writenp() completes. This will result in
3798 + * the write through smbfs_putapage() being dropped.
3799 + *
3800 + * More precisely, there is a window between the time the uiomove()
3801 + * completes and the time the r_size is updated. If a VOP_PUTPAGE()
3802 + * operation intervenes in this window, the page will be picked up,
3803 + * because it is dirty (it will be unlocked, unless it was
3804 + * pagecreate'd). When the page is picked up as dirty, the dirty bit
3805 + * is reset (pvn_getdirty()). In smbfs_putapage(), r_size is checked.
3806 + * This will still be the old size. Therefore the page will not be
3807 + * written out. When segmap_release() calls VOP_PUTPAGE(), the page
3808 + * will be found to be clean and the write will be dropped.
3809 + */
3810 + if (np->r_flags & RMODINPROGRESS) {
3811 +
3812 + mutex_enter(&np->r_statelock);
3813 + if ((np->r_flags & RMODINPROGRESS) &&
3814 + np->r_modaddr + MAXBSIZE > io_off &&
3815 + np->r_modaddr < io_off + io_len) {
3816 + page_t *plist;
3817 + /*
3818 + * A write is in progress for this region of the
3819 + * file. If we did not detect RMODINPROGRESS here,
3820 + * the data beyond the file size won't be write out.
3821 + * We end up losing data. So we decide to set the
3822 + * modified bit on each page in the page list and
3823 + * mark the smbnode with RDIRTY. This write will be
3824 + * restarted at some later time.
3825 + */
3826 + plist = pp;
3827 + while (plist != NULL) {
3828 + pp = plist;
3829 + page_sub(&plist, pp);
3830 + hat_setmod(pp);
3831 + page_io_unlock(pp);
3832 + page_unlock(pp);
3833 + }
3834 + np->r_flags |= RDIRTY;
3835 + mutex_exit(&np->r_statelock);
3836 + if (offp)
3837 + *offp = io_off;
3838 + if (lenp)
3839 + *lenp = io_len;
3840 + return (0);
3841 + }
3842 + mutex_exit(&np->r_statelock);
3843 + }
3844 +
3845 + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
3846 + return (EINTR);
3847 + smb_credinit(&scred, cr);
3848 +
3849 + if (np->n_vcgenid != ssp->ss_vcgenid)
3850 + error = ESTALE;
3851 + else {
3852 + /* just use uio instead of buf, since smb_rwuio need uio. */
3853 + uiov.iov_base = 0;
3854 + uiov.iov_len = 0;
3855 + uio.uio_iov = &uiov;
3856 + uio.uio_iovcnt = 1;
3857 + uio.uio_loffset = io_off;
3858 + uio.uio_resid = io_len;
3859 + uio.uio_segflg = UIO_SYSSPACE;
3860 + uio.uio_llimit = MAXOFFSET_T;
3861 + /* map pages into kernel address space, and setup uio. */
3862 + error = uio_page_mapin(&uio, pp);
3863 + if (error == 0) {
3864 + uiov_bak.iov_base = uiov.iov_base;
3865 + uiov_bak.iov_len = uiov.iov_len;
3866 + error = smb_rwuio(ssp, np->n_fid, UIO_WRITE, &uio, &scred, smb_timo_write);
3867 + if (error == 0) {
3868 + mutex_enter(&np->r_statelock);
3869 + np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
3870 + mutex_exit(&np->r_statelock);
3871 + (void) smbfs_smb_flush(np, &scred);
3872 + }
3873 + /* unmap pages from kernel address space. */
3874 + uio.uio_iov = &uiov_bak;
3875 + uio_page_mapout(&uio, pp);
3876 + }
3877 + }
3878 +
3879 + smb_credrele(&scred);
3880 + smbfs_rw_exit(&np->r_lkserlock);
3881 +
3882 +out:
3883 + pvn_write_done(pp, ((error) ? B_ERROR : 0) | B_WRITE | flags);
3884 +
3885 + if (offp)
3886 + *offp = io_off;
3887 + if (lenp)
3888 + *lenp = io_len;
3889 +
3890 + return (error);
3891 +}
3892 +
3893 +static int
3894 +smbfs_getpage(vnode_t * vp, offset_t off, size_t len, uint_t * protp,
3895 + page_t * pl[], size_t plsz, struct seg * seg, caddr_t addr,
3896 + enum seg_rw rw, cred_t * cr, caller_context_t * ct)
3897 +{
3898 +
3899 + smbnode_t *np;
3900 + int error;
3901 +
3902 + /* these pages have all protections. */
3903 + if (protp)
3904 + *protp = PROT_ALL;
3905 +
3906 + np = VTOSMB(vp);
3907 +
3908 + /* Don't allow get pages beyond EOF, unless it's segkmap. */
3909 + mutex_enter(&np->r_statelock);
3910 + if (off + len > np->r_size + PAGESIZE && seg != segkmap){
3911 + mutex_exit(&np->r_statelock);
3912 + return (EFAULT);
3913 + }
3914 + mutex_exit(&np->r_statelock);
3915 +
3916 + if (len <= PAGESIZE) {
3917 + error = smbfs_getapage(vp, off, len, protp, pl, plsz, seg, addr, rw,
3918 + cr);
3919 + } else {
3920 + error = pvn_getpages(smbfs_getapage, vp, off, len, protp, pl, plsz, seg,
3921 + addr, rw, cr);
3922 + }
3923 +
3924 + return (error);
3925 +}
3926 +
3927 +static int
3928 +smbfs_getapage(vnode_t * vp, u_offset_t off, size_t len,
3929 + uint_t * protp, page_t * pl[], size_t plsz, struct seg * seg, caddr_t addr,
3930 + enum seg_rw rw, cred_t * cr)
3931 +{
3932 +
3933 + smbnode_t *np;
3934 + smbmntinfo_t *smi;
3935 + smb_share_t *ssp;
3936 + smb_cred_t scred;
3937 +
3938 + page_t *pp;
3939 + uio_t uio;
3940 + iovec_t uiov, uiov_bak;
3941 +
3942 + u_offset_t blkoff;
3943 + size_t bsize;
3944 + size_t blksize;
3945 +
3946 + u_offset_t io_off;
3947 + size_t io_len;
3948 + size_t pages_len;
3949 +
3950 + int error = 0;
3951 +
3952 + np = VTOSMB(vp);
3953 + smi = VTOSMI(vp);
3954 + ssp = smi->smi_share;
3955 +
3956 + /* if pl is null,it's meaningless */
3957 + if (pl == NULL)
3958 + return (EFAULT);
3959 +
3960 +again:
3961 + if (page_exists(vp, off) == NULL) {
3962 + if (rw == S_CREATE) {
3963 + /* just return a empty page if asked to create. */
3964 + if ((pp = page_create_va(vp, off, PAGESIZE, PG_WAIT | PG_EXCL, seg, addr)) == NULL)
3965 + goto again;
3966 + pages_len = PAGESIZE;
3967 + } else {
3968 +
3969 + /*
3970 + * do block io, get a kluster of non-exist pages in a
3971 + * block.
3972 + */
3973 + bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE);
3974 + blkoff = off / bsize;
3975 + blkoff *= bsize;
3976 + blksize = roundup(bsize, PAGESIZE);
3977 +
3978 + pp = pvn_read_kluster(vp, off, seg, addr, &io_off, &io_len, blkoff, blksize, 0);
3979 +
3980 + if (pp == NULL)
3981 + goto again;
3982 +
3983 + pages_len = io_len;
3984 +
3985 + /* Don't need to get pages from server if it's segkmap
3986 + * that reads beyond EOF. */
3987 + mutex_enter(&np->r_statelock);
3988 + if (io_off >= np->r_size && seg == segkmap) {
3989 + mutex_exit(&np->r_statelock);
3990 + error = 0;
3991 + goto out;
3992 + } else if (io_off + io_len > np->r_size) {
3993 + int npages = btopr(np->r_size - io_off);
3994 + page_t *trunc;
3995 +
3996 + page_list_break(&pp, &trunc, npages);
3997 + if (trunc)
3998 + pvn_read_done(trunc, 0);
3999 + io_len = np->r_size - io_off;
4000 + }
4001 + mutex_exit(&np->r_statelock);
4002 +
4003 + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
4004 + return EINTR;
4005 + smb_credinit(&scred, cr);
4006 +
4007 + /*
4008 + * just use uio instead of buf, since smb_rwuio need
4009 + * uio.
4010 + */
4011 + uiov.iov_base = 0;
4012 + uiov.iov_len = 0;
4013 + uio.uio_iov = &uiov;
4014 + uio.uio_iovcnt = 1;
4015 + uio.uio_loffset = io_off;
4016 + uio.uio_resid = io_len;
4017 + uio.uio_segflg = UIO_SYSSPACE;
4018 + uio.uio_llimit = MAXOFFSET_T;
4019 +
4020 + /*
4021 + * map pages into kernel address space, and setup
4022 + * uio.
4023 + */
4024 + error = uio_page_mapin(&uio, pp);
4025 + if (error == 0) {
4026 + uiov_bak.iov_base = uiov.iov_base;
4027 + uiov_bak.iov_len = uiov.iov_len;
4028 + error = smb_rwuio(ssp, np->n_fid, UIO_READ, &uio, &scred, smb_timo_read);
4029 + /* unmap pages from kernel address space. */
4030 + uio.uio_iov = &uiov_bak;
4031 + uio_page_mapout(&uio, pp);
4032 + }
4033 + smb_credrele(&scred);
4034 + smbfs_rw_exit(&np->r_lkserlock);
4035 + }
4036 + } else {
4037 + se_t se = rw == S_CREATE ? SE_EXCL : SE_SHARED;
4038 + if ((pp = page_lookup(vp, off, se)) == NULL) {
4039 + goto again;
4040 + }
4041 + }
4042 +
4043 +out:
4044 + if (pp) {
4045 + if (error) {
4046 + pvn_read_done(pp, B_ERROR);
4047 + } else {
4048 + /* init page list, unlock pages. */
4049 + pvn_plist_init(pp, pl, plsz, off, pages_len, rw);
4050 + }
4051 + }
4052 + return (error);
4053 +}
4054 +
4055 +/* correspond to nfs_invalidate_pages() in nfs_client.c */
4056 +void
4057 +smbfs_invalidate_pages(vnode_t * vp, u_offset_t off, cred_t * cr)
4058 +{
4059 +
4060 + smbnode_t *np;
4061 +
4062 + np = VTOSMB(vp);
4063 + /* will flush the whole file, so clear RDIRTY */
4064 + if (off == (u_offset_t) 0 && (np->r_flags & RDIRTY)) {
4065 + mutex_enter(&np->r_statelock);
4066 + np->r_flags &= ~RDIRTY;
4067 + mutex_exit(&np->r_statelock);
4068 + }
4069 + (void) pvn_vplist_dirty(vp, off, smbfs_putapage, B_INVAL | B_TRUNC, cr);
4070 +}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX