Blame view

fs/ceph/ioctl.c 7.41 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
96c57ade7   Linus Torvalds   ceph: fix pr_fmt(...
2
  #include <linux/ceph/ceph_debug.h>
8f4e91dee   Sage Weil   ceph: ioctls
3
  #include <linux/in.h>
8f4e91dee   Sage Weil   ceph: ioctls
4
  #include "super.h"
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
5
  #include "mds_client.h"
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
6
  #include "ioctl.h"
8f4e91dee   Sage Weil   ceph: ioctls
7
8
9
10
11
12
13
14
15
16
17
  
  
  /*
   * ioctls
   */
  
  /*
   * get and set the file layout
   */
  static long ceph_ioctl_get_layout(struct file *file, void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
18
  	struct ceph_inode_info *ci = ceph_inode(file_inode(file));
8f4e91dee   Sage Weil   ceph: ioctls
19
20
  	struct ceph_ioctl_layout l;
  	int err;
508b32d86   Yan, Zheng   ceph: request xat...
21
  	err = ceph_do_getattr(file_inode(file), CEPH_STAT_CAP_LAYOUT, false);
8f4e91dee   Sage Weil   ceph: ioctls
22
  	if (!err) {
7627151ea   Yan, Zheng   libceph: define n...
23
24
25
26
  		l.stripe_unit = ci->i_layout.stripe_unit;
  		l.stripe_count = ci->i_layout.stripe_count;
  		l.object_size = ci->i_layout.object_size;
  		l.data_pool = ci->i_layout.pool_id;
24c149ad6   Jeff Layton   ceph: fix bogus e...
27
  		l.preferred_osd = -1;
8f4e91dee   Sage Weil   ceph: ioctls
28
29
30
31
32
33
  		if (copy_to_user(arg, &l, sizeof(l)))
  			return -EFAULT;
  	}
  
  	return err;
  }
e49bf4c51   Sage Weil   ceph: refactor SE...
34
35
36
37
  static long __validate_layout(struct ceph_mds_client *mdsc,
  			      struct ceph_ioctl_layout *l)
  {
  	int i, err;
e49bf4c51   Sage Weil   ceph: refactor SE...
38
39
40
  	/* validate striping parameters */
  	if ((l->object_size & ~PAGE_MASK) ||
  	    (l->stripe_unit & ~PAGE_MASK) ||
0bc62284e   Yan, Zheng   ceph: fix divide-...
41
  	    ((unsigned)l->stripe_unit != 0 &&
45f2e081f   Sage Weil   ceph: avoid divid...
42
  	     ((unsigned)l->object_size % (unsigned)l->stripe_unit)))
e49bf4c51   Sage Weil   ceph: refactor SE...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  		return -EINVAL;
  
  	/* make sure it's a valid data pool */
  	mutex_lock(&mdsc->mutex);
  	err = -EINVAL;
  	for (i = 0; i < mdsc->mdsmap->m_num_data_pg_pools; i++)
  		if (mdsc->mdsmap->m_data_pg_pools[i] == l->data_pool) {
  			err = 0;
  			break;
  		}
  	mutex_unlock(&mdsc->mutex);
  	if (err)
  		return err;
  
  	return 0;
  }
8f4e91dee   Sage Weil   ceph: ioctls
59
60
  static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
61
  	struct inode *inode = file_inode(file);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
62
  	struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
8f4e91dee   Sage Weil   ceph: ioctls
63
64
  	struct ceph_mds_request *req;
  	struct ceph_ioctl_layout l;
496ad9aa8   Al Viro   new helper: file_...
65
  	struct ceph_inode_info *ci = ceph_inode(file_inode(file));
a35eca958   Greg Farnum   ceph: let the set...
66
  	struct ceph_ioctl_layout nl;
e49bf4c51   Sage Weil   ceph: refactor SE...
67
  	int err;
8f4e91dee   Sage Weil   ceph: ioctls
68

8f4e91dee   Sage Weil   ceph: ioctls
69
70
  	if (copy_from_user(&l, arg, sizeof(l)))
  		return -EFAULT;
a35eca958   Greg Farnum   ceph: let the set...
71
  	/* validate changed params against current layout */
508b32d86   Yan, Zheng   ceph: request xat...
72
  	err = ceph_do_getattr(file_inode(file), CEPH_STAT_CAP_LAYOUT, false);
702aeb1f8   Sage Weil   ceph: fully initi...
73
  	if (err)
a35eca958   Greg Farnum   ceph: let the set...
74
  		return err;
702aeb1f8   Sage Weil   ceph: fully initi...
75
  	memset(&nl, 0, sizeof(nl));
a35eca958   Greg Farnum   ceph: let the set...
76
77
  	if (l.stripe_count)
  		nl.stripe_count = l.stripe_count;
702aeb1f8   Sage Weil   ceph: fully initi...
78
  	else
7627151ea   Yan, Zheng   libceph: define n...
79
  		nl.stripe_count = ci->i_layout.stripe_count;
a35eca958   Greg Farnum   ceph: let the set...
80
81
  	if (l.stripe_unit)
  		nl.stripe_unit = l.stripe_unit;
702aeb1f8   Sage Weil   ceph: fully initi...
82
  	else
7627151ea   Yan, Zheng   libceph: define n...
83
  		nl.stripe_unit = ci->i_layout.stripe_unit;
a35eca958   Greg Farnum   ceph: let the set...
84
85
  	if (l.object_size)
  		nl.object_size = l.object_size;
702aeb1f8   Sage Weil   ceph: fully initi...
86
  	else
7627151ea   Yan, Zheng   libceph: define n...
87
  		nl.object_size = ci->i_layout.object_size;
a35eca958   Greg Farnum   ceph: let the set...
88
89
  	if (l.data_pool)
  		nl.data_pool = l.data_pool;
702aeb1f8   Sage Weil   ceph: fully initi...
90
  	else
7627151ea   Yan, Zheng   libceph: define n...
91
  		nl.data_pool = ci->i_layout.pool_id;
702aeb1f8   Sage Weil   ceph: fully initi...
92
93
  
  	/* this is obsolete, and always -1 */
24c149ad6   Jeff Layton   ceph: fix bogus e...
94
  	nl.preferred_osd = -1;
a35eca958   Greg Farnum   ceph: let the set...
95

e49bf4c51   Sage Weil   ceph: refactor SE...
96
97
98
  	err = __validate_layout(mdsc, &nl);
  	if (err)
  		return err;
8f4e91dee   Sage Weil   ceph: ioctls
99
100
101
102
103
  
  	req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETLAYOUT,
  				       USE_AUTH_MDS);
  	if (IS_ERR(req))
  		return PTR_ERR(req);
