Skip to content

Commit 988bec4

Browse files
ubifs: orphan: Handle xattrs like files
Like for the journal case, make sure that we track all xattr inodes. Otherwise UBIFS might not be able to locate stale xattr inodes upon recovery. Reported-by: Stefan Agner <[email protected]> Fixes: 1e51764 ("UBIFS: add new flash file system") Signed-off-by: Richard Weinberger <[email protected]>
1 parent 7959cf3 commit 988bec4

File tree

2 files changed

+144
-67
lines changed

2 files changed

+144
-67
lines changed

fs/ubifs/orphan.c

Lines changed: 141 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -54,30 +54,24 @@
5454

5555
static int dbg_check_orphans(struct ubifs_info *c);
5656

57-
/**
58-
* ubifs_add_orphan - add an orphan.
59-
* @c: UBIFS file-system description object
60-
* @inum: orphan inode number
61-
*
62-
* Add an orphan. This function is called when an inodes link count drops to
63-
* zero.
64-
*/
65-
int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
57+
static struct ubifs_orphan *orphan_add(struct ubifs_info *c, ino_t inum,
58+
struct ubifs_orphan *parent_orphan)
6659
{
6760
struct ubifs_orphan *orphan, *o;
6861
struct rb_node **p, *parent = NULL;
6962

7063
orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_NOFS);
7164
if (!orphan)
72-
return -ENOMEM;
65+
return ERR_PTR(-ENOMEM);
7366
orphan->inum = inum;
7467
orphan->new = 1;
68+
INIT_LIST_HEAD(&orphan->child_list);
7569

7670
spin_lock(&c->orphan_lock);
7771
if (c->tot_orphans >= c->max_orphans) {
7872
spin_unlock(&c->orphan_lock);
7973
kfree(orphan);
80-
return -ENFILE;
74+
return ERR_PTR(-ENFILE);
8175
}
8276
p = &c->orph_tree.rb_node;
8377
while (*p) {
@@ -91,7 +85,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
9185
ubifs_err(c, "orphaned twice");
9286
spin_unlock(&c->orphan_lock);
9387
kfree(orphan);
94-
return 0;
88+
return ERR_PTR(-EINVAL);
9589
}
9690
}
9791
c->tot_orphans += 1;
@@ -100,24 +94,22 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
10094
rb_insert_color(&orphan->rb, &c->orph_tree);
10195
list_add_tail(&orphan->list, &c->orph_list);
10296
list_add_tail(&orphan->new_list, &c->orph_new);
97+
98+
if (parent_orphan) {
99+
list_add_tail(&orphan->child_list,
100+
&parent_orphan->child_list);
101+
}
102+
103103
spin_unlock(&c->orphan_lock);
104104
dbg_gen("ino %lu", (unsigned long)inum);
105-
return 0;
105+
return orphan;
106106
}
107107

