smbfs_vnops.c revision 42d159821800ff240cc201c8fe07f575b9e8a62b
* These characters are illegal in NTFS file names. * Careful! The check in the XATTR case skips the * first character to allow colon in XATTR names. ':',
/* colon - keep this first! */ '<',
/* less than sign */ '>',
/* greater than sign */ * Turning this on causes nodes to be created in the cache * during directory listings, normally avoiding a second * OtW attribute fetch just after a readdir. /* local static function defines */ * These are the vnode ops routines which implement the vnode interface to * the networked file system. These routines just take their parameters, * make them look networkish by putting the right info into interface structs, * and then calling the appropriate remote routine(s) to do the work. * Note on directory name lookup cacheing: If we detect a stale fhandle, * we purge the directory cache relative to that vnode. This way, the * user won't get burned by the cache repeatedly. See <smbfs/smbnode.h> for * more details on smbnode locking. /* Dummy function to use until correct function is ported in */ * Most unimplemented ops will return ENOSYS because of fs_nosys(). * The only ops where that won't work are ACCESS (due to open(2) * failures) and ... (anything else left?) * When new and relevant functionality is enabled, we should be * calling vfs_set_feature() to inform callers that pieces of * functionality are available, per PSARC 2007/227. * Get exclusive access to n_fid and related stuff. * No returns after this until out. * Keep track of the vnode type at first open. * It may change later, and we need close to do * cleanup for the type we opened. Also deny * open of new types until old type is closed. * XXX: Per-open instance nodes whould help. * Directory open. See smbfs_readvdir() * FWRITE (to drive successful setattr(size=0) after open) * If we already have it open, and the FID is still valid, * check whether the rights are sufficient for FID reuse. * the existing open is good enough * we always ask for READ_CONTROL so we can always get the * owner/group IDs to satisfy a stat. Ditto attributes. NULL, 0, 0,
/* name nmlen xattr */ * We have a new FID and access rights. * We already had it open (presumably because * it was open with insufficient rights.) * This thread did the open. * Save our credentials too. * Keep track of the vnode type at first open. * Don't "bail out" for VFS_UNMOUNTED here, * as we want to do cleanup, etc. * zone_enter(2) prevents processes from changing zones with SMBFS files * open; if we happen to get here from the wrong zone we can't do * anything over the wire. * We could attempt to clean up locks, except we're sure * that the current process didn't acquire any locks on * the file: any attempt to lock a file belong to another zone * will fail, and one can't lock an SMBFS file and then change * zones, as that fails too. * Returning an error here is the sane thing to do. A * subsequent call to VN_RELE() which translates to a * smbfs_inactive() will clean up state: if the zone of the * vnode's origin is still alive and kicking, an async worker * thread will handle the request (from the correct zone), and * everything (minus the final smbfs_getattr_otw() call) should * be OK. If the zone is going away smbfs_async_inactive() will * throw away cached pages inline. * If we are using local locking for this filesystem, then * release all of the SYSV style record locks. Otherwise, * we are doing network locking and we need to release all * of the network locks. All of the locks held by this * process on this file are released no matter what the * incoming reference count is. * This (passed in) count is the ref. count from the * user's file_t before the closef call (fio.c). * We only care when the reference goes away. * Decrement the reference count for the FID * and possibly do the OtW close. * Exclusive lock for modifying n_fid stuff. * Don't want this one ever interruptible. * Helper for smbfs_close. Decrement the reference count * for an SMB-level file or directory ID, and when the last * reference for the fid goes away, do the OtW close. * Also called in smbfs_inactive (defensive cleanup). /* Make sure we serialize for n_dirseq use. */ * Note that vp->v_type may change if a remote node * is deleted and recreated as a different type, and * our getattr may change v_type accordingly. * Now use n_ovtype to keep track of the v_type * we had during open (see comments above). /* After reconnect, n_fid is invalid */ /* Allow next open to use any v_type. */ * Other "last close" stuff. * Like NFS3, just check for 63-bit overflow. * Our SMB layer takes care to return EFBIG * when it has to fallback to a 32-bit call. /* get vnode attributes from server */ /* Update mtime with mtime from server here? */ /* if offset is beyond EOF, read nothing */ * Limit the read to the remaining file size. * Do this by temporarily reducing uio_resid * by the amount the lies beyoned the EOF. /* Shared lock for n_fid use in smb_rwuio */ /* After reconnect, n_fid is invalid */ /* undo adjustment of resid */ * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC) /* XXX: smbfs_vinvalbuf? */ * File size can be changed by another client * Like NFS3, just check for 63-bit overflow. * Check to make sure that the process will not exceed * its limit on file size. It is okay to write up to * the limit, but not beyond. Thus, the write which * reaches the limit will be short and the next write * So if we're starting at or beyond the limit, EFBIG. * Otherwise, temporarily reduce resid to the amount * the falls after the limit. /* Timeout: longer for append. */ /* Shared lock for n_fid use in smb_rwuio */ /* After reconnect, n_fid is invalid */ /* Don't error the I/O if this fails. */ /* undo adjustment of resid */ /* First three from ZFS. XXX - need these? */ * The following two ioctls are used by bfu. * Silently ignore to avoid bfu errors. #
ifdef NOT_YET /* XXX - from the NFS code. */ * Allow get/set with "raw" security descriptor (SD) data. * Useful for testing, diagnosing idmap problems, etc. * Return either cached or remote attributes. If get remote attr * use them to check and invalidate caches, then cache the new attributes. * This op should eventually support PSARC 2007/315, Extensible Attribute * Interfaces, for richer metadata. * If it has been specified that the return value will * just be used as a hint, and we are only being asked * for size, fsid or rdevid, then return the client's * notion of these values without checking to make sure * that the attribute cache is up to date. * The whole point is to avoid an over the wire GETATTR * This op should eventually support PSARC 2007/315, Extensible Attribute * Interfaces, for richer metadata. * This is a _local_ access check so that only the owner of * this mount can set attributes. With ACLs enabled, the * file owner can be different from the mount owner, and we * need to check the _mount_ owner here. See _access_rwx * It might be more correct to return the * error here, but that causes complaints * when root extracts a cpio archive, etc. * So ignore this error, and go ahead with * the rest of the setattr work. * Mostly from Darwin smbfs_setattr() * but then modified a lot. * There are no settable attributes on the XATTR dir, * so just silently ignore these. On XATTR files, * you can set the size but nothing else. * If our caller is trying to set multiple attributes, they * can make no assumption about what order they are done in. * Here we try to do them in order of decreasing likelihood * of failure, just to minimize the chance we'll wind up * with a partially complete request. /* Shared lock for (possible) n_fid use. */ * Will we need an open handle for this setattr? * If so, what rights will we need? * Only SIZE really requires a handle, but it's * simpler and more reliable to set via a handle. * Some servers like NT4 won't set times by path. * Also, we're usually setting everything anyway. * If the server supports the UNIX extensions, right here is where * we'd support changes to uid, gid, mode, and possibly va_flags. * For now we claim to have made any such changes. * If the new file size is less than what the client sees as * the file size, then just change the size and invalidate * I am commenting this code at present because the function * smbfs_putapage() is not yet implemented. * Set the file size to vap->va_size. * Darwin had code here to zero-extend. * Tests indicate the server will zero-fill, * so looks like we don't need to do this. * Good thing, as this could take forever. * XXX: Reportedly, writing one byte of zero * at the end offset avoids problems here. * XXX: When Solaris has create_time, set that too. * Note: create_time is different from ctime. * Always use the handle-based set attr call now. * Not trying to set DOS attributes here so pass zero. * Invalidate attribute cache in case the server * doesn't set exactly the attributes we asked. * Common function for smbfs_access, etc. * The security model implemented by the FS is unusual * due to the current "single user mounts" restriction: * All access under a given mount point uses the CIFS * credentials established by the owner of the mount. * Most access checking is handled by the CIFS server, * but we need sufficient Unix access checks here to * prevent other local Unix users from having access * to objects under this mount that the uid/gid/mode * settings in the mount would not allow. * With this model, there is a case where we need the * ability to do an access check before we have the * vnode for an object. This function takes advantage * of the fact that the uid/gid/mode is per mount, and * avoids the need for a vnode. * We still (sort of) need a vnode when we call * secpolicy_vnode_access, but that only uses * the vtype field, so we can use a pair of fake * vnodes that have only v_type filled in. * XXX: Later, add a new secpolicy_vtype_access() * that takes the vtype instead of a vnode, and * get rid of the tmpl_vxxx fake vnodes below. /* See the secpolicy call below. */ * Build our (fabricated) vnode attributes. * XXX: Could make these templates in the * per-mount struct and use them here. * Disallow write attempts on read-only file systems, * unless the file is a device or fifo node. Note: * Inline vn_is_readonly and IS_DEVVP here because * we may not have a vnode ptr. Original expr. was: * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp)) * Disallow attempts to access mandatory lock files. * Similarly, expand MANDLOCK here. * XXX: not sure we need this. * Access check is based on only * one of owner, group, public. * If not owner, then check group. * If not a member of the group, * then check public access. * We need a vnode for secpolicy_vnode_access, * but the only thing it looks at is v_type, * so pass one of the templates above. * Note: The caller has checked the current zone, * the SMI_DEAD and VFS_UNMOUNTED flags, etc. * This op should support PSARC 2007/403, Modified Access Checks for CIFS * Flush local dirty pages to stable storage on the server. * If FNODSYNC is specified, then there is nothing to do because * metadata changes are not cached on the client before being /* Shared lock for n_fid use in _flush */ * Last reference to vnode went away. * Don't "bail out" for VFS_UNMOUNTED here, * as we want to do cleanup, etc. * If this is coming from the wrong zone, we let someone in the right * zone take care of it asynchronously. We can get here due to * VN_RELE() being called from pageout() or fsflush(). This call may * potentially turn into an expensive no-op if, for instance, v_count * gets incremented in the meantime, but it's still correct. * Defend against the possibility that higher-level callers * might not correctly balance open and close calls. If we * get here with open references remaining, it means there * was a missing VOP_CLOSE somewhere. If that happens, do * the close here so we don't "leak" FIDs on the server. * Exclusive lock for modifying n_fid stuff. * Don't want this one ever interruptible. SMBVDEBUG(
"open file: refs %d id 0x%x path %s\n",
* Remote file system operations having to do with directory manipulation. * Are we looking up extended attributes? If so, "dvp" is * the file or directory for which we want attributes, and * we need a lookup of the (faked up) attribute directory * before we lookup the rest of the path. * Require the xattr mount option. int supplen;
/* supported length */ /* struct smb_vc *vcp; */ const char *
name = (
const char *)
nm;
/* XXX: Should compute this once and store it in smbmntinfo_t */ * RWlock must be held, either reader or writer. * XXX: Can we check without looking directly * inside the struct smbfs_rwlock_t? * If lookup is for "", just return dvp. * No need to perform any access checks. * Can't do lookups in non-directories. * Need search permission in the directory. * If lookup is for ".", just return dvp. * Access check was done above. * Now some sanity checks on the name. * First check the length. * Avoid surprises with characters that are * illegal in Windows file names. * Todo: CATIA mappings XXX * Special handling for lookup of ".." * We keep full pathnames (as seen on the server) * so we can just trim off the last component to * get the full pathname of the parent. Note: * We don't actually copy and modify, but just * compute the trimmed length and pass that with * the current dir path (not null terminated). * We don't go over-the-wire to get attributes * for ".." because we know it's a directory, * and we can just leave the rest "stale" * until someone does a getattr. * Already at the root. This can happen * with directory listings at the root, * which lookup "." and ".." to get the * inode numbers. Let ".." be the same * Special case for XATTR directory * Find the parent path length. /* Found our way to the root. */ * Normal lookup of a name under this directory. * Note we handled "", ".", ".." above. * The caller indicated that it's OK to use a * cached result for this lookup, so try to * reclaim a node from the smbfs node cache. /* hold taken in lookup_cache */ * OK, go over-the-wire to get the attributes, /* Note: this can allocate a new "name" */ * Lookup failed because this directory was * removed or renamed by another client. * Remove any cached attributes under it. /* smbfs_smb_lookup may have allocated name. */ * Try to reclaim a node from the smbfs node cache. * Some statistics for DEBUG. * This mechanism lets us avoid many of the five (or more) * OtW lookup calls per file seen with "ls -l" if we search * the smbfs node cache for recently inactive(ated) nodes. * First make sure we can get attributes for the * directory. Cached attributes are OK here. * If we removed or renamed the directory, this * will return ENOENT. If someone else removed * this directory or file, we'll find out when we * try to open or get attributes. * Passing NULL smbfattr here so we will * Found it. Attributes still valid? * Caller gets hold from smbfs_node_findcreate * vsecattr_t is new to build 77, and we need to eventually support * it in order to create an ACL when an object is created. * This op should support the new FIGNORECASE flag for case-insensitive * lookups, per PSARC 2007/244. const char *
name = (
const char *)
nm;
* Note: this may break mknod(2) calls to create a directory, * but that's obscure use. Some other filesystems do this. * XXX: Later, redirect VDIR type here to _mkdir. * If the pathname is "", just use dvp, no checks. * Do this outside of the rwlock (like zfs). /* Don't allow "." or ".." through here. */ * We make a copy of the attributes because the caller does not * expect us to change what va points to. * XXX: Do we need r_lkserlock too? * No use of any shared fid or fctx... * NFS needs to go over the wire, just to be sure whether the * file exists or not. Using a cached result is dangerous in * this case when making a decision regarding existence. * The SMB protocol does NOT really need to go OTW here * thanks to the expressive NTCREATE disposition values. * Unfortunately, to do Unix access checks correctly, * we need to know if the object already exists. * When the object does not exist, we need VWRITE on * the directory. Note: smbfslookup() checks VEXEC. * The file already exists. Error? * NB: have a hold from smbfslookup * Verify requested access. * Truncate (if requested). * The file did not exist. Need VWRITE in the directory. * Now things get tricky. We also need to check the * requested open mode against the file we may create. * See comments at smbfs_access_rwx * Now the code derived from Darwin, * but with greater use of NT_CREATE * disposition options. Much changed. * Create (or open) a new child node. * Note we handled "." and ".." above. /* Truncate regular files if requested. */ * XXX: Missing some code here to deal with * the case where we opened an existing file, * it's size is larger than 32-bits, and we're * setting the size from a process that's not * aware of large file offsets. i.e. * Check here for large file handled * by LF-unaware process (as * Should use the fid to get/set the size * while we have it opened here. See above. * In the open case, the name may differ a little * from what we passed to create (case, etc.) * so call lookup to get the (opened) name. * XXX: Could avoid this extra lookup if the * "createact" result from NT_CREATE says we /* update attr and directory cache */ /* XXX invalidate pages if we truncated? */ * This op should support the new FIGNORECASE flag for case-insensitive * lookups, per PSARC 2007/244. /* enum smbfsstat status; */ * Verify access to the dirctory. * NOTE: the darwin code gets the "vp" passed in so it looks * like the "vp" has probably been "lookup"ed by the VFS layer. * It looks like we will need to lookup the vp to check the * caches and check if the object being deleted is a directory. /* Never allow link/unlink directories on CIFS. */ * Now we have the real reference count on the vnode * Do we have the file open? * NFS does a rename on remove here. * Probably not applicable for SMB. * Like Darwin, just return EBUSY. * XXX: Todo - Use Trans2rename, and * if that fails, ask the server to * set the delete-on-close flag. * If the file should no longer exist, discard * any cached attributes under this node. * This op should support the new FIGNORECASE flag for case-insensitive * lookups, per PSARC 2007/244. * smbfsrename does the real work of renaming in SMBFS /* enum smbfsstat status; */ * Check that everything is on the same filesystem. * vn_rename checks the fsid's, but in case we don't * fill those in correctly, check here too. * Avoid deadlock here on old vs new directory nodes * by always taking the locks in order of address. * The order is arbitrary, but must be consistent. * No returns after this point (goto out) * Need write access on source and target. * Server takes care of most checks. * Lookup the source name. Must already exist. * Lookup the target file. If it exists, it needs to be * checked to see whether it is a mount point and whether * Target (nvp) already exists. Check that it * has the same type as the source. The server * will check this also, (and more reliably) but * this lets us return the correct error codes. * POSIX dictates that when the source and target * entries refer to the same file object, rename * must do nothing and exit without error. * Also must ensure the target is not a mount point, * CIFS gives a SHARING_VIOLATION error when * trying to rename onto an exising object, * so try to remove the target first. * (Only for files, not directories.) * Nodes that are "not active" here have v_count=2 * because vn_renameat (our caller) did a lookup on * both the source and target before this call. * Otherwise this similar to smbfs_remove. * The target file exists, is not the same as * the source file, and is active. Other FS * implementations unlink the target here. * For SMB, we don't assume we can remove an * open file. Return an error instead. * Target file is not active. Try to remove it. * Similar to smbfs_remove * OK, removed the target file. Continue as if * lookup target had failed (nvp == NULL). * If the old name should no longer exist, * discard any cached attributes under it. * vsecattr_t is new to build 77, and we need to eventually support * it in order to create an ACL when an object is created. * This op should support the new FIGNORECASE flag for case-insensitive * lookups, per PSARC 2007/244. const char *
name = (
const char *)
nm;
/* Only plain files are allowed in V_XATTRDIR. */ * XXX: Do we need r_lkserlock too? * No use of any shared fid or fctx... * Require write access in the containing directory. * This op should support the new FIGNORECASE flag for case-insensitive * lookups, per PSARC 2007/244. * Require w/x access in the containing directory. * Server handles all other access checks. * First lookup the entry to be removed. * Disallow rmdir of "." or current dir, or the FS root. * Also make sure it's a directory, not a mount point, * Similar to smbfs_remove * Require read access in the directory. * XXX: Todo readdir cache here * Note: NFS code is just below this. * I am serializing the entire readdir opreation * now since we have not yet implemented readdir * cache. This fix needs to be revisited once * we implement readdir cache. * functions how many directory entries to request in * each OtW call. It needs to be large enough so that * we don't make lots of tiny OtW requests, but there's * no point making it larger than the maximum number of * OtW entries that would fit in a maximum sized trans2 * response (64k / 48). Beyond that, it's just tuning. * WinNT used 512, Win2k used 1366. We use 1000. static const int limit =
1000;
/* Largest possible dirent size. */ int offset;
/* yes, 32 bits */ /* Make sure we serialize for n_dirseq use. */ * Make sure smbfs_open filled in n_dirseq /* Check for overflow of (32-bit) directory offset. */ /* Require space for at least one dirent. */ * Generate the "." and ".." entries here so we can * (1) make sure they appear (but only once), and * (2) deal with getting their I numbers which the * findnext below does only for normal names. * Tricky bit filling in the first two: * offset 0 is ".", offset 1 is ".." * so strlen of these is offset+1. * Want the real I-numbers for the "." and ".." * entries. For these two names, we know that * smbfslookup can get the nodes efficiently. * Note: d_off is the offset that a user-level program * should seek to for reading the NEXT directory entry. * See libc: readdir, telldir, seekdir * Note: uiomove updates uio->uio_offset, * but we want it to be our "cookie" value, * which just counts dirents ignoring size. * If there was a backward seek, we have to reopen. * Skip entries before the requested offset. * While there's room in the caller's buffer: * get a directory entry from SMB, * convert to a dirent, copyout. * We stop when there is no longer room for a * maximum sized dirent because we must decide * before we know anything about the next entry. /* Sanity check the name length. */ /* See comment at smbfs_fastlookup above. */ /* See comment re. uio_offset above. */ * When we come to the end of a directory, the * SMB-level functions return ENOENT, but the * caller is not expecting an error return. * Also note that we must delay the call to * smbfs_smb_findclose(np->n_dirseq, ...) * until smbfs_close so that all reads at the * end of the directory will return no data. * If we encountered an error (i.e. "access denied") * from the FindFirst call, we will have copied out * the "." and ".." entries leaving offset == 2. * so the caller gets no data with the error. * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK * are optional functions that are called by: * Careful here: None of the above check for any * error returns from VOP_RWLOCK / VOP_RWUNLOCK! * In fact, the return value from _rwlock is NOT * an error code, but V_WRITELOCK_TRUE / _FALSE. * Therefore, it's up to _this_ code to make sure * the lock state remains balanced, which means * we can't "bail out" on interrupts, etc. * Because we stuff the readdir cookie into the offset field * someone may attempt to do an lseek with the cookie which /* Like NFS3, just check for 63-bit overflow. */ * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service. * Free storage space associated with the specified vnode. The portion * to be freed is specified by bfp->l_start and bfp->l_len (already * normalized to a "whence" of 0). * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc. /* Caller (fcntl) has checked v_type */ * Like NFS3, no 32-bit offset checks here. * Our SMB layer takes care to return EFBIG * when it has to fallback to a 32-bit call. * ftruncate should not change the ctime and * mtime if we truncate the file to its /* We only ever report one link to an object */ * Always indicate that ACLs are enabled and * that we support ACE_T format, otherwise * libsec will ask for ACLENT_T format data * which we don't support. * Windows times are tenths of microseconds * (multiples of 100 nanoseconds). * Our _pathconf indicates _ACL_ACE_ENABLED, * so we should only see VSA_ACE, etc here. * Note: vn_create asks for VSA_DFACLCNT, * and it expects ENOSYS and empty data. * Our _pathconf indicates _ACL_ACE_ENABLED, * so we should only see VSA_ACE, etc here. * Allow only the mount owner to do this. * See comments at smbfs_access_rwx. * This op should eventually support PSARC 2007/268.