]>
Commit | Line | Data |
---|---|---|
5f2aa075 NJ |
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* | |
3 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. | |
4 | */ | |
5 | ||
6 | #include <linux/iversion.h> | |
7 | #include <linux/namei.h> | |
8 | #include <linux/slab.h> | |
9 | #include <linux/buffer_head.h> | |
10 | #include <linux/nls.h> | |
11 | ||
12 | #include "exfat_raw.h" | |
13 | #include "exfat_fs.h" | |
14 | ||
15 | static inline unsigned long exfat_d_version(struct dentry *dentry) | |
16 | { | |
17 | return (unsigned long) dentry->d_fsdata; | |
18 | } | |
19 | ||
20 | static inline void exfat_d_version_set(struct dentry *dentry, | |
21 | unsigned long version) | |
22 | { | |
23 | dentry->d_fsdata = (void *) version; | |
24 | } | |
25 | ||
26 | /* | |
27 | * If new entry was created in the parent, it could create the 8.3 alias (the | |
28 | * shortname of logname). So, the parent may have the negative-dentry which | |
29 | * matches the created 8.3 alias. | |
30 | * | |
31 | * If it happened, the negative dentry isn't actually negative anymore. So, | |
32 | * drop it. | |
33 | */ | |
34 | static int exfat_d_revalidate(struct dentry *dentry, unsigned int flags) | |
35 | { | |
36 | int ret; | |
37 | ||
38 | if (flags & LOOKUP_RCU) | |
39 | return -ECHILD; | |
40 | ||
41 | /* | |
42 | * This is not negative dentry. Always valid. | |
43 | * | |
44 | * Note, rename() to existing directory entry will have ->d_inode, and | |
45 | * will use existing name which isn't specified name by user. | |
46 | * | |
47 | * We may be able to drop this positive dentry here. But dropping | |
48 | * positive dentry isn't good idea. So it's unsupported like | |
49 | * rename("filename", "FILENAME") for now. | |
50 | */ | |
51 | if (d_really_is_positive(dentry)) | |
52 | return 1; | |
53 | ||
54 | /* | |
55 | * Drop the negative dentry, in order to make sure to use the case | |
56 | * sensitive name which is specified by user if this is for creation. | |
57 | */ | |
58 | if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) | |
59 | return 0; | |
60 | ||
61 | spin_lock(&dentry->d_lock); | |
62 | ret = inode_eq_iversion(d_inode(dentry->d_parent), | |
63 | exfat_d_version(dentry)); | |
64 | spin_unlock(&dentry->d_lock); | |
65 | return ret; | |
66 | } | |
67 | ||
68 | /* returns the length of a struct qstr, ignoring trailing dots */ | |
69 | static unsigned int exfat_striptail_len(unsigned int len, const char *name) | |
70 | { | |
71 | while (len && name[len - 1] == '.') | |
72 | len--; | |
73 | return len; | |
74 | } | |
75 | ||
76 | /* | |
77 | * Compute the hash for the exfat name corresponding to the dentry. If the name | |
78 | * is invalid, we leave the hash code unchanged so that the existing dentry can | |
79 | * be used. The exfat fs routines will return ENOENT or EINVAL as appropriate. | |
80 | */ | |
81 | static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr) | |
82 | { | |
83 | struct super_block *sb = dentry->d_sb; | |
84 | struct nls_table *t = EXFAT_SB(sb)->nls_io; | |
85 | const unsigned char *name = qstr->name; | |
86 | unsigned int len = exfat_striptail_len(qstr->len, qstr->name); | |
87 | unsigned long hash = init_name_hash(dentry); | |
88 | int i, charlen; | |
89 | wchar_t c; | |
90 | ||
91 | for (i = 0; i < len; i += charlen) { | |
92 | charlen = t->char2uni(&name[i], len - i, &c); | |
93 | if (charlen < 0) | |
94 | return charlen; | |
95 | hash = partial_name_hash(exfat_toupper(sb, c), hash); | |
96 | } | |
97 | ||
98 | qstr->hash = end_name_hash(hash); | |
99 | return 0; | |
100 | } | |
101 | ||
102 | static int exfat_d_cmp(const struct dentry *dentry, unsigned int len, | |
103 | const char *str, const struct qstr *name) | |
104 | { | |
105 | struct super_block *sb = dentry->d_sb; | |
106 | struct nls_table *t = EXFAT_SB(sb)->nls_io; | |
107 | unsigned int alen = exfat_striptail_len(name->len, name->name); | |
108 | unsigned int blen = exfat_striptail_len(len, str); | |
109 | wchar_t c1, c2; | |
110 | int charlen, i; | |
111 | ||
112 | if (alen != blen) | |
113 | return 1; | |
114 | ||
115 | for (i = 0; i < len; i += charlen) { | |
116 | charlen = t->char2uni(&name->name[i], alen - i, &c1); | |
117 | if (charlen < 0) | |
118 | return 1; | |
119 | if (charlen != t->char2uni(&str[i], blen - i, &c2)) | |
120 | return 1; | |
121 | ||
122 | if (exfat_toupper(sb, c1) != exfat_toupper(sb, c2)) | |
123 | return 1; | |
124 | } | |
125 | ||
126 | return 0; | |
127 | } | |
128 | ||
129 | const struct dentry_operations exfat_dentry_ops = { | |
130 | .d_revalidate = exfat_d_revalidate, | |
131 | .d_hash = exfat_d_hash, | |
132 | .d_compare = exfat_d_cmp, | |
133 | }; | |
134 | ||
135 | static int exfat_utf8_d_hash(const struct dentry *dentry, struct qstr *qstr) | |
136 | { | |
137 | struct super_block *sb = dentry->d_sb; | |
138 | const unsigned char *name = qstr->name; | |
139 | unsigned int len = exfat_striptail_len(qstr->len, qstr->name); | |
140 | unsigned long hash = init_name_hash(dentry); | |
141 | int i, charlen; | |
142 | unicode_t u; | |
143 | ||
144 | for (i = 0; i < len; i += charlen) { | |
145 | charlen = utf8_to_utf32(&name[i], len - i, &u); | |
146 | if (charlen < 0) | |
147 | return charlen; | |
148 | ||
149 | /* | |
150 | * Convert to UTF-16: code points above U+FFFF are encoded as | |
151 | * surrogate pairs. | |
152 | * exfat_toupper() works only for code points up to the U+FFFF. | |
153 | */ | |
154 | if (u > 0xFFFF) { | |
155 | hash = partial_name_hash(exfat_high_surrogate(u), hash); | |
156 | hash = partial_name_hash(exfat_low_surrogate(u), hash); | |
157 | } else { | |
158 | hash = partial_name_hash(exfat_toupper(sb, u), hash); | |
159 | } | |
160 | } | |
161 | ||
162 | qstr->hash = end_name_hash(hash); | |
163 | return 0; | |
164 | } | |
165 | ||
166 | static int exfat_utf8_d_cmp(const struct dentry *dentry, unsigned int len, | |
167 | const char *str, const struct qstr *name) | |
168 | { | |
169 | struct super_block *sb = dentry->d_sb; | |
170 | unsigned int alen = exfat_striptail_len(name->len, name->name); | |
171 | unsigned int blen = exfat_striptail_len(len, str); | |
172 | unicode_t u_a, u_b; | |
173 | int charlen, i; | |
174 | ||
175 | if (alen != blen) | |
176 | return 1; | |
177 | ||
178 | for (i = 0; i < alen; i += charlen) { | |
179 | charlen = utf8_to_utf32(&name->name[i], alen - i, &u_a); | |
180 | if (charlen < 0) | |
181 | return 1; | |
182 | if (charlen != utf8_to_utf32(&str[i], blen - i, &u_b)) | |
183 | return 1; | |
184 | ||
185 | if (u_a <= 0xFFFF && u_b <= 0xFFFF) { | |
186 | if (exfat_toupper(sb, u_a) != exfat_toupper(sb, u_b)) | |
187 | return 1; | |
188 | } else if (u_a > 0xFFFF && u_b > 0xFFFF) { | |
189 | if (exfat_low_surrogate(u_a) != | |
190 | exfat_low_surrogate(u_b) || | |
191 | exfat_high_surrogate(u_a) != | |
192 | exfat_high_surrogate(u_b)) | |
193 | return 1; | |
194 | } else { | |
195 | return 1; | |
196 | } | |
197 | } | |
198 | ||
199 | return 0; | |
200 | } | |
201 | ||
202 | const struct dentry_operations exfat_utf8_dentry_ops = { | |
203 | .d_revalidate = exfat_d_revalidate, | |
204 | .d_hash = exfat_utf8_d_hash, | |
205 | .d_compare = exfat_utf8_d_cmp, | |
206 | }; | |
207 | ||
208 | /* used only in search empty_slot() */ | |
209 | #define CNT_UNUSED_NOHIT (-1) | |
210 | #define CNT_UNUSED_HIT (-2) | |
211 | /* search EMPTY CONTINUOUS "num_entries" entries */ | |
212 | static int exfat_search_empty_slot(struct super_block *sb, | |
213 | struct exfat_hint_femp *hint_femp, struct exfat_chain *p_dir, | |
214 | int num_entries) | |
215 | { | |
216 | int i, dentry, num_empty = 0; | |
217 | int dentries_per_clu; | |
218 | unsigned int type; | |
219 | struct exfat_chain clu; | |
220 | struct exfat_dentry *ep; | |
221 | struct exfat_sb_info *sbi = EXFAT_SB(sb); | |
222 | struct buffer_head *bh; | |
223 | ||
224 | dentries_per_clu = sbi->dentries_per_clu; | |
225 | ||
226 | if (hint_femp->eidx != EXFAT_HINT_NONE) { | |
227 | dentry = hint_femp->eidx; | |
228 | if (num_entries <= hint_femp->count) { | |
229 | hint_femp->eidx = EXFAT_HINT_NONE; | |
230 | return dentry; | |
231 | } | |
232 | ||
233 | exfat_chain_dup(&clu, &hint_femp->cur); | |
234 | } else { | |
235 | exfat_chain_dup(&clu, p_dir); | |
236 | dentry = 0; | |
237 | } | |
238 | ||
239 | while (clu.dir != EXFAT_EOF_CLUSTER) { | |
240 | i = dentry & (dentries_per_clu - 1); | |
241 | ||
242 | for (; i < dentries_per_clu; i++, dentry++) { | |
243 | ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); | |
244 | if (!ep) | |
245 | return -EIO; | |
246 | type = exfat_get_entry_type(ep); | |
247 | brelse(bh); | |
248 | ||
249 | if (type == TYPE_UNUSED || type == TYPE_DELETED) { | |
250 | num_empty++; | |
251 | if (hint_femp->eidx == EXFAT_HINT_NONE) { | |
252 | hint_femp->eidx = dentry; | |
253 | hint_femp->count = CNT_UNUSED_NOHIT; | |
254 | exfat_chain_set(&hint_femp->cur, | |
255 | clu.dir, clu.size, clu.flags); | |
256 | } | |
257 | ||
258 | if (type == TYPE_UNUSED && | |
259 | hint_femp->count != CNT_UNUSED_HIT) | |
260 | hint_femp->count = CNT_UNUSED_HIT; | |
261 | } else { | |
262 | if (hint_femp->eidx != EXFAT_HINT_NONE && | |
263 | hint_femp->count == CNT_UNUSED_HIT) { | |
264 | /* unused empty group means | |
265 | * an empty group which includes | |
266 | * unused dentry | |
267 | */ | |
268 | exfat_fs_error(sb, | |
269 | "found bogus dentry(%d) beyond unused empty group(%d) (start_clu : %u, cur_clu : %u)", | |
270 | dentry, hint_femp->eidx, | |
271 | p_dir->dir, clu.dir); | |
272 | return -EIO; | |
273 | } | |
274 | ||
275 | num_empty = 0; | |
276 | hint_femp->eidx = EXFAT_HINT_NONE; | |
277 | } | |
278 | ||
279 | if (num_empty >= num_entries) { | |
280 | /* found and invalidate hint_femp */ | |
281 | hint_femp->eidx = EXFAT_HINT_NONE; | |
282 | return (dentry - (num_entries - 1)); | |
283 | } | |
284 | } | |
285 | ||
286 | if (clu.flags == ALLOC_NO_FAT_CHAIN) { | |
287 | if (--clu.size > 0) | |
288 | clu.dir++; | |
289 | else | |
290 | clu.dir = EXFAT_EOF_CLUSTER; | |
291 | } else { | |
292 | if (exfat_get_next_cluster(sb, &clu.dir)) | |
293 | return -EIO; | |
294 | } | |
295 | } | |
296 | ||
297 | return -ENOSPC; | |
298 | } | |
299 | ||
300 | static int exfat_check_max_dentries(struct inode *inode) | |
301 | { | |
302 | if (EXFAT_B_TO_DEN(i_size_read(inode)) >= MAX_EXFAT_DENTRIES) { | |
303 | /* | |
304 | * exFAT spec allows a dir to grow upto 8388608(256MB) | |
305 | * dentries | |
306 | */ | |
307 | return -ENOSPC; | |
308 | } | |
309 | return 0; | |
310 | } | |
311 | ||
312 | /* find empty directory entry. | |
313 | * if there isn't any empty slot, expand cluster chain. | |
314 | */ | |
315 | static int exfat_find_empty_entry(struct inode *inode, | |
316 | struct exfat_chain *p_dir, int num_entries) | |
317 | { | |
318 | int dentry; | |
319 | unsigned int ret, last_clu; | |
320 | sector_t sector; | |
321 | loff_t size = 0; | |
322 | struct exfat_chain clu; | |
323 | struct exfat_dentry *ep = NULL; | |
324 | struct super_block *sb = inode->i_sb; | |
325 | struct exfat_sb_info *sbi = EXFAT_SB(sb); | |
326 | struct exfat_inode_info *ei = EXFAT_I(inode); | |
327 | struct exfat_hint_femp hint_femp; | |
328 | ||
329 | hint_femp.eidx = EXFAT_HINT_NONE; | |
330 | ||
331 | if (ei->hint_femp.eidx != EXFAT_HINT_NONE) { | |
332 | memcpy(&hint_femp, &ei->hint_femp, | |
333 | sizeof(struct exfat_hint_femp)); | |
334 | ei->hint_femp.eidx = EXFAT_HINT_NONE; | |
335 | } | |
336 | ||
337 | while ((dentry = exfat_search_empty_slot(sb, &hint_femp, p_dir, | |
338 | num_entries)) < 0) { | |
339 | if (dentry == -EIO) | |
340 | break; | |
341 | ||
342 | if (exfat_check_max_dentries(inode)) | |
343 | return -ENOSPC; | |
344 | ||
345 | /* we trust p_dir->size regardless of FAT type */ | |
346 | if (exfat_find_last_cluster(sb, p_dir, &last_clu)) | |
347 | return -EIO; | |
348 | ||
349 | /* | |
350 | * Allocate new cluster to this directory | |
351 | */ | |
352 | exfat_chain_set(&clu, last_clu + 1, 0, p_dir->flags); | |
353 | ||
354 | /* allocate a cluster */ | |
355 | ret = exfat_alloc_cluster(inode, 1, &clu); | |
356 | if (ret) | |
357 | return ret; | |
358 | ||
359 | if (exfat_zeroed_cluster(inode, clu.dir)) | |
360 | return -EIO; | |
361 | ||
362 | /* append to the FAT chain */ | |
363 | if (clu.flags != p_dir->flags) { | |
364 | /* no-fat-chain bit is disabled, | |
365 | * so fat-chain should be synced with alloc-bitmap | |
366 | */ | |
367 | exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size); | |
368 | p_dir->flags = ALLOC_FAT_CHAIN; | |
369 | hint_femp.cur.flags = ALLOC_FAT_CHAIN; | |
370 | } | |
371 | ||
372 | if (clu.flags == ALLOC_FAT_CHAIN) | |
373 | if (exfat_ent_set(sb, last_clu, clu.dir)) | |
374 | return -EIO; | |
375 | ||
376 | if (hint_femp.eidx == EXFAT_HINT_NONE) { | |
377 | /* the special case that new dentry | |
378 | * should be allocated from the start of new cluster | |
379 | */ | |
380 | hint_femp.eidx = EXFAT_B_TO_DEN_IDX(p_dir->size, sbi); | |
381 | hint_femp.count = sbi->dentries_per_clu; | |
382 | ||
383 | exfat_chain_set(&hint_femp.cur, clu.dir, 0, clu.flags); | |
384 | } | |
385 | hint_femp.cur.size++; | |
386 | p_dir->size++; | |
387 | size = EXFAT_CLU_TO_B(p_dir->size, sbi); | |
388 | ||
389 | /* update the directory entry */ | |
390 | if (p_dir->dir != sbi->root_dir) { | |
391 | struct buffer_head *bh; | |
392 | ||
393 | ep = exfat_get_dentry(sb, | |
394 | &(ei->dir), ei->entry + 1, &bh, §or); | |
395 | if (!ep) | |
396 | return -EIO; | |
397 | ||
398 | ep->dentry.stream.valid_size = cpu_to_le64(size); | |
399 | ep->dentry.stream.size = ep->dentry.stream.valid_size; | |
400 | ep->dentry.stream.flags = p_dir->flags; | |
401 | exfat_update_bh(sb, bh, IS_DIRSYNC(inode)); | |
402 | brelse(bh); | |
403 | if (exfat_update_dir_chksum(inode, &(ei->dir), | |
404 | ei->entry)) | |
405 | return -EIO; | |
406 | } | |
407 | ||
408 | /* directory inode should be updated in here */ | |
409 | i_size_write(inode, size); | |
410 | EXFAT_I(inode)->i_size_ondisk += sbi->cluster_size; | |
411 | EXFAT_I(inode)->i_size_aligned += sbi->cluster_size; | |
412 | EXFAT_I(inode)->flags = p_dir->flags; | |
413 | inode->i_blocks += 1 << sbi->sect_per_clus_bits; | |
414 | } | |
415 | ||
416 | return dentry; | |
417 | } | |
418 | ||
419 | /* | |
420 | * Name Resolution Functions : | |
421 | * Zero if it was successful; otherwise nonzero. | |
422 | */ | |
423 | static int __exfat_resolve_path(struct inode *inode, const unsigned char *path, | |
424 | struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, | |
425 | int lookup) | |
426 | { | |
427 | int namelen; | |
428 | int lossy = NLS_NAME_NO_LOSSY; | |
429 | struct super_block *sb = inode->i_sb; | |
430 | struct exfat_sb_info *sbi = EXFAT_SB(sb); | |
431 | struct exfat_inode_info *ei = EXFAT_I(inode); | |
432 | ||
433 | /* strip all trailing periods */ | |
434 | namelen = exfat_striptail_len(strlen(path), path); | |
435 | if (!namelen) | |
436 | return -ENOENT; | |
437 | ||
438 | if (strlen(path) > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE)) | |
439 | return -ENAMETOOLONG; | |
440 | ||
441 | /* | |
442 | * strip all leading spaces : | |
443 | * "MS windows 7" supports leading spaces. | |
444 | * So we should skip this preprocessing for compatibility. | |
445 | */ | |
446 | ||
447 | /* file name conversion : | |
448 | * If lookup case, we allow bad-name for compatibility. | |
449 | */ | |
450 | namelen = exfat_nls_to_utf16(sb, path, namelen, p_uniname, | |
451 | &lossy); | |
452 | if (namelen < 0) | |
453 | return namelen; /* return error value */ | |
454 | ||
455 | if ((lossy && !lookup) || !namelen) | |
456 | return -EINVAL; | |
457 | ||
458 | exfat_chain_set(p_dir, ei->start_clu, | |
459 | EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags); | |
460 | ||
461 | return 0; | |
462 | } | |
463 | ||
464 | static inline int exfat_resolve_path(struct inode *inode, | |
465 | const unsigned char *path, struct exfat_chain *dir, | |
466 | struct exfat_uni_name *uni) | |
467 | { | |
468 | return __exfat_resolve_path(inode, path, dir, uni, 0); | |
469 | } | |
470 | ||
471 | static inline int exfat_resolve_path_for_lookup(struct inode *inode, | |
472 | const unsigned char *path, struct exfat_chain *dir, | |
473 | struct exfat_uni_name *uni) | |
474 | { | |
475 | return __exfat_resolve_path(inode, path, dir, uni, 1); | |
476 | } | |
477 | ||
478 | static inline loff_t exfat_make_i_pos(struct exfat_dir_entry *info) | |
479 | { | |
480 | return ((loff_t) info->dir.dir << 32) | (info->entry & 0xffffffff); | |
481 | } | |
482 | ||
483 | static int exfat_add_entry(struct inode *inode, const char *path, | |
484 | struct exfat_chain *p_dir, unsigned int type, | |
485 | struct exfat_dir_entry *info) | |
486 | { | |
487 | int ret, dentry, num_entries; | |
488 | struct super_block *sb = inode->i_sb; | |
489 | struct exfat_sb_info *sbi = EXFAT_SB(sb); | |
490 | struct exfat_uni_name uniname; | |
491 | struct exfat_chain clu; | |
492 | int clu_size = 0; | |
493 | unsigned int start_clu = EXFAT_FREE_CLUSTER; | |
494 | ||
495 | ret = exfat_resolve_path(inode, path, p_dir, &uniname); | |
496 | if (ret) | |
497 | goto out; | |
498 | ||
499 | num_entries = exfat_calc_num_entries(&uniname); | |
500 | if (num_entries < 0) { | |
501 | ret = num_entries; | |
502 | goto out; | |
503 | } | |
504 | ||
505 | /* exfat_find_empty_entry must be called before alloc_cluster() */ | |
506 | dentry = exfat_find_empty_entry(inode, p_dir, num_entries); | |
507 | if (dentry < 0) { | |
508 | ret = dentry; /* -EIO or -ENOSPC */ | |
509 | goto out; | |
510 | } | |
511 | ||
512 | if (type == TYPE_DIR) { | |
513 | ret = exfat_alloc_new_dir(inode, &clu); | |
514 | if (ret) | |
515 | goto out; | |
516 | start_clu = clu.dir; | |
517 | clu_size = sbi->cluster_size; | |
518 | } | |
519 | ||
520 | /* update the directory entry */ | |
521 | /* fill the dos name directory entry information of the created file. | |
522 | * the first cluster is not determined yet. (0) | |
523 | */ | |
524 | ret = exfat_init_dir_entry(inode, p_dir, dentry, type, | |
525 | start_clu, clu_size); | |
526 | if (ret) | |
527 | goto out; | |
528 | ||
529 | ret = exfat_init_ext_entry(inode, p_dir, dentry, num_entries, &uniname); | |
530 | if (ret) | |
531 | goto out; | |
532 | ||
533 | memcpy(&info->dir, p_dir, sizeof(struct exfat_chain)); | |
534 | info->entry = dentry; | |
535 | info->flags = ALLOC_NO_FAT_CHAIN; | |
536 | info->type = type; | |
537 | ||
538 | if (type == TYPE_FILE) { | |
539 | info->attr = ATTR_ARCHIVE; | |
540 | info->start_clu = EXFAT_EOF_CLUSTER; | |
541 | info->size = 0; | |
542 | info->num_subdirs = 0; | |
543 | } else { | |
544 | int count; | |
545 | struct exfat_chain cdir; | |
546 | ||
547 | info->attr = ATTR_SUBDIR; | |
548 | info->start_clu = start_clu; | |
549 | info->size = clu_size; | |
550 | ||
551 | exfat_chain_set(&cdir, info->start_clu, | |
552 | EXFAT_B_TO_CLU(info->size, sbi), info->flags); | |
553 | count = exfat_count_dir_entries(sb, &cdir); | |
554 | if (count < 0) | |
555 | return -EIO; | |
556 | info->num_subdirs = count + EXFAT_MIN_SUBDIR; | |
557 | } | |
558 | memset(&info->crtime, 0, sizeof(info->crtime)); | |
559 | memset(&info->mtime, 0, sizeof(info->mtime)); | |
560 | memset(&info->atime, 0, sizeof(info->atime)); | |
561 | out: | |
562 | return ret; | |
563 | } | |
564 | ||
565 | static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |
566 | bool excl) | |
567 | { | |
568 | struct super_block *sb = dir->i_sb; | |
569 | struct inode *inode; | |
570 | struct exfat_chain cdir; | |
571 | struct exfat_dir_entry info; | |
572 | loff_t i_pos; | |
573 | int err; | |
574 | ||
575 | mutex_lock(&EXFAT_SB(sb)->s_lock); | |
576 | exfat_set_vol_flags(sb, VOL_DIRTY); | |
577 | err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_FILE, | |
578 | &info); | |
579 | exfat_set_vol_flags(sb, VOL_CLEAN); | |
580 | if (err) | |
581 | goto unlock; | |
582 | ||
583 | inode_inc_iversion(dir); | |
584 | dir->i_ctime = dir->i_mtime = current_time(dir); | |
585 | if (IS_DIRSYNC(dir)) | |
586 | exfat_sync_inode(dir); | |
587 | else | |
588 | mark_inode_dirty(dir); | |
589 | ||
590 | i_pos = exfat_make_i_pos(&info); | |
591 | inode = exfat_build_inode(sb, &info, i_pos); | |
592 | if (IS_ERR(inode)) | |
593 | goto unlock; | |
594 | ||
595 | inode_inc_iversion(inode); | |
596 | inode->i_mtime = inode->i_atime = inode->i_ctime = | |
597 | EXFAT_I(inode)->i_crtime = current_time(inode); | |
81df1ad4 | 598 | exfat_truncate_atime(&inode->i_atime); |
5f2aa075 NJ |
599 | /* timestamp is already written, so mark_inode_dirty() is unneeded. */ |
600 | ||
601 | d_instantiate(dentry, inode); | |
602 | unlock: | |
603 | mutex_unlock(&EXFAT_SB(sb)->s_lock); | |
604 | return err; | |
605 | } | |
606 | ||
607 | /* lookup a file */ | |
608 | static int exfat_find(struct inode *dir, struct qstr *qname, | |
609 | struct exfat_dir_entry *info) | |
610 | { | |
611 | int ret, dentry, num_entries, count; | |
612 | struct exfat_chain cdir; | |
613 | struct exfat_uni_name uni_name; | |
614 | struct exfat_dentry *ep, *ep2; | |
615 | struct exfat_entry_set_cache *es = NULL; | |
616 | struct super_block *sb = dir->i_sb; | |
617 | struct exfat_sb_info *sbi = EXFAT_SB(sb); | |
618 | struct exfat_inode_info *ei = EXFAT_I(dir); | |
619 | ||
620 | if (qname->len == 0) | |
621 | return -ENOENT; | |
622 | ||
623 | /* check the validity of directory name in the given pathname */ | |
624 | ret = exfat_resolve_path_for_lookup(dir, qname->name, &cdir, &uni_name); | |
625 | if (ret) | |
626 | return ret; | |
627 | ||
628 | num_entries = exfat_calc_num_entries(&uni_name); | |
629 | if (num_entries < 0) | |
630 | return num_entries; | |
631 | ||
632 | /* check the validation of hint_stat and initialize it if required */ | |
633 | if (ei->version != (inode_peek_iversion_raw(dir) & 0xffffffff)) { | |
634 | ei->hint_stat.clu = cdir.dir; | |
635 | ei->hint_stat.eidx = 0; | |
636 | ei->version = (inode_peek_iversion_raw(dir) & 0xffffffff); | |
637 | ei->hint_femp.eidx = EXFAT_HINT_NONE; | |
638 | } | |
639 | ||
640 | /* search the file name for directories */ | |
641 | dentry = exfat_find_dir_entry(sb, ei, &cdir, &uni_name, | |
642 | num_entries, TYPE_ALL); | |
643 | ||
644 | if ((dentry < 0) && (dentry != -EEXIST)) | |
645 | return dentry; /* -error value */ | |
646 | ||
647 | memcpy(&info->dir, &cdir.dir, sizeof(struct exfat_chain)); | |
648 | info->entry = dentry; | |
649 | info->num_subdirs = 0; | |
650 | ||
651 | /* root directory itself */ | |
652 | if (unlikely(dentry == -EEXIST)) { | |
653 | int num_clu = 0; | |
654 | ||
655 | info->type = TYPE_DIR; | |
656 | info->attr = ATTR_SUBDIR; | |
657 | info->flags = ALLOC_FAT_CHAIN; | |
658 | info->start_clu = sbi->root_dir; | |
659 | memset(&info->crtime, 0, sizeof(info->crtime)); | |
660 | memset(&info->mtime, 0, sizeof(info->mtime)); | |
661 | memset(&info->atime, 0, sizeof(info->atime)); | |
662 | ||
663 | exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); | |
664 | if (exfat_count_num_clusters(sb, &cdir, &num_clu)) | |
665 | return -EIO; | |
666 | info->size = num_clu << sbi->cluster_size_bits; | |
667 | ||
668 | count = exfat_count_dir_entries(sb, &cdir); | |
669 | if (count < 0) | |
670 | return -EIO; | |
671 | ||
672 | info->num_subdirs = count; | |
673 | } else { | |
674 | es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES, &ep); | |
675 | if (!es) | |
676 | return -EIO; | |
677 | ep2 = ep + 1; | |
678 | ||
679 | info->type = exfat_get_entry_type(ep); | |
680 | info->attr = le16_to_cpu(ep->dentry.file.attr); | |
681 | info->size = le64_to_cpu(ep2->dentry.stream.valid_size); | |
682 | if ((info->type == TYPE_FILE) && (info->size == 0)) { | |
683 | info->flags = ALLOC_NO_FAT_CHAIN; | |
684 | info->start_clu = EXFAT_EOF_CLUSTER; | |
685 | } else { | |
686 | info->flags = ep2->dentry.stream.flags; | |
687 | info->start_clu = | |
688 | le32_to_cpu(ep2->dentry.stream.start_clu); | |
689 | } | |
690 | ||
691 | if (ei->start_clu == EXFAT_FREE_CLUSTER) { | |
692 | exfat_fs_error(sb, | |
693 | "non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)", | |
694 | i_size_read(dir), ei->dir.dir, ei->entry); | |
94182167 | 695 | kfree(es); |
5f2aa075 NJ |
696 | return -EIO; |
697 | } | |
698 | ||
699 | exfat_get_entry_time(sbi, &info->crtime, | |
700 | ep->dentry.file.create_tz, | |
701 | ep->dentry.file.create_time, | |
702 | ep->dentry.file.create_date, | |
703 | ep->dentry.file.create_time_ms); | |
704 | exfat_get_entry_time(sbi, &info->mtime, | |
705 | ep->dentry.file.modify_tz, | |
706 | ep->dentry.file.modify_time, | |
707 | ep->dentry.file.modify_date, | |
708 | ep->dentry.file.modify_time_ms); | |
709 | exfat_get_entry_time(sbi, &info->atime, | |
710 | ep->dentry.file.access_tz, | |
711 | ep->dentry.file.access_time, | |
712 | ep->dentry.file.access_date, | |
713 | 0); | |
714 | kfree(es); | |
715 | ||
716 | if (info->type == TYPE_DIR) { | |
717 | exfat_chain_set(&cdir, info->start_clu, | |
718 | EXFAT_B_TO_CLU(info->size, sbi), info->flags); | |
719 | count = exfat_count_dir_entries(sb, &cdir); | |
720 | if (count < 0) | |
721 | return -EIO; | |
722 | ||
723 | info->num_subdirs = count + EXFAT_MIN_SUBDIR; | |
724 | } | |
725 | } | |
726 | return 0; | |
727 | } | |
728 | ||
729 | static int exfat_d_anon_disconn(struct dentry *dentry) | |
730 | { | |
731 | return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); | |
732 | } | |
733 | ||
734 | static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, | |
735 | unsigned int flags) | |
736 | { | |
737 | struct super_block *sb = dir->i_sb; | |
738 | struct inode *inode; | |
739 | struct dentry *alias; | |
740 | struct exfat_dir_entry info; | |
741 | int err; | |
742 | loff_t i_pos; | |
743 | mode_t i_mode; | |
744 | ||
745 | mutex_lock(&EXFAT_SB(sb)->s_lock); | |
746 | err = exfat_find(dir, &dentry->d_name, &info); | |
747 | if (err) { | |
748 | if (err == -ENOENT) { | |
749 | inode = NULL; | |
750 | goto out; | |
751 | } | |
752 | goto unlock; | |
753 | } | |
754 | ||
755 | i_pos = exfat_make_i_pos(&info); | |
756 | inode = exfat_build_inode(sb, &info, i_pos); | |
757 | if (IS_ERR(inode)) { | |
758 | err = PTR_ERR(inode); | |
759 | goto unlock; | |
760 | } | |
761 | ||
762 | i_mode = inode->i_mode; | |
763 | alias = d_find_alias(inode); | |
764 | ||
765 | /* | |
766 | * Checking "alias->d_parent == dentry->d_parent" to make sure | |
767 | * FS is not corrupted (especially double linked dir). | |
768 | */ | |
769 | if (alias && alias->d_parent == dentry->d_parent && | |
770 | !exfat_d_anon_disconn(alias)) { | |
771 | ||
772 | /* | |
773 | * Unhashed alias is able to exist because of revalidate() | |
774 | * called by lookup_fast. You can easily make this status | |
775 | * by calling create and lookup concurrently | |
776 | * In such case, we reuse an alias instead of new dentry | |
777 | */ | |
778 | if (d_unhashed(alias)) { | |
779 | WARN_ON(alias->d_name.hash_len != | |
780 | dentry->d_name.hash_len); | |
781 | exfat_msg(sb, KERN_INFO, | |
782 | "rehashed a dentry(%p) in read lookup", alias); | |
783 | d_drop(dentry); | |
784 | d_rehash(alias); | |
785 | } else if (!S_ISDIR(i_mode)) { | |
786 | /* | |
787 | * This inode has non anonymous-DCACHE_DISCONNECTED | |
788 | * dentry. This means, the user did ->lookup() by an | |
789 | * another name (longname vs 8.3 alias of it) in past. | |
790 | * | |
791 | * Switch to new one for reason of locality if possible. | |
792 | */ | |
793 | d_move(alias, dentry); | |
794 | } | |
795 | iput(inode); | |
796 | mutex_unlock(&EXFAT_SB(sb)->s_lock); | |
797 | return alias; | |
798 | } | |
799 | dput(alias); | |
800 | out: | |
801 | mutex_unlock(&EXFAT_SB(sb)->s_lock); | |
802 | if (!inode) | |
803 | exfat_d_version_set(dentry, inode_query_iversion(dir)); | |
804 | ||
805 | return d_splice_alias(inode, dentry); | |
806 | unlock: | |
807 | mutex_unlock(&EXFAT_SB(sb)->s_lock); | |
808 | return ERR_PTR(err); | |
809 | } | |
810 | ||
811 | /* remove an entry, BUT don't truncate */ | |
812 | static int exfat_unlink(struct inode *dir, struct dentry *dentry) | |
813 | { | |
814 | struct exfat_chain cdir; | |
815 | struct exfat_dentry *ep; | |
816 | struct super_block *sb = dir->i_sb; | |
817 | struct inode *inode = dentry->d_inode; | |
818 | struct exfat_inode_info *ei = EXFAT_I(inode); | |
819 | struct buffer_head *bh; | |
820 | sector_t sector; | |
821 | int num_entries, entry, err = 0; | |
822 | ||
823 | mutex_lock(&EXFAT_SB(sb)->s_lock); | |
824 | exfat_chain_dup(&cdir, &ei->dir); | |
825 | entry = ei->entry; | |
826 | if (ei->dir.dir == DIR_DELETED) { | |
827 | exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry"); | |
828 | err = -ENOENT; | |
829 | goto unlock; | |
830 | } | |
831 | ||
832 | ep = exfat_get_dentry(sb, &cdir, entry, &bh, §or); | |
833 | if (!ep) { | |
834 | err = -EIO; | |
835 | goto unlock; | |
836 | } | |
837 | num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep); | |
838 | if (num_entries < 0) { | |
839 | err = -EIO; | |
840 | brelse(bh); | |
841 | goto unlock; | |
842 | } | |
843 | num_entries++; | |
844 | brelse(bh); | |
845 | ||
846 | exfat_set_vol_flags(sb, VOL_DIRTY); | |
847 | /* update the directory entry */ | |
848 | if (exfat_remove_entries(dir, &cdir, entry, 0, num_entries)) { | |
849 | err = -EIO; | |
850 | goto unlock; | |
851 | } | |
852 | ||
853 | /* This doesn't modify ei */ | |
854 | ei->dir.dir = DIR_DELETED; | |
855 | exfat_set_vol_flags(sb, VOL_CLEAN); | |
856 | ||
857 | inode_inc_iversion(dir); | |
858 | dir->i_mtime = dir->i_atime = current_time(dir); | |
81df1ad4 | 859 | exfat_truncate_atime(&dir->i_atime); |
5f2aa075 NJ |
860 | if (IS_DIRSYNC(dir)) |
861 | exfat_sync_inode(dir); | |
862 | else | |
863 | mark_inode_dirty(dir); | |
864 | ||
865 | clear_nlink(inode); | |
866 | inode->i_mtime = inode->i_atime = current_time(inode); | |
81df1ad4 | 867 | exfat_truncate_atime(&inode->i_atime); |
5f2aa075 NJ |
868 | exfat_unhash_inode(inode); |
869 | exfat_d_version_set(dentry, inode_query_iversion(dir)); | |
870 | unlock: | |
871 | mutex_unlock(&EXFAT_SB(sb)->s_lock); | |
872 | return err; | |
873 | } | |
874 | ||
875 | static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |
876 | { | |
877 | struct super_block *sb = dir->i_sb; | |
878 | struct inode *inode; | |
879 | struct exfat_dir_entry info; | |
880 | struct exfat_chain cdir; | |
881 | loff_t i_pos; | |
882 | int err; | |
883 | ||
884 | mutex_lock(&EXFAT_SB(sb)->s_lock); | |
885 | exfat_set_vol_flags(sb, VOL_DIRTY); | |
886 | err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_DIR, | |
887 | &info); | |
888 | exfat_set_vol_flags(sb, VOL_CLEAN); | |
889 | if (err) | |
890 | goto unlock; | |
891 | ||
892 | inode_inc_iversion(dir); | |
893 | dir->i_ctime = dir->i_mtime = current_time(dir); | |
894 | if (IS_DIRSYNC(dir)) | |
895 | exfat_sync_inode(dir); | |
896 | else | |
897 | mark_inode_dirty(dir); | |
898 | inc_nlink(dir); | |
899 | ||
900 | i_pos = exfat_make_i_pos(&info); | |
901 | inode = exfat_build_inode(sb, &info, i_pos); | |
902 | if (IS_ERR(inode)) { | |
903 | err = PTR_ERR(inode); | |
904 | goto unlock; | |
905 | } | |
906 | ||
907 | inode_inc_iversion(inode); | |
908 | inode->i_mtime = inode->i_atime = inode->i_ctime = | |
909 | EXFAT_I(inode)->i_crtime = current_time(inode); | |
81df1ad4 | 910 | exfat_truncate_atime(&inode->i_atime); |
5f2aa075 NJ |
911 | /* timestamp is already written, so mark_inode_dirty() is unneeded. */ |
912 | ||
913 | d_instantiate(dentry, inode); | |
914 | ||
915 | unlock: | |
916 | mutex_unlock(&EXFAT_SB(sb)->s_lock); | |
917 | return err; | |
918 | } | |
919 | ||
920 | static int exfat_check_dir_empty(struct super_block *sb, | |
921 | struct exfat_chain *p_dir) | |
922 | { | |
923 | int i, dentries_per_clu; | |
924 | unsigned int type; | |
925 | struct exfat_chain clu; | |
926 | struct exfat_dentry *ep; | |
927 | struct exfat_sb_info *sbi = EXFAT_SB(sb); | |
928 | struct buffer_head *bh; | |
929 | ||
930 | dentries_per_clu = sbi->dentries_per_clu; | |
931 | ||
932 | exfat_chain_dup(&clu, p_dir); | |
933 | ||
934 | while (clu.dir != EXFAT_EOF_CLUSTER) { | |
935 | for (i = 0; i < dentries_per_clu; i++) { | |
936 | ep = exfat_get_dentry(sb, &clu, i, &bh, NULL); | |
937 | if (!ep) | |
938 | return -EIO; | |
939 | type = exfat_get_entry_type(ep); | |
940 | brelse(bh); | |
941 | if (type == TYPE_UNUSED) | |
942 | return 0; | |
943 | ||
944 | if (type != TYPE_FILE && type != TYPE_DIR) | |
945 | continue; | |
946 | ||
947 | return -ENOTEMPTY; | |
948 | } | |
949 | ||
950 | if (clu.flags == ALLOC_NO_FAT_CHAIN) { | |
951 | if (--clu.size > 0) | |
952 | clu.dir++; | |
953 | else | |
954 | clu.dir = EXFAT_EOF_CLUSTER; | |
955 | } else { | |
956 | if (exfat_get_next_cluster(sb, &(clu.dir))) | |
957 | return -EIO; | |
958 | } | |
959 | } | |
960 | ||
961 | return 0; | |
962 | } | |
963 | ||
964 | static int exfat_rmdir(struct inode *dir, struct dentry *dentry) | |
965 | { | |
966 | struct inode *inode = dentry->d_inode; | |
967 | struct exfat_dentry *ep; | |
968 | struct exfat_chain cdir, clu_to_free; | |
969 | struct super_block *sb = inode->i_sb; | |
970 | struct exfat_sb_info *sbi = EXFAT_SB(sb); | |
971 | struct exfat_inode_info *ei = EXFAT_I(inode); | |
972 | struct buffer_head *bh; | |
973 | sector_t sector; | |
974 | int num_entries, entry, err; | |
975 | ||
976 | mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock); | |
977 | ||
978 | exfat_chain_dup(&cdir, &ei->dir); | |
979 | entry = ei->entry; | |
980 | ||
981 | if (ei->dir.dir == DIR_DELETED) { | |
982 | exfat_msg(sb, KERN_ERR, "abnormal access to deleted dentry"); | |
983 | err = -ENOENT; | |
984 | goto unlock; | |
985 | } | |
986 | ||
987 | exfat_set_vol_flags(sb, VOL_DIRTY); | |
988 | exfat_chain_set(&clu_to_free, ei->start_clu, | |
989 | EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi), ei->flags); | |
990 | ||
991 | err = exfat_check_dir_empty(sb, &clu_to_free); | |
992 | if (err) { | |
993 | if (err == -EIO) | |
994 | exfat_msg(sb, KERN_ERR, | |
995 | "failed to exfat_check_dir_empty : err(%d)", | |
996 | err); | |
997 | goto unlock; | |
998 | } | |
999 | ||
1000 | ep = exfat_get_dentry(sb, &cdir, entry, &bh, §or); | |
1001 | if (!ep) { | |
1002 | err = -EIO; | |
1003 | goto unlock; | |
1004 | } | |
1005 | ||
1006 | num_entries = exfat_count_ext_entries(sb, &cdir, entry, ep); | |
1007 | if (num_entries < 0) { | |
1008 | err = -EIO; | |
1009 | brelse(bh); | |
1010 | goto unlock; | |
1011 | } | |
1012 | num_entries++; | |
1013 | brelse(bh); | |
1014 | ||
1015 | err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries); | |
1016 | if (err) { | |
1017 | exfat_msg(sb, KERN_ERR, | |
1018 | "failed to exfat_remove_entries : err(%d)", | |
1019 | err); | |
1020 | goto unlock; | |
1021 | } | |
1022 | ei->dir.dir = DIR_DELETED; | |
1023 | exfat_set_vol_flags(sb, VOL_CLEAN); | |
1024 | ||
1025 | inode_inc_iversion(dir); | |
1026 | dir->i_mtime = dir->i_atime = current_time(dir); | |
81df1ad4 | 1027 | exfat_truncate_atime(&dir->i_atime); |
5f2aa075 NJ |
1028 | if (IS_DIRSYNC(dir)) |
1029 | exfat_sync_inode(dir); | |
1030 | else | |
1031 | mark_inode_dirty(dir); | |
1032 | drop_nlink(dir); | |
1033 | ||
1034 | clear_nlink(inode); | |
1035 | inode->i_mtime = inode->i_atime = current_time(inode); | |
81df1ad4 | 1036 | exfat_truncate_atime(&inode->i_atime); |
5f2aa075 NJ |
1037 | exfat_unhash_inode(inode); |
1038 | exfat_d_version_set(dentry, inode_query_iversion(dir)); | |
1039 | unlock: | |
1040 | mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock); | |
1041 | return err; | |
1042 | } | |
1043 | ||
1044 | static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir, | |
1045 | int oldentry, struct exfat_uni_name *p_uniname, | |
1046 | struct exfat_inode_info *ei) | |
1047 | { | |
1048 | int ret, num_old_entries, num_new_entries; | |
1049 | sector_t sector_old, sector_new; | |
1050 | struct exfat_dentry *epold, *epnew; | |
1051 | struct super_block *sb = inode->i_sb; | |
1052 | struct buffer_head *new_bh, *old_bh; | |
1053 | int sync = IS_DIRSYNC(inode); | |
1054 | ||
1055 | epold = exfat_get_dentry(sb, p_dir, oldentry, &old_bh, §or_old); | |
1056 | if (!epold) | |
1057 | return -EIO; | |
1058 | ||
1059 | num_old_entries = exfat_count_ext_entries(sb, p_dir, oldentry, epold); | |
1060 | if (num_old_entries < 0) | |
1061 | return -EIO; | |
1062 | num_old_entries++; | |
1063 | ||
1064 | num_new_entries = exfat_calc_num_entries(p_uniname); | |
1065 | if (num_new_entries < 0) | |
1066 | return num_new_entries; | |
1067 | ||
1068 | if (num_old_entries < num_new_entries) { | |
1069 | int newentry; | |
1070 | ||
1071 | newentry = | |
1072 | exfat_find_empty_entry(inode, p_dir, num_new_entries); | |
1073 | if (newentry < 0) | |
1074 | return newentry; /* -EIO or -ENOSPC */ | |
1075 | ||
1076 | epnew = exfat_get_dentry(sb, p_dir, newentry, &new_bh, | |
1077 | §or_new); | |
1078 | if (!epnew) | |
1079 | return -EIO; | |
1080 | ||
1081 | memcpy(epnew, epold, DENTRY_SIZE); | |
1082 | if (exfat_get_entry_type(epnew) == TYPE_FILE) { | |
1083 | epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE); | |
1084 | ei->attr |= ATTR_ARCHIVE; | |
1085 | } | |
1086 | exfat_update_bh(sb, new_bh, sync); | |
1087 | brelse(old_bh); | |
1088 | brelse(new_bh); | |
1089 | ||
1090 | epold = exfat_get_dentry(sb, p_dir, oldentry + 1, &old_bh, | |
1091 | §or_old); | |
1092 | epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh, | |
1093 | §or_new); | |
1094 | if (!epold || !epnew) | |
1095 | return -EIO; | |
1096 | ||
1097 | memcpy(epnew, epold, DENTRY_SIZE); | |
1098 | exfat_update_bh(sb, new_bh, sync); | |
1099 | brelse(old_bh); | |
1100 | brelse(new_bh); | |
1101 | ||
1102 | ret = exfat_init_ext_entry(inode, p_dir, newentry, | |
1103 | num_new_entries, p_uniname); | |
1104 | if (ret) | |
1105 | return ret; | |
1106 | ||
1107 | exfat_remove_entries(inode, p_dir, oldentry, 0, | |
1108 | num_old_entries); | |
1109 | ei->entry = newentry; | |
1110 | } else { | |
1111 | if (exfat_get_entry_type(epold) == TYPE_FILE) { | |
1112 | epold->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE); | |
1113 | ei->attr |= ATTR_ARCHIVE; | |
1114 | } | |
1115 | exfat_update_bh(sb, old_bh, sync); | |
1116 | brelse(old_bh); | |
1117 | ret = exfat_init_ext_entry(inode, p_dir, oldentry, | |
1118 | num_new_entries, p_uniname); | |
1119 | if (ret) | |
1120 | return ret; | |
1121 | ||
1122 | exfat_remove_entries(inode, p_dir, oldentry, num_new_entries, | |
1123 | num_old_entries); | |
1124 | } | |
1125 | return 0; | |
1126 | } | |
1127 | ||
1128 | static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir, | |
1129 | int oldentry, struct exfat_chain *p_newdir, | |
1130 | struct exfat_uni_name *p_uniname, struct exfat_inode_info *ei) | |
1131 | { | |
1132 | int ret, newentry, num_new_entries, num_old_entries; | |
1133 | sector_t sector_mov, sector_new; | |
1134 | struct exfat_dentry *epmov, *epnew; | |
1135 | struct super_block *sb = inode->i_sb; | |
1136 | struct buffer_head *mov_bh, *new_bh; | |
1137 | ||
1138 | epmov = exfat_get_dentry(sb, p_olddir, oldentry, &mov_bh, §or_mov); | |
1139 | if (!epmov) | |
1140 | return -EIO; | |
1141 | ||
1142 | /* check if the source and target directory is the same */ | |
1143 | if (exfat_get_entry_type(epmov) == TYPE_DIR && | |
1144 | le32_to_cpu(epmov->dentry.stream.start_clu) == p_newdir->dir) | |
1145 | return -EINVAL; | |
1146 | ||
1147 | num_old_entries = exfat_count_ext_entries(sb, p_olddir, oldentry, | |
1148 | epmov); | |
1149 | if (num_old_entries < 0) | |
1150 | return -EIO; | |
1151 | num_old_entries++; | |
1152 | ||
1153 | num_new_entries = exfat_calc_num_entries(p_uniname); | |
1154 | if (num_new_entries < 0) | |
1155 | return num_new_entries; | |
1156 | ||
1157 | newentry = exfat_find_empty_entry(inode, p_newdir, num_new_entries); | |
1158 | if (newentry < 0) | |
1159 | return newentry; /* -EIO or -ENOSPC */ | |
1160 | ||
1161 | epnew = exfat_get_dentry(sb, p_newdir, newentry, &new_bh, §or_new); | |
1162 | if (!epnew) | |
1163 | return -EIO; | |
1164 | ||
1165 | memcpy(epnew, epmov, DENTRY_SIZE); | |
1166 | if (exfat_get_entry_type(epnew) == TYPE_FILE) { | |
1167 | epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE); | |
1168 | ei->attr |= ATTR_ARCHIVE; | |
1169 | } | |
1170 | exfat_update_bh(sb, new_bh, IS_DIRSYNC(inode)); | |
1171 | brelse(mov_bh); | |
1172 | brelse(new_bh); | |
1173 | ||
1174 | epmov = exfat_get_dentry(sb, p_olddir, oldentry + 1, &mov_bh, | |
1175 | §or_mov); | |
1176 | epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh, | |
1177 | §or_new); | |
1178 | if (!epmov || !epnew) | |
1179 | return -EIO; | |
1180 | ||
1181 | memcpy(epnew, epmov, DENTRY_SIZE); | |
1182 | exfat_update_bh(sb, new_bh, IS_DIRSYNC(inode)); | |
1183 | brelse(mov_bh); | |
1184 | brelse(new_bh); | |
1185 | ||
1186 | ret = exfat_init_ext_entry(inode, p_newdir, newentry, num_new_entries, | |
1187 | p_uniname); | |
1188 | if (ret) | |
1189 | return ret; | |
1190 | ||
1191 | exfat_remove_entries(inode, p_olddir, oldentry, 0, num_old_entries); | |
1192 | ||
1193 | exfat_chain_set(&ei->dir, p_newdir->dir, p_newdir->size, | |
1194 | p_newdir->flags); | |
1195 | ||
1196 | ei->entry = newentry; | |
1197 | return 0; | |
1198 | } | |
1199 | ||
1200 | static void exfat_update_parent_info(struct exfat_inode_info *ei, | |
1201 | struct inode *parent_inode) | |
1202 | { | |
1203 | struct exfat_sb_info *sbi = EXFAT_SB(parent_inode->i_sb); | |
1204 | struct exfat_inode_info *parent_ei = EXFAT_I(parent_inode); | |
1205 | loff_t parent_isize = i_size_read(parent_inode); | |
1206 | ||
1207 | /* | |
1208 | * the problem that struct exfat_inode_info caches wrong parent info. | |
1209 | * | |
1210 | * because of flag-mismatch of ei->dir, | |
1211 | * there is abnormal traversing cluster chain. | |
1212 | */ | |
1213 | if (unlikely(parent_ei->flags != ei->dir.flags || | |
1214 | parent_isize != EXFAT_CLU_TO_B(ei->dir.size, sbi) || | |
1215 | parent_ei->start_clu != ei->dir.dir)) { | |
1216 | exfat_chain_set(&ei->dir, parent_ei->start_clu, | |
1217 | EXFAT_B_TO_CLU_ROUND_UP(parent_isize, sbi), | |
1218 | parent_ei->flags); | |
1219 | } | |
1220 | } | |
1221 | ||
1222 | /* rename or move a old file into a new file */ | |
1223 | static int __exfat_rename(struct inode *old_parent_inode, | |
1224 | struct exfat_inode_info *ei, struct inode *new_parent_inode, | |
1225 | struct dentry *new_dentry) | |
1226 | { | |
1227 | int ret; | |
1228 | int dentry; | |
1229 | struct exfat_chain olddir, newdir; | |
1230 | struct exfat_chain *p_dir = NULL; | |
1231 | struct exfat_uni_name uni_name; | |
1232 | struct exfat_dentry *ep; | |
1233 | struct super_block *sb = old_parent_inode->i_sb; | |
1234 | struct exfat_sb_info *sbi = EXFAT_SB(sb); | |
1235 | const unsigned char *new_path = new_dentry->d_name.name; | |
1236 | struct inode *new_inode = new_dentry->d_inode; | |
1237 | int num_entries; | |
1238 | struct exfat_inode_info *new_ei = NULL; | |
1239 | unsigned int new_entry_type = TYPE_UNUSED; | |
1240 | int new_entry = 0; | |
1241 | struct buffer_head *old_bh, *new_bh = NULL; | |
1242 | ||
1243 | /* check the validity of pointer parameters */ | |
1244 | if (new_path == NULL || strlen(new_path) == 0) | |
1245 | return -EINVAL; | |
1246 | ||
1247 | if (ei->dir.dir == DIR_DELETED) { | |
1248 | exfat_msg(sb, KERN_ERR, | |
1249 | "abnormal access to deleted source dentry"); | |
1250 | return -ENOENT; | |
1251 | } | |
1252 | ||
1253 | exfat_update_parent_info(ei, old_parent_inode); | |
1254 | ||
1255 | exfat_chain_dup(&olddir, &ei->dir); | |
1256 | dentry = ei->entry; | |
1257 | ||
1258 | ep = exfat_get_dentry(sb, &olddir, dentry, &old_bh, NULL); | |
1259 | if (!ep) { | |
1260 | ret = -EIO; | |
1261 | goto out; | |
1262 | } | |
1263 | brelse(old_bh); | |
1264 | ||
1265 | /* check whether new dir is existing directory and empty */ | |
1266 | if (new_inode) { | |
1267 | ret = -EIO; | |
1268 | new_ei = EXFAT_I(new_inode); | |
1269 | ||
1270 | if (new_ei->dir.dir == DIR_DELETED) { | |
1271 | exfat_msg(sb, KERN_ERR, | |
1272 | "abnormal access to deleted target dentry"); | |
1273 | goto out; | |
1274 | } | |
1275 | ||
1276 | exfat_update_parent_info(new_ei, new_parent_inode); | |
1277 | ||
1278 | p_dir = &(new_ei->dir); | |
1279 | new_entry = new_ei->entry; | |
1280 | ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL); | |
1281 | if (!ep) | |
1282 | goto out; | |
1283 | ||
1284 | new_entry_type = exfat_get_entry_type(ep); | |
1285 | brelse(new_bh); | |
1286 | ||
1287 | /* if new_inode exists, update ei */ | |
1288 | if (new_entry_type == TYPE_DIR) { | |
1289 | struct exfat_chain new_clu; | |
1290 | ||
1291 | new_clu.dir = new_ei->start_clu; | |
1292 | new_clu.size = | |
1293 | EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode), | |
1294 | sbi); | |
1295 | new_clu.flags = new_ei->flags; | |
1296 | ||
1297 | ret = exfat_check_dir_empty(sb, &new_clu); | |
1298 | if (ret) | |
1299 | goto out; | |
1300 | } | |
1301 | } | |
1302 | ||
1303 | /* check the validity of directory name in the given new pathname */ | |
1304 | ret = exfat_resolve_path(new_parent_inode, new_path, &newdir, | |
1305 | &uni_name); | |
1306 | if (ret) | |
1307 | goto out; | |
1308 | ||
1309 | exfat_set_vol_flags(sb, VOL_DIRTY); | |
1310 | ||
1311 | if (olddir.dir == newdir.dir) | |
1312 | ret = exfat_rename_file(new_parent_inode, &olddir, dentry, | |
1313 | &uni_name, ei); | |
1314 | else | |
1315 | ret = exfat_move_file(new_parent_inode, &olddir, dentry, | |
1316 | &newdir, &uni_name, ei); | |
1317 | ||
1318 | if (!ret && new_inode) { | |
1319 | /* delete entries of new_dir */ | |
1320 | ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh, NULL); | |
1321 | if (!ep) { | |
1322 | ret = -EIO; | |
1323 | goto del_out; | |
1324 | } | |
1325 | ||
1326 | num_entries = exfat_count_ext_entries(sb, p_dir, new_entry, ep); | |
1327 | if (num_entries < 0) { | |
1328 | ret = -EIO; | |
1329 | goto del_out; | |
1330 | } | |
1331 | brelse(new_bh); | |
1332 | ||
1333 | if (exfat_remove_entries(new_inode, p_dir, new_entry, 0, | |
1334 | num_entries + 1)) { | |
1335 | ret = -EIO; | |
1336 | goto del_out; | |
1337 | } | |
1338 | ||
1339 | /* Free the clusters if new_inode is a dir(as if exfat_rmdir) */ | |
1340 | if (new_entry_type == TYPE_DIR) { | |
1341 | /* new_ei, new_clu_to_free */ | |
1342 | struct exfat_chain new_clu_to_free; | |
1343 | ||
1344 | exfat_chain_set(&new_clu_to_free, new_ei->start_clu, | |
1345 | EXFAT_B_TO_CLU_ROUND_UP(i_size_read(new_inode), | |
1346 | sbi), new_ei->flags); | |
1347 | ||
1348 | if (exfat_free_cluster(new_inode, &new_clu_to_free)) { | |
1349 | /* just set I/O error only */ | |
1350 | ret = -EIO; | |
1351 | } | |
1352 | ||
1353 | i_size_write(new_inode, 0); | |
1354 | new_ei->start_clu = EXFAT_EOF_CLUSTER; | |
1355 | new_ei->flags = ALLOC_NO_FAT_CHAIN; | |
1356 | } | |
1357 | del_out: | |
1358 | /* Update new_inode ei | |
1359 | * Prevent syncing removed new_inode | |
1360 | * (new_ei is already initialized above code ("if (new_inode)") | |
1361 | */ | |
1362 | new_ei->dir.dir = DIR_DELETED; | |
1363 | } | |
1364 | exfat_set_vol_flags(sb, VOL_CLEAN); | |
1365 | out: | |
1366 | return ret; | |
1367 | } | |
1368 | ||
1369 | static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, | |
1370 | struct inode *new_dir, struct dentry *new_dentry, | |
1371 | unsigned int flags) | |
1372 | { | |
1373 | struct inode *old_inode, *new_inode; | |
1374 | struct super_block *sb = old_dir->i_sb; | |
1375 | loff_t i_pos; | |
1376 | int err; | |
1377 | ||
1378 | /* | |
1379 | * The VFS already checks for existence, so for local filesystems | |
1380 | * the RENAME_NOREPLACE implementation is equivalent to plain rename. | |
1381 | * Don't support any other flags | |
1382 | */ | |
1383 | if (flags & ~RENAME_NOREPLACE) | |
1384 | return -EINVAL; | |
1385 | ||
1386 | mutex_lock(&EXFAT_SB(sb)->s_lock); | |
1387 | old_inode = old_dentry->d_inode; | |
1388 | new_inode = new_dentry->d_inode; | |
1389 | ||
1390 | err = __exfat_rename(old_dir, EXFAT_I(old_inode), new_dir, new_dentry); | |
1391 | if (err) | |
1392 | goto unlock; | |
1393 | ||
1394 | inode_inc_iversion(new_dir); | |
1395 | new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = | |
1396 | EXFAT_I(new_dir)->i_crtime = current_time(new_dir); | |
81df1ad4 | 1397 | exfat_truncate_atime(&new_dir->i_atime); |
5f2aa075 NJ |
1398 | if (IS_DIRSYNC(new_dir)) |
1399 | exfat_sync_inode(new_dir); | |
1400 | else | |
1401 | mark_inode_dirty(new_dir); | |
1402 | ||
1403 | i_pos = ((loff_t)EXFAT_I(old_inode)->dir.dir << 32) | | |
1404 | (EXFAT_I(old_inode)->entry & 0xffffffff); | |
1405 | exfat_unhash_inode(old_inode); | |
1406 | exfat_hash_inode(old_inode, i_pos); | |
1407 | if (IS_DIRSYNC(new_dir)) | |
1408 | exfat_sync_inode(old_inode); | |
1409 | else | |
1410 | mark_inode_dirty(old_inode); | |
1411 | ||
1412 | if (S_ISDIR(old_inode->i_mode) && old_dir != new_dir) { | |
1413 | drop_nlink(old_dir); | |
1414 | if (!new_inode) | |
1415 | inc_nlink(new_dir); | |
1416 | } | |
1417 | ||
1418 | inode_inc_iversion(old_dir); | |
1419 | old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); | |
1420 | if (IS_DIRSYNC(old_dir)) | |
1421 | exfat_sync_inode(old_dir); | |
1422 | else | |
1423 | mark_inode_dirty(old_dir); | |
1424 | ||
1425 | if (new_inode) { | |
1426 | exfat_unhash_inode(new_inode); | |
1427 | ||
1428 | /* skip drop_nlink if new_inode already has been dropped */ | |
1429 | if (new_inode->i_nlink) { | |
1430 | drop_nlink(new_inode); | |
1431 | if (S_ISDIR(new_inode->i_mode)) | |
1432 | drop_nlink(new_inode); | |
1433 | } else { | |
1434 | exfat_msg(sb, KERN_WARNING, | |
1435 | "abnormal access to an inode dropped"); | |
1436 | WARN_ON(new_inode->i_nlink == 0); | |
1437 | } | |
1438 | new_inode->i_ctime = EXFAT_I(new_inode)->i_crtime = | |
1439 | current_time(new_inode); | |
1440 | } | |
1441 | ||
1442 | unlock: | |
1443 | mutex_unlock(&EXFAT_SB(sb)->s_lock); | |
1444 | return err; | |
1445 | } | |
1446 | ||
1447 | const struct inode_operations exfat_dir_inode_operations = { | |
1448 | .create = exfat_create, | |
1449 | .lookup = exfat_lookup, | |
1450 | .unlink = exfat_unlink, | |
1451 | .mkdir = exfat_mkdir, | |
1452 | .rmdir = exfat_rmdir, | |
1453 | .rename = exfat_rename, | |
1454 | .setattr = exfat_setattr, | |
1455 | .getattr = exfat_getattr, | |
1456 | }; |