Blame view

drivers/target/target_core_file.c 21.7 KB
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
1
2
3
4
5
  /*******************************************************************************
   * Filename:  target_core_file.c
   *
   * This file contains the Storage Engine <-> FILEIO transport specific functions
   *
4c76251e8   Nicholas Bellinger   target: Update co...
6
   * (c) Copyright 2005-2013 Datera, Inc.
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   *
   * Nicholas A. Bellinger <nab@kernel.org>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   *
   ******************************************************************************/
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
25
26
27
28
29
30
  #include <linux/string.h>
  #include <linux/parser.h>
  #include <linux/timer.h>
  #include <linux/blkdev.h>
  #include <linux/slab.h>
  #include <linux/spinlock.h>
827509e38   Paul Gortmaker   drivers/target: A...
31
  #include <linux/module.h>
5538d294d   David S. Miller   treewide: Add mis...
32
  #include <linux/vmalloc.h>
70d3ae5c8   Asias He   target/file: Add ...
33
  #include <linux/falloc.h>
ba9299925   Bart Van Assche   target: Minimize ...
34
  #include <scsi/scsi_proto.h>
506427628   Asias He   target/file: Add ...
35
  #include <asm/unaligned.h>
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
36
37
  
  #include <target/target_core_base.h>
c4795fb20   Christoph Hellwig   target: header re...
38
  #include <target/target_core_backend.h>
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
39
40
  
  #include "target_core_file.h"
0fd97ccf4   Christoph Hellwig   target: kill stru...
41
42
43
44
  static inline struct fd_dev *FD_DEV(struct se_device *dev)
  {
  	return container_of(dev, struct fd_dev, dev);
  }
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
45