70b666c3b   Sage Weil   ceph: use ihold w...
104
105
  	req->r_inode = inode;
  	ihold(inode);
3bd58143b   Yan, Zheng   ceph: reserve cap...
106
  	req->r_num_caps = 1;
8f4e91dee   Sage Weil   ceph: ioctls
107
108
109
110
111
112
113
114
115
  	req->r_inode_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL;
  
  	req->r_args.setlayout.layout.fl_stripe_unit =
  		cpu_to_le32(l.stripe_unit);
  	req->r_args.setlayout.layout.fl_stripe_count =
  		cpu_to_le32(l.stripe_count);
  	req->r_args.setlayout.layout.fl_object_size =
  		cpu_to_le32(l.object_size);
  	req->r_args.setlayout.layout.fl_pg_pool = cpu_to_le32(l.data_pool);
8f4e91dee   Sage Weil   ceph: ioctls
116

752c8bdcf   Sage Weil   ceph: do not chai...
117
  	err = ceph_mdsc_do_request(mdsc, NULL, req);
8f4e91dee   Sage Weil   ceph: ioctls
118
119
120
121
122
  	ceph_mdsc_put_request(req);
  	return err;
  }
  
  /*
571dba52a   Greg Farnum   ceph: add CEPH_MD...
123
124
125
126
127
128
129
   * Set a layout policy on a directory inode. All items in the tree
   * rooted at this inode will inherit this layout on creation,
   * (It doesn't apply retroactively )
   * unless a subdirectory has its own layout policy.
   */
  static long ceph_ioctl_set_layout_policy (struct file *file, void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
130
  	struct inode *inode = file_inode(file);
571dba52a   Greg Farnum   ceph: add CEPH_MD...
131
132
  	struct ceph_mds_request *req;
  	struct ceph_ioctl_layout l;
e49bf4c51   Sage Weil   ceph: refactor SE...
133
  	int err;
571dba52a   Greg Farnum   ceph: add CEPH_MD...
134
135
136
137
138
  	struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
  
  	/* copy and validate */
  	if (copy_from_user(&l, arg, sizeof(l)))
  		return -EFAULT;
e49bf4c51   Sage Weil   ceph: refactor SE...
139
140
141
  	err = __validate_layout(mdsc, &l);
  	if (err)
  		return err;
571dba52a   Greg Farnum   ceph: add CEPH_MD...
142
143
144
145
146
147
  
  	req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETDIRLAYOUT,
  				       USE_AUTH_MDS);
  
  	if (IS_ERR(req))
  		return PTR_ERR(req);
70b666c3b   Sage Weil   ceph: use ihold w...
148
149
  	req->r_inode = inode;
  	ihold(inode);
