zftape-write.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. * Copyright (C) 1996, 1997 Claus Heine
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; see the file COPYING. If not, write to
  13. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  14. *
  15. * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-write.c,v $
  16. * $Revision: 1.3 $
  17. * $Date: 1997/11/06 00:50:29 $
  18. *
  19. * This file contains the writing code
  20. * for the QIC-117 floppy-tape driver for Linux.
  21. */
  22. #include <linux/errno.h>
  23. #include <linux/mm.h>
  24. #include <linux/zftape.h>
  25. #include <asm/uaccess.h>
  26. #include "../zftape/zftape-init.h"
  27. #include "../zftape/zftape-eof.h"
  28. #include "../zftape/zftape-ctl.h"
  29. #include "../zftape/zftape-write.h"
  30. #include "../zftape/zftape-read.h"
  31. #include "../zftape/zftape-rw.h"
  32. #include "../zftape/zftape-vtbl.h"
  33. /* Global vars.
  34. */
  35. /* Local vars.
  36. */
  37. static int last_write_failed;
  38. static int need_flush;
  39. void zft_prevent_flush(void)
  40. {
  41. need_flush = 0;
  42. }
  43. static int zft_write_header_segments(__u8* buffer)
  44. {
  45. int header_1_ok = 0;
  46. int header_2_ok = 0;
  47. unsigned int time_stamp;
  48. TRACE_FUN(ft_t_noise);
  49. TRACE_CATCH(ftape_abort_operation(),);
  50. ftape_seek_to_bot(); /* prevents extra rewind */
  51. if (GET4(buffer, 0) != FT_HSEG_MAGIC) {
  52. TRACE_ABORT(-EIO, ft_t_err,
  53. "wrong header signature found, aborting");
  54. }
  55. /* Be optimistic: */
  56. PUT4(buffer, FT_SEG_CNT,
  57. zft_written_segments + GET4(buffer, FT_SEG_CNT) + 2);
  58. if ((time_stamp = zft_get_time()) != 0) {
  59. PUT4(buffer, FT_WR_DATE, time_stamp);
  60. if (zft_label_changed) {
  61. PUT4(buffer, FT_LABEL_DATE, time_stamp);
  62. }
  63. }
  64. TRACE(ft_t_noise,
  65. "writing first header segment %d", ft_header_segment_1);
  66. header_1_ok = zft_verify_write_segments(ft_header_segment_1,
  67. buffer, FT_SEGMENT_SIZE,
  68. zft_deblock_buf) >= 0;
  69. TRACE(ft_t_noise,
  70. "writing second header segment %d", ft_header_segment_2);
  71. header_2_ok = zft_verify_write_segments(ft_header_segment_2,
  72. buffer, FT_SEGMENT_SIZE,
  73. zft_deblock_buf) >= 0;
  74. if (!header_1_ok) {
  75. TRACE(ft_t_warn, "Warning: "
  76. "update of first header segment failed");
  77. }
  78. if (!header_2_ok) {
  79. TRACE(ft_t_warn, "Warning: "
  80. "update of second header segment failed");
  81. }
  82. if (!header_1_ok && !header_2_ok) {
  83. TRACE_ABORT(-EIO, ft_t_err, "Error: "
  84. "update of both header segments failed.");
  85. }
  86. TRACE_EXIT 0;
  87. }
  88. int zft_update_header_segments(void)
  89. {
  90. TRACE_FUN(ft_t_noise);
  91. /* must NOT use zft_write_protected, as it also includes the
  92. * file access mode. But we also want to update when soft
  93. * write protection is enabled (O_RDONLY)
  94. */
  95. if (ft_write_protected || zft_old_ftape) {
  96. TRACE_ABORT(0, ft_t_noise, "Tape set read-only: no update");
  97. }
  98. if (!zft_header_read) {
  99. TRACE_ABORT(0, ft_t_noise, "Nothing to update");
  100. }
  101. if (!zft_header_changed) {
  102. zft_header_changed = zft_written_segments > 0;
  103. }
  104. if (!zft_header_changed && !zft_volume_table_changed) {
  105. TRACE_ABORT(0, ft_t_noise, "Nothing to update");
  106. }
  107. TRACE(ft_t_noise, "Updating header segments");
  108. if (ftape_get_status()->fti_state == writing) {
  109. TRACE_CATCH(ftape_loop_until_writes_done(),);
  110. }
  111. TRACE_CATCH(ftape_abort_operation(),);
  112. zft_deblock_segment = -1; /* invalidate the cache */
  113. if (zft_header_changed) {
  114. TRACE_CATCH(zft_write_header_segments(zft_hseg_buf),);
  115. }
  116. if (zft_volume_table_changed) {
  117. TRACE_CATCH(zft_update_volume_table(ft_first_data_segment),);
  118. }
  119. zft_header_changed =
  120. zft_volume_table_changed =
  121. zft_label_changed =
  122. zft_written_segments = 0;
  123. TRACE_CATCH(ftape_abort_operation(),);
  124. ftape_seek_to_bot();
  125. TRACE_EXIT 0;
  126. }
  127. static int read_merge_buffer(int seg_pos, __u8 *buffer, int offset, int seg_sz)
  128. {
  129. int result = 0;
  130. const ft_trace_t old_tracing = TRACE_LEVEL;
  131. TRACE_FUN(ft_t_flow);
  132. if (zft_qic_mode) {
  133. /* writing in the middle of a volume is NOT allowed
  134. *
  135. */
  136. TRACE(ft_t_noise, "No need to read a segment");
  137. memset(buffer + offset, 0, seg_sz - offset);
  138. TRACE_EXIT 0;
  139. }
  140. TRACE(ft_t_any, "waiting");
  141. ftape_start_writing(FT_WR_MULTI);
  142. TRACE_CATCH(ftape_loop_until_writes_done(),);
  143. TRACE(ft_t_noise, "trying to read segment %d from offset %d",
  144. seg_pos, offset);
  145. SET_TRACE_LEVEL(ft_t_bug);
  146. result = zft_fetch_segment_fraction(seg_pos, buffer,
  147. FT_RD_SINGLE,
  148. offset, seg_sz - offset);
  149. SET_TRACE_LEVEL(old_tracing);
  150. if (result != (seg_sz - offset)) {
  151. TRACE(ft_t_noise, "Ignore error: read_segment() result: %d",
  152. result);
  153. memset(buffer + offset, 0, seg_sz - offset);
  154. }
  155. TRACE_EXIT 0;
  156. }
  157. /* flush the write buffer to tape and write an eof-marker at the
  158. * current position if not in raw mode. This function always
  159. * positions the tape before the eof-marker. _ftape_close() should
  160. * then advance to the next segment.
  161. *
  162. * the parameter "finish_volume" describes whether to position before
  163. * or after the possibly created file-mark. We always position after
  164. * the file-mark when called from ftape_close() and a flush was needed
  165. * (that is ftape_write() was the last tape operation before calling
  166. * ftape_flush) But we always position before the file-mark when this
  167. * function get's called from outside ftape_close()
  168. */
  169. int zft_flush_buffers(void)
  170. {
  171. int result;
  172. int data_remaining;
  173. int this_segs_size;
  174. TRACE_FUN(ft_t_flow);
  175. TRACE(ft_t_data_flow,
  176. "entered, ftape_state = %d", ftape_get_status()->fti_state);
  177. if (ftape_get_status()->fti_state != writing && !need_flush) {
  178. TRACE_ABORT(0, ft_t_noise, "no need for flush");
  179. }
  180. zft_io_state = zft_idle; /* triggers some initializations for the
  181. * read and write routines
  182. */
  183. if (last_write_failed) {
  184. ftape_abort_operation();
  185. TRACE_EXIT -EIO;
  186. }
  187. TRACE(ft_t_noise, "flushing write buffers");
  188. this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);
  189. if (this_segs_size == zft_pos.seg_byte_pos) {
  190. zft_pos.seg_pos ++;
  191. data_remaining = zft_pos.seg_byte_pos = 0;
  192. } else {
  193. data_remaining = zft_pos.seg_byte_pos;
  194. }
  195. /* If there is any data not written to tape yet, append zero's
  196. * up to the end of the sector (if using compression) or merge
  197. * it with the data existing on the tape Then write the
  198. * segment(s) to tape.
  199. */
  200. TRACE(ft_t_noise, "Position:\n"
  201. KERN_INFO "seg_pos : %d\n"
  202. KERN_INFO "byte pos : %d\n"
  203. KERN_INFO "remaining: %d",
  204. zft_pos.seg_pos, zft_pos.seg_byte_pos, data_remaining);
  205. if (data_remaining > 0) {
  206. do {
  207. this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);
  208. if (this_segs_size > data_remaining) {
  209. TRACE_CATCH(read_merge_buffer(zft_pos.seg_pos,
  210. zft_deblock_buf,
  211. data_remaining,
  212. this_segs_size),
  213. last_write_failed = 1);
  214. }
  215. result = ftape_write_segment(zft_pos.seg_pos,
  216. zft_deblock_buf,
  217. FT_WR_MULTI);
  218. if (result != this_segs_size) {
  219. TRACE(ft_t_err, "flush buffers failed");
  220. zft_pos.tape_pos -= zft_pos.seg_byte_pos;
  221. zft_pos.seg_byte_pos = 0;
  222. last_write_failed = 1;
  223. TRACE_EXIT result;
  224. }
  225. zft_written_segments ++;
  226. TRACE(ft_t_data_flow,
  227. "flush, moved out buffer: %d", result);
  228. /* need next segment for more data (empty segments?)
  229. */
  230. if (result < data_remaining) {
  231. if (result > 0) {
  232. /* move remainder to buffer beginning
  233. */
  234. memmove(zft_deblock_buf,
  235. zft_deblock_buf + result,
  236. FT_SEGMENT_SIZE - result);
  237. }
  238. }
  239. data_remaining -= result;
  240. zft_pos.seg_pos ++;
  241. } while (data_remaining > 0);
  242. TRACE(ft_t_any, "result: %d", result);
  243. zft_deblock_segment = --zft_pos.seg_pos;
  244. if (data_remaining == 0) { /* first byte next segment */
  245. zft_pos.seg_byte_pos = this_segs_size;
  246. } else { /* after data previous segment, data_remaining < 0 */
  247. zft_pos.seg_byte_pos = data_remaining + result;
  248. }
  249. } else {
  250. TRACE(ft_t_noise, "zft_deblock_buf empty");
  251. zft_pos.seg_pos --;
  252. zft_pos.seg_byte_pos = zft_get_seg_sz (zft_pos.seg_pos);
  253. ftape_start_writing(FT_WR_MULTI);
  254. }
  255. TRACE(ft_t_any, "waiting");
  256. if ((result = ftape_loop_until_writes_done()) < 0) {
  257. /* that's really bad. What to to with zft_tape_pos?
  258. */
  259. TRACE(ft_t_err, "flush buffers failed");
  260. }
  261. TRACE(ft_t_any, "zft_seg_pos: %d, zft_seg_byte_pos: %d",
  262. zft_pos.seg_pos, zft_pos.seg_byte_pos);
  263. last_write_failed =
  264. need_flush = 0;
  265. TRACE_EXIT result;
  266. }
  267. /* return-value: the number of bytes removed from the user-buffer
  268. *
  269. * out:
  270. * int *write_cnt: how much actually has been moved to the
  271. * zft_deblock_buf
  272. * int req_len : MUST NOT BE CHANGED, except at EOT, in
  273. * which case it may be adjusted
  274. * in :
  275. * char *buff : the user buffer
  276. * int buf_pos_write : copy of buf_len_wr int
  277. * this_segs_size : the size in bytes of the actual segment
  278. * char
  279. * *zft_deblock_buf : zft_deblock_buf
  280. */
  281. static int zft_simple_write(int *cnt,
  282. __u8 *dst_buf, const int seg_sz,
  283. const __u8 __user *src_buf, const int req_len,
  284. const zft_position *pos,const zft_volinfo *volume)
  285. {
  286. int space_left;
  287. TRACE_FUN(ft_t_flow);
  288. /* volume->size holds the tape capacity while volume is open */
  289. if (pos->tape_pos + volume->blk_sz > volume->size) {
  290. TRACE_EXIT -ENOSPC;
  291. }
  292. /* remaining space in this segment, NOT zft_deblock_buf
  293. */
  294. space_left = seg_sz - pos->seg_byte_pos;
  295. *cnt = req_len < space_left ? req_len : space_left;
  296. if (copy_from_user(dst_buf + pos->seg_byte_pos, src_buf, *cnt) != 0) {
  297. TRACE_EXIT -EFAULT;
  298. }
  299. TRACE_EXIT *cnt;
  300. }
  301. static int check_write_access(int req_len,
  302. const zft_volinfo **volume,
  303. zft_position *pos,
  304. const unsigned int blk_sz)
  305. {
  306. int result;
  307. TRACE_FUN(ft_t_flow);
  308. if ((req_len % zft_blk_sz) != 0) {
  309. TRACE_ABORT(-EINVAL, ft_t_info,
  310. "write-count %d must be multiple of block-size %d",
  311. req_len, blk_sz);
  312. }
  313. if (zft_io_state == zft_writing) {
  314. /* all other error conditions have been checked earlier
  315. */
  316. TRACE_EXIT 0;
  317. }
  318. zft_io_state = zft_idle;
  319. TRACE_CATCH(zft_check_write_access(pos),);
  320. /* If we haven't read the header segment yet, do it now.
  321. * This will verify the configuration, get the bad sector
  322. * table and read the volume table segment
  323. */
  324. if (!zft_header_read) {
  325. TRACE_CATCH(zft_read_header_segments(),);
  326. }
  327. /* fine. Now the tape is either at BOT or at EOD,
  328. * Write start of volume now
  329. */
  330. TRACE_CATCH(zft_open_volume(pos, blk_sz, zft_use_compression),);
  331. *volume = zft_find_volume(pos->seg_pos);
  332. DUMP_VOLINFO(ft_t_noise, "", *volume);
  333. zft_just_before_eof = 0;
  334. /* now merge with old data if necessary */
  335. if (!zft_qic_mode && pos->seg_byte_pos != 0){
  336. result = zft_fetch_segment(pos->seg_pos,
  337. zft_deblock_buf,
  338. FT_RD_SINGLE);
  339. if (result < 0) {
  340. if (result == -EINTR || result == -ENOSPC) {
  341. TRACE_EXIT result;
  342. }
  343. TRACE(ft_t_noise,
  344. "ftape_read_segment() result: %d. "
  345. "This might be normal when using "
  346. "a newly\nformatted tape", result);
  347. memset(zft_deblock_buf, '\0', pos->seg_byte_pos);
  348. }
  349. }
  350. zft_io_state = zft_writing;
  351. TRACE_EXIT 0;
  352. }
  353. static int fill_deblock_buf(__u8 *dst_buf, const int seg_sz,
  354. zft_position *pos, const zft_volinfo *volume,
  355. const char __user *usr_buf, const int req_len)
  356. {
  357. int cnt = 0;
  358. int result = 0;
  359. TRACE_FUN(ft_t_flow);
  360. if (seg_sz == 0) {
  361. TRACE_ABORT(0, ft_t_data_flow, "empty segment");
  362. }
  363. TRACE(ft_t_data_flow, "\n"
  364. KERN_INFO "remaining req_len: %d\n"
  365. KERN_INFO " buf_pos: %d",
  366. req_len, pos->seg_byte_pos);
  367. /* zft_deblock_buf will not contain a valid segment any longer */
  368. zft_deblock_segment = -1;
  369. if (zft_use_compression) {
  370. TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
  371. TRACE_CATCH(result= (*zft_cmpr_ops->write)(&cnt,
  372. dst_buf, seg_sz,
  373. usr_buf, req_len,
  374. pos, volume),);
  375. } else {
  376. TRACE_CATCH(result= zft_simple_write(&cnt,
  377. dst_buf, seg_sz,
  378. usr_buf, req_len,
  379. pos, volume),);
  380. }
  381. pos->volume_pos += result;
  382. pos->seg_byte_pos += cnt;
  383. pos->tape_pos += cnt;
  384. TRACE(ft_t_data_flow, "\n"
  385. KERN_INFO "removed from user-buffer : %d bytes.\n"
  386. KERN_INFO "copied to zft_deblock_buf: %d bytes.\n"
  387. KERN_INFO "zft_tape_pos : " LL_X " bytes.",
  388. result, cnt, LL(pos->tape_pos));
  389. TRACE_EXIT result;
  390. }
  391. /* called by the kernel-interface routine "zft_write()"
  392. */
  393. int _zft_write(const char __user *buff, int req_len)
  394. {
  395. int result = 0;
  396. int written = 0;
  397. int write_cnt;
  398. int seg_sz;
  399. static const zft_volinfo *volume = NULL;
  400. TRACE_FUN(ft_t_flow);
  401. zft_resid = req_len;
  402. last_write_failed = 1; /* reset to 0 when successful */
  403. /* check if write is allowed
  404. */
  405. TRACE_CATCH(check_write_access(req_len, &volume,&zft_pos,zft_blk_sz),);
  406. while (req_len > 0) {
  407. /* Allow us to escape from this loop with a signal !
  408. */
  409. FT_SIGNAL_EXIT(_DONT_BLOCK);
  410. seg_sz = zft_get_seg_sz(zft_pos.seg_pos);
  411. if ((write_cnt = fill_deblock_buf(zft_deblock_buf,
  412. seg_sz,
  413. &zft_pos,
  414. volume,
  415. buff,
  416. req_len)) < 0) {
  417. zft_resid -= written;
  418. if (write_cnt == -ENOSPC) {
  419. /* leave the remainder to flush_buffers()
  420. */
  421. TRACE(ft_t_info, "No space left on device");
  422. last_write_failed = 0;
  423. if (!need_flush) {
  424. need_flush = written > 0;
  425. }
  426. TRACE_EXIT written > 0 ? written : -ENOSPC;
  427. } else {
  428. TRACE_EXIT result;
  429. }
  430. }
  431. if (zft_pos.seg_byte_pos == seg_sz) {
  432. TRACE_CATCH(ftape_write_segment(zft_pos.seg_pos,
  433. zft_deblock_buf,
  434. FT_WR_ASYNC),
  435. zft_resid -= written);
  436. zft_written_segments ++;
  437. zft_pos.seg_byte_pos = 0;
  438. zft_deblock_segment = zft_pos.seg_pos;
  439. ++zft_pos.seg_pos;
  440. }
  441. written += write_cnt;
  442. buff += write_cnt;
  443. req_len -= write_cnt;
  444. } /* while (req_len > 0) */
  445. TRACE(ft_t_data_flow, "remaining in blocking buffer: %d",
  446. zft_pos.seg_byte_pos);
  447. TRACE(ft_t_data_flow, "just written bytes: %d", written);
  448. last_write_failed = 0;
  449. zft_resid -= written;
  450. need_flush = need_flush || written > 0;
  451. TRACE_EXIT written; /* bytes written */
  452. }