Skip to content

Commit 6a1c4c4

Browse files
author
Al Viro
committed
ufs: fix handling of delete_entry and set_link failures
similar to minixfs series - make ufs_set_link() report failures, lift folio_release_kmap() into the callers of ufs_set_link() and ufs_delete_entry(), make ufs_rename() handle failures in both. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 8cf0b93 commit 6a1c4c4

3 files changed

Lines changed: 33 additions & 39 deletions

File tree

fs/ufs/dir.c

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -81,28 +81,29 @@ ino_t ufs_inode_by_name(struct inode *dir, const struct qstr *qstr)
8181
}
8282

8383

84-
/* Releases the page */
85-
void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
86-
struct folio *folio, struct inode *inode,
87-
bool update_times)
84+
int ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
85+
struct folio *folio, struct inode *inode,
86+
bool update_times)
8887
{
8988
loff_t pos = folio_pos(folio) + offset_in_folio(folio, de);
9089
unsigned len = fs16_to_cpu(dir->i_sb, de->d_reclen);
9190
int err;
9291

9392
folio_lock(folio);
9493
err = ufs_prepare_chunk(folio, pos, len);
95-
BUG_ON(err);
94+
if (unlikely(err)) {
95+
folio_unlock(folio);
96+
return err;
97+
}
9698

9799
de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
98100
ufs_set_de_type(dir->i_sb, de, inode->i_mode);
99101

100102
ufs_commit_chunk(folio, pos, len);
101-
folio_release_kmap(folio, de);
102103
if (update_times)
103104
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
104105
mark_inode_dirty(dir);
105-
ufs_handle_dirsync(dir);
106+
return ufs_handle_dirsync(dir);
106107
}
107108

108109
static bool ufs_check_folio(struct folio *folio, char *kaddr)
@@ -505,8 +506,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
505506
if (de->d_reclen == 0) {
506507
ufs_error(inode->i_sb, __func__,
507508
"zero-length directory entry");
508-
err = -EIO;
509-
goto out;
509+
return -EIO;
510510
}
511511
pde = de;
512512
de = ufs_next_entry(sb, de);
@@ -516,18 +516,17 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
516516
pos = folio_pos(folio) + from;
517517
folio_lock(folio);
518518
err = ufs_prepare_chunk(folio, pos, to - from);
519-
BUG_ON(err);
519+
if (unlikely(err)) {
520+
folio_unlock(folio);
521+
return err;
522+
}
520523
if (pde)
521524
pde->d_reclen = cpu_to_fs16(sb, to - from);
522525
dir->d_ino = 0;
523526
ufs_commit_chunk(folio, pos, to - from);
524527
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
525528
mark_inode_dirty(inode);
526-
err = ufs_handle_dirsync(inode);
527-
out:
528-
folio_release_kmap(folio, kaddr);
529-
UFSD("EXIT\n");
530-
return err;
529+
return ufs_handle_dirsync(inode);
531530
}
532531

533532
int ufs_make_empty(struct inode * inode, struct inode *dir)

fs/ufs/namei.c

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -210,20 +210,18 @@ static int ufs_unlink(struct inode *dir, struct dentry *dentry)
210210
struct inode * inode = d_inode(dentry);
211211
struct ufs_dir_entry *de;
212212
struct folio *folio;
213-
int err = -ENOENT;
213+
int err;
214214

215215
de = ufs_find_entry(dir, &dentry->d_name, &folio);
216216
if (!de)
217-
goto out;
217+
return -ENOENT;
218218

219219
err = ufs_delete_entry(dir, de, folio);
220-
if (err)
221-
goto out;
222-
223-
inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
224-
inode_dec_link_count(inode);
225-
err = 0;
226-
out:
220+
if (!err) {
221+
inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
222+
inode_dec_link_count(inode);
223+
}
224+
folio_release_kmap(folio, de);
227225
return err;
228226
}
229227

@@ -253,14 +251,14 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
253251
struct ufs_dir_entry * dir_de = NULL;
254252
struct folio *old_folio;
255253
struct ufs_dir_entry *old_de;
256-
int err = -ENOENT;
254+
int err;
257255

258256
if (flags & ~RENAME_NOREPLACE)
259257
return -EINVAL;
260258

261259
old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_folio);
262260
if (!old_de)
263-
goto out;
261+
return -ENOENT;
264262

265263
if (S_ISDIR(old_inode->i_mode)) {
266264
err = -EIO;
@@ -281,7 +279,10 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
281279
new_de = ufs_find_entry(new_dir, &new_dentry->d_name, &new_folio);
282280
if (!new_de)
283281
goto out_dir;
284-
ufs_set_link(new_dir, new_de, new_folio, old_inode, 1);
282+
err = ufs_set_link(new_dir, new_de, new_folio, old_inode, 1);
283+
folio_release_kmap(new_folio, new_de);
284+
if (err)
285+
goto out_dir;
285286
inode_set_ctime_current(new_inode);
286287
if (dir_de)
287288
drop_nlink(new_inode);
@@ -299,26 +300,20 @@ static int ufs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
299300
* rename.
300301
*/
301302
inode_set_ctime_current(old_inode);
302-
303-
ufs_delete_entry(old_dir, old_de, old_folio);
304303
mark_inode_dirty(old_inode);
305304

306-
if (dir_de) {
305+
err = ufs_delete_entry(old_dir, old_de, old_folio);
306+
if (!err && dir_de) {
307307
if (old_dir != new_dir)
308-
ufs_set_link(old_inode, dir_de, dir_folio, new_dir, 0);
309-
else
310-
folio_release_kmap(dir_folio, dir_de);
308+
err = ufs_set_link(old_inode, dir_de, dir_folio,
309+
new_dir, 0);
311310
inode_dec_link_count(old_dir);
312311
}
313-
return 0;
314-
315-
316312
out_dir:
317313
if (dir_de)
318314
folio_release_kmap(dir_folio, dir_de);
319315
out_old:
320316
folio_release_kmap(old_folio, old_de);
321-
out:
322317
return err;
323318
}
324319

fs/ufs/ufs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ struct ufs_dir_entry *ufs_find_entry(struct inode *, const struct qstr *,
108108
int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct folio *);
109109
int ufs_empty_dir(struct inode *);
110110
struct ufs_dir_entry *ufs_dotdot(struct inode *, struct folio **);
111-
void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
112-
struct folio *folio, struct inode *inode, bool update_times);
111+
int ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
112+
struct folio *folio, struct inode *inode, bool update_times);
113113

114114
/* file.c */
115115
extern const struct inode_operations ufs_file_inode_operations;

0 commit comments

Comments
 (0)