3bd58143b   Yan, Zheng   ceph: reserve cap...
150
  	req->r_num_caps = 1;
571dba52a   Greg Farnum   ceph: add CEPH_MD...
151
152
153
154
155
156
157
158
159
  
  	req->r_args.setlayout.layout.fl_stripe_unit =
  			cpu_to_le32(l.stripe_unit);
  	req->r_args.setlayout.layout.fl_stripe_count =
  			cpu_to_le32(l.stripe_count);
  	req->r_args.setlayout.layout.fl_object_size =
  			cpu_to_le32(l.object_size);
  	req->r_args.setlayout.layout.fl_pg_pool =
  			cpu_to_le32(l.data_pool);
571dba52a   Greg Farnum   ceph: add CEPH_MD...
160
161
162
163
164
165
166
  
  	err = ceph_mdsc_do_request(mdsc, inode, req);
  	ceph_mdsc_put_request(req);
  	return err;
  }
  
  /*
8f4e91dee   Sage Weil   ceph: ioctls
167
168
169
170
171
172
   * Return object name, size/offset information, and location (OSD
   * number, network address) for a given file offset.
   */
  static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
  {
  	struct ceph_ioctl_dataloc dl;
496ad9aa8   Al Viro   new helper: file_...
173
  	struct inode *inode = file_inode(file);
8f4e91dee   Sage Weil   ceph: ioctls
174
  	struct ceph_inode_info *ci = ceph_inode(inode);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
175
176
  	struct ceph_osd_client *osdc =
  		&ceph_sb_to_client(inode->i_sb)->client->osdc;
7c13cb643   Ilya Dryomov   libceph: replace ...
177
  	struct ceph_object_locator oloc;
281dbe5db   Ilya Dryomov   libceph: add an O...
178
  	CEPH_DEFINE_OID_ONSTACK(oid);
8f4e91dee   Sage Weil   ceph: ioctls
179
180
  	u64 len = 1, olen;
  	u64 tmp;
51042122d   Sage Weil   ceph: fix endian ...
181
  	struct ceph_pg pgid;
457712a0b   Sage Weil   ceph: return EIO ...
182
  	int r;
8f4e91dee   Sage Weil   ceph: ioctls
183
184
185
186
  
  	/* copy and validate */
  	if (copy_from_user(&dl, arg, sizeof(dl)))
  		return -EFAULT;
5aea3dcd5   Ilya Dryomov   libceph: a major ...
187
  	down_read(&osdc->lock);
e8afad656   Alex Elder   libceph: pass len...
188
  	r = ceph_calc_file_object_mapping(&ci->i_layout, dl.file_offset, len,
457712a0b   Sage Weil   ceph: return EIO ...
189
190
  					  &dl.object_no, &dl.object_offset,
  					  &olen);
494ddd11b   majianpeng   ceph: Don't forge...
191
  	if (r < 0) {
5aea3dcd5   Ilya Dryomov   libceph: a major ...
192
  		up_read(&osdc->lock);
457712a0b   Sage Weil   ceph: return EIO ...
193
  		return -EIO;
494ddd11b   majianpeng   ceph: Don't forge...
194
  	}
8f4e91dee   Sage Weil   ceph: ioctls
195
  	dl.file_offset -= dl.object_offset;
7627151ea   Yan, Zheng   libceph: define n...
196
197
  	dl.object_size = ci->i_layout.object_size;
  	dl.block_size = ci->i_layout.stripe_unit;
8f4e91dee   Sage Weil   ceph: ioctls
198
199
200
201
202
203
204
  
  	/* block_offset = object_offset % block_size */
  	tmp = dl.object_offset;
  	dl.block_offset = do_div(tmp, dl.block_size);
  
  	snprintf(dl.object_name, sizeof(dl.object_name), "%llx.%08llx",
  		 ceph_ino(inode), dl.object_no);
41766f87f   Alex Elder   libceph: rename c...
205

7627151ea   Yan, Zheng   libceph: define n...
206
  	oloc.pool = ci->i_layout.pool_id;
779fe0fb8   Yan, Zheng   ceph: rados pool ...
207
  	oloc.pool_ns = ceph_try_get_string(ci->i_layout.pool_ns);
d30291b98   Ilya Dryomov   libceph: variable...
208
  	ceph_oid_printf(&oid, "%s", dl.object_name);
7c13cb643   Ilya Dryomov   libceph: replace ...
209

d9591f5e2   Ilya Dryomov   libceph: rename c...
210
  	r = ceph_object_locator_to_pg(osdc->osdmap, &oid, &oloc, &pgid);
779fe0fb8   Yan, Zheng   ceph: rados pool ...
211
212
  
  	ceph_oloc_destroy(&oloc);
2fbcbff1d   majianpeng   ceph: Add check r...
213
  	if (r < 0) {
5aea3dcd5   Ilya Dryomov   libceph: a major ...
214
  		up_read(&osdc->lock);
2fbcbff1d   majianpeng   ceph: Add check r...
215
216
  		return r;
  	}
8f4e91dee   Sage Weil   ceph: ioctls
217

f81f16339   Ilya Dryomov   libceph: rename c...
218
  	dl.osd = ceph_pg_to_acting_primary(osdc->osdmap, &pgid);
8f4e91dee   Sage Weil   ceph: ioctls
219
220
221
222
223
224
225
226
  	if (dl.osd >= 0) {
  		struct ceph_entity_addr *a =
  			ceph_osd_addr(osdc->osdmap, dl.osd);
  		if (a)
  			memcpy(&dl.osd_addr, &a->in_addr, sizeof(dl.osd_addr));
  	} else {
  		memset(&dl.osd_addr, 0, sizeof(dl.osd_addr));
  	}
5aea3dcd5   Ilya Dryomov   libceph: a major ...
227
  	up_read(&osdc->lock);
8f4e91dee   Sage Weil   ceph: ioctls
228
229
230
231
232
233
234
  
  	/* send result back to user */
  	if (copy_to_user(arg, &dl, sizeof(dl)))
  		return -EFAULT;
  
  	return 0;
  }
