static void smb_put_super(struct super_block *sb) { struct smb_sb_info *server = SMB_SB(sb); lock_kernel(); smb_lock_server(server); server->state = CONN_INVALID; smbiod_unregister_server(server); smb_close_socket(server); if (server->conn_pid) kill_pid(server->conn_pid, SIGTERM, 1); bdi_destroy(&server->bdi); kfree(server->ops); smb_unload_nls(server); sb->s_fs_info = NULL; smb_unlock_server(server); put_pid(server->conn_pid); kfree(server); unlock_kernel(); }
static int smb_fsync(struct file *file, struct dentry * dentry, int datasync) { struct smb_sb_info *server = server_from_dentry(dentry); int result; VERBOSE("sync file %s/%s\n", DENTRY_PATH(dentry)); /* * The VFS will writepage() all dirty pages for us, but we * should send a SMBflush to the server, letting it know that * we want things synchronized with actual storage. * * Note: this function requires all pages to have been written already * (should be ok with writepage_sync) */ smb_lock_server(server); result = smb_proc_flush(server, dentry->d_inode->u.smbfs_i.fileid); smb_unlock_server(server); return result; }
/* * Add a request and tell smbiod to process it */ int smb_add_request(struct smb_request *req) { long timeleft; struct smb_sb_info *server = req->rq_server; int result = 0; smb_setup_request(req); if (req->rq_trans2_command) { if (req->rq_buffer == NULL) { PARANOIA("trans2 attempted without response buffer!\n"); return -EIO; } result = smb_setup_trans2request(req); } if (result < 0) return result; #ifdef SMB_DEBUG_PACKET_SIZE add_xmit_stats(req); #endif /* add 'req' to the queue of requests */ if (smb_lock_server_interruptible(server)) return -EINTR; /* * Try to send the request as the process. If that fails we queue the * request and let smbiod send it later. */ /* FIXME: each server has a number on the maximum number of parallel requests. 10, 50 or so. We should not allow more requests to be active. */ if (server->mid > 0xf000) server->mid = 0; req->rq_mid = server->mid++; WSET(req->rq_header, smb_mid, req->rq_mid); result = 0; if (server->state == CONN_VALID) { if (list_empty(&server->xmitq)) result = smb_request_send_req(req); if (result < 0) { /* Connection lost? */ server->conn_error = result; server->state = CONN_INVALID; } } if (result != 1) list_add_tail(&req->rq_queue, &server->xmitq); smb_rget(req); if (server->state != CONN_VALID) smbiod_retry(server); smb_unlock_server(server); smbiod_wake_up(); timeleft = wait_event_interruptible_timeout(req->rq_wait, req->rq_flags & SMB_REQ_RECEIVED, 30*HZ); if (!timeleft || signal_pending(current)) { /* * On timeout or on interrupt we want to try and remove the * request from the recvq/xmitq. * First check if the request is still part of a queue. (May * have been removed by some error condition) */ smb_lock_server(server); if (!list_empty(&req->rq_queue)) { list_del_init(&req->rq_queue); smb_rput(req); } smb_unlock_server(server); } if (!timeleft) { PARANOIA("request [%p, mid=%d] timed out!\n", req, req->rq_mid); VERBOSE("smb_com: %02x\n", *(req->rq_header + smb_com)); VERBOSE("smb_rcls: %02x\n", *(req->rq_header + smb_rcls)); VERBOSE("smb_flg: %02x\n", *(req->rq_header + smb_flg)); VERBOSE("smb_tid: %04x\n", WVAL(req->rq_header, smb_tid)); VERBOSE("smb_pid: %04x\n", WVAL(req->rq_header, smb_pid)); VERBOSE("smb_uid: %04x\n", WVAL(req->rq_header, smb_uid)); VERBOSE("smb_mid: %04x\n", WVAL(req->rq_header, smb_mid)); VERBOSE("smb_wct: %02x\n", *(req->rq_header + smb_wct)); req->rq_rcls = ERRSRV; req->rq_err = ERRtimeout; /* Just in case it was "stuck" */ smbiod_wake_up(); } VERBOSE("woke up, rcls=%d\n", req->rq_rcls); if (req->rq_rcls != 0) req->rq_errno = smb_errno(req); if (signal_pending(current)) req->rq_errno = -ERESTARTSYS; return req->rq_errno; }