c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
46
47
48
49
50
  static int fd_attach_hba(struct se_hba *hba, u32 host_id)
  {
  	struct fd_host *fd_host;
  
  	fd_host = kzalloc(sizeof(struct fd_host), GFP_KERNEL);
6708bb27b   Andy Grover   target: Follow up...
51
52
53
  	if (!fd_host) {
  		pr_err("Unable to allocate memory for struct fd_host
  ");
e3d6f909e   Andy Grover   target: Core clea...
54
  		return -ENOMEM;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
55
56
57
  	}
  
  	fd_host->fd_host_id = host_id;
e3d6f909e   Andy Grover   target: Core clea...
58
  	hba->hba_ptr = fd_host;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
59

6708bb27b   Andy Grover   target: Follow up...
60
  	pr_debug("CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic"
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
61
62
  		" Target Core Stack %s
  ", hba->hba_id, FD_VERSION,
ce8dd25d0   Christoph Hellwig   target: consolida...
63
  		TARGET_CORE_VERSION);
95cadace8   Nicholas Bellinger   target/file: Upda...
64
65
66
  	pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic
  ",
  		hba->hba_id, fd_host->fd_host_id);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
67
68
69
70
71
72
73
  
  	return 0;
  }
  
  static void fd_detach_hba(struct se_hba *hba)
  {
  	struct fd_host *fd_host = hba->hba_ptr;
6708bb27b   Andy Grover   target: Follow up...
74
  	pr_debug("CORE_HBA[%d] - Detached FILEIO HBA: %u from Generic"
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
75
76
77
78
79
80
  		" Target Core
  ", hba->hba_id, fd_host->fd_host_id);
  
  	kfree(fd_host);
  	hba->hba_ptr = NULL;
  }
0fd97ccf4   Christoph Hellwig   target: kill stru...
81
  static struct se_device *fd_alloc_device(struct se_hba *hba, const char *name)
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
82
83
  {
  	struct fd_dev *fd_dev;
8359cf43b   Jörn Engel   target: remove us...
84
  	struct fd_host *fd_host = hba->hba_ptr;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
85
86
  
  	fd_dev = kzalloc(sizeof(struct fd_dev), GFP_KERNEL);
6708bb27b   Andy Grover   target: Follow up...
87
88
89
  	if (!fd_dev) {
  		pr_err("Unable to allocate memory for struct fd_dev
  ");
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
90
91
92
93
  		return NULL;
  	}
  
  	fd_dev->fd_host = fd_host;
6708bb27b   Andy Grover   target: Follow up...
94
95
  	pr_debug("FILEIO: Allocated fd_dev for %p
  ", name);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
96

0fd97ccf4   Christoph Hellwig   target: kill stru...
97
  	return &fd_dev->dev;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
98
  }
0fd97ccf4   Christoph Hellwig   target: kill stru...
99
  static int fd_configure_device(struct se_device *dev)
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
100
  {
0fd97ccf4   Christoph Hellwig   target: kill stru...
101
102
  	struct fd_dev *fd_dev = FD_DEV(dev);
  	struct fd_host *fd_host = dev->se_hba->hba_ptr;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
103
104
  	struct file *file;
  	struct inode *inode = NULL;
0fd97ccf4   Christoph Hellwig   target: kill stru...
105
  	int flags, ret = -EINVAL;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
106

0fd97ccf4   Christoph Hellwig   target: kill stru...
107
108
109
110
111
  	if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) {
  		pr_err("Missing fd_dev_name=
  ");
  		return -EINVAL;
  	}
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
112

c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
113
  	/*
a4dff3043   Nicholas Bellinger   target/file: Use ...
114
115
  	 * Use O_DSYNC by default instead of O_SYNC to forgo syncing
  	 * of pure timestamp updates.
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
116
  	 */
a4dff3043   Nicholas Bellinger   target/file: Use ...
117
  	flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC;
0fd97ccf4   Christoph Hellwig   target: kill stru...
118

b32f4c7ed   Nicholas Bellinger   target/file: Re-e...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  	/*
  	 * Optionally allow fd_buffered_io=1 to be enabled for people
  	 * who want use the fs buffer cache as an WriteCache mechanism.
  	 *
  	 * This means that in event of a hard failure, there is a risk
  	 * of silent data-loss if the SCSI client has *not* performed a
  	 * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE
  	 * to write-out the entire device cache.
  	 */
  	if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
  		pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO
  ");
  		flags &= ~O_DSYNC;
  	}
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
133

dbc6e0222   Al Viro   delousing target_...
134
  	file = filp_open(fd_dev->fd_dev_name, flags, 0600);
613640e4e   Nicholas Bellinger   [SCSI] target: Co...
135
  	if (IS_ERR(file)) {
dbc6e0222   Al Viro   delousing target_...
136
137
  		pr_err("filp_open(%s) failed
  ", fd_dev->fd_dev_name);
613640e4e   Nicholas Bellinger   [SCSI] target: Co...
138
139
140
  		ret = PTR_ERR(file);
  		goto fail;
  	}
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
141
142
143
144
145
146
147
148
149
  	fd_dev->fd_file = file;
  	/*
  	 * If using a block backend with this struct file, we extract
  	 * fd_dev->fd_[block,dev]_size from struct block_device.
  	 *
  	 * Otherwise, we use the passed fd_size= from configfs
  	 */
  	inode = file->f_mapping->host;
  	if (S_ISBLK(inode->i_mode)) {
0fd97ccf4   Christoph Hellwig   target: kill stru...
150
  		struct request_queue *q = bdev_get_queue(inode->i_bdev);
cd9323fd6   Nicholas Bellinger   target: Fix bug i...
151
  		unsigned long long dev_size;
0fd97ccf4   Christoph Hellwig   target: kill stru...
152

21363ca87   Nicholas Bellinger   target/file: Fix ...
153
  		fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
154
155
156
157
  		/*
  		 * Determine the number of bytes from i_size_read() minus
  		 * one (1) logical sector from underlying struct block_device
  		 */
cd9323fd6   Nicholas Bellinger   target: Fix bug i...
158
  		dev_size = (i_size_read(file->f_mapping->host) -
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
159
  				       fd_dev->fd_block_size);
6708bb27b   Andy Grover   target: Follow up...
160
  		pr_debug("FILEIO: Using size: %llu bytes from struct"
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
161
162
  			" block_device blocks: %llu logical_block_size: %d
  ",
cd9323fd6   Nicholas Bellinger   target: Fix bug i...
163
  			dev_size, div_u64(dev_size, fd_dev->fd_block_size),
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
164
  			fd_dev->fd_block_size);
8a9ebe717   Mike Christie   target: Fix WRITE...
165

ea263c7fa   Mike Christie   target: Fix max_u...
166
  		if (target_configure_unmap_from_queue(&dev->dev_attrib, q))
70d3ae5c8   Asias He   target/file: Add ...
167
  			pr_debug("IFILE: BLOCK Discard support available,"
8a9ebe717   Mike Christie   target: Fix WRITE...
168
169
  				 " disabled by default
  ");
70d3ae5c8   Asias He   target/file: Add ...
170
171
172
173
174
  		/*
  		 * Enable write same emulation for IBLOCK and use 0xFFFF as
  		 * the smaller WRITE_SAME(10) only has a two-byte block count.
  		 */
  		dev->dev_attrib.max_write_same_len = 0xFFFF;
0463a3fef   Asias He   target/file: Set ...
175
176
177
  
  		if (blk_queue_nonrot(q))
  			dev->dev_attrib.is_nonrot = 1;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
178
179
  	} else {
  		if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) {
6708bb27b   Andy Grover   target: Follow up...
180
  			pr_err("FILEIO: Missing fd_dev_size="
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
181
182
183
184
185
  				" parameter, and no backing struct"
  				" block_device
  ");
  			goto fail;
  		}
21363ca87   Nicholas Bellinger   target/file: Fix ...
186
  		fd_dev->fd_block_size = FD_BLOCKSIZE;
70d3ae5c8   Asias He   target/file: Add ...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  		/*
  		 * Limit UNMAP emulation to 8k Number of LBAs (NoLB)
  		 */
  		dev->dev_attrib.max_unmap_lba_count = 0x2000;
  		/*
  		 * Currently hardcoded to 1 in Linux/SCSI code..
  		 */
  		dev->dev_attrib.max_unmap_block_desc_count = 1;
  		dev->dev_attrib.unmap_granularity = 1;
  		dev->dev_attrib.unmap_granularity_alignment = 0;
  
  		/*
  		 * Limit WRITE_SAME w/ UNMAP=0 emulation to 8k Number of LBAs (NoLB)
  		 * based upon struct iovec limit for vfs_writev()
  		 */
  		dev->dev_attrib.max_write_same_len = 0x1000;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
203
  	}
21363ca87   Nicholas Bellinger   target/file: Fix ...
204
  	dev->dev_attrib.hw_block_size = fd_dev->fd_block_size;
95cadace8   Nicholas Bellinger   target/file: Upda...
205
206
  	dev->dev_attrib.max_bytes_per_io = FD_MAX_BYTES;
  	dev->dev_attrib.hw_max_sectors = FD_MAX_BYTES / fd_dev->fd_block_size;
0fd97ccf4   Christoph Hellwig   target: kill stru...
207
  	dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
208

b32f4c7ed   Nicholas Bellinger   target/file: Re-e...
209
210
211
212
  	if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
  		pr_debug("FILEIO: Forcing setting of emulate_write_cache=1"
  			" with FDBD_HAS_BUFFERED_IO_WCE
  ");
0fd97ccf4   Christoph Hellwig   target: kill stru...
213
  		dev->dev_attrib.emulate_write_cache = 1;
b32f4c7ed   Nicholas Bellinger   target/file: Re-e...
214
  	}
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
215
216
  	fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++;
  	fd_dev->fd_queue_depth = dev->queue_depth;
6708bb27b   Andy Grover   target: Follow up...
217
  	pr_debug("CORE_FILE[%u] - Added TCM FILEIO Device ID: %u at %s,"
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
218
219
220
  		" %llu total bytes
  ", fd_host->fd_host_id, fd_dev->fd_dev_id,
  			fd_dev->fd_dev_name, fd_dev->fd_dev_size);
0fd97ccf4   Christoph Hellwig   target: kill stru...
221
  	return 0;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
222
223
224
225
226
  fail:
  	if (fd_dev->fd_file) {
  		filp_close(fd_dev->fd_file, NULL);
  		fd_dev->fd_file = NULL;
  	}
0fd97ccf4   Christoph Hellwig   target: kill stru...
227
  	return ret;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
228
  }
4cc987eaf   Nicholas Bellinger   target: Drop lun_...
229
  static void fd_dev_call_rcu(struct rcu_head *p)
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
230
  {
4cc987eaf   Nicholas Bellinger   target: Drop lun_...
231
  	struct se_device *dev = container_of(p, struct se_device, rcu_head);
0fd97ccf4   Christoph Hellwig   target: kill stru...
232
  	struct fd_dev *fd_dev = FD_DEV(dev);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
233

c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
234
235
  	kfree(fd_dev);
  }
0fd97ccf4   Christoph Hellwig   target: kill stru...
236
  static void fd_free_device(struct se_device *dev)
42201b557   Nicholas Bellinger   target/file: Add ...
237
  {
0fd97ccf4   Christoph Hellwig   target: kill stru...
238
  	struct fd_dev *fd_dev = FD_DEV(dev);
42201b557   Nicholas Bellinger   target/file: Add ...
239

c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
240
241
242
  	if (fd_dev->fd_file) {
  		filp_close(fd_dev->fd_file, NULL);
  		fd_dev->fd_file = NULL;
42201b557   Nicholas Bellinger   target/file: Add ...
243
  	}
4cc987eaf   Nicholas Bellinger   target: Drop lun_...
244
  	call_rcu(&dev->rcu_head, fd_dev_call_rcu);
42201b557   Nicholas Bellinger   target/file: Add ...
245
  }
8287fa5fb   Sagi Grimberg   target/file: Remo...
246
247
248
  static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
  		    u32 block_size, struct scatterlist *sgl,
  		    u32 sgl_nents, u32 data_length, int is_write)
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
249
  {
5787cacd0   Christoph Hellwig   target: remove st...
250
  	struct scatterlist *sg;
6b9a44d09   Christoph Hellwig   target: use vfs_i...
251
252
253
  	struct iov_iter iter;
  	struct bio_vec *bvec;
  	ssize_t len = 0;
8287fa5fb   Sagi Grimberg   target/file: Remo...
254
  	loff_t pos = (cmd->t_task_lba * block_size);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
255
  	int ret = 0, i;
6b9a44d09   Christoph Hellwig   target: use vfs_i...
256
257
  	bvec = kcalloc(sgl_nents, sizeof(struct bio_vec), GFP_KERNEL);
  	if (!bvec) {
6708bb27b   Andy Grover   target: Follow up...
258
259
  		pr_err("Unable to allocate fd_do_readv iov[]
  ");
e3d6f909e   Andy Grover   target: Core clea...
260
  		return -ENOMEM;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
261
  	}
5787cacd0   Christoph Hellwig   target: remove st...
262
  	for_each_sg(sgl, sg, sgl_nents, i) {
6b9a44d09   Christoph Hellwig   target: use vfs_i...
263
264
265
  		bvec[i].bv_page = sg_page(sg);
  		bvec[i].bv_len = sg->length;
  		bvec[i].bv_offset = sg->offset;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
266

6b9a44d09   Christoph Hellwig   target: use vfs_i...
267
268
  		len += sg->length;
  	}
778229af9   Sebastian Andrzej Siewior   target/file: merg...
269

6b9a44d09   Christoph Hellwig   target: use vfs_i...
270
  	iov_iter_bvec(&iter, ITER_BVEC, bvec, sgl_nents, len);
778229af9   Sebastian Andrzej Siewior   target/file: merg...
271
  	if (is_write)
6b9a44d09   Christoph Hellwig   target: use vfs_i...
272
  		ret = vfs_iter_write(fd, &iter, &pos);
778229af9   Sebastian Andrzej Siewior   target/file: merg...
273
  	else
6b9a44d09   Christoph Hellwig   target: use vfs_i...
274
  		ret = vfs_iter_read(fd, &iter, &pos);
778229af9   Sebastian Andrzej Siewior   target/file: merg...
275

6b9a44d09   Christoph Hellwig   target: use vfs_i...
276
  	kfree(bvec);
778229af9   Sebastian Andrzej Siewior   target/file: merg...
277
278
  
  	if (is_write) {
8287fa5fb   Sagi Grimberg   target/file: Remo...
279
  		if (ret < 0 || ret != data_length) {
778229af9   Sebastian Andrzej Siewior   target/file: merg...
280
281
  			pr_err("%s() write returned %d
  ", __func__, ret);
e3d6f909e   Andy Grover   target: Core clea...
282
  			return (ret < 0 ? ret : -EINVAL);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
283
284
  		}
  	} else {
778229af9   Sebastian Andrzej Siewior   target/file: merg...
285
286
287
288
289
  		/*
  		 * Return zeros and GOOD status even if the READ did not return
  		 * the expected virt_size for struct file w/o a backing struct
  		 * block_device.
  		 */
496ad9aa8   Al Viro   new helper: file_...
290
  		if (S_ISBLK(file_inode(fd)->i_mode)) {
8287fa5fb   Sagi Grimberg   target/file: Remo...
291
  			if (ret < 0 || ret != data_length) {
778229af9   Sebastian Andrzej Siewior   target/file: merg...
292
293
294
  				pr_err("%s() returned %d, expecting %u for "
  						"S_ISBLK
  ", __func__, ret,
8287fa5fb   Sagi Grimberg   target/file: Remo...
295
  						data_length);
778229af9   Sebastian Andrzej Siewior   target/file: merg...
296
297
298
299
300
301
302
303
304
  				return (ret < 0 ? ret : -EINVAL);
  			}
  		} else {
  			if (ret < 0) {
  				pr_err("%s() returned %d for non S_ISBLK
  ",
  						__func__, ret);
  				return ret;
  			}
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
305
306
  		}
  	}
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
307
308
  	return 1;
  }
de103c93a   Christoph Hellwig   target: pass sens...
309
310
  static sense_reason_t
  fd_execute_sync_cache(struct se_cmd *cmd)
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
311
  {
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
312
  	struct se_device *dev = cmd->se_dev;
0fd97ccf4   Christoph Hellwig   target: kill stru...
313
  	struct fd_dev *fd_dev = FD_DEV(dev);
a1d8b49ab   Andy Grover   target: Updates f...
314
  	int immed = (cmd->t_task_cdb[1] & 0x2);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
315
316
317
318
319
320
321
322
  	loff_t start, end;
  	int ret;
  
  	/*
  	 * If the Immediate bit is set, queue up the GOOD response
  	 * for this SYNCHRONIZE_CACHE op
  	 */
  	if (immed)
5787cacd0   Christoph Hellwig   target: remove st...
323
  		target_complete_cmd(cmd, SAM_STAT_GOOD);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
324
325
326
327
  
  	/*
  	 * Determine if we will be flushing the entire device.
  	 */
a1d8b49ab   Andy Grover   target: Updates f...
328
  	if (cmd->t_task_lba == 0 && cmd->data_length == 0) {
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
329
330
331
  		start = 0;
  		end = LLONG_MAX;
  	} else {
0fd97ccf4   Christoph Hellwig   target: kill stru...
332
  		start = cmd->t_task_lba * dev->dev_attrib.block_size;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
333
  		if (cmd->data_length)
62d3ab49b   Zach Brown   target/file: fix ...
334
  			end = start + cmd->data_length - 1;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
335
336
337
338
339
340
  		else
  			end = LLONG_MAX;
  	}
  
  	ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1);
  	if (ret != 0)
6708bb27b   Andy Grover   target: Follow up...
341
342
  		pr_err("FILEIO: vfs_fsync_range() failed: %d
  ", ret);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
343

5787cacd0   Christoph Hellwig   target: remove st...
344
  	if (immed)
ad67f0d9e   Christoph Hellwig   target: move sync...
345
  		return 0;
5787cacd0   Christoph Hellwig   target: remove st...
346

de103c93a   Christoph Hellwig   target: pass sens...
347
  	if (ret)
5787cacd0   Christoph Hellwig   target: remove st...
348
  		target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
de103c93a   Christoph Hellwig   target: pass sens...
349
  	else
5787cacd0   Christoph Hellwig   target: remove st...
350
  		target_complete_cmd(cmd, SAM_STAT_GOOD);
ad67f0d9e   Christoph Hellwig   target: move sync...
351
352
  
  	return 0;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
353
  }
7b745c84a   Nicholas Bellinger   target/file: Add ...
354
355
356
357
358
  static sense_reason_t
  fd_execute_write_same(struct se_cmd *cmd)
  {
  	struct se_device *se_dev = cmd->se_dev;
  	struct fd_dev *fd_dev = FD_DEV(se_dev);
7b745c84a   Nicholas Bellinger   target/file: Add ...
359
  	loff_t pos = cmd->t_task_lba * se_dev->dev_attrib.block_size;
d4c5dcacf   Christoph Hellwig   target: rewrite f...
360
361
362
363
364
  	sector_t nolb = sbc_get_write_same_sectors(cmd);
  	struct iov_iter iter;
  	struct bio_vec *bvec;
  	unsigned int len = 0, i;
  	ssize_t ret;
7b745c84a   Nicholas Bellinger   target/file: Add ...
365
366
367
368
369
  
  	if (!nolb) {
  		target_complete_cmd(cmd, SAM_STAT_GOOD);
  		return 0;
  	}
afd73f1b6   Nicholas Bellinger   target: Perform P...
370
371
372
373
374
375
  	if (cmd->prot_op) {
  		pr_err("WRITE_SAME: Protection information with FILEIO"
  		       " backends not supported
  ");
  		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  	}
7b745c84a   Nicholas Bellinger   target/file: Add ...
376
377
  
  	if (cmd->t_data_nents > 1 ||
d4c5dcacf   Christoph Hellwig   target: rewrite f...
378
  	    cmd->t_data_sg[0].length != cmd->se_dev->dev_attrib.block_size) {
7b745c84a   Nicholas Bellinger   target/file: Add ...
379
  		pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u"
d4c5dcacf   Christoph Hellwig   target: rewrite f...
380
381
382
383
  			" block_size: %u
  ",
  			cmd->t_data_nents,
  			cmd->t_data_sg[0].length,
7b745c84a   Nicholas Bellinger   target/file: Add ...
384
385
386
  			cmd->se_dev->dev_attrib.block_size);
  		return TCM_INVALID_CDB_FIELD;
  	}
d4c5dcacf   Christoph Hellwig   target: rewrite f...
387
388
  	bvec = kcalloc(nolb, sizeof(struct bio_vec), GFP_KERNEL);
  	if (!bvec)
7b745c84a   Nicholas Bellinger   target/file: Add ...
389
  		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
d4c5dcacf   Christoph Hellwig   target: rewrite f...
390
391
392
393
  	for (i = 0; i < nolb; i++) {
  		bvec[i].bv_page = sg_page(&cmd->t_data_sg[0]);
  		bvec[i].bv_len = cmd->t_data_sg[0].length;
  		bvec[i].bv_offset = cmd->t_data_sg[0].offset;
7b745c84a   Nicholas Bellinger   target/file: Add ...
394

d4c5dcacf   Christoph Hellwig   target: rewrite f...
395
396
  		len += se_dev->dev_attrib.block_size;
  	}
7b745c84a   Nicholas Bellinger   target/file: Add ...
397

d4c5dcacf   Christoph Hellwig   target: rewrite f...
398
399
  	iov_iter_bvec(&iter, ITER_BVEC, bvec, nolb, len);
  	ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos);
7b745c84a   Nicholas Bellinger   target/file: Add ...
400

d4c5dcacf   Christoph Hellwig   target: rewrite f...
401
402
403
404
  	kfree(bvec);
  	if (ret < 0 || ret != len) {
  		pr_err("vfs_iter_write() returned %zd for write same
  ", ret);
7b745c84a   Nicholas Bellinger   target/file: Add ...
405
406
407
408
409
410
  		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  	}
  
  	target_complete_cmd(cmd, SAM_STAT_GOOD);
  	return 0;
  }
64d240b72   Akinobu Mita   target/file: Fix ...
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
  static int
  fd_do_prot_fill(struct se_device *se_dev, sector_t lba, sector_t nolb,
  		void *buf, size_t bufsize)
  {
  	struct fd_dev *fd_dev = FD_DEV(se_dev);
  	struct file *prot_fd = fd_dev->fd_prot_file;
  	sector_t prot_length, prot;
  	loff_t pos = lba * se_dev->prot_length;
  
  	if (!prot_fd) {
  		pr_err("Unable to locate fd_dev->fd_prot_file
  ");
  		return -ENODEV;
  	}
  
  	prot_length = nolb * se_dev->prot_length;
  
  	for (prot = 0; prot < prot_length;) {
  		sector_t len = min_t(sector_t, bufsize, prot_length - prot);
  		ssize_t ret = kernel_write(prot_fd, buf, len, pos + prot);
  
  		if (ret != len) {
  			pr_err("vfs_write to prot file failed: %zd
  ", ret);
  			return ret < 0 ? ret : -ENODEV;
  		}
  		prot += ret;
  	}
  
  	return 0;
  }
  
  static int
  fd_do_prot_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
  {
  	void *buf;
  	int rc;
  
  	buf = (void *)__get_free_page(GFP_KERNEL);
  	if (!buf) {
  		pr_err("Unable to allocate FILEIO prot buf
  ");
  		return -ENOMEM;
  	}
  	memset(buf, 0xff, PAGE_SIZE);
  
  	rc = fd_do_prot_fill(cmd->se_dev, lba, nolb, buf, PAGE_SIZE);
  
  	free_page((unsigned long)buf);
  
  	return rc;
  }
de103c93a   Christoph Hellwig   target: pass sens...
463
  static sense_reason_t
62e469425   Christoph Hellwig   target: simplify ...
464
  fd_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
70d3ae5c8   Asias He   target/file: Add ...
465
  {
62e469425   Christoph Hellwig   target: simplify ...
466
  	struct file *file = FD_DEV(cmd->se_dev)->fd_file;
70d3ae5c8   Asias He   target/file: Add ...
467
  	struct inode *inode = file->f_mapping->host;
70d3ae5c8   Asias He   target/file: Add ...
468
  	int ret;
64d240b72   Akinobu Mita   target/file: Fix ...
469
470
471
472
473
  	if (cmd->se_dev->dev_attrib.pi_prot_type) {
  		ret = fd_do_prot_unmap(cmd, lba, nolb);
  		if (ret)
  			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  	}
70d3ae5c8   Asias He   target/file: Add ...
474
475
476
  	if (S_ISBLK(inode->i_mode)) {
  		/* The backend is block device, use discard */
  		struct block_device *bdev = inode->i_bdev;
8a9ebe717   Mike Christie   target: Fix WRITE...
477
  		struct se_device *dev = cmd->se_dev;
70d3ae5c8   Asias He   target/file: Add ...
478

8a9ebe717   Mike Christie   target: Fix WRITE...
479
480
481
482
  		ret = blkdev_issue_discard(bdev,
  					   target_to_linux_sector(dev, lba),
  					   target_to_linux_sector(dev,  nolb),
  					   GFP_KERNEL, 0);
70d3ae5c8   Asias He   target/file: Add ...
483
484
485
486
487
488
489
490
  		if (ret < 0) {
  			pr_warn("FILEIO: blkdev_issue_discard() failed: %d
  ",
  				ret);
  			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  		}
  	} else {
  		/* The backend is normal file, use fallocate */
43f55bbb1   Asias He   target/file: Add ...
491
492
  		struct se_device *se_dev = cmd->se_dev;
  		loff_t pos = lba * se_dev->dev_attrib.block_size;
70d3ae5c8   Asias He   target/file: Add ...
493
494
495
496
497
498
499
500
501
502
503
504
505
  		unsigned int len = nolb * se_dev->dev_attrib.block_size;
  		int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
  
  		if (!file->f_op->fallocate)
  			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  
  		ret = file->f_op->fallocate(file, mode, pos, len);
  		if (ret < 0) {
  			pr_warn("FILEIO: fallocate() failed: %d
  ", ret);
  			return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  		}
  	}
43f55bbb1   Asias He   target/file: Add ...
506
507
508
509
  	return 0;
  }
  
  static sense_reason_t
a82a9538d   Nicholas Bellinger   target: Allow sbc...
510
511
  fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
  	      enum dma_data_direction data_direction)
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
512
  {
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
513
  	struct se_device *dev = cmd->se_dev;
8287fa5fb   Sagi Grimberg   target/file: Remo...
514
515
516
  	struct fd_dev *fd_dev = FD_DEV(dev);
  	struct file *file = fd_dev->fd_file;
  	struct file *pfile = fd_dev->fd_prot_file;
42201b557   Nicholas Bellinger   target/file: Add ...
517
  	sense_reason_t rc;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
518
  	int ret = 0;
046ba6428   Nicholas Bellinger   target: Drop arbi...
519
520
521
522
523
524
  	/*
  	 * We are currently limited by the number of iovecs (2048) per
  	 * single vfs_[writev,readv] call.
  	 */
  	if (cmd->data_length > FD_MAX_BYTES) {
  		pr_err("FILEIO: Not able to process I/O of %u bytes due to"
291e3e51a   Colin Ian King   target: fix spell...
525
526
  		       "FD_MAX_BYTES: %u iovec count limitation
  ",
046ba6428   Nicholas Bellinger   target: Drop arbi...
527
528
529
  			cmd->data_length, FD_MAX_BYTES);
  		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  	}
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
530
531
532
533
  	/*
  	 * Call vectorized fileio functions to map struct scatterlist
  	 * physical memory addresses to struct iovec virtual memory.
  	 */
5787cacd0   Christoph Hellwig   target: remove st...
534
  	if (data_direction == DMA_FROM_DEVICE) {
ee920469d   Nicholas Bellinger   target/file: Add ...
535
  		if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {
8287fa5fb   Sagi Grimberg   target/file: Remo...
536
537
538
  			ret = fd_do_rw(cmd, pfile, dev->prot_length,
  				       cmd->t_prot_sg, cmd->t_prot_nents,
  				       cmd->prot_length, 0);
42201b557   Nicholas Bellinger   target/file: Add ...
539
540
541
  			if (ret < 0)
  				return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  		}
8287fa5fb   Sagi Grimberg   target/file: Remo...
542
543
  		ret = fd_do_rw(cmd, file, dev->dev_attrib.block_size,
  			       sgl, sgl_nents, cmd->data_length, 0);
42201b557   Nicholas Bellinger   target/file: Add ...
544

ee920469d   Nicholas Bellinger   target/file: Add ...
545
  		if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) {
8287fa5fb   Sagi Grimberg   target/file: Remo...
546
547
  			u32 sectors = cmd->data_length >>
  					ilog2(dev->dev_attrib.block_size);
42201b557   Nicholas Bellinger   target/file: Add ...
548

f75b6fae1   Sagi Grimberg   target: Merge sbc...
549
  			rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors,
8287fa5fb   Sagi Grimberg   target/file: Remo...
550
551
  					    0, cmd->t_prot_sg, 0);
  			if (rc)
42201b557   Nicholas Bellinger   target/file: Add ...
552
  				return rc;
42201b557   Nicholas Bellinger   target/file: Add ...
553
  		}
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
554
  	} else {
ee920469d   Nicholas Bellinger   target/file: Add ...
555
  		if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {
8287fa5fb   Sagi Grimberg   target/file: Remo...
556
557
  			u32 sectors = cmd->data_length >>
  					ilog2(dev->dev_attrib.block_size);
42201b557   Nicholas Bellinger   target/file: Add ...
558

f75b6fae1   Sagi Grimberg   target: Merge sbc...
559
560
  			rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors,
  					    0, cmd->t_prot_sg, 0);
8287fa5fb   Sagi Grimberg   target/file: Remo...
561
  			if (rc)
42201b557   Nicholas Bellinger   target/file: Add ...
562
  				return rc;
42201b557   Nicholas Bellinger   target/file: Add ...
563
  		}
8287fa5fb   Sagi Grimberg   target/file: Remo...
564
565
  		ret = fd_do_rw(cmd, file, dev->dev_attrib.block_size,
  			       sgl, sgl_nents, cmd->data_length, 1);
a4dff3043   Nicholas Bellinger   target/file: Use ...
566
  		/*
125d0119d   Hannes Reinecke   target core: rena...
567
  		 * Perform implicit vfs_fsync_range() for fd_do_writev() ops
a4dff3043   Nicholas Bellinger   target/file: Use ...
568
569
570
  		 * for SCSI WRITEs with Forced Unit Access (FUA) set.
  		 * Allow this to happen independent of WCE=0 setting.
  		 */
814e5b451   Christoph Hellwig   target: fix DPO a...
571
  		if (ret > 0 && (cmd->se_cmd_flags & SCF_FUA)) {
a4dff3043   Nicholas Bellinger   target/file: Use ...
572
  			loff_t start = cmd->t_task_lba *
0fd97ccf4   Christoph Hellwig   target: kill stru...
573
  				dev->dev_attrib.block_size;
62d3ab49b   Zach Brown   target/file: fix ...
574
575
576
577
578
579
  			loff_t end;
  
  			if (cmd->data_length)
  				end = start + cmd->data_length - 1;
  			else
  				end = LLONG_MAX;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
580

a4dff3043   Nicholas Bellinger   target/file: Use ...
581
582
  			vfs_fsync_range(fd_dev->fd_file, start, end, 1);
  		}
42201b557   Nicholas Bellinger   target/file: Add ...
583

ee920469d   Nicholas Bellinger   target/file: Add ...
584
  		if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) {
8287fa5fb   Sagi Grimberg   target/file: Remo...
585
586
587
  			ret = fd_do_rw(cmd, pfile, dev->prot_length,
  				       cmd->t_prot_sg, cmd->t_prot_nents,
  				       cmd->prot_length, 1);
42201b557   Nicholas Bellinger   target/file: Add ...
588
589
590
  			if (ret < 0)
  				return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
  		}
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
591
  	}
8287fa5fb   Sagi Grimberg   target/file: Remo...
592
  	if (ret < 0)
de103c93a   Christoph Hellwig   target: pass sens...
593
  		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
5787cacd0   Christoph Hellwig   target: remove st...
594
595
  	if (ret)
  		target_complete_cmd(cmd, SAM_STAT_GOOD);
03e98c9eb   Nicholas Bellinger   target: Address l...
596
  	return 0;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
597
  }
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
598
599
600
601
602
603
604
  enum {
  	Opt_fd_dev_name, Opt_fd_dev_size, Opt_fd_buffered_io, Opt_err
  };
  
  static match_table_t tokens = {
  	{Opt_fd_dev_name, "fd_dev_name=%s"},
  	{Opt_fd_dev_size, "fd_dev_size=%s"},
b32f4c7ed   Nicholas Bellinger   target/file: Re-e...
605
  	{Opt_fd_buffered_io, "fd_buffered_io=%d"},
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
606
607
  	{Opt_err, NULL}
  };
0fd97ccf4   Christoph Hellwig   target: kill stru...
608
609
  static ssize_t fd_set_configfs_dev_params(struct se_device *dev,
  		const char *page, ssize_t count)
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
610
  {
0fd97ccf4   Christoph Hellwig   target: kill stru...
611
  	struct fd_dev *fd_dev = FD_DEV(dev);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
612
613
  	char *orig, *ptr, *arg_p, *opts;
  	substring_t args[MAX_OPT_ARGS];
b32f4c7ed   Nicholas Bellinger   target/file: Re-e...
614
  	int ret = 0, arg, token;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
615
616
617
618
619
620
  
  	opts = kstrdup(page, GFP_KERNEL);
  	if (!opts)
  		return -ENOMEM;
  
  	orig = opts;
90c161b64   Sebastian Andrzej Siewior   target: use \n as...
621
622
  	while ((ptr = strsep(&opts, ",
  ")) != NULL) {
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
623
624
625
626
627
628
  		if (!*ptr)
  			continue;
  
  		token = match_token(ptr, tokens, args);
  		switch (token) {
  		case Opt_fd_dev_name:
dbc6e0222   Al Viro   delousing target_...
629
630
631
  			if (match_strlcpy(fd_dev->fd_dev_name, &args[0],
  				FD_MAX_DEV_NAME) == 0) {
  				ret = -EINVAL;
6d1802539   Jesper Juhl   [SCSI] target: Fi...
632
633
  				break;
  			}
6708bb27b   Andy Grover   target: Follow up...
634
635
  			pr_debug("FILEIO: Referencing Path: %s
  ",
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
636
637
638
639
640
  					fd_dev->fd_dev_name);
  			fd_dev->fbd_flags |= FBDF_HAS_PATH;
  			break;
  		case Opt_fd_dev_size:
  			arg_p = match_strdup(&args[0]);
6d1802539   Jesper Juhl   [SCSI] target: Fi...
641
642
643
644
  			if (!arg_p) {
  				ret = -ENOMEM;
  				break;
  			}
57103d7fe   Jingoo Han   target: replace s...
645
  			ret = kstrtoull(arg_p, 0, &fd_dev->fd_dev_size);
6d1802539   Jesper Juhl   [SCSI] target: Fi...
646
  			kfree(arg_p);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
647
  			if (ret < 0) {
57103d7fe   Jingoo Han   target: replace s...
648
  				pr_err("kstrtoull() failed for"
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
649
650
651
652
  						" fd_dev_size=
  ");
  				goto out;
  			}
6708bb27b   Andy Grover   target: Follow up...
653
  			pr_debug("FILEIO: Referencing Size: %llu"
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
654
655
656
657
  					" bytes
  ", fd_dev->fd_dev_size);
  			fd_dev->fbd_flags |= FBDF_HAS_SIZE;
  			break;
b32f4c7ed   Nicholas Bellinger   target/file: Re-e...
658
  		case Opt_fd_buffered_io:
ce31c1b0d   Joern Engel   target: correctly...
659
660
661
  			ret = match_int(args, &arg);
  			if (ret)
  				goto out;
b32f4c7ed   Nicholas Bellinger   target/file: Re-e...
662
663
664
665
666
667
668
669
670
671
672
673
674
  			if (arg != 1) {
  				pr_err("bogus fd_buffered_io=%d value
  ", arg);
  				ret = -EINVAL;
  				goto out;
  			}
  
  			pr_debug("FILEIO: Using buffered I/O"
  				" operations for struct fd_dev
  ");
  
  			fd_dev->fbd_flags |= FDBD_HAS_BUFFERED_IO_WCE;
  			break;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
675
676
677
678
679
680
681
682
683
  		default:
  			break;
  		}
  	}
  
  out:
  	kfree(orig);
  	return (!ret) ? count : ret;
  }
0fd97ccf4   Christoph Hellwig   target: kill stru...
684
  static ssize_t fd_show_configfs_dev_params(struct se_device *dev, char *b)
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
685
  {
0fd97ccf4   Christoph Hellwig   target: kill stru...
686
  	struct fd_dev *fd_dev = FD_DEV(dev);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
687
688
689
  	ssize_t bl = 0;
  
  	bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id);
b32f4c7ed   Nicholas Bellinger   target/file: Re-e...
690
691
692
693
694
  	bl += sprintf(b + bl, "        File: %s  Size: %llu  Mode: %s
  ",
  		fd_dev->fd_dev_name, fd_dev->fd_dev_size,
  		(fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) ?
  		"Buffered-WCE" : "O_DSYNC");
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
695
696
  	return bl;
  }
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
697
698
  static sector_t fd_get_blocks(struct se_device *dev)
  {
0fd97ccf4   Christoph Hellwig   target: kill stru...
699
  	struct fd_dev *fd_dev = FD_DEV(dev);
cd9323fd6   Nicholas Bellinger   target: Fix bug i...
700
701
702
703
704
705
706
707
708
  	struct file *f = fd_dev->fd_file;
  	struct inode *i = f->f_mapping->host;
  	unsigned long long dev_size;
  	/*
  	 * When using a file that references an underlying struct block_device,
  	 * ensure dev_size is always based on the current inode size in order
  	 * to handle underlying block_device resize operations.
  	 */
  	if (S_ISBLK(i->i_mode))
21363ca87   Nicholas Bellinger   target/file: Fix ...
709
  		dev_size = i_size_read(i);
cd9323fd6   Nicholas Bellinger   target: Fix bug i...
710
711
  	else
  		dev_size = fd_dev->fd_dev_size;
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
712

21363ca87   Nicholas Bellinger   target/file: Fix ...
713
714
  	return div_u64(dev_size - dev->dev_attrib.block_size,
  		       dev->dev_attrib.block_size);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
715
  }
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
  static int fd_init_prot(struct se_device *dev)
  {
  	struct fd_dev *fd_dev = FD_DEV(dev);
  	struct file *prot_file, *file = fd_dev->fd_file;
  	struct inode *inode;
  	int ret, flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC;
  	char buf[FD_MAX_DEV_PROT_NAME];
  
  	if (!file) {
  		pr_err("Unable to locate fd_dev->fd_file
  ");
  		return -ENODEV;
  	}
  
  	inode = file->f_mapping->host;
  	if (S_ISBLK(inode->i_mode)) {
  		pr_err("FILEIO Protection emulation only supported on"
  		       " !S_ISBLK
  ");
  		return -ENOSYS;
  	}
  
  	if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE)
  		flags &= ~O_DSYNC;
  
  	snprintf(buf, FD_MAX_DEV_PROT_NAME, "%s.protection",
  		 fd_dev->fd_dev_name);
  
  	prot_file = filp_open(buf, flags, 0600);
  	if (IS_ERR(prot_file)) {
  		pr_err("filp_open(%s) failed
  ", buf);
  		ret = PTR_ERR(prot_file);
  		return ret;
  	}
  	fd_dev->fd_prot_file = prot_file;
  
  	return 0;
  }
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
755
756
  static int fd_format_prot(struct se_device *dev)
  {
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
757
  	unsigned char *buf;
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
758
  	int unit_size = FDBD_FORMAT_UNIT_SIZE * dev->dev_attrib.block_size;
64d240b72   Akinobu Mita   target/file: Fix ...
759
  	int ret;
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
760
761
762
763
764
765
  
  	if (!dev->dev_attrib.pi_prot_type) {
  		pr_err("Unable to format_prot while pi_prot_type == 0
  ");
  		return -ENODEV;
  	}
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
766

0f5e2ec46   Nicholas Bellinger   target/file: Add ...
767
768
769
770
771
772
  	buf = vzalloc(unit_size);
  	if (!buf) {
  		pr_err("Unable to allocate FILEIO prot buf
  ");
  		return -ENOMEM;
  	}
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
773
774
775
  
  	pr_debug("Using FILEIO prot_length: %llu
  ",
64d240b72   Akinobu Mita   target/file: Fix ...
776
777
  		 (unsigned long long)(dev->transport->get_blocks(dev) + 1) *
  					dev->prot_length);
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
778

80dcd0c10   Sagi Grimberg   Target/file: plac...
779
  	memset(buf, 0xff, unit_size);
64d240b72   Akinobu Mita   target/file: Fix ...
780
781
  	ret = fd_do_prot_fill(dev, 0, dev->transport->get_blocks(dev) + 1,
  			      buf, unit_size);
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
782
783
784
785
786
787
788
789
790
791
792
793
794
795
  	vfree(buf);
  	return ret;
  }
  
  static void fd_free_prot(struct se_device *dev)
  {
  	struct fd_dev *fd_dev = FD_DEV(dev);
  
  	if (!fd_dev->fd_prot_file)
  		return;
  
  	filp_close(fd_dev->fd_prot_file, NULL);
  	fd_dev->fd_prot_file = NULL;
  }
9e999a6c5   Christoph Hellwig   target: rename sp...
796
  static struct sbc_ops fd_sbc_ops = {
0c2ad7d11   Christoph Hellwig   target: add struc...
797
  	.execute_rw		= fd_execute_rw,
ad67f0d9e   Christoph Hellwig   target: move sync...
798
  	.execute_sync_cache	= fd_execute_sync_cache,
7b745c84a   Nicholas Bellinger   target/file: Add ...
799
  	.execute_write_same	= fd_execute_write_same,
506427628   Asias He   target/file: Add ...
800
  	.execute_unmap		= fd_execute_unmap,
0c2ad7d11   Christoph Hellwig   target: add struc...
801
  };
de103c93a   Christoph Hellwig   target: pass sens...
802
803
  static sense_reason_t
  fd_parse_cdb(struct se_cmd *cmd)
0c2ad7d11   Christoph Hellwig   target: add struc...
804
  {
9e999a6c5   Christoph Hellwig   target: rename sp...
805
  	return sbc_parse_cdb(cmd, &fd_sbc_ops);
0c2ad7d11   Christoph Hellwig   target: add struc...
806
  }
0a06d4309   Christoph Hellwig   target: simplify ...
807
  static const struct target_backend_ops fileio_ops = {
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
808
  	.name			= "fileio",
0fd97ccf4   Christoph Hellwig   target: kill stru...
809
810
  	.inquiry_prod		= "FILEIO",
  	.inquiry_rev		= FD_VERSION,
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
811
  	.owner			= THIS_MODULE,
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
812
813
  	.attach_hba		= fd_attach_hba,
  	.detach_hba		= fd_detach_hba,
0fd97ccf4   Christoph Hellwig   target: kill stru...
814
815
  	.alloc_device		= fd_alloc_device,
  	.configure_device	= fd_configure_device,
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
816
  	.free_device		= fd_free_device,
0c2ad7d11   Christoph Hellwig   target: add struc...
817
  	.parse_cdb		= fd_parse_cdb,
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
818
819
  	.set_configfs_dev_params = fd_set_configfs_dev_params,
  	.show_configfs_dev_params = fd_show_configfs_dev_params,
6f23ac8a3   Christoph Hellwig   target: provide g...
820
  	.get_device_type	= sbc_get_device_type,
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
821
  	.get_blocks		= fd_get_blocks,
0f5e2ec46   Nicholas Bellinger   target/file: Add ...
822
823
824
  	.init_prot		= fd_init_prot,
  	.format_prot		= fd_format_prot,
  	.free_prot		= fd_free_prot,
5873c4d15   Christoph Hellwig   target: consolida...
825
  	.tb_dev_attrib_attrs	= sbc_attrib_attrs,
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
826
827
828
829
  };
  
  static int __init fileio_module_init(void)
  {
0a06d4309   Christoph Hellwig   target: simplify ...
830
  	return transport_backend_register(&fileio_ops);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
831
  }
63b91d5a4   Asias He   target: Add __exi...
832
  static void __exit fileio_module_exit(void)
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
833
  {
0a06d4309   Christoph Hellwig   target: simplify ...
834
  	target_backend_unregister(&fileio_ops);
c66ac9db8   Nicholas Bellinger   [SCSI] target: Ad...
835
836
837
838
839
840
841
842
  }
  
  MODULE_DESCRIPTION("TCM FILEIO subsystem plugin");
  MODULE_AUTHOR("nab@Linux-iSCSI.org");
  MODULE_LICENSE("GPL");
  
  module_init(fileio_module_init);
  module_exit(fileio_module_exit);