108-
/**
109-
* ubifs_delete_orphan - delete an orphan.
110-
* @c: UBIFS file-system description object
111-
* @inum: orphan inode number
112-
*
113-
* Delete an orphan. This function is called when an inode is deleted.
114-
*/
115-
void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
108+
static struct ubifs_orphan *lookup_orphan(struct ubifs_info *c, ino_t inum)
116109
{
117110
struct ubifs_orphan *o;
118111
struct rb_node *p;
119112

120-
spin_lock(&c->orphan_lock);
121113
p = c->orph_tree.rb_node;
122114
while (p) {
123115
o = rb_entry(p, struct ubifs_orphan, rb);
@@ -126,37 +118,124 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
126118
else if (inum > o->inum)
127119
p = p->rb_right;
128120
else {
129-
if (o->del) {
130-
spin_unlock(&c->orphan_lock);
131-
dbg_gen("deleted twice ino %lu",
132-
(unsigned long)inum);
133-
return;
134-
}
135-
if (o->cmt) {
136-
o->del = 1;
137-
o->dnext = c->orph_dnext;
138-
c->orph_dnext = o;
139-
spin_unlock(&c->orphan_lock);
140-
dbg_gen("delete later ino %lu",
141-
(unsigned long)inum);
142-
return;
143-
}
144-
rb_erase(p, &c->orph_tree);
145-
list_del(&o->list);
146-
c->tot_orphans -= 1;
147-
if (o->new) {
148-
list_del(&o->new_list);
149-
c->new_orphans -= 1;
150-
}
151-
spin_unlock(&c->orphan_lock);
152-
kfree(o);
153-
dbg_gen("inum %lu", (unsigned long)inum);
154-
return;
121+
return o;
155122
}
156123
}
124+
return NULL;
125+
}
126+
127+
static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o)
128+
{
129+
rb_erase(&o->rb, &c->orph_tree);
130+
list_del(&o->list);
131+
c->tot_orphans -= 1;
132+
133+
if (o->new) {
134+
list_del(&o->new_list);
135+
c->new_orphans -= 1;
136+
}
137+
138+
kfree(o);
139+
}
140+
141+
static void orphan_delete(struct ubifs_info *c, ino_t inum)
142+
{
143+
struct ubifs_orphan *orph, *child_orph, *tmp_o;
144+
145+
spin_lock(&c->orphan_lock);
146+
147+
orph = lookup_orphan(c, inum);
148+
if (!orph) {
149+
spin_unlock(&c->orphan_lock);
150+
ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum);
151+
dump_stack();
152+
153+
return;
154+
}
155+
156+
if (orph->del) {
157+
spin_unlock(&c->orphan_lock);
158+
dbg_gen("deleted twice ino %lu",
159+
(unsigned long)inum);
160+
return;
161+
}
162+
163+
if (orph->cmt) {
164+
orph->del = 1;
165+
orph->dnext = c->orph_dnext;
166+
c->orph_dnext = orph;
167+
spin_unlock(&c->orphan_lock);
168+
dbg_gen("delete later ino %lu",
169+
(unsigned long)inum);
170+
return;
171+
}
172+
173+
list_for_each_entry_safe(child_orph, tmp_o, &orph->child_list, child_list) {
174+
list_del(&child_orph->child_list);
175+
__orphan_drop(c, child_orph);
176+
}
177+
178+
__orphan_drop(c, orph);
179+
157180
spin_unlock(&c->orphan_lock);
158-
ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum);
159-
dump_stack();
181+
}
182+
183+
/**
184+
* ubifs_add_orphan - add an orphan.
185+
* @c: UBIFS file-system description object
186+
* @inum: orphan inode number
187+
*
188+
* Add an orphan. This function is called when an inodes link count drops to
189+
* zero.
190+
*/
191+
int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
192+
{
193+
int err = 0;
194+
ino_t xattr_inum;
195+
union ubifs_key key;
196+
struct ubifs_dent_node *xent;
197+
struct fscrypt_name nm = {0};
198+
struct ubifs_orphan *xattr_orphan;
199+
struct ubifs_orphan *orphan;
200+
201+
orphan = orphan_add(c, inum, NULL);
202+
if (IS_ERR(orphan))
203+
return PTR_ERR(orphan);
204+
205+
lowest_xent_key(c, &key, inum);
206+
while (1) {
207+
xent = ubifs_tnc_next_ent(c, &key, &nm);
208+
if (IS_ERR(xent)) {
209+
err = PTR_ERR(xent);
210+
if (err == -ENOENT)
211+
break;
212+
return err;
213+
}
214+
215+
fname_name(&nm) = xent->name;
216+
fname_len(&nm) = le16_to_cpu(xent->nlen);
217+
xattr_inum = le64_to_cpu(xent->inum);
218+
219+
xattr_orphan = orphan_add(c, xattr_inum, orphan);
220+
if (IS_ERR(xattr_orphan))
221+
return PTR_ERR(xattr_orphan);
222+
223+
key_read(c, &xent->key, &key);
224+
}
225+
226+
return 0;
227+
}
228+
229+
/**
230+
* ubifs_delete_orphan - delete an orphan.
231+
* @c: UBIFS file-system description object
232+
* @inum: orphan inode number
233+
*
234+
* Delete an orphan. This function is called when an inode is deleted.
235+
*/
236+
void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum)
237+
{
238+
orphan_delete(c, inum);
160239
}
161240

162241
/**
@@ -611,10 +690,16 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
611690

612691
n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3;
613692
for (i = 0; i < n; i++) {
693+
union ubifs_key key1, key2;
694+
614695
inum = le64_to_cpu(orph->inos[i]);
615696
dbg_rcvry("deleting orphaned inode %lu",
616697
(unsigned long)inum);
617-
err = ubifs_tnc_remove_ino(c, inum);
698+
699+
lowest_ino_key(c, &key1, inum);
700+
highest_ino_key(c, &key2, inum);
701+
702+
err = ubifs_tnc_remove_range(c, &key1, &key2);
618703
if (err)
619704
return err;
620705
err = insert_dead_orphan(c, inum);
@@ -744,26 +829,15 @@ struct check_info {
744829
struct rb_root root;
745830
};
746831

747-
static int dbg_find_orphan(struct ubifs_info *c, ino_t inum)
832+
static bool dbg_find_orphan(struct ubifs_info *c, ino_t inum)
748833
{
749-
struct ubifs_orphan *o;
750-
struct rb_node *p;
834+
bool found = false;
751835

752836
spin_lock(&c->orphan_lock);
753-
p = c->orph_tree.rb_node;
754-
while (p) {
755-
o = rb_entry(p, struct ubifs_orphan, rb);
756-
if (inum < o->inum)
757-
p = p->rb_left;
758-
else if (inum > o->inum)
759-
p = p->rb_right;
760-
else {
761-
spin_unlock(&c->orphan_lock);
762-
return 1;
763-
}
764-
}
837+
found = !!lookup_orphan(c, inum);
765838
spin_unlock(&c->orphan_lock);
766-
return 0;
839+
840+
return found;
767841
}
768842

769843
static int dbg_ins_check_orphan(struct rb_root *root, ino_t inum)

fs/ubifs/ubifs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,8 @@ struct ubifs_budget_req {
924924
* @rb: rb-tree node of rb-tree of orphans sorted by inode number
925925
* @list: list head of list of orphans in order added
926926
* @new_list: list head of list of orphans added since the last commit
927+
* @child_list: list of xattr childs if this orphan hosts xattrs, list head
928+
* if this orphan is a xattr, not used otherwise.
927929
* @cnext: next orphan to commit
928930
* @dnext: next orphan to delete
929931
* @inum: inode number
@@ -935,6 +937,7 @@ struct ubifs_orphan {
935937
struct rb_node rb;
936938
struct list_head list;
937939
struct list_head new_list;
940+
struct list_head child_list;
938941
struct ubifs_orphan *cnext;
939942
struct ubifs_orphan *dnext;
940943
ino_t inum;

0 commit comments

Comments
 (0)