Blame view
fs/ubifs/dir.c
42.1 KB
2b27bdcc2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
1e51764a3 UBIFS: add new fl... |
2 3 4 5 6 |
/* * This file is part of UBIFS. * * Copyright (C) 2006-2008 Nokia Corporation. * Copyright (C) 2006, 2007 University of Szeged, Hungary * |
1e51764a3 UBIFS: add new fl... |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
* Authors: Artem Bityutskiy (Битюцкий Артём) * Adrian Hunter * Zoltan Sogor */ /* * This file implements directory operations. * * All FS operations in this file allocate budget before writing anything to the * media. If they fail to allocate it, the error is returned. The only * exceptions are 'ubifs_unlink()' and 'ubifs_rmdir()' which keep working even * if they unable to allocate the budget, because deletion %-ENOSPC failure is * not what users are usually ready to get. UBIFS budgeting subsystem has some * space reserved for these purposes. * * All operations in this file write all inodes which they change straight * away, instead of marking them dirty. For example, 'ubifs_link()' changes * @i_size of the parent inode and writes the parent inode together with the * target inode. This was done to simplify file-system recovery which would * otherwise be very difficult to do. The only exception is rename which marks * the re-named inode dirty (because its @i_ctime is updated) but does not * write it, but just marks it as dirty. */ #include "ubifs.h" /** * inherit_flags - inherit flags of the parent inode. * @dir: parent inode * @mode: new inode mode flags * * This is a helper function for 'ubifs_new_inode()' which inherits flag of the * parent directory inode @dir. UBIFS inodes inherit the following flags: * o %UBIFS_COMPR_FL, which is useful to switch compression on/of on * sub-directory basis; * o %UBIFS_SYNC_FL - useful for the same reasons; * o %UBIFS_DIRSYNC_FL - similar, but relevant only to directories. * * This function returns the inherited flags. */ |
ad44be5c7 ubifs: propagate ... |
47 |
static int inherit_flags(const struct inode *dir, umode_t mode) |
1e51764a3 UBIFS: add new fl... |
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
{ int flags; const struct ubifs_inode *ui = ubifs_inode(dir); if (!S_ISDIR(dir->i_mode)) /* * The parent is not a directory, which means that an extended * attribute inode is being created. No flags. */ return 0; flags = ui->flags & (UBIFS_COMPR_FL | UBIFS_SYNC_FL | UBIFS_DIRSYNC_FL); if (!S_ISDIR(mode)) /* The "DIRSYNC" flag only applies to directories */ flags &= ~UBIFS_DIRSYNC_FL; return flags; } /** * ubifs_new_inode - allocate new UBIFS inode object. * @c: UBIFS file-system description object * @dir: parent directory inode * @mode: inode mode flags * * This function finds an unused inode number, allocates new inode and * initializes it. Returns new inode in case of success and an error code in * case of failure. */ |
d475a5074 ubifs: Add skelet... |
76 |
struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir, |
ad44be5c7 ubifs: propagate ... |
77 |
umode_t mode) |
1e51764a3 UBIFS: add new fl... |
78 |
{ |
d475a5074 ubifs: Add skelet... |
79 |
int err; |
1e51764a3 UBIFS: add new fl... |
80 81 |
struct inode *inode; struct ubifs_inode *ui; |
d475a5074 ubifs: Add skelet... |
82 |
bool encrypted = false; |
1e51764a3 UBIFS: add new fl... |
83 84 85 86 87 88 89 90 91 92 93 |
inode = new_inode(c->vfs_sb); ui = ubifs_inode(inode); if (!inode) return ERR_PTR(-ENOMEM); /* * Set 'S_NOCMTIME' to prevent VFS form updating [mc]time of inodes and * marking them dirty in file write path (see 'file_update_time()'). * UBIFS has to fully control "clean <-> dirty" transitions of inodes * to make budgeting work. */ |
12e776a08 UBIFS: remove unn... |
94 |
inode->i_flags |= S_NOCMTIME; |
1e51764a3 UBIFS: add new fl... |
95 |
|
abf5d08ac ubifs: replace in... |
96 |
inode_init_owner(inode, dir, mode); |
1e51764a3 UBIFS: add new fl... |
97 |
inode->i_mtime = inode->i_atime = inode->i_ctime = |
607a11ad9 fs: ubifs: replac... |
98 |
current_time(inode); |
1e51764a3 UBIFS: add new fl... |
99 |
inode->i_mapping->nrpages = 0; |
1e51764a3 UBIFS: add new fl... |
100 |
|
4c030fa88 ubifs: use fscryp... |
101 102 103 104 105 |
err = fscrypt_prepare_new_inode(dir, inode, &encrypted); if (err) { ubifs_err(c, "fscrypt_prepare_new_inode failed: %i", err); goto out_iput; } |
1e51764a3 UBIFS: add new fl... |
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
switch (mode & S_IFMT) { case S_IFREG: inode->i_mapping->a_ops = &ubifs_file_address_operations; inode->i_op = &ubifs_file_inode_operations; inode->i_fop = &ubifs_file_operations; break; case S_IFDIR: inode->i_op = &ubifs_dir_inode_operations; inode->i_fop = &ubifs_dir_operations; inode->i_size = ui->ui_size = UBIFS_INO_NODE_SZ; break; case S_IFLNK: inode->i_op = &ubifs_symlink_inode_operations; break; case S_IFSOCK: case S_IFIFO: case S_IFBLK: case S_IFCHR: inode->i_op = &ubifs_file_inode_operations; break; default: BUG(); } ui->flags = inherit_flags(dir, mode); ubifs_set_inode_flags(inode); if (S_ISREG(mode)) ui->compr_type = c->default_compr; else ui->compr_type = UBIFS_COMPR_NONE; ui->synced_i_size = 0; spin_lock(&c->cnt_lock); /* Inode number overflow is currently not supported */ if (c->highest_inum >= INUM_WARN_WATERMARK) { if (c->highest_inum >= INUM_WATERMARK) { spin_unlock(&c->cnt_lock); |
235c362bd UBIFS: extend deb... |
143 |
ubifs_err(c, "out of inode numbers"); |
4c030fa88 ubifs: use fscryp... |
144 145 |
err = -EINVAL; goto out_iput; |
1e51764a3 UBIFS: add new fl... |
146 |
} |
1a7e985dd UBIFS: fix output... |
147 |
ubifs_warn(c, "running out of inode numbers (current %lu, max %u)", |
e84461ad9 UBIFS: fix compil... |
148 |
(unsigned long)c->highest_inum, INUM_WATERMARK); |
1e51764a3 UBIFS: add new fl... |
149 150 151 |
} inode->i_ino = ++c->highest_inum; |
1e51764a3 UBIFS: add new fl... |
152 153 154 155 156 157 158 159 160 |
/* * The creation sequence number remains with this inode for its * lifetime. All nodes for this inode have a greater sequence number, * and so it is possible to distinguish obsolete nodes belonging to a * previous incarnation of the same inode number - for example, for the * purpose of rebuilding the index. */ ui->creat_sqnum = ++c->max_sqnum; spin_unlock(&c->cnt_lock); |
d475a5074 ubifs: Add skelet... |
161 162 |
if (encrypted) { |
4c030fa88 ubifs: use fscryp... |
163 |
err = fscrypt_set_context(inode, NULL); |
d475a5074 ubifs: Add skelet... |
164 |
if (err) { |
4c030fa88 ubifs: use fscryp... |
165 166 |
ubifs_err(c, "fscrypt_set_context failed: %i", err); goto out_iput; |
d475a5074 ubifs: Add skelet... |
167 168 |
} } |
1e51764a3 UBIFS: add new fl... |
169 |
return inode; |
4c030fa88 ubifs: use fscryp... |
170 171 172 173 174 |
out_iput: make_bad_inode(inode); iput(inode); return ERR_PTR(err); |
1e51764a3 UBIFS: add new fl... |
175 |
} |
bb2615d4d UBIFS: amend debu... |
176 177 |
static int dbg_check_name(const struct ubifs_info *c, const struct ubifs_dent_node *dent, |
f4f61d2cc ubifs: Implement ... |
178 |
const struct fscrypt_name *nm) |
1e51764a3 UBIFS: add new fl... |
179 |
{ |
2b1844a8c UBIFS: introduce ... |
180 |
if (!dbg_is_chk_gen(c)) |
1e51764a3 UBIFS: add new fl... |
181 |
return 0; |
f4f61d2cc ubifs: Implement ... |
182 |
if (le16_to_cpu(dent->nlen) != fname_len(nm)) |
1e51764a3 UBIFS: add new fl... |
183 |
return -EINVAL; |
f4f61d2cc ubifs: Implement ... |
184 |
if (memcmp(dent->name, fname_name(nm), fname_len(nm))) |
1e51764a3 UBIFS: add new fl... |
185 186 187 |
return -EINVAL; return 0; } |
1e51764a3 UBIFS: add new fl... |
188 |
static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, |
00cd8dd3b stop passing name... |
189 |
unsigned int flags) |
1e51764a3 UBIFS: add new fl... |
190 191 192 193 |
{ int err; union ubifs_key key; struct inode *inode = NULL; |
191ac107f ubifs_lookup: use... |
194 |
struct ubifs_dent_node *dent = NULL; |
1e51764a3 UBIFS: add new fl... |
195 |
struct ubifs_info *c = dir->i_sb->s_fs_info; |
f4f61d2cc ubifs: Implement ... |
196 |
struct fscrypt_name nm; |
1e51764a3 UBIFS: add new fl... |
197 |
|
4cb2a01d8 ubifs: switch to %pd |
198 |
dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino); |
1e51764a3 UBIFS: add new fl... |
199 |
|
b01531db6 fscrypt: fix race... |
200 201 202 |
err = fscrypt_prepare_lookup(dir, dentry, &nm); if (err == -ENOENT) return d_splice_alias(NULL, dentry); |
f4f61d2cc ubifs: Implement ... |
203 204 205 206 |
if (err) return ERR_PTR(err); if (fname_len(&nm) > UBIFS_MAX_NLEN) { |
191ac107f ubifs_lookup: use... |
207 208 |
inode = ERR_PTR(-ENAMETOOLONG); goto done; |
f4f61d2cc ubifs: Implement ... |
209 |
} |
1e51764a3 UBIFS: add new fl... |
210 211 |
dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS); |
f4f61d2cc ubifs: Implement ... |
212 |
if (!dent) { |
191ac107f ubifs_lookup: use... |
213 214 |
inode = ERR_PTR(-ENOMEM); goto done; |
f4f61d2cc ubifs: Implement ... |
215 |
} |
1e51764a3 UBIFS: add new fl... |
216 |
|
aec992aab ubifs: allow both... |
217 |
if (fname_name(&nm) == NULL) { |
f0d07a98a ubifs: don't trig... |
218 219 |
if (nm.hash & ~UBIFS_S_KEY_HASH_MASK) goto done; /* ENOENT */ |
f4f61d2cc ubifs: Implement ... |
220 |
dent_key_init_hash(c, &key, dir->i_ino, nm.hash); |
528e3d178 ubifs: Add full h... |
221 |
err = ubifs_tnc_lookup_dh(c, &key, dent, nm.minor_hash); |
f4f61d2cc ubifs: Implement ... |
222 223 224 225 |
} else { dent_key_init(c, &key, dir->i_ino, &nm); err = ubifs_tnc_lookup_nm(c, &key, dent, &nm); } |
1e51764a3 UBIFS: add new fl... |
226 |
|
1e51764a3 UBIFS: add new fl... |
227 |
if (err) { |
191ac107f ubifs_lookup: use... |
228 |
if (err == -ENOENT) |
1e51764a3 UBIFS: add new fl... |
229 |
dbg_gen("not found"); |
191ac107f ubifs_lookup: use... |
230 231 232 |
else inode = ERR_PTR(err); goto done; |
1e51764a3 UBIFS: add new fl... |
233 |
} |
f4f61d2cc ubifs: Implement ... |
234 |
if (dbg_check_name(c, dent, &nm)) { |
191ac107f ubifs_lookup: use... |
235 236 |
inode = ERR_PTR(-EINVAL); goto done; |
1e51764a3 UBIFS: add new fl... |
237 238 239 240 241 242 243 244 245 |
} inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum)); if (IS_ERR(inode)) { /* * This should not happen. Probably the file-system needs * checking. */ err = PTR_ERR(inode); |
235c362bd UBIFS: extend deb... |
246 |
ubifs_err(c, "dead directory entry '%pd', error %d", |
4cb2a01d8 ubifs: switch to %pd |
247 |
dentry, err); |
1e51764a3 UBIFS: add new fl... |
248 |
ubifs_ro_mode(c, err); |
191ac107f ubifs_lookup: use... |
249 |
goto done; |
1e51764a3 UBIFS: add new fl... |
250 |
} |
50d9fad73 ubifs: use IS_ENC... |
251 |
if (IS_ENCRYPTED(dir) && |
413d5a9ed ubifs: check for ... |
252 253 254 255 |
(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) && !fscrypt_has_permitted_context(dir, inode)) { ubifs_warn(c, "Inconsistent encryption contexts: %lu/%lu", dir->i_ino, inode->i_ino); |
191ac107f ubifs_lookup: use... |
256 257 |
iput(inode); inode = ERR_PTR(-EPERM); |
413d5a9ed ubifs: check for ... |
258 |
} |
1e51764a3 UBIFS: add new fl... |
259 260 |
done: kfree(dent); |
f4f61d2cc ubifs: Implement ... |
261 |
fscrypt_free_filename(&nm); |
191ac107f ubifs_lookup: use... |
262 |
return d_splice_alias(inode, dentry); |
1e51764a3 UBIFS: add new fl... |
263 |
} |
456fcfca6 ubifs: prevent cr... |
264 265 266 267 268 269 270 271 |
static int ubifs_prepare_create(struct inode *dir, struct dentry *dentry, struct fscrypt_name *nm) { if (fscrypt_is_nokey_name(dentry)) return -ENOKEY; return fscrypt_setup_filename(dir, &dentry->d_name, 0, nm); } |
4acdaf27e switch ->create()... |
272 |
static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
ebfc3b49a don't pass nameid... |
273 |
bool excl) |
1e51764a3 UBIFS: add new fl... |
274 275 276 |
{ struct inode *inode; struct ubifs_info *c = dir->i_sb->s_fs_info; |
1e51764a3 UBIFS: add new fl... |
277 278 279 |
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, .dirtied_ino = 1 }; struct ubifs_inode *dir_ui = ubifs_inode(dir); |
f4f61d2cc ubifs: Implement ... |
280 281 |
struct fscrypt_name nm; int err, sz_change; |
1e51764a3 UBIFS: add new fl... |
282 283 284 285 286 |
/* * Budget request settings: new inode, new direntry, changing the * parent directory inode. */ |
4cb2a01d8 ubifs: switch to %pd |
287 288 |
dbg_gen("dent '%pd', mode %#hx in dir ino %lu", dentry, mode, dir->i_ino); |
1e51764a3 UBIFS: add new fl... |
289 290 291 292 |
err = ubifs_budget_space(c, &req); if (err) return err; |
456fcfca6 ubifs: prevent cr... |
293 |
err = ubifs_prepare_create(dir, dentry, &nm); |
f4f61d2cc ubifs: Implement ... |
294 295 296 297 |
if (err) goto out_budg; sz_change = CALC_DENT_SIZE(fname_len(&nm)); |
1e51764a3 UBIFS: add new fl... |
298 299 300 |
inode = ubifs_new_inode(c, dir, mode); if (IS_ERR(inode)) { err = PTR_ERR(inode); |
f4f61d2cc ubifs: Implement ... |
301 |
goto out_fname; |
1e51764a3 UBIFS: add new fl... |
302 |
} |
d7f0b70d3 UBIFS: Add securi... |
303 304 |
err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) |
9401a795c UBIFS: fix incorr... |
305 |
goto out_inode; |
d7f0b70d3 UBIFS: Add securi... |
306 |
|
1e51764a3 UBIFS: add new fl... |
307 308 309 310 |
mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; |
f4f61d2cc ubifs: Implement ... |
311 |
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); |
1e51764a3 UBIFS: add new fl... |
312 313 314 315 316 |
if (err) goto out_cancel; mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); |
f4f61d2cc ubifs: Implement ... |
317 |
fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
318 319 320 321 322 323 324 325 |
insert_inode_hash(inode); d_instantiate(dentry, inode); return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); |
9401a795c UBIFS: fix incorr... |
326 |
out_inode: |
1e51764a3 UBIFS: add new fl... |
327 328 |
make_bad_inode(inode); iput(inode); |
f4f61d2cc ubifs: Implement ... |
329 330 |
out_fname: fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
331 332 |
out_budg: ubifs_release_budget(c, &req); |
235c362bd UBIFS: extend deb... |
333 |
ubifs_err(c, "cannot create regular file, error %d", err); |
1e51764a3 UBIFS: add new fl... |
334 335 |
return err; } |
9e0a1fff8 ubifs: Implement ... |
336 337 |
static int do_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode, struct inode **whiteout) |
474b93704 ubifs: Implement ... |
338 339 340 341 342 343 344 |
{ struct inode *inode; struct ubifs_info *c = dir->i_sb->s_fs_info; struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1}; struct ubifs_budget_req ino_req = { .dirtied_ino = 1 }; struct ubifs_inode *ui, *dir_ui = ubifs_inode(dir); int err, instantiated = 0; |
f4f61d2cc ubifs: Implement ... |
345 |
struct fscrypt_name nm; |
474b93704 ubifs: Implement ... |
346 347 348 349 350 351 352 353 |
/* * Budget request settings: new dirty inode, new direntry, * budget for dirtied inode will be released via writeback. */ dbg_gen("dent '%pd', mode %#hx in dir ino %lu", dentry, mode, dir->i_ino); |
f4f61d2cc ubifs: Implement ... |
354 |
err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm); |
474b93704 ubifs: Implement ... |
355 356 |
if (err) return err; |
f4f61d2cc ubifs: Implement ... |
357 358 359 360 361 |
err = ubifs_budget_space(c, &req); if (err) { fscrypt_free_filename(&nm); return err; } |
474b93704 ubifs: Implement ... |
362 363 364 |
err = ubifs_budget_space(c, &ino_req); if (err) { ubifs_release_budget(c, &req); |
f4f61d2cc ubifs: Implement ... |
365 |
fscrypt_free_filename(&nm); |
474b93704 ubifs: Implement ... |
366 367 368 369 370 371 372 373 374 |
return err; } inode = ubifs_new_inode(c, dir, mode); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out_budg; } ui = ubifs_inode(inode); |
9e0a1fff8 ubifs: Implement ... |
375 376 |
if (whiteout) { init_special_inode(inode, inode->i_mode, WHITEOUT_DEV); |
6eb61d587 ubifs: Pass struc... |
377 |
ubifs_assert(c, inode->i_op == &ubifs_file_inode_operations); |
9e0a1fff8 ubifs: Implement ... |
378 |
} |
474b93704 ubifs: Implement ... |
379 380 381 382 383 384 |
err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) goto out_inode; mutex_lock(&ui->ui_mutex); insert_inode_hash(inode); |
9e0a1fff8 ubifs: Implement ... |
385 386 387 388 389 390 391 392 |
if (whiteout) { mark_inode_dirty(inode); drop_nlink(inode); *whiteout = inode; } else { d_tmpfile(dentry, inode); } |
6eb61d587 ubifs: Pass struc... |
393 |
ubifs_assert(c, ui->dirty); |
9e0a1fff8 ubifs: Implement ... |
394 |
|
474b93704 ubifs: Implement ... |
395 396 397 398 |
instantiated = 1; mutex_unlock(&ui->ui_mutex); mutex_lock(&dir_ui->ui_mutex); |
f4f61d2cc ubifs: Implement ... |
399 |
err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0); |
474b93704 ubifs: Implement ... |
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
if (err) goto out_cancel; mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); return 0; out_cancel: mutex_unlock(&dir_ui->ui_mutex); out_inode: make_bad_inode(inode); if (!instantiated) iput(inode); out_budg: ubifs_release_budget(c, &req); if (!instantiated) ubifs_release_budget(c, &ino_req); |
f4f61d2cc ubifs: Implement ... |
418 |
fscrypt_free_filename(&nm); |
474b93704 ubifs: Implement ... |
419 420 421 |
ubifs_err(c, "cannot create temporary file, error %d", err); return err; } |
9e0a1fff8 ubifs: Implement ... |
422 423 424 425 426 |
static int ubifs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) { return do_tmpfile(dir, dentry, mode, NULL); } |
1e51764a3 UBIFS: add new fl... |
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 463 464 465 466 467 468 469 470 471 472 473 |
/** * vfs_dent_type - get VFS directory entry type. * @type: UBIFS directory entry type * * This function converts UBIFS directory entry type into VFS directory entry * type. */ static unsigned int vfs_dent_type(uint8_t type) { switch (type) { case UBIFS_ITYPE_REG: return DT_REG; case UBIFS_ITYPE_DIR: return DT_DIR; case UBIFS_ITYPE_LNK: return DT_LNK; case UBIFS_ITYPE_BLK: return DT_BLK; case UBIFS_ITYPE_CHR: return DT_CHR; case UBIFS_ITYPE_FIFO: return DT_FIFO; case UBIFS_ITYPE_SOCK: return DT_SOCK; default: BUG(); } return 0; } /* * The classical Unix view for directory is that it is a linear array of * (name, inode number) entries. Linux/VFS assumes this model as well. * Particularly, 'readdir()' call wants us to return a directory entry offset * which later may be used to continue 'readdir()'ing the directory or to * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this * model because directory entries are identified by keys, which may collide. * * UBIFS uses directory entry hash value for directory offsets, so * 'seekdir()'/'telldir()' may not always work because of possible key * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work * properly by means of saving full directory entry name in the private field * of the file description object. * * This means that UBIFS cannot support NFS which requires full * 'seekdir()'/'telldir()' support. */ |
01122e068 [readdir] convert... |
474 |
static int ubifs_readdir(struct file *file, struct dir_context *ctx) |
1e51764a3 UBIFS: add new fl... |
475 |
{ |
ba75d570b ubifs: Initialize... |
476 |
int fstr_real_len = 0, err = 0; |
f4f61d2cc ubifs: Implement ... |
477 478 |
struct fscrypt_name nm; struct fscrypt_str fstr = {0}; |
1e51764a3 UBIFS: add new fl... |
479 480 |
union ubifs_key key; struct ubifs_dent_node *dent; |
496ad9aa8 new helper: file_... |
481 |
struct inode *dir = file_inode(file); |
1e51764a3 UBIFS: add new fl... |
482 |
struct ubifs_info *c = dir->i_sb->s_fs_info; |
50d9fad73 ubifs: use IS_ENC... |
483 |
bool encrypted = IS_ENCRYPTED(dir); |
1e51764a3 UBIFS: add new fl... |
484 |
|
01122e068 [readdir] convert... |
485 |
dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos); |
1e51764a3 UBIFS: add new fl... |
486 |
|
01122e068 [readdir] convert... |
487 |
if (ctx->pos > UBIFS_S_KEY_HASH_MASK || ctx->pos == 2) |
1e51764a3 UBIFS: add new fl... |
488 489 490 491 492 |
/* * The directory was seek'ed to a senseless position or there * are no more entries. */ return 0; |
f4f61d2cc ubifs: Implement ... |
493 494 |
if (encrypted) { err = fscrypt_get_encryption_info(dir); |
3b1ada55b fscrypt: don't ch... |
495 |
if (err) |
f4f61d2cc ubifs: Implement ... |
496 |
return err; |
8b10fe689 fscrypt: drop unu... |
497 |
err = fscrypt_fname_alloc_buffer(UBIFS_MAX_NLEN, &fstr); |
f4f61d2cc ubifs: Implement ... |
498 499 500 501 502 |
if (err) return err; fstr_real_len = fstr.len; } |
605c912bb UBIFS: fix a horr... |
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 |
if (file->f_version == 0) { /* * The file was seek'ed, which means that @file->private_data * is now invalid. This may also be just the first * 'ubifs_readdir()' invocation, in which case * @file->private_data is NULL, and the below code is * basically a no-op. */ kfree(file->private_data); file->private_data = NULL; } /* * 'generic_file_llseek()' unconditionally sets @file->f_version to * zero, and we use this for detecting whether the file was seek'ed. */ file->f_version = 1; |
1e51764a3 UBIFS: add new fl... |
520 |
/* File positions 0 and 1 correspond to "." and ".." */ |
01122e068 [readdir] convert... |
521 |
if (ctx->pos < 2) { |
6eb61d587 ubifs: Pass struc... |
522 |
ubifs_assert(c, !file->private_data); |
f4f61d2cc ubifs: Implement ... |
523 524 525 |
if (!dir_emit_dots(file, ctx)) { if (encrypted) fscrypt_fname_free_buffer(&fstr); |
1e51764a3 UBIFS: add new fl... |
526 |
return 0; |
f4f61d2cc ubifs: Implement ... |
527 |
} |
1e51764a3 UBIFS: add new fl... |
528 529 530 |
/* Find the first entry in TNC and save it */ lowest_dent_key(c, &key, dir->i_ino); |
f4f61d2cc ubifs: Implement ... |
531 |
fname_len(&nm) = 0; |
1e51764a3 UBIFS: add new fl... |
532 533 534 535 536 |
dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } |
01122e068 [readdir] convert... |
537 |
ctx->pos = key_hash_flash(c, &dent->key); |
1e51764a3 UBIFS: add new fl... |
538 539 540 541 542 543 544 |
file->private_data = dent; } dent = file->private_data; if (!dent) { /* * The directory was seek'ed to and is now readdir'ed. |
01122e068 [readdir] convert... |
545 |
* Find the entry corresponding to @ctx->pos or the closest one. |
1e51764a3 UBIFS: add new fl... |
546 |
*/ |
01122e068 [readdir] convert... |
547 |
dent_key_init_hash(c, &key, dir->i_ino, ctx->pos); |
f4f61d2cc ubifs: Implement ... |
548 |
fname_len(&nm) = 0; |
1e51764a3 UBIFS: add new fl... |
549 550 551 552 553 |
dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } |
01122e068 [readdir] convert... |
554 |
ctx->pos = key_hash_flash(c, &dent->key); |
1e51764a3 UBIFS: add new fl... |
555 556 557 558 |
file->private_data = dent; } while (1) { |
b20e2d999 ubifs: Remove fil... |
559 560 |
dbg_gen("ino %llu, new f_pos %#x", (unsigned long long)le64_to_cpu(dent->inum), |
1e51764a3 UBIFS: add new fl... |
561 |
key_hash_flash(c, &dent->key)); |
6eb61d587 ubifs: Pass struc... |
562 |
ubifs_assert(c, le64_to_cpu(dent->ch.sqnum) > |
0ecb9529a UBIFS: endian han... |
563 |
ubifs_inode(dir)->creat_sqnum); |
1e51764a3 UBIFS: add new fl... |
564 |
|
f4f61d2cc ubifs: Implement ... |
565 566 567 568 569 |
fname_len(&nm) = le16_to_cpu(dent->nlen); fname_name(&nm) = dent->name; if (encrypted) { fstr.len = fstr_real_len; |
528e3d178 ubifs: Add full h... |
570 571 572 573 |
err = fscrypt_fname_disk_to_usr(dir, key_hash_flash(c, &dent->key), le32_to_cpu(dent->cookie), &nm.disk_name, &fstr); |
ca7f85be8 ubifs: Add suppor... |
574 |
if (err) |
f4f61d2cc ubifs: Implement ... |
575 576 577 578 579 580 581 |
goto out; } else { fstr.len = fname_len(&nm); fstr.name = fname_name(&nm); } if (!dir_emit(ctx, fstr.name, fstr.len, |
1e51764a3 UBIFS: add new fl... |
582 |
le64_to_cpu(dent->inum), |
f4f61d2cc ubifs: Implement ... |
583 584 585 |
vfs_dent_type(dent->type))) { if (encrypted) fscrypt_fname_free_buffer(&fstr); |
1e51764a3 UBIFS: add new fl... |
586 |
return 0; |
f4f61d2cc ubifs: Implement ... |
587 |
} |
1e51764a3 UBIFS: add new fl... |
588 589 590 |
/* Switch to the next entry */ key_read(c, &dent->key, &key); |
1e51764a3 UBIFS: add new fl... |
591 592 593 594 595 596 597 |
dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } kfree(file->private_data); |
01122e068 [readdir] convert... |
598 |
ctx->pos = key_hash_flash(c, &dent->key); |
1e51764a3 UBIFS: add new fl... |
599 600 601 602 603 |
file->private_data = dent; cond_resched(); } out: |
aeeb14f76 UBIFS: Fix possib... |
604 605 |
kfree(file->private_data); file->private_data = NULL; |
f4f61d2cc ubifs: Implement ... |
606 607 |
if (encrypted) fscrypt_fname_free_buffer(&fstr); |
c83ed4c9d ubifs: Abort read... |
608 |
if (err != -ENOENT) |
235c362bd UBIFS: extend deb... |
609 |
ubifs_err(c, "cannot find next direntry, error %d", err); |
a00052a29 ubifs: Fix regres... |
610 611 612 613 614 615 616 |
else /* * -ENOENT is a non-fatal error in this context, the TNC uses * it to indicate that the cursor moved past the current directory * and readdir() has to stop. */ err = 0; |
1e51764a3 UBIFS: add new fl... |
617 |
|
605c912bb UBIFS: fix a horr... |
618 |
/* 2 is a special value indicating that there are no more direntries */ |
01122e068 [readdir] convert... |
619 |
ctx->pos = 2; |
c83ed4c9d ubifs: Abort read... |
620 |
return err; |
1e51764a3 UBIFS: add new fl... |
621 |
} |
1e51764a3 UBIFS: add new fl... |
622 623 624 625 626 627 628 629 630 |
/* Free saved readdir() state when the directory is closed */ static int ubifs_dir_release(struct inode *dir, struct file *file) { kfree(file->private_data); file->private_data = NULL; return 0; } /** |
82c1593ca UBIFS: simplify l... |
631 |
* lock_2_inodes - a wrapper for locking two UBIFS inodes. |
1e51764a3 UBIFS: add new fl... |
632 633 |
* @inode1: first inode * @inode2: second inode |
82c1593ca UBIFS: simplify l... |
634 635 636 637 |
* * We do not implement any tricks to guarantee strict lock ordering, because * VFS has already done it for us on the @i_mutex. So this is just a simple * wrapper function. |
1e51764a3 UBIFS: add new fl... |
638 639 640 |
*/ static void lock_2_inodes(struct inode *inode1, struct inode *inode2) { |
82c1593ca UBIFS: simplify l... |
641 642 |
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); |
1e51764a3 UBIFS: add new fl... |
643 644 645 |
} /** |
82c1593ca UBIFS: simplify l... |
646 |
* unlock_2_inodes - a wrapper for unlocking two UBIFS inodes. |
1e51764a3 UBIFS: add new fl... |
647 648 649 650 651 |
* @inode1: first inode * @inode2: second inode */ static void unlock_2_inodes(struct inode *inode1, struct inode *inode2) { |
1e51764a3 UBIFS: add new fl... |
652 |
mutex_unlock(&ubifs_inode(inode2)->ui_mutex); |
82c1593ca UBIFS: simplify l... |
653 |
mutex_unlock(&ubifs_inode(inode1)->ui_mutex); |
1e51764a3 UBIFS: add new fl... |
654 655 656 657 658 659 |
} static int ubifs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct ubifs_info *c = dir->i_sb->s_fs_info; |
2b0143b5c VFS: normal files... |
660 |
struct inode *inode = d_inode(old_dentry); |
1e51764a3 UBIFS: add new fl... |
661 662 663 664 |
struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_inode *dir_ui = ubifs_inode(dir); int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2, |
dab4b4d2f UBIFS: align inod... |
665 |
.dirtied_ino_d = ALIGN(ui->data_len, 8) }; |
f4f61d2cc ubifs: Implement ... |
666 |
struct fscrypt_name nm; |
1e51764a3 UBIFS: add new fl... |
667 668 669 670 671 |
/* * Budget request settings: new direntry, changing the target inode, * changing the parent inode. */ |
4cb2a01d8 ubifs: switch to %pd |
672 673 |
dbg_gen("dent '%pd' to ino %lu (nlink %d) in dir ino %lu", dentry, inode->i_ino, |
1e51764a3 UBIFS: add new fl... |
674 |
inode->i_nlink, dir->i_ino); |
6eb61d587 ubifs: Pass struc... |
675 676 |
ubifs_assert(c, inode_is_locked(dir)); ubifs_assert(c, inode_is_locked(inode)); |
8b3884a84 UBIFS: return err... |
677 |
|
5653878c8 ubifs: switch to ... |
678 679 680 |
err = fscrypt_prepare_link(old_dentry, dir, dentry); if (err) return err; |
f4f61d2cc ubifs: Implement ... |
681 682 |
err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm); |
1e51764a3 UBIFS: add new fl... |
683 684 |
if (err) return err; |
f4f61d2cc ubifs: Implement ... |
685 686 687 |
err = dbg_check_synced_i_size(c, inode); if (err) goto out_fname; |
1e51764a3 UBIFS: add new fl... |
688 689 |
err = ubifs_budget_space(c, &req); if (err) |
f4f61d2cc ubifs: Implement ... |
690 |
goto out_fname; |
1e51764a3 UBIFS: add new fl... |
691 692 |
lock_2_inodes(dir, inode); |
32fe905c1 ubifs: Fix O_TMPF... |
693 694 695 696 |
/* Handle O_TMPFILE corner case, it is allowed to link a O_TMPFILE. */ if (inode->i_nlink == 0) ubifs_delete_orphan(c, inode->i_ino); |
1e51764a3 UBIFS: add new fl... |
697 |
inc_nlink(inode); |
7de9c6ee3 new helper: ihold() |
698 |
ihold(inode); |
607a11ad9 fs: ubifs: replac... |
699 |
inode->i_ctime = current_time(inode); |
1e51764a3 UBIFS: add new fl... |
700 701 702 |
dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; |
f4f61d2cc ubifs: Implement ... |
703 |
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); |
1e51764a3 UBIFS: add new fl... |
704 705 706 707 708 709 |
if (err) goto out_cancel; unlock_2_inodes(dir, inode); ubifs_release_budget(c, &req); d_instantiate(dentry, inode); |
f4f61d2cc ubifs: Implement ... |
710 |
fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
711 712 713 714 715 716 |
return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; drop_nlink(inode); |
32fe905c1 ubifs: Fix O_TMPF... |
717 718 |
if (inode->i_nlink == 0) ubifs_add_orphan(c, inode->i_ino); |
1e51764a3 UBIFS: add new fl... |
719 720 721 |
unlock_2_inodes(dir, inode); ubifs_release_budget(c, &req); iput(inode); |
f4f61d2cc ubifs: Implement ... |
722 723 |
out_fname: fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
724 725 726 727 728 729 |
return err; } static int ubifs_unlink(struct inode *dir, struct dentry *dentry) { struct ubifs_info *c = dir->i_sb->s_fs_info; |
2b0143b5c VFS: normal files... |
730 |
struct inode *inode = d_inode(dentry); |
1e51764a3 UBIFS: add new fl... |
731 |
struct ubifs_inode *dir_ui = ubifs_inode(dir); |
f4f61d2cc ubifs: Implement ... |
732 |
int err, sz_change, budgeted = 1; |
1e51764a3 UBIFS: add new fl... |
733 |
struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; |
c43be1085 UBIFS: do not use... |
734 |
unsigned int saved_nlink = inode->i_nlink; |
f4f61d2cc ubifs: Implement ... |
735 |
struct fscrypt_name nm; |
1e51764a3 UBIFS: add new fl... |
736 737 738 739 740 741 742 |
/* * Budget request settings: deletion direntry, deletion inode (+1 for * @dirtied_ino), changing the parent directory inode. If budgeting * fails, go ahead anyway because we have extra space reserved for * deletions. */ |
4cb2a01d8 ubifs: switch to %pd |
743 744 |
dbg_gen("dent '%pd' from ino %lu (nlink %d) in dir ino %lu", dentry, inode->i_ino, |
1e51764a3 UBIFS: add new fl... |
745 |
inode->i_nlink, dir->i_ino); |
f4f61d2cc ubifs: Implement ... |
746 |
|
f4f61d2cc ubifs: Implement ... |
747 748 749 |
err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm); if (err) return err; |
9ca2d7326 ubifs: Limit numb... |
750 751 752 |
err = ubifs_purge_xattrs(inode); if (err) return err; |
f4f61d2cc ubifs: Implement ... |
753 |
sz_change = CALC_DENT_SIZE(fname_len(&nm)); |
6eb61d587 ubifs: Pass struc... |
754 755 |
ubifs_assert(c, inode_is_locked(dir)); ubifs_assert(c, inode_is_locked(inode)); |
d808efb40 UBIFS: amend debu... |
756 |
err = dbg_check_synced_i_size(c, inode); |
1e51764a3 UBIFS: add new fl... |
757 |
if (err) |
f4f61d2cc ubifs: Implement ... |
758 |
goto out_fname; |
1e51764a3 UBIFS: add new fl... |
759 760 761 762 |
err = ubifs_budget_space(c, &req); if (err) { if (err != -ENOSPC) |
f4f61d2cc ubifs: Implement ... |
763 |
goto out_fname; |
1e51764a3 UBIFS: add new fl... |
764 765 766 767 |
budgeted = 0; } lock_2_inodes(dir, inode); |
607a11ad9 fs: ubifs: replac... |
768 |
inode->i_ctime = current_time(dir); |
1e51764a3 UBIFS: add new fl... |
769 770 771 772 |
drop_nlink(inode); dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; |
f4f61d2cc ubifs: Implement ... |
773 |
err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0); |
1e51764a3 UBIFS: add new fl... |
774 775 776 777 778 779 780 781 |
if (err) goto out_cancel; unlock_2_inodes(dir, inode); if (budgeted) ubifs_release_budget(c, &req); else { /* We've deleted something - clean the "no space" flags */ |
b137545c4 UBIFS: introduce ... |
782 |
c->bi.nospace = c->bi.nospace_rp = 0; |
1e51764a3 UBIFS: add new fl... |
783 784 |
smp_wmb(); } |
f4f61d2cc ubifs: Implement ... |
785 |
fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
786 787 788 789 790 |
return 0; out_cancel: dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; |
c43be1085 UBIFS: do not use... |
791 |
set_nlink(inode, saved_nlink); |
1e51764a3 UBIFS: add new fl... |
792 793 794 |
unlock_2_inodes(dir, inode); if (budgeted) ubifs_release_budget(c, &req); |
f4f61d2cc ubifs: Implement ... |
795 796 |
out_fname: fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
797 798 799 800 801 |
return err; } /** * check_dir_empty - check if a directory is empty or not. |
1e51764a3 UBIFS: add new fl... |
802 803 804 805 806 807 |
* @dir: VFS inode object of the directory to check * * This function checks if directory @dir is empty. Returns zero if the * directory is empty, %-ENOTEMPTY if it is not, and other negative error codes * in case of of errors. */ |
f6337d842 ubifs: Export ubi... |
808 |
int ubifs_check_dir_empty(struct inode *dir) |
1e51764a3 UBIFS: add new fl... |
809 |
{ |
f6337d842 ubifs: Export ubi... |
810 |
struct ubifs_info *c = dir->i_sb->s_fs_info; |
f4f61d2cc ubifs: Implement ... |
811 |
struct fscrypt_name nm = { 0 }; |
1e51764a3 UBIFS: add new fl... |
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 |
struct ubifs_dent_node *dent; union ubifs_key key; int err; lowest_dent_key(c, &key, dir->i_ino); dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); if (err == -ENOENT) err = 0; } else { kfree(dent); err = -ENOTEMPTY; } return err; } static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) { struct ubifs_info *c = dir->i_sb->s_fs_info; |
2b0143b5c VFS: normal files... |
832 |
struct inode *inode = d_inode(dentry); |
f4f61d2cc ubifs: Implement ... |
833 |
int err, sz_change, budgeted = 1; |
1e51764a3 UBIFS: add new fl... |
834 835 |
struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; |
f4f61d2cc ubifs: Implement ... |
836 |
struct fscrypt_name nm; |
1e51764a3 UBIFS: add new fl... |
837 838 839 840 841 842 |
/* * Budget request settings: deletion direntry, deletion inode and * changing the parent inode. If budgeting fails, go ahead anyway * because we have extra space reserved for deletions. */ |
4cb2a01d8 ubifs: switch to %pd |
843 844 |
dbg_gen("directory '%pd', ino %lu in dir ino %lu", dentry, inode->i_ino, dir->i_ino); |
6eb61d587 ubifs: Pass struc... |
845 846 |
ubifs_assert(c, inode_is_locked(dir)); ubifs_assert(c, inode_is_locked(inode)); |
f6337d842 ubifs: Export ubi... |
847 |
err = ubifs_check_dir_empty(d_inode(dentry)); |
1e51764a3 UBIFS: add new fl... |
848 849 |
if (err) return err; |
f4f61d2cc ubifs: Implement ... |
850 851 852 |
err = fscrypt_setup_filename(dir, &dentry->d_name, 1, &nm); if (err) return err; |
9ca2d7326 ubifs: Limit numb... |
853 854 855 |
err = ubifs_purge_xattrs(inode); if (err) return err; |
f4f61d2cc ubifs: Implement ... |
856 |
sz_change = CALC_DENT_SIZE(fname_len(&nm)); |
1e51764a3 UBIFS: add new fl... |
857 858 859 |
err = ubifs_budget_space(c, &req); if (err) { if (err != -ENOSPC) |
f4f61d2cc ubifs: Implement ... |
860 |
goto out_fname; |
1e51764a3 UBIFS: add new fl... |
861 862 863 864 |
budgeted = 0; } lock_2_inodes(dir, inode); |
607a11ad9 fs: ubifs: replac... |
865 |
inode->i_ctime = current_time(dir); |
1e51764a3 UBIFS: add new fl... |
866 867 868 869 870 |
clear_nlink(inode); drop_nlink(dir); dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; |
f4f61d2cc ubifs: Implement ... |
871 |
err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0); |
1e51764a3 UBIFS: add new fl... |
872 873 874 875 876 877 878 879 |
if (err) goto out_cancel; unlock_2_inodes(dir, inode); if (budgeted) ubifs_release_budget(c, &req); else { /* We've deleted something - clean the "no space" flags */ |
b137545c4 UBIFS: introduce ... |
880 |
c->bi.nospace = c->bi.nospace_rp = 0; |
1e51764a3 UBIFS: add new fl... |
881 882 |
smp_wmb(); } |
f4f61d2cc ubifs: Implement ... |
883 |
fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
884 885 886 887 888 889 |
return 0; out_cancel: dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; inc_nlink(dir); |
c43be1085 UBIFS: do not use... |
890 |
set_nlink(inode, 2); |
1e51764a3 UBIFS: add new fl... |
891 892 893 |
unlock_2_inodes(dir, inode); if (budgeted) ubifs_release_budget(c, &req); |
f4f61d2cc ubifs: Implement ... |
894 895 |
out_fname: fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
896 897 |
return err; } |
18bb1db3e switch vfs_mkdir(... |
898 |
static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
1e51764a3 UBIFS: add new fl... |
899 900 901 902 |
{ struct inode *inode; struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_info *c = dir->i_sb->s_fs_info; |
f4f61d2cc ubifs: Implement ... |
903 |
int err, sz_change; |
182854b46 UBIFS: fix budget... |
904 |
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 }; |
f4f61d2cc ubifs: Implement ... |
905 |
struct fscrypt_name nm; |
1e51764a3 UBIFS: add new fl... |
906 907 908 909 910 |
/* * Budget request settings: new inode, new direntry and changing parent * directory inode. */ |
4cb2a01d8 ubifs: switch to %pd |
911 912 |
dbg_gen("dent '%pd', mode %#hx in dir ino %lu", dentry, mode, dir->i_ino); |
1e51764a3 UBIFS: add new fl... |
913 914 915 916 |
err = ubifs_budget_space(c, &req); if (err) return err; |
456fcfca6 ubifs: prevent cr... |
917 |
err = ubifs_prepare_create(dir, dentry, &nm); |
f4f61d2cc ubifs: Implement ... |
918 919 920 921 |
if (err) goto out_budg; sz_change = CALC_DENT_SIZE(fname_len(&nm)); |
1e51764a3 UBIFS: add new fl... |
922 923 924 |
inode = ubifs_new_inode(c, dir, S_IFDIR | mode); if (IS_ERR(inode)) { err = PTR_ERR(inode); |
f4f61d2cc ubifs: Implement ... |
925 |
goto out_fname; |
1e51764a3 UBIFS: add new fl... |
926 |
} |
d7f0b70d3 UBIFS: Add securi... |
927 928 |
err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) |
9401a795c UBIFS: fix incorr... |
929 |
goto out_inode; |
d7f0b70d3 UBIFS: Add securi... |
930 |
|
1e51764a3 UBIFS: add new fl... |
931 932 933 934 935 936 937 |
mutex_lock(&dir_ui->ui_mutex); insert_inode_hash(inode); inc_nlink(inode); inc_nlink(dir); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; |
f4f61d2cc ubifs: Implement ... |
938 |
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); |
1e51764a3 UBIFS: add new fl... |
939 |
if (err) { |
235c362bd UBIFS: extend deb... |
940 |
ubifs_err(c, "cannot create directory, error %d", err); |
1e51764a3 UBIFS: add new fl... |
941 942 943 944 945 946 |
goto out_cancel; } mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); d_instantiate(dentry, inode); |
f4f61d2cc ubifs: Implement ... |
947 |
fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
948 949 950 951 952 953 954 |
return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; drop_nlink(dir); mutex_unlock(&dir_ui->ui_mutex); |
9401a795c UBIFS: fix incorr... |
955 |
out_inode: |
1e51764a3 UBIFS: add new fl... |
956 957 |
make_bad_inode(inode); iput(inode); |
f4f61d2cc ubifs: Implement ... |
958 959 |
out_fname: fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
960 961 962 963 964 965 |
out_budg: ubifs_release_budget(c, &req); return err; } static int ubifs_mknod(struct inode *dir, struct dentry *dentry, |
1a67aafb5 switch ->mknod() ... |
966 |
umode_t mode, dev_t rdev) |
1e51764a3 UBIFS: add new fl... |
967 968 969 970 971 972 |
{ struct inode *inode; struct ubifs_inode *ui; struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_info *c = dir->i_sb->s_fs_info; union ubifs_dev_desc *dev = NULL; |
f4f61d2cc ubifs: Implement ... |
973 |
int sz_change; |
1e51764a3 UBIFS: add new fl... |
974 975 |
int err, devlen = 0; struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, |
dab4b4d2f UBIFS: align inod... |
976 |
.dirtied_ino = 1 }; |
f4f61d2cc ubifs: Implement ... |
977 |
struct fscrypt_name nm; |
1e51764a3 UBIFS: add new fl... |
978 979 980 981 982 |
/* * Budget request settings: new inode, new direntry and changing parent * directory inode. */ |
4cb2a01d8 ubifs: switch to %pd |
983 |
dbg_gen("dent '%pd' in dir ino %lu", dentry, dir->i_ino); |
1e51764a3 UBIFS: add new fl... |
984 |
|
1e51764a3 UBIFS: add new fl... |
985 986 987 988 989 990 |
if (S_ISBLK(mode) || S_ISCHR(mode)) { dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); if (!dev) return -ENOMEM; devlen = ubifs_encode_dev(dev, rdev); } |
4d35ca4f7 ubifs: Fix inode ... |
991 |
req.new_ino_d = ALIGN(devlen, 8); |
1e51764a3 UBIFS: add new fl... |
992 993 994 995 996 |
err = ubifs_budget_space(c, &req); if (err) { kfree(dev); return err; } |
456fcfca6 ubifs: prevent cr... |
997 |
err = ubifs_prepare_create(dir, dentry, &nm); |
63ed65736 ubifs: Fix memory... |
998 999 |
if (err) { kfree(dev); |
f4f61d2cc ubifs: Implement ... |
1000 |
goto out_budg; |
63ed65736 ubifs: Fix memory... |
1001 |
} |
f4f61d2cc ubifs: Implement ... |
1002 1003 |
sz_change = CALC_DENT_SIZE(fname_len(&nm)); |
1e51764a3 UBIFS: add new fl... |
1004 1005 1006 1007 |
inode = ubifs_new_inode(c, dir, mode); if (IS_ERR(inode)) { kfree(dev); err = PTR_ERR(inode); |
f4f61d2cc ubifs: Implement ... |
1008 |
goto out_fname; |
1e51764a3 UBIFS: add new fl... |
1009 1010 1011 1012 1013 1014 1015 |
} init_special_inode(inode, inode->i_mode, rdev); inode->i_size = ubifs_inode(inode)->ui_size = devlen; ui = ubifs_inode(inode); ui->data = dev; ui->data_len = devlen; |
d7f0b70d3 UBIFS: Add securi... |
1016 1017 |
err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) |
9401a795c UBIFS: fix incorr... |
1018 |
goto out_inode; |
d7f0b70d3 UBIFS: Add securi... |
1019 |
|
1e51764a3 UBIFS: add new fl... |
1020 1021 1022 1023 |
mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; |
f4f61d2cc ubifs: Implement ... |
1024 |
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); |
1e51764a3 UBIFS: add new fl... |
1025 1026 1027 1028 1029 1030 1031 |
if (err) goto out_cancel; mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); insert_inode_hash(inode); d_instantiate(dentry, inode); |
f4f61d2cc ubifs: Implement ... |
1032 |
fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
1033 1034 1035 1036 1037 1038 |
return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); |
9401a795c UBIFS: fix incorr... |
1039 |
out_inode: |
1e51764a3 UBIFS: add new fl... |
1040 1041 |
make_bad_inode(inode); iput(inode); |
f4f61d2cc ubifs: Implement ... |
1042 1043 |
out_fname: fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 |
out_budg: ubifs_release_budget(c, &req); return err; } static int ubifs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct inode *inode; struct ubifs_inode *ui; struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_info *c = dir->i_sb->s_fs_info; |
00ee8b601 ubifs: Fix direct... |
1056 |
int err, sz_change, len = strlen(symname); |
0e4dda290 ubifs: switch to ... |
1057 |
struct fscrypt_str disk_link; |
1e51764a3 UBIFS: add new fl... |
1058 |
struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, |
dab4b4d2f UBIFS: align inod... |
1059 1060 |
.new_ino_d = ALIGN(len, 8), .dirtied_ino = 1 }; |
ca7f85be8 ubifs: Add suppor... |
1061 |
struct fscrypt_name nm; |
0e4dda290 ubifs: switch to ... |
1062 1063 |
dbg_gen("dent '%pd', target '%s' in dir ino %lu", dentry, symname, dir->i_ino); |
ca7f85be8 ubifs: Add suppor... |
1064 |
|
0e4dda290 ubifs: switch to ... |
1065 1066 1067 1068 |
err = fscrypt_prepare_symlink(dir, symname, len, UBIFS_MAX_INO_DATA, &disk_link); if (err) return err; |
1e51764a3 UBIFS: add new fl... |
1069 1070 1071 1072 1073 |
/* * Budget request settings: new inode, new direntry and changing parent * directory inode. */ |
1e51764a3 UBIFS: add new fl... |
1074 1075 1076 |
err = ubifs_budget_space(c, &req); if (err) return err; |
456fcfca6 ubifs: prevent cr... |
1077 |
err = ubifs_prepare_create(dir, dentry, &nm); |
ca7f85be8 ubifs: Add suppor... |
1078 1079 |
if (err) goto out_budg; |
00ee8b601 ubifs: Fix direct... |
1080 |
sz_change = CALC_DENT_SIZE(fname_len(&nm)); |
1e51764a3 UBIFS: add new fl... |
1081 1082 1083 |
inode = ubifs_new_inode(c, dir, S_IFLNK | S_IRWXUGO); if (IS_ERR(inode)) { err = PTR_ERR(inode); |
ca7f85be8 ubifs: Add suppor... |
1084 |
goto out_fname; |
1e51764a3 UBIFS: add new fl... |
1085 1086 1087 |
} ui = ubifs_inode(inode); |
ca7f85be8 ubifs: Add suppor... |
1088 |
ui->data = kmalloc(disk_link.len, GFP_NOFS); |
1e51764a3 UBIFS: add new fl... |
1089 1090 1091 1092 |
if (!ui->data) { err = -ENOMEM; goto out_inode; } |
0e4dda290 ubifs: switch to ... |
1093 1094 1095 |
if (IS_ENCRYPTED(inode)) { disk_link.name = ui->data; /* encrypt directly into ui->data */ err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link); |
6b46d4441 ubifs: free the e... |
1096 |
if (err) |
ca7f85be8 ubifs: Add suppor... |
1097 |
goto out_inode; |
ca7f85be8 ubifs: Add suppor... |
1098 |
} else { |
0e4dda290 ubifs: switch to ... |
1099 |
memcpy(ui->data, disk_link.name, disk_link.len); |
ca7f85be8 ubifs: Add suppor... |
1100 1101 |
inode->i_link = ui->data; } |
1e51764a3 UBIFS: add new fl... |
1102 1103 1104 |
/* * The terminating zero byte is not written to the flash media and it * is put just to make later in-memory string processing simpler. Thus, |
0e4dda290 ubifs: switch to ... |
1105 |
* data length is @disk_link.len - 1, not @disk_link.len. |
1e51764a3 UBIFS: add new fl... |
1106 |
*/ |
ca7f85be8 ubifs: Add suppor... |
1107 1108 |
ui->data_len = disk_link.len - 1; inode->i_size = ubifs_inode(inode)->ui_size = disk_link.len - 1; |
1e51764a3 UBIFS: add new fl... |
1109 |
|
d7f0b70d3 UBIFS: Add securi... |
1110 1111 |
err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) |
9401a795c UBIFS: fix incorr... |
1112 |
goto out_inode; |
d7f0b70d3 UBIFS: Add securi... |
1113 |
|
1e51764a3 UBIFS: add new fl... |
1114 1115 1116 1117 |
mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; |
ca7f85be8 ubifs: Add suppor... |
1118 |
err = ubifs_jnl_update(c, dir, &nm, inode, 0, 0); |
1e51764a3 UBIFS: add new fl... |
1119 1120 1121 |
if (err) goto out_cancel; mutex_unlock(&dir_ui->ui_mutex); |
1e51764a3 UBIFS: add new fl... |
1122 1123 |
insert_inode_hash(inode); d_instantiate(dentry, inode); |
6b46d4441 ubifs: free the e... |
1124 1125 |
err = 0; goto out_fname; |
1e51764a3 UBIFS: add new fl... |
1126 1127 1128 1129 1130 1131 1132 1133 |
out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); out_inode: make_bad_inode(inode); iput(inode); |
ca7f85be8 ubifs: Add suppor... |
1134 1135 |
out_fname: fscrypt_free_filename(&nm); |
1e51764a3 UBIFS: add new fl... |
1136 1137 1138 1139 1140 1141 |
out_budg: ubifs_release_budget(c, &req); return err; } /** |
9e0a1fff8 ubifs: Implement ... |
1142 |
* lock_4_inodes - a wrapper for locking three UBIFS inodes. |
1e51764a3 UBIFS: add new fl... |
1143 1144 1145 |
* @inode1: first inode * @inode2: second inode * @inode3: third inode |
9e0a1fff8 ubifs: Implement ... |
1146 |
* @inode4: fouth inode |
1e51764a3 UBIFS: add new fl... |
1147 |
* |
82c1593ca UBIFS: simplify l... |
1148 |
* This function is used for 'ubifs_rename()' and @inode1 may be the same as |
9e0a1fff8 ubifs: Implement ... |
1149 |
* @inode2 whereas @inode3 and @inode4 may be %NULL. |
82c1593ca UBIFS: simplify l... |
1150 1151 1152 1153 |
* * We do not implement any tricks to guarantee strict lock ordering, because * VFS has already done it for us on the @i_mutex. So this is just a simple * wrapper function. |
1e51764a3 UBIFS: add new fl... |
1154 |
*/ |
9e0a1fff8 ubifs: Implement ... |
1155 1156 |
static void lock_4_inodes(struct inode *inode1, struct inode *inode2, struct inode *inode3, struct inode *inode4) |
1e51764a3 UBIFS: add new fl... |
1157 |
{ |
82c1593ca UBIFS: simplify l... |
1158 1159 1160 1161 1162 |
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); if (inode2 != inode1) mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); if (inode3) mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3); |
9e0a1fff8 ubifs: Implement ... |
1163 1164 |
if (inode4) mutex_lock_nested(&ubifs_inode(inode4)->ui_mutex, WB_MUTEX_4); |
1e51764a3 UBIFS: add new fl... |
1165 1166 1167 |
} /** |
9e0a1fff8 ubifs: Implement ... |
1168 |
* unlock_4_inodes - a wrapper for unlocking three UBIFS inodes for rename. |
1e51764a3 UBIFS: add new fl... |
1169 1170 1171 |
* @inode1: first inode * @inode2: second inode * @inode3: third inode |
9e0a1fff8 ubifs: Implement ... |
1172 |
* @inode4: fouth inode |
1e51764a3 UBIFS: add new fl... |
1173 |
*/ |
9e0a1fff8 ubifs: Implement ... |
1174 1175 |
static void unlock_4_inodes(struct inode *inode1, struct inode *inode2, struct inode *inode3, struct inode *inode4) |
1e51764a3 UBIFS: add new fl... |
1176 |
{ |
9e0a1fff8 ubifs: Implement ... |
1177 1178 |
if (inode4) mutex_unlock(&ubifs_inode(inode4)->ui_mutex); |
1e51764a3 UBIFS: add new fl... |
1179 1180 |
if (inode3) mutex_unlock(&ubifs_inode(inode3)->ui_mutex); |
82c1593ca UBIFS: simplify l... |
1181 1182 1183 |
if (inode1 != inode2) mutex_unlock(&ubifs_inode(inode2)->ui_mutex); mutex_unlock(&ubifs_inode(inode1)->ui_mutex); |
1e51764a3 UBIFS: add new fl... |
1184 |
} |
390975ac3 ubifs: Rename ubi... |
1185 1186 1187 |
static int do_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) |
1e51764a3 UBIFS: add new fl... |
1188 1189 |
{ struct ubifs_info *c = old_dir->i_sb->s_fs_info; |
2b0143b5c VFS: normal files... |
1190 1191 |
struct inode *old_inode = d_inode(old_dentry); struct inode *new_inode = d_inode(new_dentry); |
9e0a1fff8 ubifs: Implement ... |
1192 |
struct inode *whiteout = NULL; |
1e51764a3 UBIFS: add new fl... |
1193 |
struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode); |
9e0a1fff8 ubifs: Implement ... |
1194 |
struct ubifs_inode *whiteout_ui = NULL; |
1e51764a3 UBIFS: add new fl... |
1195 1196 |
int err, release, sync = 0, move = (new_dir != old_dir); int is_dir = S_ISDIR(old_inode->i_mode); |
f4f61d2cc ubifs: Implement ... |
1197 |
int unlink = !!new_inode, new_sz, old_sz; |
1e51764a3 UBIFS: add new fl... |
1198 1199 1200 |
struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1, .dirtied_ino = 3 }; struct ubifs_budget_req ino_req = { .dirtied_ino = 1, |
dab4b4d2f UBIFS: align inod... |
1201 |
.dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) }; |
95582b008 vfs: change inode... |
1202 |
struct timespec64 time; |
3f649ab72 treewide: Remove ... |
1203 |
unsigned int saved_nlink; |
f4f61d2cc ubifs: Implement ... |
1204 |
struct fscrypt_name old_nm, new_nm; |
1e51764a3 UBIFS: add new fl... |
1205 1206 1207 1208 1209 1210 1211 1212 1213 |
/* * Budget request settings: deletion direntry, new direntry, removing * the old inode, and changing old and new parent directory inodes. * * However, this operation also marks the target inode as dirty and * does not write it, so we allocate budget for the target inode * separately. */ |
9e0a1fff8 ubifs: Implement ... |
1214 |
dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu flags 0x%x", |
4cb2a01d8 ubifs: switch to %pd |
1215 |
old_dentry, old_inode->i_ino, old_dir->i_ino, |
9e0a1fff8 ubifs: Implement ... |
1216 |
new_dentry, new_dir->i_ino, flags); |
9ca2d7326 ubifs: Limit numb... |
1217 |
if (unlink) { |
6eb61d587 ubifs: Pass struc... |
1218 |
ubifs_assert(c, inode_is_locked(new_inode)); |
82c1593ca UBIFS: simplify l... |
1219 |
|
9ca2d7326 ubifs: Limit numb... |
1220 1221 1222 1223 |
err = ubifs_purge_xattrs(new_inode); if (err) return err; } |
1e51764a3 UBIFS: add new fl... |
1224 |
if (unlink && is_dir) { |
f6337d842 ubifs: Export ubi... |
1225 |
err = ubifs_check_dir_empty(new_inode); |
1e51764a3 UBIFS: add new fl... |
1226 1227 1228 |
if (err) return err; } |
f4f61d2cc ubifs: Implement ... |
1229 |
err = fscrypt_setup_filename(old_dir, &old_dentry->d_name, 0, &old_nm); |
1e51764a3 UBIFS: add new fl... |
1230 1231 |
if (err) return err; |
f4f61d2cc ubifs: Implement ... |
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 |
err = fscrypt_setup_filename(new_dir, &new_dentry->d_name, 0, &new_nm); if (err) { fscrypt_free_filename(&old_nm); return err; } new_sz = CALC_DENT_SIZE(fname_len(&new_nm)); old_sz = CALC_DENT_SIZE(fname_len(&old_nm)); err = ubifs_budget_space(c, &req); if (err) { fscrypt_free_filename(&old_nm); fscrypt_free_filename(&new_nm); return err; } |
1e51764a3 UBIFS: add new fl... |
1248 1249 |
err = ubifs_budget_space(c, &ino_req); if (err) { |
f4f61d2cc ubifs: Implement ... |
1250 1251 |
fscrypt_free_filename(&old_nm); fscrypt_free_filename(&new_nm); |
1e51764a3 UBIFS: add new fl... |
1252 1253 1254 |
ubifs_release_budget(c, &req); return err; } |
9e0a1fff8 ubifs: Implement ... |
1255 1256 1257 1258 1259 |
if (flags & RENAME_WHITEOUT) { union ubifs_dev_desc *dev = NULL; dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); if (!dev) { |
bb50c6324 ubifs: Fix memory... |
1260 1261 |
err = -ENOMEM; goto out_release; |
9e0a1fff8 ubifs: Implement ... |
1262 1263 1264 1265 |
} err = do_tmpfile(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, &whiteout); if (err) { |
9e0a1fff8 ubifs: Implement ... |
1266 |
kfree(dev); |
bb50c6324 ubifs: Fix memory... |
1267 |
goto out_release; |
9e0a1fff8 ubifs: Implement ... |
1268 1269 1270 1271 1272 1273 |
} whiteout->i_state |= I_LINKABLE; whiteout_ui = ubifs_inode(whiteout); whiteout_ui->data = dev; whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0)); |
6eb61d587 ubifs: Pass struc... |
1274 |
ubifs_assert(c, !whiteout_ui->dirty); |
9e0a1fff8 ubifs: Implement ... |
1275 1276 1277 |
} lock_4_inodes(old_dir, new_dir, new_inode, whiteout); |
1e51764a3 UBIFS: add new fl... |
1278 1279 1280 1281 1282 |
/* * Like most other Unix systems, set the @i_ctime for inodes on a * rename. */ |
607a11ad9 fs: ubifs: replac... |
1283 |
time = current_time(old_dir); |
1e51764a3 UBIFS: add new fl... |
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 |
old_inode->i_ctime = time; /* We must adjust parent link count when renaming directories */ if (is_dir) { if (move) { /* * @old_dir loses a link because we are moving * @old_inode to a different directory. */ drop_nlink(old_dir); /* * @new_dir only gains a link if we are not also * overwriting an existing directory. */ if (!unlink) inc_nlink(new_dir); } else { /* * @old_inode is not moving to a different directory, * but @old_dir still loses a link if we are * overwriting an existing directory. */ if (unlink) drop_nlink(old_dir); } } old_dir->i_size -= old_sz; ubifs_inode(old_dir)->ui_size = old_dir->i_size; old_dir->i_mtime = old_dir->i_ctime = time; new_dir->i_mtime = new_dir->i_ctime = time; /* * And finally, if we unlinked a direntry which happened to have the * same name as the moved direntry, we have to decrement @i_nlink of * the unlinked inode and change its ctime. */ if (unlink) { /* * Directories cannot have hard-links, so if this is a |
c43be1085 UBIFS: do not use... |
1324 |
* directory, just clear @i_nlink. |
1e51764a3 UBIFS: add new fl... |
1325 |
*/ |
c43be1085 UBIFS: do not use... |
1326 |
saved_nlink = new_inode->i_nlink; |
1e51764a3 UBIFS: add new fl... |
1327 |
if (is_dir) |
c43be1085 UBIFS: do not use... |
1328 1329 |
clear_nlink(new_inode); else |
1e51764a3 UBIFS: add new fl... |
1330 1331 |
drop_nlink(new_inode); new_inode->i_ctime = time; |
1e51764a3 UBIFS: add new fl... |
1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 |
} else { new_dir->i_size += new_sz; ubifs_inode(new_dir)->ui_size = new_dir->i_size; } /* * Do not ask 'ubifs_jnl_rename()' to flush write-buffer if @old_inode * is dirty, because this will be done later on at the end of * 'ubifs_rename()'. */ if (IS_SYNC(old_inode)) { sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir); if (unlink && IS_SYNC(new_inode)) sync = 1; } |
9e0a1fff8 ubifs: Implement ... |
1347 1348 1349 1350 1351 1352 1353 1354 |
if (whiteout) { struct ubifs_budget_req wht_req = { .dirtied_ino = 1, .dirtied_ino_d = \ ALIGN(ubifs_inode(whiteout)->data_len, 8) }; err = ubifs_budget_space(c, &wht_req); if (err) { |
9e0a1fff8 ubifs: Implement ... |
1355 1356 1357 |
kfree(whiteout_ui->data); whiteout_ui->data_len = 0; iput(whiteout); |
bb50c6324 ubifs: Fix memory... |
1358 |
goto out_release; |
9e0a1fff8 ubifs: Implement ... |
1359 1360 1361 1362 1363 1364 1365 |
} inc_nlink(whiteout); mark_inode_dirty(whiteout); whiteout->i_state &= ~I_LINKABLE; iput(whiteout); } |
f4f61d2cc ubifs: Implement ... |
1366 1367 |
err = ubifs_jnl_rename(c, old_dir, old_inode, &old_nm, new_dir, new_inode, &new_nm, whiteout, sync); |
1e51764a3 UBIFS: add new fl... |
1368 1369 |
if (err) goto out_cancel; |
9e0a1fff8 ubifs: Implement ... |
1370 |
unlock_4_inodes(old_dir, new_dir, new_inode, whiteout); |
1e51764a3 UBIFS: add new fl... |
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 |
ubifs_release_budget(c, &req); mutex_lock(&old_inode_ui->ui_mutex); release = old_inode_ui->dirty; mark_inode_dirty_sync(old_inode); mutex_unlock(&old_inode_ui->ui_mutex); if (release) ubifs_release_budget(c, &ino_req); if (IS_SYNC(old_inode)) |
a9185b41a pass writeback_co... |
1381 |
err = old_inode->i_sb->s_op->write_inode(old_inode, NULL); |
f4f61d2cc ubifs: Implement ... |
1382 1383 1384 |
fscrypt_free_filename(&old_nm); fscrypt_free_filename(&new_nm); |
1e51764a3 UBIFS: add new fl... |
1385 1386 1387 1388 |
return err; out_cancel: if (unlink) { |
c43be1085 UBIFS: do not use... |
1389 |
set_nlink(new_inode, saved_nlink); |
1e51764a3 UBIFS: add new fl... |
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 |
} else { new_dir->i_size -= new_sz; ubifs_inode(new_dir)->ui_size = new_dir->i_size; } old_dir->i_size += old_sz; ubifs_inode(old_dir)->ui_size = old_dir->i_size; if (is_dir) { if (move) { inc_nlink(old_dir); if (!unlink) drop_nlink(new_dir); } else { if (unlink) inc_nlink(old_dir); } } |
9e0a1fff8 ubifs: Implement ... |
1406 1407 1408 1409 1410 |
if (whiteout) { drop_nlink(whiteout); iput(whiteout); } unlock_4_inodes(old_dir, new_dir, new_inode, whiteout); |
bb50c6324 ubifs: Fix memory... |
1411 |
out_release: |
1e51764a3 UBIFS: add new fl... |
1412 1413 |
ubifs_release_budget(c, &ino_req); ubifs_release_budget(c, &req); |
f4f61d2cc ubifs: Implement ... |
1414 1415 |
fscrypt_free_filename(&old_nm); fscrypt_free_filename(&new_nm); |
1e51764a3 UBIFS: add new fl... |
1416 1417 |
return err; } |
9ec64962a ubifs: Implement ... |
1418 1419 1420 1421 1422 1423 1424 1425 1426 |
static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { struct ubifs_info *c = old_dir->i_sb->s_fs_info; struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1, .dirtied_ino = 2 }; int sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir); struct inode *fst_inode = d_inode(old_dentry); struct inode *snd_inode = d_inode(new_dentry); |
95582b008 vfs: change inode... |
1427 |
struct timespec64 time; |
9ec64962a ubifs: Implement ... |
1428 |
int err; |
f4f61d2cc ubifs: Implement ... |
1429 |
struct fscrypt_name fst_nm, snd_nm; |
9ec64962a ubifs: Implement ... |
1430 |
|
6eb61d587 ubifs: Pass struc... |
1431 |
ubifs_assert(c, fst_inode && snd_inode); |
9ec64962a ubifs: Implement ... |
1432 |
|
f4f61d2cc ubifs: Implement ... |
1433 1434 1435 1436 1437 1438 1439 1440 1441 |
err = fscrypt_setup_filename(old_dir, &old_dentry->d_name, 0, &fst_nm); if (err) return err; err = fscrypt_setup_filename(new_dir, &new_dentry->d_name, 0, &snd_nm); if (err) { fscrypt_free_filename(&fst_nm); return err; } |
9ec64962a ubifs: Implement ... |
1442 |
lock_4_inodes(old_dir, new_dir, NULL, NULL); |
607a11ad9 fs: ubifs: replac... |
1443 |
time = current_time(old_dir); |
9ec64962a ubifs: Implement ... |
1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 |
fst_inode->i_ctime = time; snd_inode->i_ctime = time; old_dir->i_mtime = old_dir->i_ctime = time; new_dir->i_mtime = new_dir->i_ctime = time; if (old_dir != new_dir) { if (S_ISDIR(fst_inode->i_mode) && !S_ISDIR(snd_inode->i_mode)) { inc_nlink(new_dir); drop_nlink(old_dir); } else if (!S_ISDIR(fst_inode->i_mode) && S_ISDIR(snd_inode->i_mode)) { drop_nlink(new_dir); inc_nlink(old_dir); } } |
f4f61d2cc ubifs: Implement ... |
1459 1460 |
err = ubifs_jnl_xrename(c, old_dir, fst_inode, &fst_nm, new_dir, snd_inode, &snd_nm, sync); |
9ec64962a ubifs: Implement ... |
1461 1462 1463 |
unlock_4_inodes(old_dir, new_dir, NULL, NULL); ubifs_release_budget(c, &req); |
f4f61d2cc ubifs: Implement ... |
1464 1465 |
fscrypt_free_filename(&fst_nm); fscrypt_free_filename(&snd_nm); |
9ec64962a ubifs: Implement ... |
1466 1467 |
return err; } |
390975ac3 ubifs: Rename ubi... |
1468 |
static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, |
9ec64962a ubifs: Implement ... |
1469 1470 1471 |
struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) { |
0c1ad5242 ubifs: switch to ... |
1472 |
int err; |
6eb61d587 ubifs: Pass struc... |
1473 |
struct ubifs_info *c = old_dir->i_sb->s_fs_info; |
0c1ad5242 ubifs: switch to ... |
1474 |
|
9ec64962a ubifs: Implement ... |
1475 1476 |
if (flags & ~(RENAME_NOREPLACE | RENAME_WHITEOUT | RENAME_EXCHANGE)) return -EINVAL; |
6eb61d587 ubifs: Pass struc... |
1477 1478 |
ubifs_assert(c, inode_is_locked(old_dir)); ubifs_assert(c, inode_is_locked(new_dir)); |
9ec64962a ubifs: Implement ... |
1479 |
|
0c1ad5242 ubifs: switch to ... |
1480 1481 1482 1483 |
err = fscrypt_prepare_rename(old_dir, old_dentry, new_dir, new_dentry, flags); if (err) return err; |
9ec64962a ubifs: Implement ... |
1484 1485 |
if (flags & RENAME_EXCHANGE) return ubifs_xrename(old_dir, old_dentry, new_dir, new_dentry); |
390975ac3 ubifs: Rename ubi... |
1486 |
return do_rename(old_dir, old_dentry, new_dir, new_dentry, flags); |
9ec64962a ubifs: Implement ... |
1487 |
} |
a528d35e8 statx: Add a syst... |
1488 1489 |
int ubifs_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags) |
1e51764a3 UBIFS: add new fl... |
1490 1491 |
{ loff_t size; |
a528d35e8 statx: Add a syst... |
1492 |
struct inode *inode = d_inode(path->dentry); |
1e51764a3 UBIFS: add new fl... |
1493 1494 1495 |
struct ubifs_inode *ui = ubifs_inode(inode); mutex_lock(&ui->ui_mutex); |
a02a6eba9 ubifs: Wire-up st... |
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 |
if (ui->flags & UBIFS_APPEND_FL) stat->attributes |= STATX_ATTR_APPEND; if (ui->flags & UBIFS_COMPR_FL) stat->attributes |= STATX_ATTR_COMPRESSED; if (ui->flags & UBIFS_CRYPT_FL) stat->attributes |= STATX_ATTR_ENCRYPTED; if (ui->flags & UBIFS_IMMUTABLE_FL) stat->attributes |= STATX_ATTR_IMMUTABLE; stat->attributes_mask |= (STATX_ATTR_APPEND | STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED | STATX_ATTR_IMMUTABLE); |
6d42e7e9f ubifs: use generi... |
1510 |
generic_fillattr(inode, stat); |
1e51764a3 UBIFS: add new fl... |
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 |
stat->blksize = UBIFS_BLOCK_SIZE; stat->size = ui->ui_size; /* * Unfortunately, the 'stat()' system call was designed for block * device based file systems, and it is not appropriate for UBIFS, * because UBIFS does not have notion of "block". For example, it is * difficult to tell how many block a directory takes - it actually * takes less than 300 bytes, but we have to round it to block size, * which introduces large mistake. This makes utilities like 'du' to * report completely senseless numbers. This is the reason why UBIFS * goes the same way as JFFS2 - it reports zero blocks for everything * but regular files, which makes more sense than reporting completely * wrong sizes. */ if (S_ISREG(inode->i_mode)) { size = ui->xattr_size; size += stat->size; size = ALIGN(size, UBIFS_BLOCK_SIZE); /* * Note, user-space expects 512-byte blocks count irrespectively * of what was reported in @stat->size. */ stat->blocks = size >> 9; } else stat->blocks = 0; mutex_unlock(&ui->ui_mutex); return 0; } |
ba40e6a3c ubifs: Implement ... |
1540 1541 |
static int ubifs_dir_open(struct inode *dir, struct file *file) { |
50d9fad73 ubifs: use IS_ENC... |
1542 |
if (IS_ENCRYPTED(dir)) |
ba40e6a3c ubifs: Implement ... |
1543 1544 1545 1546 |
return fscrypt_get_encryption_info(dir) ? -EACCES : 0; return 0; } |
e8b815663 UBIFS: constify o... |
1547 |
const struct inode_operations ubifs_dir_inode_operations = { |
1e51764a3 UBIFS: add new fl... |
1548 1549 1550 1551 1552 1553 1554 1555 |
.lookup = ubifs_lookup, .create = ubifs_create, .link = ubifs_link, .symlink = ubifs_symlink, .unlink = ubifs_unlink, .mkdir = ubifs_mkdir, .rmdir = ubifs_rmdir, .mknod = ubifs_mknod, |
390975ac3 ubifs: Rename ubi... |
1556 |
.rename = ubifs_rename, |
1e51764a3 UBIFS: add new fl... |
1557 1558 |
.setattr = ubifs_setattr, .getattr = ubifs_getattr, |
7e5471ce6 ubifs: introduce ... |
1559 |
#ifdef CONFIG_UBIFS_FS_XATTR |
1e51764a3 UBIFS: add new fl... |
1560 |
.listxattr = ubifs_listxattr, |
7e5471ce6 ubifs: introduce ... |
1561 |
#endif |
8c1c5f263 ubifs: introduce ... |
1562 |
.update_time = ubifs_update_time, |
474b93704 ubifs: Implement ... |
1563 |
.tmpfile = ubifs_tmpfile, |
1e51764a3 UBIFS: add new fl... |
1564 |
}; |
e8b815663 UBIFS: constify o... |
1565 |
const struct file_operations ubifs_dir_operations = { |
01122e068 [readdir] convert... |
1566 |
.llseek = generic_file_llseek, |
1e51764a3 UBIFS: add new fl... |
1567 1568 |
.release = ubifs_dir_release, .read = generic_read_dir, |
c51da20c4 more trivial ->it... |
1569 |
.iterate_shared = ubifs_readdir, |
1e51764a3 UBIFS: add new fl... |
1570 1571 |
.fsync = ubifs_fsync, .unlocked_ioctl = ubifs_ioctl, |
ba40e6a3c ubifs: Implement ... |
1572 |
.open = ubifs_dir_open, |
1e51764a3 UBIFS: add new fl... |
1573 1574 1575 1576 |
#ifdef CONFIG_COMPAT .compat_ioctl = ubifs_compat_ioctl, #endif }; |