/* * smb_ofile_is_open */ boolean_t smb_ofile_is_open(smb_ofile_t *of) { boolean_t rc; SMB_OFILE_VALID(of); mutex_enter(&of->f_mutex); rc = smb_ofile_is_open_locked(of); mutex_exit(&of->f_mutex); return (rc); }
/* * smb_ofile_request_complete * * During oplock acquisition, all other oplock requests on the node * are blocked until the acquire request completes and the response * is on the wire. * Call smb_oplock_broadcast to notify the node that the request * has completed. * * THIS MECHANISM RELIES ON THE FACT THAT THE OFILE IS NOT REMOVED * FROM THE SR UNTIL REQUEST COMPLETION (when the sr is destroyed) */ void smb_ofile_request_complete(smb_ofile_t *of) { SMB_OFILE_VALID(of); switch (of->f_ftype) { case SMB_FTYPE_DISK: ASSERT(of->f_node); smb_oplock_broadcast(of->f_node); break; case SMB_FTYPE_MESG_PIPE: break; default: break; } }
/* * Delete an ofile. * * Remove the ofile from the tree list before freeing resources * associated with the ofile. */ void smb_ofile_delete(void *arg) { smb_tree_t *tree; smb_ofile_t *of = (smb_ofile_t *)arg; SMB_OFILE_VALID(of); ASSERT(of->f_refcnt == 0); ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED); ASSERT(!SMB_OFILE_OPLOCK_GRANTED(of)); tree = of->f_tree; smb_llist_enter(&tree->t_ofile_list, RW_WRITER); smb_llist_remove(&tree->t_ofile_list, of); smb_idpool_free(&tree->t_fid_pool, of->f_fid); atomic_dec_32(&tree->t_session->s_file_cnt); smb_llist_exit(&tree->t_ofile_list); mutex_enter(&of->f_mutex); mutex_exit(&of->f_mutex); switch (of->f_ftype) { case SMB_FTYPE_BYTE_PIPE: case SMB_FTYPE_MESG_PIPE: smb_opipe_dealloc(of->f_pipe); of->f_pipe = NULL; break; case SMB_FTYPE_DISK: if (of->f_odir != NULL) smb_odir_release(of->f_odir); smb_node_rem_ofile(of->f_node, of); smb_node_release(of->f_node); break; default: ASSERT(!"f_ftype"); break; } of->f_magic = (uint32_t)~SMB_OFILE_MAGIC; mutex_destroy(&of->f_mutex); crfree(of->f_cr); smb_user_release(of->f_user); kmem_cache_free(smb_cache_ofile, of); }
/* * Release a reference on a file. If the reference count falls to * zero and the file has been closed, post the object for deletion. * Object deletion is deferred to avoid modifying a list while an * iteration may be in progress. */ void smb_ofile_release(smb_ofile_t *of) { SMB_OFILE_VALID(of); mutex_enter(&of->f_mutex); ASSERT(of->f_refcnt); of->f_refcnt--; switch (of->f_state) { case SMB_OFILE_STATE_OPEN: case SMB_OFILE_STATE_CLOSING: break; case SMB_OFILE_STATE_CLOSED: if (of->f_refcnt == 0) smb_tree_post_ofile(of->f_tree, of); break; default: ASSERT(0); break; } mutex_exit(&of->f_mutex); }
/* * smb_ofile_close */ void smb_ofile_close(smb_ofile_t *of, int32_t mtime_sec) { timestruc_t now; uint32_t flags = 0; SMB_OFILE_VALID(of); mutex_enter(&of->f_mutex); ASSERT(of->f_refcnt); switch (of->f_state) { case SMB_OFILE_STATE_OPEN: { of->f_state = SMB_OFILE_STATE_CLOSING; mutex_exit(&of->f_mutex); if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { smb_opipe_close(of); smb_server_dec_pipes(of->f_server); } else { smb_attr_t *pa = &of->f_pending_attr; /* * In here we make changes to of->f_pending_attr * while not holding of->f_mutex. This is OK * because we've changed f_state to CLOSING, * so no more threads will take this path. */ if (mtime_sec != 0) { pa->sa_vattr.va_mtime.tv_sec = mtime_sec; pa->sa_mask |= SMB_AT_MTIME; } /* * If we have ever modified data via this handle * (write or truncate) and if the mtime was not * set via this handle, update the mtime again * during the close. Windows expects this. * [ MS-FSA 2.1.5.4 "Update Timestamps" ] */ if (of->f_written && (pa->sa_mask & SMB_AT_MTIME) == 0) { pa->sa_mask |= SMB_AT_MTIME; gethrestime(&now); pa->sa_vattr.va_mtime = now; } if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) { if (smb_tree_has_feature(of->f_tree, SMB_TREE_CATIA)) { flags |= SMB_CATIA; } (void) smb_node_set_delete_on_close(of->f_node, of->f_cr, flags); } smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid); smb_node_destroy_lock_by_ofile(of->f_node, of); if (smb_node_is_file(of->f_node)) { (void) smb_fsop_close(of->f_node, of->f_mode, of->f_cr); smb_oplock_release(of->f_node, of); } if (smb_node_dec_open_ofiles(of->f_node) == 0) { /* * Last close. The f_pending_attr has * only times (atime,ctime,mtime) so * we can borrow it to commit the * n_pending_dosattr from the node. */ pa->sa_dosattr = of->f_node->n_pending_dosattr; if (pa->sa_dosattr != 0) pa->sa_mask |= SMB_AT_DOSATTR; /* Let's leave this zero when not in use. */ of->f_node->n_allocsz = 0; } if (pa->sa_mask != 0) { /* * Commit any pending attributes from * the ofile we're closing. Note that * we pass NULL as the ofile to setattr * so it will write to the file system * and not keep anything on the ofile. * This clears n_pending_dosattr if * there are no opens, otherwise the * dosattr will be pending again. */ (void) smb_node_setattr(NULL, of->f_node, of->f_cr, NULL, pa); } /* * Cancel any notify change requests that * may be using this open instance. */ if (of->f_node->n_fcn.fcn_count) smb_notify_file_closed(of); smb_server_dec_files(of->f_server); } atomic_dec_32(&of->f_tree->t_open_files); mutex_enter(&of->f_mutex); ASSERT(of->f_refcnt); ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING); of->f_state = SMB_OFILE_STATE_CLOSED; break; } case SMB_OFILE_STATE_CLOSED: case SMB_OFILE_STATE_CLOSING: break; default: ASSERT(0); break; } mutex_exit(&of->f_mutex); }