8c6e9229f   Sage Weil   ceph: add LAZYIO ...
235
236
237
  static long ceph_ioctl_lazyio(struct file *file)
  {
  	struct ceph_file_info *fi = file->private_data;
496ad9aa8   Al Viro   new helper: file_...
238
  	struct inode *inode = file_inode(file);
8c6e9229f   Sage Weil   ceph: add LAZYIO ...
239
240
241
  	struct ceph_inode_info *ci = ceph_inode(inode);
  
  	if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) {
be655596b   Sage Weil   ceph: use i_ceph_...
242
  		spin_lock(&ci->i_ceph_lock);
8c6e9229f   Sage Weil   ceph: add LAZYIO ...
243
  		fi->fmode |= CEPH_FILE_MODE_LAZY;
774a6a118   Yan, Zheng   ceph: reduce i_nr...
244
  		ci->i_nr_by_mode[ffs(CEPH_FILE_MODE_LAZY)]++;
be655596b   Sage Weil   ceph: use i_ceph_...
245
  		spin_unlock(&ci->i_ceph_lock);
8c6e9229f   Sage Weil   ceph: add LAZYIO ...
246
247
248
249
250
251
252
253
254
255
  		dout("ioctl_layzio: file %p marked lazy
  ", file);
  
  		ceph_check_caps(ci, 0, NULL);
  	} else {
  		dout("ioctl_layzio: file %p already lazy
  ", file);
  	}
  	return 0;
  }
4918b6d14   Sage Weil   ceph: add F_SYNC ...
256
257
258
259
260
261
262
  static long ceph_ioctl_syncio(struct file *file)
  {
  	struct ceph_file_info *fi = file->private_data;
  
  	fi->flags |= CEPH_F_SYNC;
  	return 0;
  }
8f4e91dee   Sage Weil   ceph: ioctls
263
264
265
266
267
268
269
270
271
272
  long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
  	dout("ioctl file %p cmd %u arg %lu
  ", file, cmd, arg);
  	switch (cmd) {
  	case CEPH_IOC_GET_LAYOUT:
  		return ceph_ioctl_get_layout(file, (void __user *)arg);
  
  	case CEPH_IOC_SET_LAYOUT:
  		return ceph_ioctl_set_layout(file, (void __user *)arg);
571dba52a   Greg Farnum   ceph: add CEPH_MD...
273
274
  	case CEPH_IOC_SET_LAYOUT_POLICY:
  		return ceph_ioctl_set_layout_policy(file, (void __user *)arg);
8f4e91dee   Sage Weil   ceph: ioctls
275
276
  	case CEPH_IOC_GET_DATALOC:
  		return ceph_ioctl_get_dataloc(file, (void __user *)arg);
8c6e9229f   Sage Weil   ceph: add LAZYIO ...
277
278
279
  
  	case CEPH_IOC_LAZYIO:
  		return ceph_ioctl_lazyio(file);
4918b6d14   Sage Weil   ceph: add F_SYNC ...
280
281
282
  
  	case CEPH_IOC_SYNCIO:
  		return ceph_ioctl_syncio(file);
8f4e91dee   Sage Weil   ceph: ioctls
283
  	}
571dba52a   Greg Farnum   ceph: add CEPH_MD...
284

8f4e91dee   Sage Weil   ceph: ioctls
285
286
  	return -ENOTTY;
  }