1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * linux/fs/hpfs/dnode.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Mikulas Patocka ([email protected]), 1998-1999 5*1da177e4SLinus Torvalds * 6*1da177e4SLinus Torvalds * handling directory dnode tree - adding, deleteing & searching for dirents 7*1da177e4SLinus Torvalds */ 8*1da177e4SLinus Torvalds 9*1da177e4SLinus Torvalds #include "hpfs_fn.h" 10*1da177e4SLinus Torvalds 11*1da177e4SLinus Torvalds static loff_t get_pos(struct dnode *d, struct hpfs_dirent *fde) 12*1da177e4SLinus Torvalds { 13*1da177e4SLinus Torvalds struct hpfs_dirent *de; 14*1da177e4SLinus Torvalds struct hpfs_dirent *de_end = dnode_end_de(d); 15*1da177e4SLinus Torvalds int i = 1; 16*1da177e4SLinus Torvalds for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { 17*1da177e4SLinus Torvalds if (de == fde) return ((loff_t) d->self << 4) | (loff_t)i; 18*1da177e4SLinus Torvalds i++; 19*1da177e4SLinus Torvalds } 20*1da177e4SLinus Torvalds printk("HPFS: get_pos: not_found\n"); 21*1da177e4SLinus Torvalds return ((loff_t)d->self << 4) | (loff_t)1; 22*1da177e4SLinus Torvalds } 23*1da177e4SLinus Torvalds 24*1da177e4SLinus Torvalds void hpfs_add_pos(struct inode *inode, loff_t *pos) 25*1da177e4SLinus Torvalds { 26*1da177e4SLinus Torvalds struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); 27*1da177e4SLinus Torvalds int i = 0; 28*1da177e4SLinus Torvalds loff_t **ppos; 29*1da177e4SLinus Torvalds 30*1da177e4SLinus Torvalds if (hpfs_inode->i_rddir_off) 31*1da177e4SLinus Torvalds for (; hpfs_inode->i_rddir_off[i]; i++) 32*1da177e4SLinus Torvalds if (hpfs_inode->i_rddir_off[i] == pos) return; 33*1da177e4SLinus Torvalds if (!(i&0x0f)) { 34*1da177e4SLinus Torvalds if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_NOFS))) { 35*1da177e4SLinus Torvalds printk("HPFS: out of memory for position list\n"); 36*1da177e4SLinus Torvalds return; 37*1da177e4SLinus Torvalds } 38*1da177e4SLinus Torvalds if (hpfs_inode->i_rddir_off) { 39*1da177e4SLinus Torvalds memcpy(ppos, hpfs_inode->i_rddir_off, i * sizeof(loff_t)); 40*1da177e4SLinus Torvalds kfree(hpfs_inode->i_rddir_off); 41*1da177e4SLinus Torvalds } 42*1da177e4SLinus Torvalds hpfs_inode->i_rddir_off = ppos; 43*1da177e4SLinus Torvalds } 44*1da177e4SLinus Torvalds hpfs_inode->i_rddir_off[i] = pos; 45*1da177e4SLinus Torvalds hpfs_inode->i_rddir_off[i + 1] = NULL; 46*1da177e4SLinus Torvalds } 47*1da177e4SLinus Torvalds 48*1da177e4SLinus Torvalds void hpfs_del_pos(struct inode *inode, loff_t *pos) 49*1da177e4SLinus Torvalds { 50*1da177e4SLinus Torvalds struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); 51*1da177e4SLinus Torvalds loff_t **i, **j; 52*1da177e4SLinus Torvalds 53*1da177e4SLinus Torvalds if (!hpfs_inode->i_rddir_off) goto not_f; 54*1da177e4SLinus Torvalds for (i = hpfs_inode->i_rddir_off; *i; i++) if (*i == pos) goto fnd; 55*1da177e4SLinus Torvalds goto not_f; 56*1da177e4SLinus Torvalds fnd: 57*1da177e4SLinus Torvalds for (j = i + 1; *j; j++) ; 58*1da177e4SLinus Torvalds *i = *(j - 1); 59*1da177e4SLinus Torvalds *(j - 1) = NULL; 60*1da177e4SLinus Torvalds if (j - 1 == hpfs_inode->i_rddir_off) { 61*1da177e4SLinus Torvalds kfree(hpfs_inode->i_rddir_off); 62*1da177e4SLinus Torvalds hpfs_inode->i_rddir_off = NULL; 63*1da177e4SLinus Torvalds } 64*1da177e4SLinus Torvalds return; 65*1da177e4SLinus Torvalds not_f: 66*1da177e4SLinus Torvalds /*printk("HPFS: warning: position pointer %p->%08x not found\n", pos, (int)*pos);*/ 67*1da177e4SLinus Torvalds return; 68*1da177e4SLinus Torvalds } 69*1da177e4SLinus Torvalds 70*1da177e4SLinus Torvalds static void for_all_poss(struct inode *inode, void (*f)(loff_t *, loff_t, loff_t), 71*1da177e4SLinus Torvalds loff_t p1, loff_t p2) 72*1da177e4SLinus Torvalds { 73*1da177e4SLinus Torvalds struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); 74*1da177e4SLinus Torvalds loff_t **i; 75*1da177e4SLinus Torvalds 76*1da177e4SLinus Torvalds if (!hpfs_inode->i_rddir_off) return; 77*1da177e4SLinus Torvalds for (i = hpfs_inode->i_rddir_off; *i; i++) (*f)(*i, p1, p2); 78*1da177e4SLinus Torvalds return; 79*1da177e4SLinus Torvalds } 80*1da177e4SLinus Torvalds 81*1da177e4SLinus Torvalds static void hpfs_pos_subst(loff_t *p, loff_t f, loff_t t) 82*1da177e4SLinus Torvalds { 83*1da177e4SLinus Torvalds if (*p == f) *p = t; 84*1da177e4SLinus Torvalds } 85*1da177e4SLinus Torvalds 86*1da177e4SLinus Torvalds /*void hpfs_hpfs_pos_substd(loff_t *p, loff_t f, loff_t t) 87*1da177e4SLinus Torvalds { 88*1da177e4SLinus Torvalds if ((*p & ~0x3f) == (f & ~0x3f)) *p = (t & ~0x3f) | (*p & 0x3f); 89*1da177e4SLinus Torvalds }*/ 90*1da177e4SLinus Torvalds 91*1da177e4SLinus Torvalds static void hpfs_pos_ins(loff_t *p, loff_t d, loff_t c) 92*1da177e4SLinus Torvalds { 93*1da177e4SLinus Torvalds if ((*p & ~0x3f) == (d & ~0x3f) && (*p & 0x3f) >= (d & 0x3f)) { 94*1da177e4SLinus Torvalds int n = (*p & 0x3f) + c; 95*1da177e4SLinus Torvalds if (n > 0x3f) printk("HPFS: hpfs_pos_ins: %08x + %d\n", (int)*p, (int)c >> 8); 96*1da177e4SLinus Torvalds else *p = (*p & ~0x3f) | n; 97*1da177e4SLinus Torvalds } 98*1da177e4SLinus Torvalds } 99*1da177e4SLinus Torvalds 100*1da177e4SLinus Torvalds static void hpfs_pos_del(loff_t *p, loff_t d, loff_t c) 101*1da177e4SLinus Torvalds { 102*1da177e4SLinus Torvalds if ((*p & ~0x3f) == (d & ~0x3f) && (*p & 0x3f) >= (d & 0x3f)) { 103*1da177e4SLinus Torvalds int n = (*p & 0x3f) - c; 104*1da177e4SLinus Torvalds if (n < 1) printk("HPFS: hpfs_pos_ins: %08x - %d\n", (int)*p, (int)c >> 8); 105*1da177e4SLinus Torvalds else *p = (*p & ~0x3f) | n; 106*1da177e4SLinus Torvalds } 107*1da177e4SLinus Torvalds } 108*1da177e4SLinus Torvalds 109*1da177e4SLinus Torvalds static struct hpfs_dirent *dnode_pre_last_de(struct dnode *d) 110*1da177e4SLinus Torvalds { 111*1da177e4SLinus Torvalds struct hpfs_dirent *de, *de_end, *dee = NULL, *deee = NULL; 112*1da177e4SLinus Torvalds de_end = dnode_end_de(d); 113*1da177e4SLinus Torvalds for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { 114*1da177e4SLinus Torvalds deee = dee; dee = de; 115*1da177e4SLinus Torvalds } 116*1da177e4SLinus Torvalds return deee; 117*1da177e4SLinus Torvalds } 118*1da177e4SLinus Torvalds 119*1da177e4SLinus Torvalds static struct hpfs_dirent *dnode_last_de(struct dnode *d) 120*1da177e4SLinus Torvalds { 121*1da177e4SLinus Torvalds struct hpfs_dirent *de, *de_end, *dee = NULL; 122*1da177e4SLinus Torvalds de_end = dnode_end_de(d); 123*1da177e4SLinus Torvalds for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { 124*1da177e4SLinus Torvalds dee = de; 125*1da177e4SLinus Torvalds } 126*1da177e4SLinus Torvalds return dee; 127*1da177e4SLinus Torvalds } 128*1da177e4SLinus Torvalds 129*1da177e4SLinus Torvalds static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno ptr) 130*1da177e4SLinus Torvalds { 131*1da177e4SLinus Torvalds struct hpfs_dirent *de; 132*1da177e4SLinus Torvalds if (!(de = dnode_last_de(d))) { 133*1da177e4SLinus Torvalds hpfs_error(s, "set_last_pointer: empty dnode %08x", d->self); 134*1da177e4SLinus Torvalds return; 135*1da177e4SLinus Torvalds } 136*1da177e4SLinus Torvalds if (hpfs_sb(s)->sb_chk) { 137*1da177e4SLinus Torvalds if (de->down) { 138*1da177e4SLinus Torvalds hpfs_error(s, "set_last_pointer: dnode %08x has already last pointer %08x", 139*1da177e4SLinus Torvalds d->self, de_down_pointer(de)); 140*1da177e4SLinus Torvalds return; 141*1da177e4SLinus Torvalds } 142*1da177e4SLinus Torvalds if (de->length != 32) { 143*1da177e4SLinus Torvalds hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", d->self); 144*1da177e4SLinus Torvalds return; 145*1da177e4SLinus Torvalds } 146*1da177e4SLinus Torvalds } 147*1da177e4SLinus Torvalds if (ptr) { 148*1da177e4SLinus Torvalds if ((d->first_free += 4) > 2048) { 149*1da177e4SLinus Torvalds hpfs_error(s,"set_last_pointer: too long dnode %08x", d->self); 150*1da177e4SLinus Torvalds d->first_free -= 4; 151*1da177e4SLinus Torvalds return; 152*1da177e4SLinus Torvalds } 153*1da177e4SLinus Torvalds de->length = 36; 154*1da177e4SLinus Torvalds de->down = 1; 155*1da177e4SLinus Torvalds *(dnode_secno *)((char *)de + 32) = ptr; 156*1da177e4SLinus Torvalds } 157*1da177e4SLinus Torvalds } 158*1da177e4SLinus Torvalds 159*1da177e4SLinus Torvalds /* Add an entry to dnode and don't care if it grows over 2048 bytes */ 160*1da177e4SLinus Torvalds 161*1da177e4SLinus Torvalds struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d, unsigned char *name, 162*1da177e4SLinus Torvalds unsigned namelen, secno down_ptr) 163*1da177e4SLinus Torvalds { 164*1da177e4SLinus Torvalds struct hpfs_dirent *de; 165*1da177e4SLinus Torvalds struct hpfs_dirent *de_end = dnode_end_de(d); 166*1da177e4SLinus Torvalds unsigned d_size = de_size(namelen, down_ptr); 167*1da177e4SLinus Torvalds for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { 168*1da177e4SLinus Torvalds int c = hpfs_compare_names(s, name, namelen, de->name, de->namelen, de->last); 169*1da177e4SLinus Torvalds if (!c) { 170*1da177e4SLinus Torvalds hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, d->self); 171*1da177e4SLinus Torvalds return NULL; 172*1da177e4SLinus Torvalds } 173*1da177e4SLinus Torvalds if (c < 0) break; 174*1da177e4SLinus Torvalds } 175*1da177e4SLinus Torvalds memmove((char *)de + d_size, de, (char *)de_end - (char *)de); 176*1da177e4SLinus Torvalds memset(de, 0, d_size); 177*1da177e4SLinus Torvalds if (down_ptr) { 178*1da177e4SLinus Torvalds *(int *)((char *)de + d_size - 4) = down_ptr; 179*1da177e4SLinus Torvalds de->down = 1; 180*1da177e4SLinus Torvalds } 181*1da177e4SLinus Torvalds de->length = d_size; 182*1da177e4SLinus Torvalds if (down_ptr) de->down = 1; 183*1da177e4SLinus Torvalds de->not_8x3 = hpfs_is_name_long(name, namelen); 184*1da177e4SLinus Torvalds de->namelen = namelen; 185*1da177e4SLinus Torvalds memcpy(de->name, name, namelen); 186*1da177e4SLinus Torvalds d->first_free += d_size; 187*1da177e4SLinus Torvalds return de; 188*1da177e4SLinus Torvalds } 189*1da177e4SLinus Torvalds 190*1da177e4SLinus Torvalds /* Delete dirent and don't care about its subtree */ 191*1da177e4SLinus Torvalds 192*1da177e4SLinus Torvalds static void hpfs_delete_de(struct super_block *s, struct dnode *d, 193*1da177e4SLinus Torvalds struct hpfs_dirent *de) 194*1da177e4SLinus Torvalds { 195*1da177e4SLinus Torvalds if (de->last) { 196*1da177e4SLinus Torvalds hpfs_error(s, "attempt to delete last dirent in dnode %08x", d->self); 197*1da177e4SLinus Torvalds return; 198*1da177e4SLinus Torvalds } 199*1da177e4SLinus Torvalds d->first_free -= de->length; 200*1da177e4SLinus Torvalds memmove(de, de_next_de(de), d->first_free + (char *)d - (char *)de); 201*1da177e4SLinus Torvalds } 202*1da177e4SLinus Torvalds 203*1da177e4SLinus Torvalds static void fix_up_ptrs(struct super_block *s, struct dnode *d) 204*1da177e4SLinus Torvalds { 205*1da177e4SLinus Torvalds struct hpfs_dirent *de; 206*1da177e4SLinus Torvalds struct hpfs_dirent *de_end = dnode_end_de(d); 207*1da177e4SLinus Torvalds dnode_secno dno = d->self; 208*1da177e4SLinus Torvalds for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) 209*1da177e4SLinus Torvalds if (de->down) { 210*1da177e4SLinus Torvalds struct quad_buffer_head qbh; 211*1da177e4SLinus Torvalds struct dnode *dd; 212*1da177e4SLinus Torvalds if ((dd = hpfs_map_dnode(s, de_down_pointer(de), &qbh))) { 213*1da177e4SLinus Torvalds if (dd->up != dno || dd->root_dnode) { 214*1da177e4SLinus Torvalds dd->up = dno; 215*1da177e4SLinus Torvalds dd->root_dnode = 0; 216*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 217*1da177e4SLinus Torvalds } 218*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 219*1da177e4SLinus Torvalds } 220*1da177e4SLinus Torvalds } 221*1da177e4SLinus Torvalds } 222*1da177e4SLinus Torvalds 223*1da177e4SLinus Torvalds /* Add an entry to dnode and do dnode splitting if required */ 224*1da177e4SLinus Torvalds 225*1da177e4SLinus Torvalds static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, 226*1da177e4SLinus Torvalds unsigned char *name, unsigned namelen, 227*1da177e4SLinus Torvalds struct hpfs_dirent *new_de, dnode_secno down_ptr) 228*1da177e4SLinus Torvalds { 229*1da177e4SLinus Torvalds struct quad_buffer_head qbh, qbh1, qbh2; 230*1da177e4SLinus Torvalds struct dnode *d, *ad, *rd, *nd = NULL; 231*1da177e4SLinus Torvalds dnode_secno adno, rdno; 232*1da177e4SLinus Torvalds struct hpfs_dirent *de; 233*1da177e4SLinus Torvalds struct hpfs_dirent nde; 234*1da177e4SLinus Torvalds char *nname; 235*1da177e4SLinus Torvalds int h; 236*1da177e4SLinus Torvalds int pos; 237*1da177e4SLinus Torvalds struct buffer_head *bh; 238*1da177e4SLinus Torvalds struct fnode *fnode; 239*1da177e4SLinus Torvalds int c1, c2 = 0; 240*1da177e4SLinus Torvalds if (!(nname = kmalloc(256, GFP_NOFS))) { 241*1da177e4SLinus Torvalds printk("HPFS: out of memory, can't add to dnode\n"); 242*1da177e4SLinus Torvalds return 1; 243*1da177e4SLinus Torvalds } 244*1da177e4SLinus Torvalds go_up: 245*1da177e4SLinus Torvalds if (namelen >= 256) { 246*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "hpfs_add_to_dnode: namelen == %d", namelen); 247*1da177e4SLinus Torvalds if (nd) kfree(nd); 248*1da177e4SLinus Torvalds kfree(nname); 249*1da177e4SLinus Torvalds return 1; 250*1da177e4SLinus Torvalds } 251*1da177e4SLinus Torvalds if (!(d = hpfs_map_dnode(i->i_sb, dno, &qbh))) { 252*1da177e4SLinus Torvalds if (nd) kfree(nd); 253*1da177e4SLinus Torvalds kfree(nname); 254*1da177e4SLinus Torvalds return 1; 255*1da177e4SLinus Torvalds } 256*1da177e4SLinus Torvalds go_up_a: 257*1da177e4SLinus Torvalds if (hpfs_sb(i->i_sb)->sb_chk) 258*1da177e4SLinus Torvalds if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "hpfs_add_to_dnode")) { 259*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 260*1da177e4SLinus Torvalds if (nd) kfree(nd); 261*1da177e4SLinus Torvalds kfree(nname); 262*1da177e4SLinus Torvalds return 1; 263*1da177e4SLinus Torvalds } 264*1da177e4SLinus Torvalds if (d->first_free + de_size(namelen, down_ptr) <= 2048) { 265*1da177e4SLinus Torvalds loff_t t; 266*1da177e4SLinus Torvalds copy_de(de=hpfs_add_de(i->i_sb, d, name, namelen, down_ptr), new_de); 267*1da177e4SLinus Torvalds t = get_pos(d, de); 268*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_ins, t, 1); 269*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, 4, t); 270*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, 5, t + 1); 271*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 272*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 273*1da177e4SLinus Torvalds if (nd) kfree(nd); 274*1da177e4SLinus Torvalds kfree(nname); 275*1da177e4SLinus Torvalds return 0; 276*1da177e4SLinus Torvalds } 277*1da177e4SLinus Torvalds if (!nd) if (!(nd = kmalloc(0x924, GFP_NOFS))) { 278*1da177e4SLinus Torvalds /* 0x924 is a max size of dnode after adding a dirent with 279*1da177e4SLinus Torvalds max name length. We alloc this only once. There must 280*1da177e4SLinus Torvalds not be any error while splitting dnodes, otherwise the 281*1da177e4SLinus Torvalds whole directory, not only file we're adding, would 282*1da177e4SLinus Torvalds be lost. */ 283*1da177e4SLinus Torvalds printk("HPFS: out of memory for dnode splitting\n"); 284*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 285*1da177e4SLinus Torvalds kfree(nname); 286*1da177e4SLinus Torvalds return 1; 287*1da177e4SLinus Torvalds } 288*1da177e4SLinus Torvalds memcpy(nd, d, d->first_free); 289*1da177e4SLinus Torvalds copy_de(de = hpfs_add_de(i->i_sb, nd, name, namelen, down_ptr), new_de); 290*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_ins, get_pos(nd, de), 1); 291*1da177e4SLinus Torvalds h = ((char *)dnode_last_de(nd) - (char *)nd) / 2 + 10; 292*1da177e4SLinus Torvalds if (!(ad = hpfs_alloc_dnode(i->i_sb, d->up, &adno, &qbh1, 0))) { 293*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted"); 294*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 295*1da177e4SLinus Torvalds kfree(nd); 296*1da177e4SLinus Torvalds kfree(nname); 297*1da177e4SLinus Torvalds return 1; 298*1da177e4SLinus Torvalds } 299*1da177e4SLinus Torvalds i->i_size += 2048; 300*1da177e4SLinus Torvalds i->i_blocks += 4; 301*1da177e4SLinus Torvalds pos = 1; 302*1da177e4SLinus Torvalds for (de = dnode_first_de(nd); (char *)de_next_de(de) - (char *)nd < h; de = de_next_de(de)) { 303*1da177e4SLinus Torvalds copy_de(hpfs_add_de(i->i_sb, ad, de->name, de->namelen, de->down ? de_down_pointer(de) : 0), de); 304*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | pos, ((loff_t)adno << 4) | pos); 305*1da177e4SLinus Torvalds pos++; 306*1da177e4SLinus Torvalds } 307*1da177e4SLinus Torvalds copy_de(new_de = &nde, de); 308*1da177e4SLinus Torvalds memcpy(name = nname, de->name, namelen = de->namelen); 309*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | pos, 4); 310*1da177e4SLinus Torvalds down_ptr = adno; 311*1da177e4SLinus Torvalds set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0); 312*1da177e4SLinus Torvalds de = de_next_de(de); 313*1da177e4SLinus Torvalds memmove((char *)nd + 20, de, nd->first_free + (char *)nd - (char *)de); 314*1da177e4SLinus Torvalds nd->first_free -= (char *)de - (char *)nd - 20; 315*1da177e4SLinus Torvalds memcpy(d, nd, nd->first_free); 316*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_del, (loff_t)dno << 4, pos); 317*1da177e4SLinus Torvalds fix_up_ptrs(i->i_sb, ad); 318*1da177e4SLinus Torvalds if (!d->root_dnode) { 319*1da177e4SLinus Torvalds dno = ad->up = d->up; 320*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 321*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 322*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh1); 323*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 324*1da177e4SLinus Torvalds goto go_up; 325*1da177e4SLinus Torvalds } 326*1da177e4SLinus Torvalds if (!(rd = hpfs_alloc_dnode(i->i_sb, d->up, &rdno, &qbh2, 0))) { 327*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted"); 328*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 329*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 330*1da177e4SLinus Torvalds kfree(nd); 331*1da177e4SLinus Torvalds kfree(nname); 332*1da177e4SLinus Torvalds return 1; 333*1da177e4SLinus Torvalds } 334*1da177e4SLinus Torvalds i->i_size += 2048; 335*1da177e4SLinus Torvalds i->i_blocks += 4; 336*1da177e4SLinus Torvalds rd->root_dnode = 1; 337*1da177e4SLinus Torvalds rd->up = d->up; 338*1da177e4SLinus Torvalds if (!(fnode = hpfs_map_fnode(i->i_sb, d->up, &bh))) { 339*1da177e4SLinus Torvalds hpfs_free_dnode(i->i_sb, rdno); 340*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 341*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 342*1da177e4SLinus Torvalds hpfs_brelse4(&qbh2); 343*1da177e4SLinus Torvalds kfree(nd); 344*1da177e4SLinus Torvalds kfree(nname); 345*1da177e4SLinus Torvalds return 1; 346*1da177e4SLinus Torvalds } 347*1da177e4SLinus Torvalds fnode->u.external[0].disk_secno = rdno; 348*1da177e4SLinus Torvalds mark_buffer_dirty(bh); 349*1da177e4SLinus Torvalds brelse(bh); 350*1da177e4SLinus Torvalds d->up = ad->up = hpfs_i(i)->i_dno = rdno; 351*1da177e4SLinus Torvalds d->root_dnode = ad->root_dnode = 0; 352*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 353*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 354*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh1); 355*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 356*1da177e4SLinus Torvalds qbh = qbh2; 357*1da177e4SLinus Torvalds set_last_pointer(i->i_sb, rd, dno); 358*1da177e4SLinus Torvalds dno = rdno; 359*1da177e4SLinus Torvalds d = rd; 360*1da177e4SLinus Torvalds goto go_up_a; 361*1da177e4SLinus Torvalds } 362*1da177e4SLinus Torvalds 363*1da177e4SLinus Torvalds /* 364*1da177e4SLinus Torvalds * Add an entry to directory btree. 365*1da177e4SLinus Torvalds * I hate such crazy directory structure. 366*1da177e4SLinus Torvalds * It's easy to read but terrible to write. 367*1da177e4SLinus Torvalds * I wrote this directory code 4 times. 368*1da177e4SLinus Torvalds * I hope, now it's finally bug-free. 369*1da177e4SLinus Torvalds */ 370*1da177e4SLinus Torvalds 371*1da177e4SLinus Torvalds int hpfs_add_dirent(struct inode *i, unsigned char *name, unsigned namelen, 372*1da177e4SLinus Torvalds struct hpfs_dirent *new_de, int cdepth) 373*1da177e4SLinus Torvalds { 374*1da177e4SLinus Torvalds struct hpfs_inode_info *hpfs_inode = hpfs_i(i); 375*1da177e4SLinus Torvalds struct dnode *d; 376*1da177e4SLinus Torvalds struct hpfs_dirent *de, *de_end; 377*1da177e4SLinus Torvalds struct quad_buffer_head qbh; 378*1da177e4SLinus Torvalds dnode_secno dno; 379*1da177e4SLinus Torvalds int c; 380*1da177e4SLinus Torvalds int c1, c2 = 0; 381*1da177e4SLinus Torvalds dno = hpfs_inode->i_dno; 382*1da177e4SLinus Torvalds down: 383*1da177e4SLinus Torvalds if (hpfs_sb(i->i_sb)->sb_chk) 384*1da177e4SLinus Torvalds if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "hpfs_add_dirent")) return 1; 385*1da177e4SLinus Torvalds if (!(d = hpfs_map_dnode(i->i_sb, dno, &qbh))) return 1; 386*1da177e4SLinus Torvalds de_end = dnode_end_de(d); 387*1da177e4SLinus Torvalds for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { 388*1da177e4SLinus Torvalds if (!(c = hpfs_compare_names(i->i_sb, name, namelen, de->name, de->namelen, de->last))) { 389*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 390*1da177e4SLinus Torvalds return -1; 391*1da177e4SLinus Torvalds } 392*1da177e4SLinus Torvalds if (c < 0) { 393*1da177e4SLinus Torvalds if (de->down) { 394*1da177e4SLinus Torvalds dno = de_down_pointer(de); 395*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 396*1da177e4SLinus Torvalds goto down; 397*1da177e4SLinus Torvalds } 398*1da177e4SLinus Torvalds break; 399*1da177e4SLinus Torvalds } 400*1da177e4SLinus Torvalds } 401*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 402*1da177e4SLinus Torvalds if (!cdepth) hpfs_lock_creation(i->i_sb); 403*1da177e4SLinus Torvalds if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_ADD)) { 404*1da177e4SLinus Torvalds c = 1; 405*1da177e4SLinus Torvalds goto ret; 406*1da177e4SLinus Torvalds } 407*1da177e4SLinus Torvalds i->i_version++; 408*1da177e4SLinus Torvalds c = hpfs_add_to_dnode(i, dno, name, namelen, new_de, 0); 409*1da177e4SLinus Torvalds ret: 410*1da177e4SLinus Torvalds if (!cdepth) hpfs_unlock_creation(i->i_sb); 411*1da177e4SLinus Torvalds return c; 412*1da177e4SLinus Torvalds } 413*1da177e4SLinus Torvalds 414*1da177e4SLinus Torvalds /* 415*1da177e4SLinus Torvalds * Find dirent with higher name in 'from' subtree and move it to 'to' dnode. 416*1da177e4SLinus Torvalds * Return the dnode we moved from (to be checked later if it's empty) 417*1da177e4SLinus Torvalds */ 418*1da177e4SLinus Torvalds 419*1da177e4SLinus Torvalds static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to) 420*1da177e4SLinus Torvalds { 421*1da177e4SLinus Torvalds dnode_secno dno, ddno; 422*1da177e4SLinus Torvalds dnode_secno chk_up = to; 423*1da177e4SLinus Torvalds struct dnode *dnode; 424*1da177e4SLinus Torvalds struct quad_buffer_head qbh; 425*1da177e4SLinus Torvalds struct hpfs_dirent *de, *nde; 426*1da177e4SLinus Torvalds int a; 427*1da177e4SLinus Torvalds loff_t t; 428*1da177e4SLinus Torvalds int c1, c2 = 0; 429*1da177e4SLinus Torvalds dno = from; 430*1da177e4SLinus Torvalds while (1) { 431*1da177e4SLinus Torvalds if (hpfs_sb(i->i_sb)->sb_chk) 432*1da177e4SLinus Torvalds if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "move_to_top")) 433*1da177e4SLinus Torvalds return 0; 434*1da177e4SLinus Torvalds if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return 0; 435*1da177e4SLinus Torvalds if (hpfs_sb(i->i_sb)->sb_chk) { 436*1da177e4SLinus Torvalds if (dnode->up != chk_up) { 437*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "move_to_top: up pointer from %08x should be %08x, is %08x", 438*1da177e4SLinus Torvalds dno, chk_up, dnode->up); 439*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 440*1da177e4SLinus Torvalds return 0; 441*1da177e4SLinus Torvalds } 442*1da177e4SLinus Torvalds chk_up = dno; 443*1da177e4SLinus Torvalds } 444*1da177e4SLinus Torvalds if (!(de = dnode_last_de(dnode))) { 445*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "move_to_top: dnode %08x has no last de", dno); 446*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 447*1da177e4SLinus Torvalds return 0; 448*1da177e4SLinus Torvalds } 449*1da177e4SLinus Torvalds if (!de->down) break; 450*1da177e4SLinus Torvalds dno = de_down_pointer(de); 451*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 452*1da177e4SLinus Torvalds } 453*1da177e4SLinus Torvalds while (!(de = dnode_pre_last_de(dnode))) { 454*1da177e4SLinus Torvalds dnode_secno up = dnode->up; 455*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 456*1da177e4SLinus Torvalds hpfs_free_dnode(i->i_sb, dno); 457*1da177e4SLinus Torvalds i->i_size -= 2048; 458*1da177e4SLinus Torvalds i->i_blocks -= 4; 459*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, 5); 460*1da177e4SLinus Torvalds if (up == to) return to; 461*1da177e4SLinus Torvalds if (!(dnode = hpfs_map_dnode(i->i_sb, up, &qbh))) return 0; 462*1da177e4SLinus Torvalds if (dnode->root_dnode) { 463*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "move_to_top: got to root_dnode while moving from %08x to %08x", from, to); 464*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 465*1da177e4SLinus Torvalds return 0; 466*1da177e4SLinus Torvalds } 467*1da177e4SLinus Torvalds de = dnode_last_de(dnode); 468*1da177e4SLinus Torvalds if (!de || !de->down) { 469*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "move_to_top: dnode %08x doesn't point down to %08x", up, dno); 470*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 471*1da177e4SLinus Torvalds return 0; 472*1da177e4SLinus Torvalds } 473*1da177e4SLinus Torvalds dnode->first_free -= 4; 474*1da177e4SLinus Torvalds de->length -= 4; 475*1da177e4SLinus Torvalds de->down = 0; 476*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 477*1da177e4SLinus Torvalds dno = up; 478*1da177e4SLinus Torvalds } 479*1da177e4SLinus Torvalds t = get_pos(dnode, de); 480*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, t, 4); 481*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, t + 1, 5); 482*1da177e4SLinus Torvalds if (!(nde = kmalloc(de->length, GFP_NOFS))) { 483*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "out of memory for dirent - directory will be corrupted"); 484*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 485*1da177e4SLinus Torvalds return 0; 486*1da177e4SLinus Torvalds } 487*1da177e4SLinus Torvalds memcpy(nde, de, de->length); 488*1da177e4SLinus Torvalds ddno = de->down ? de_down_pointer(de) : 0; 489*1da177e4SLinus Torvalds hpfs_delete_de(i->i_sb, dnode, de); 490*1da177e4SLinus Torvalds set_last_pointer(i->i_sb, dnode, ddno); 491*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 492*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 493*1da177e4SLinus Torvalds a = hpfs_add_to_dnode(i, to, nde->name, nde->namelen, nde, from); 494*1da177e4SLinus Torvalds kfree(nde); 495*1da177e4SLinus Torvalds if (a) return 0; 496*1da177e4SLinus Torvalds return dno; 497*1da177e4SLinus Torvalds } 498*1da177e4SLinus Torvalds 499*1da177e4SLinus Torvalds /* 500*1da177e4SLinus Torvalds * Check if a dnode is empty and delete it from the tree 501*1da177e4SLinus Torvalds * (chkdsk doesn't like empty dnodes) 502*1da177e4SLinus Torvalds */ 503*1da177e4SLinus Torvalds 504*1da177e4SLinus Torvalds static void delete_empty_dnode(struct inode *i, dnode_secno dno) 505*1da177e4SLinus Torvalds { 506*1da177e4SLinus Torvalds struct hpfs_inode_info *hpfs_inode = hpfs_i(i); 507*1da177e4SLinus Torvalds struct quad_buffer_head qbh; 508*1da177e4SLinus Torvalds struct dnode *dnode; 509*1da177e4SLinus Torvalds dnode_secno down, up, ndown; 510*1da177e4SLinus Torvalds int p; 511*1da177e4SLinus Torvalds struct hpfs_dirent *de; 512*1da177e4SLinus Torvalds int c1, c2 = 0; 513*1da177e4SLinus Torvalds try_it_again: 514*1da177e4SLinus Torvalds if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "delete_empty_dnode")) return; 515*1da177e4SLinus Torvalds if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return; 516*1da177e4SLinus Torvalds if (dnode->first_free > 56) goto end; 517*1da177e4SLinus Torvalds if (dnode->first_free == 52 || dnode->first_free == 56) { 518*1da177e4SLinus Torvalds struct hpfs_dirent *de_end; 519*1da177e4SLinus Torvalds int root = dnode->root_dnode; 520*1da177e4SLinus Torvalds up = dnode->up; 521*1da177e4SLinus Torvalds de = dnode_first_de(dnode); 522*1da177e4SLinus Torvalds down = de->down ? de_down_pointer(de) : 0; 523*1da177e4SLinus Torvalds if (hpfs_sb(i->i_sb)->sb_chk) if (root && !down) { 524*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "delete_empty_dnode: root dnode %08x is empty", dno); 525*1da177e4SLinus Torvalds goto end; 526*1da177e4SLinus Torvalds } 527*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 528*1da177e4SLinus Torvalds hpfs_free_dnode(i->i_sb, dno); 529*1da177e4SLinus Torvalds i->i_size -= 2048; 530*1da177e4SLinus Torvalds i->i_blocks -= 4; 531*1da177e4SLinus Torvalds if (root) { 532*1da177e4SLinus Torvalds struct fnode *fnode; 533*1da177e4SLinus Torvalds struct buffer_head *bh; 534*1da177e4SLinus Torvalds struct dnode *d1; 535*1da177e4SLinus Torvalds struct quad_buffer_head qbh1; 536*1da177e4SLinus Torvalds if (hpfs_sb(i->i_sb)->sb_chk) if (up != i->i_ino) { 537*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "bad pointer to fnode, dnode %08x, pointing to %08x, should be %08x", dno, up, i->i_ino); 538*1da177e4SLinus Torvalds return; 539*1da177e4SLinus Torvalds } 540*1da177e4SLinus Torvalds if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { 541*1da177e4SLinus Torvalds d1->up = up; 542*1da177e4SLinus Torvalds d1->root_dnode = 1; 543*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh1); 544*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 545*1da177e4SLinus Torvalds } 546*1da177e4SLinus Torvalds if ((fnode = hpfs_map_fnode(i->i_sb, up, &bh))) { 547*1da177e4SLinus Torvalds fnode->u.external[0].disk_secno = down; 548*1da177e4SLinus Torvalds mark_buffer_dirty(bh); 549*1da177e4SLinus Torvalds brelse(bh); 550*1da177e4SLinus Torvalds } 551*1da177e4SLinus Torvalds hpfs_inode->i_dno = down; 552*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, (loff_t) 12); 553*1da177e4SLinus Torvalds return; 554*1da177e4SLinus Torvalds } 555*1da177e4SLinus Torvalds if (!(dnode = hpfs_map_dnode(i->i_sb, up, &qbh))) return; 556*1da177e4SLinus Torvalds p = 1; 557*1da177e4SLinus Torvalds de_end = dnode_end_de(dnode); 558*1da177e4SLinus Torvalds for (de = dnode_first_de(dnode); de < de_end; de = de_next_de(de), p++) 559*1da177e4SLinus Torvalds if (de->down) if (de_down_pointer(de) == dno) goto fnd; 560*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "delete_empty_dnode: pointer to dnode %08x not found in dnode %08x", dno, up); 561*1da177e4SLinus Torvalds goto end; 562*1da177e4SLinus Torvalds fnd: 563*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, ((loff_t)up << 4) | p); 564*1da177e4SLinus Torvalds if (!down) { 565*1da177e4SLinus Torvalds de->down = 0; 566*1da177e4SLinus Torvalds de->length -= 4; 567*1da177e4SLinus Torvalds dnode->first_free -= 4; 568*1da177e4SLinus Torvalds memmove(de_next_de(de), (char *)de_next_de(de) + 4, 569*1da177e4SLinus Torvalds (char *)dnode + dnode->first_free - (char *)de_next_de(de)); 570*1da177e4SLinus Torvalds } else { 571*1da177e4SLinus Torvalds struct dnode *d1; 572*1da177e4SLinus Torvalds struct quad_buffer_head qbh1; 573*1da177e4SLinus Torvalds *(dnode_secno *) ((void *) de + de->length - 4) = down; 574*1da177e4SLinus Torvalds if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { 575*1da177e4SLinus Torvalds d1->up = up; 576*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh1); 577*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 578*1da177e4SLinus Torvalds } 579*1da177e4SLinus Torvalds } 580*1da177e4SLinus Torvalds } else { 581*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, dnode->first_free); 582*1da177e4SLinus Torvalds goto end; 583*1da177e4SLinus Torvalds } 584*1da177e4SLinus Torvalds 585*1da177e4SLinus Torvalds if (!de->last) { 586*1da177e4SLinus Torvalds struct hpfs_dirent *de_next = de_next_de(de); 587*1da177e4SLinus Torvalds struct hpfs_dirent *de_cp; 588*1da177e4SLinus Torvalds struct dnode *d1; 589*1da177e4SLinus Torvalds struct quad_buffer_head qbh1; 590*1da177e4SLinus Torvalds if (!de_next->down) goto endm; 591*1da177e4SLinus Torvalds ndown = de_down_pointer(de_next); 592*1da177e4SLinus Torvalds if (!(de_cp = kmalloc(de->length, GFP_NOFS))) { 593*1da177e4SLinus Torvalds printk("HPFS: out of memory for dtree balancing\n"); 594*1da177e4SLinus Torvalds goto endm; 595*1da177e4SLinus Torvalds } 596*1da177e4SLinus Torvalds memcpy(de_cp, de, de->length); 597*1da177e4SLinus Torvalds hpfs_delete_de(i->i_sb, dnode, de); 598*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 599*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 600*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, 4); 601*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_del, ((loff_t)up << 4) | p, 1); 602*1da177e4SLinus Torvalds if (de_cp->down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de_cp), &qbh1))) { 603*1da177e4SLinus Torvalds d1->up = ndown; 604*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh1); 605*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 606*1da177e4SLinus Torvalds } 607*1da177e4SLinus Torvalds hpfs_add_to_dnode(i, ndown, de_cp->name, de_cp->namelen, de_cp, de_cp->down ? de_down_pointer(de_cp) : 0); 608*1da177e4SLinus Torvalds /*printk("UP-TO-DNODE: %08x (ndown = %08x, down = %08x, dno = %08x)\n", up, ndown, down, dno);*/ 609*1da177e4SLinus Torvalds dno = up; 610*1da177e4SLinus Torvalds kfree(de_cp); 611*1da177e4SLinus Torvalds goto try_it_again; 612*1da177e4SLinus Torvalds } else { 613*1da177e4SLinus Torvalds struct hpfs_dirent *de_prev = dnode_pre_last_de(dnode); 614*1da177e4SLinus Torvalds struct hpfs_dirent *de_cp; 615*1da177e4SLinus Torvalds struct dnode *d1; 616*1da177e4SLinus Torvalds struct quad_buffer_head qbh1; 617*1da177e4SLinus Torvalds dnode_secno dlp; 618*1da177e4SLinus Torvalds if (!de_prev) { 619*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "delete_empty_dnode: empty dnode %08x", up); 620*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 621*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 622*1da177e4SLinus Torvalds dno = up; 623*1da177e4SLinus Torvalds goto try_it_again; 624*1da177e4SLinus Torvalds } 625*1da177e4SLinus Torvalds if (!de_prev->down) goto endm; 626*1da177e4SLinus Torvalds ndown = de_down_pointer(de_prev); 627*1da177e4SLinus Torvalds if ((d1 = hpfs_map_dnode(i->i_sb, ndown, &qbh1))) { 628*1da177e4SLinus Torvalds struct hpfs_dirent *del = dnode_last_de(d1); 629*1da177e4SLinus Torvalds dlp = del->down ? de_down_pointer(del) : 0; 630*1da177e4SLinus Torvalds if (!dlp && down) { 631*1da177e4SLinus Torvalds if (d1->first_free > 2044) { 632*1da177e4SLinus Torvalds if (hpfs_sb(i->i_sb)->sb_chk >= 2) { 633*1da177e4SLinus Torvalds printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n"); 634*1da177e4SLinus Torvalds printk("HPFS: warning: terminating balancing operation\n"); 635*1da177e4SLinus Torvalds } 636*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 637*1da177e4SLinus Torvalds goto endm; 638*1da177e4SLinus Torvalds } 639*1da177e4SLinus Torvalds if (hpfs_sb(i->i_sb)->sb_chk >= 2) { 640*1da177e4SLinus Torvalds printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n"); 641*1da177e4SLinus Torvalds printk("HPFS: warning: goin'on\n"); 642*1da177e4SLinus Torvalds } 643*1da177e4SLinus Torvalds del->length += 4; 644*1da177e4SLinus Torvalds del->down = 1; 645*1da177e4SLinus Torvalds d1->first_free += 4; 646*1da177e4SLinus Torvalds } 647*1da177e4SLinus Torvalds if (dlp && !down) { 648*1da177e4SLinus Torvalds del->length -= 4; 649*1da177e4SLinus Torvalds del->down = 0; 650*1da177e4SLinus Torvalds d1->first_free -= 4; 651*1da177e4SLinus Torvalds } else if (down) 652*1da177e4SLinus Torvalds *(dnode_secno *) ((void *) del + del->length - 4) = down; 653*1da177e4SLinus Torvalds } else goto endm; 654*1da177e4SLinus Torvalds if (!(de_cp = kmalloc(de_prev->length, GFP_NOFS))) { 655*1da177e4SLinus Torvalds printk("HPFS: out of memory for dtree balancing\n"); 656*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 657*1da177e4SLinus Torvalds goto endm; 658*1da177e4SLinus Torvalds } 659*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh1); 660*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 661*1da177e4SLinus Torvalds memcpy(de_cp, de_prev, de_prev->length); 662*1da177e4SLinus Torvalds hpfs_delete_de(i->i_sb, dnode, de_prev); 663*1da177e4SLinus Torvalds if (!de_prev->down) { 664*1da177e4SLinus Torvalds de_prev->length += 4; 665*1da177e4SLinus Torvalds de_prev->down = 1; 666*1da177e4SLinus Torvalds dnode->first_free += 4; 667*1da177e4SLinus Torvalds } 668*1da177e4SLinus Torvalds *(dnode_secno *) ((void *) de_prev + de_prev->length - 4) = ndown; 669*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 670*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 671*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4); 672*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, ((loff_t)up << 4) | (p - 1)); 673*1da177e4SLinus Torvalds if (down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de), &qbh1))) { 674*1da177e4SLinus Torvalds d1->up = ndown; 675*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh1); 676*1da177e4SLinus Torvalds hpfs_brelse4(&qbh1); 677*1da177e4SLinus Torvalds } 678*1da177e4SLinus Torvalds hpfs_add_to_dnode(i, ndown, de_cp->name, de_cp->namelen, de_cp, dlp); 679*1da177e4SLinus Torvalds dno = up; 680*1da177e4SLinus Torvalds kfree(de_cp); 681*1da177e4SLinus Torvalds goto try_it_again; 682*1da177e4SLinus Torvalds } 683*1da177e4SLinus Torvalds endm: 684*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(&qbh); 685*1da177e4SLinus Torvalds end: 686*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 687*1da177e4SLinus Torvalds } 688*1da177e4SLinus Torvalds 689*1da177e4SLinus Torvalds 690*1da177e4SLinus Torvalds /* Delete dirent from directory */ 691*1da177e4SLinus Torvalds 692*1da177e4SLinus Torvalds int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de, 693*1da177e4SLinus Torvalds struct quad_buffer_head *qbh, int depth) 694*1da177e4SLinus Torvalds { 695*1da177e4SLinus Torvalds struct dnode *dnode = qbh->data; 696*1da177e4SLinus Torvalds dnode_secno down = 0; 697*1da177e4SLinus Torvalds int lock = 0; 698*1da177e4SLinus Torvalds loff_t t; 699*1da177e4SLinus Torvalds if (de->first || de->last) { 700*1da177e4SLinus Torvalds hpfs_error(i->i_sb, "hpfs_remove_dirent: attempt to delete first or last dirent in dnode %08x", dno); 701*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 702*1da177e4SLinus Torvalds return 1; 703*1da177e4SLinus Torvalds } 704*1da177e4SLinus Torvalds if (de->down) down = de_down_pointer(de); 705*1da177e4SLinus Torvalds if (depth && (de->down || (de == dnode_first_de(dnode) && de_next_de(de)->last))) { 706*1da177e4SLinus Torvalds lock = 1; 707*1da177e4SLinus Torvalds hpfs_lock_creation(i->i_sb); 708*1da177e4SLinus Torvalds if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_DEL)) { 709*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 710*1da177e4SLinus Torvalds hpfs_unlock_creation(i->i_sb); 711*1da177e4SLinus Torvalds return 2; 712*1da177e4SLinus Torvalds } 713*1da177e4SLinus Torvalds } 714*1da177e4SLinus Torvalds i->i_version++; 715*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_del, (t = get_pos(dnode, de)) + 1, 1); 716*1da177e4SLinus Torvalds hpfs_delete_de(i->i_sb, dnode, de); 717*1da177e4SLinus Torvalds hpfs_mark_4buffers_dirty(qbh); 718*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 719*1da177e4SLinus Torvalds if (down) { 720*1da177e4SLinus Torvalds dnode_secno a = move_to_top(i, down, dno); 721*1da177e4SLinus Torvalds for_all_poss(i, hpfs_pos_subst, 5, t); 722*1da177e4SLinus Torvalds if (a) delete_empty_dnode(i, a); 723*1da177e4SLinus Torvalds if (lock) hpfs_unlock_creation(i->i_sb); 724*1da177e4SLinus Torvalds return !a; 725*1da177e4SLinus Torvalds } 726*1da177e4SLinus Torvalds delete_empty_dnode(i, dno); 727*1da177e4SLinus Torvalds if (lock) hpfs_unlock_creation(i->i_sb); 728*1da177e4SLinus Torvalds return 0; 729*1da177e4SLinus Torvalds } 730*1da177e4SLinus Torvalds 731*1da177e4SLinus Torvalds void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes, 732*1da177e4SLinus Torvalds int *n_subdirs, int *n_items) 733*1da177e4SLinus Torvalds { 734*1da177e4SLinus Torvalds struct dnode *dnode; 735*1da177e4SLinus Torvalds struct quad_buffer_head qbh; 736*1da177e4SLinus Torvalds struct hpfs_dirent *de; 737*1da177e4SLinus Torvalds dnode_secno ptr, odno = 0; 738*1da177e4SLinus Torvalds int c1, c2 = 0; 739*1da177e4SLinus Torvalds int d1, d2 = 0; 740*1da177e4SLinus Torvalds go_down: 741*1da177e4SLinus Torvalds if (n_dnodes) (*n_dnodes)++; 742*1da177e4SLinus Torvalds if (hpfs_sb(s)->sb_chk) 743*1da177e4SLinus Torvalds if (hpfs_stop_cycles(s, dno, &c1, &c2, "hpfs_count_dnodes #1")) return; 744*1da177e4SLinus Torvalds ptr = 0; 745*1da177e4SLinus Torvalds go_up: 746*1da177e4SLinus Torvalds if (!(dnode = hpfs_map_dnode(s, dno, &qbh))) return; 747*1da177e4SLinus Torvalds if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && dnode->up != odno) 748*1da177e4SLinus Torvalds hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, dnode->up); 749*1da177e4SLinus Torvalds de = dnode_first_de(dnode); 750*1da177e4SLinus Torvalds if (ptr) while(1) { 751*1da177e4SLinus Torvalds if (de->down) if (de_down_pointer(de) == ptr) goto process_de; 752*1da177e4SLinus Torvalds if (de->last) { 753*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 754*1da177e4SLinus Torvalds hpfs_error(s, "hpfs_count_dnodes: pointer to dnode %08x not found in dnode %08x, got here from %08x", 755*1da177e4SLinus Torvalds ptr, dno, odno); 756*1da177e4SLinus Torvalds return; 757*1da177e4SLinus Torvalds } 758*1da177e4SLinus Torvalds de = de_next_de(de); 759*1da177e4SLinus Torvalds } 760*1da177e4SLinus Torvalds next_de: 761*1da177e4SLinus Torvalds if (de->down) { 762*1da177e4SLinus Torvalds odno = dno; 763*1da177e4SLinus Torvalds dno = de_down_pointer(de); 764*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 765*1da177e4SLinus Torvalds goto go_down; 766*1da177e4SLinus Torvalds } 767*1da177e4SLinus Torvalds process_de: 768*1da177e4SLinus Torvalds if (!de->first && !de->last && de->directory && n_subdirs) (*n_subdirs)++; 769*1da177e4SLinus Torvalds if (!de->first && !de->last && n_items) (*n_items)++; 770*1da177e4SLinus Torvalds if ((de = de_next_de(de)) < dnode_end_de(dnode)) goto next_de; 771*1da177e4SLinus Torvalds ptr = dno; 772*1da177e4SLinus Torvalds dno = dnode->up; 773*1da177e4SLinus Torvalds if (dnode->root_dnode) { 774*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 775*1da177e4SLinus Torvalds return; 776*1da177e4SLinus Torvalds } 777*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 778*1da177e4SLinus Torvalds if (hpfs_sb(s)->sb_chk) 779*1da177e4SLinus Torvalds if (hpfs_stop_cycles(s, ptr, &d1, &d2, "hpfs_count_dnodes #2")) return; 780*1da177e4SLinus Torvalds odno = -1; 781*1da177e4SLinus Torvalds goto go_up; 782*1da177e4SLinus Torvalds } 783*1da177e4SLinus Torvalds 784*1da177e4SLinus Torvalds static struct hpfs_dirent *map_nth_dirent(struct super_block *s, dnode_secno dno, int n, 785*1da177e4SLinus Torvalds struct quad_buffer_head *qbh, struct dnode **dn) 786*1da177e4SLinus Torvalds { 787*1da177e4SLinus Torvalds int i; 788*1da177e4SLinus Torvalds struct hpfs_dirent *de, *de_end; 789*1da177e4SLinus Torvalds struct dnode *dnode; 790*1da177e4SLinus Torvalds dnode = hpfs_map_dnode(s, dno, qbh); 791*1da177e4SLinus Torvalds if (!dnode) return NULL; 792*1da177e4SLinus Torvalds if (dn) *dn=dnode; 793*1da177e4SLinus Torvalds de = dnode_first_de(dnode); 794*1da177e4SLinus Torvalds de_end = dnode_end_de(dnode); 795*1da177e4SLinus Torvalds for (i = 1; de < de_end; i++, de = de_next_de(de)) { 796*1da177e4SLinus Torvalds if (i == n) { 797*1da177e4SLinus Torvalds return de; 798*1da177e4SLinus Torvalds } 799*1da177e4SLinus Torvalds if (de->last) break; 800*1da177e4SLinus Torvalds } 801*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 802*1da177e4SLinus Torvalds hpfs_error(s, "map_nth_dirent: n too high; dnode = %08x, requested %08x", dno, n); 803*1da177e4SLinus Torvalds return NULL; 804*1da177e4SLinus Torvalds } 805*1da177e4SLinus Torvalds 806*1da177e4SLinus Torvalds dnode_secno hpfs_de_as_down_as_possible(struct super_block *s, dnode_secno dno) 807*1da177e4SLinus Torvalds { 808*1da177e4SLinus Torvalds struct quad_buffer_head qbh; 809*1da177e4SLinus Torvalds dnode_secno d = dno; 810*1da177e4SLinus Torvalds dnode_secno up = 0; 811*1da177e4SLinus Torvalds struct hpfs_dirent *de; 812*1da177e4SLinus Torvalds int c1, c2 = 0; 813*1da177e4SLinus Torvalds 814*1da177e4SLinus Torvalds again: 815*1da177e4SLinus Torvalds if (hpfs_sb(s)->sb_chk) 816*1da177e4SLinus Torvalds if (hpfs_stop_cycles(s, d, &c1, &c2, "hpfs_de_as_down_as_possible")) 817*1da177e4SLinus Torvalds return d; 818*1da177e4SLinus Torvalds if (!(de = map_nth_dirent(s, d, 1, &qbh, NULL))) return dno; 819*1da177e4SLinus Torvalds if (hpfs_sb(s)->sb_chk) 820*1da177e4SLinus Torvalds if (up && ((struct dnode *)qbh.data)->up != up) 821*1da177e4SLinus Torvalds hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, ((struct dnode *)qbh.data)->up); 822*1da177e4SLinus Torvalds if (!de->down) { 823*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 824*1da177e4SLinus Torvalds return d; 825*1da177e4SLinus Torvalds } 826*1da177e4SLinus Torvalds up = d; 827*1da177e4SLinus Torvalds d = de_down_pointer(de); 828*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 829*1da177e4SLinus Torvalds goto again; 830*1da177e4SLinus Torvalds } 831*1da177e4SLinus Torvalds 832*1da177e4SLinus Torvalds struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp, 833*1da177e4SLinus Torvalds struct quad_buffer_head *qbh) 834*1da177e4SLinus Torvalds { 835*1da177e4SLinus Torvalds loff_t pos; 836*1da177e4SLinus Torvalds unsigned c; 837*1da177e4SLinus Torvalds dnode_secno dno; 838*1da177e4SLinus Torvalds struct hpfs_dirent *de, *d; 839*1da177e4SLinus Torvalds struct hpfs_dirent *up_de; 840*1da177e4SLinus Torvalds struct hpfs_dirent *end_up_de; 841*1da177e4SLinus Torvalds struct dnode *dnode; 842*1da177e4SLinus Torvalds struct dnode *up_dnode; 843*1da177e4SLinus Torvalds struct quad_buffer_head qbh0; 844*1da177e4SLinus Torvalds 845*1da177e4SLinus Torvalds pos = *posp; 846*1da177e4SLinus Torvalds dno = pos >> 6 << 2; 847*1da177e4SLinus Torvalds pos &= 077; 848*1da177e4SLinus Torvalds if (!(de = map_nth_dirent(inode->i_sb, dno, pos, qbh, &dnode))) 849*1da177e4SLinus Torvalds goto bail; 850*1da177e4SLinus Torvalds 851*1da177e4SLinus Torvalds /* Going to the next dirent */ 852*1da177e4SLinus Torvalds if ((d = de_next_de(de)) < dnode_end_de(dnode)) { 853*1da177e4SLinus Torvalds if (!(++*posp & 077)) { 854*1da177e4SLinus Torvalds hpfs_error(inode->i_sb, "map_pos_dirent: pos crossed dnode boundary; pos = %08x", *posp); 855*1da177e4SLinus Torvalds goto bail; 856*1da177e4SLinus Torvalds } 857*1da177e4SLinus Torvalds /* We're going down the tree */ 858*1da177e4SLinus Torvalds if (d->down) { 859*1da177e4SLinus Torvalds *posp = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, de_down_pointer(d)) << 4) + 1; 860*1da177e4SLinus Torvalds } 861*1da177e4SLinus Torvalds 862*1da177e4SLinus Torvalds return de; 863*1da177e4SLinus Torvalds } 864*1da177e4SLinus Torvalds 865*1da177e4SLinus Torvalds /* Going up */ 866*1da177e4SLinus Torvalds if (dnode->root_dnode) goto bail; 867*1da177e4SLinus Torvalds 868*1da177e4SLinus Torvalds if (!(up_dnode = hpfs_map_dnode(inode->i_sb, dnode->up, &qbh0))) 869*1da177e4SLinus Torvalds goto bail; 870*1da177e4SLinus Torvalds 871*1da177e4SLinus Torvalds end_up_de = dnode_end_de(up_dnode); 872*1da177e4SLinus Torvalds c = 0; 873*1da177e4SLinus Torvalds for (up_de = dnode_first_de(up_dnode); up_de < end_up_de; 874*1da177e4SLinus Torvalds up_de = de_next_de(up_de)) { 875*1da177e4SLinus Torvalds if (!(++c & 077)) hpfs_error(inode->i_sb, 876*1da177e4SLinus Torvalds "map_pos_dirent: pos crossed dnode boundary; dnode = %08x", dnode->up); 877*1da177e4SLinus Torvalds if (up_de->down && de_down_pointer(up_de) == dno) { 878*1da177e4SLinus Torvalds *posp = ((loff_t) dnode->up << 4) + c; 879*1da177e4SLinus Torvalds hpfs_brelse4(&qbh0); 880*1da177e4SLinus Torvalds return de; 881*1da177e4SLinus Torvalds } 882*1da177e4SLinus Torvalds } 883*1da177e4SLinus Torvalds 884*1da177e4SLinus Torvalds hpfs_error(inode->i_sb, "map_pos_dirent: pointer to dnode %08x not found in parent dnode %08x", 885*1da177e4SLinus Torvalds dno, dnode->up); 886*1da177e4SLinus Torvalds hpfs_brelse4(&qbh0); 887*1da177e4SLinus Torvalds 888*1da177e4SLinus Torvalds bail: 889*1da177e4SLinus Torvalds *posp = 12; 890*1da177e4SLinus Torvalds return de; 891*1da177e4SLinus Torvalds } 892*1da177e4SLinus Torvalds 893*1da177e4SLinus Torvalds /* Find a dirent in tree */ 894*1da177e4SLinus Torvalds 895*1da177e4SLinus Torvalds struct hpfs_dirent *map_dirent(struct inode *inode, dnode_secno dno, char *name, unsigned len, 896*1da177e4SLinus Torvalds dnode_secno *dd, struct quad_buffer_head *qbh) 897*1da177e4SLinus Torvalds { 898*1da177e4SLinus Torvalds struct dnode *dnode; 899*1da177e4SLinus Torvalds struct hpfs_dirent *de; 900*1da177e4SLinus Torvalds struct hpfs_dirent *de_end; 901*1da177e4SLinus Torvalds int c1, c2 = 0; 902*1da177e4SLinus Torvalds 903*1da177e4SLinus Torvalds if (!S_ISDIR(inode->i_mode)) hpfs_error(inode->i_sb, "map_dirent: not a directory\n"); 904*1da177e4SLinus Torvalds again: 905*1da177e4SLinus Torvalds if (hpfs_sb(inode->i_sb)->sb_chk) 906*1da177e4SLinus Torvalds if (hpfs_stop_cycles(inode->i_sb, dno, &c1, &c2, "map_dirent")) return NULL; 907*1da177e4SLinus Torvalds if (!(dnode = hpfs_map_dnode(inode->i_sb, dno, qbh))) return NULL; 908*1da177e4SLinus Torvalds 909*1da177e4SLinus Torvalds de_end = dnode_end_de(dnode); 910*1da177e4SLinus Torvalds for (de = dnode_first_de(dnode); de < de_end; de = de_next_de(de)) { 911*1da177e4SLinus Torvalds int t = hpfs_compare_names(inode->i_sb, name, len, de->name, de->namelen, de->last); 912*1da177e4SLinus Torvalds if (!t) { 913*1da177e4SLinus Torvalds if (dd) *dd = dno; 914*1da177e4SLinus Torvalds return de; 915*1da177e4SLinus Torvalds } 916*1da177e4SLinus Torvalds if (t < 0) { 917*1da177e4SLinus Torvalds if (de->down) { 918*1da177e4SLinus Torvalds dno = de_down_pointer(de); 919*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 920*1da177e4SLinus Torvalds goto again; 921*1da177e4SLinus Torvalds } 922*1da177e4SLinus Torvalds break; 923*1da177e4SLinus Torvalds } 924*1da177e4SLinus Torvalds } 925*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 926*1da177e4SLinus Torvalds return NULL; 927*1da177e4SLinus Torvalds } 928*1da177e4SLinus Torvalds 929*1da177e4SLinus Torvalds /* 930*1da177e4SLinus Torvalds * Remove empty directory. In normal cases it is only one dnode with two 931*1da177e4SLinus Torvalds * entries, but we must handle also such obscure cases when it's a tree 932*1da177e4SLinus Torvalds * of empty dnodes. 933*1da177e4SLinus Torvalds */ 934*1da177e4SLinus Torvalds 935*1da177e4SLinus Torvalds void hpfs_remove_dtree(struct super_block *s, dnode_secno dno) 936*1da177e4SLinus Torvalds { 937*1da177e4SLinus Torvalds struct quad_buffer_head qbh; 938*1da177e4SLinus Torvalds struct dnode *dnode; 939*1da177e4SLinus Torvalds struct hpfs_dirent *de; 940*1da177e4SLinus Torvalds dnode_secno d1, d2, rdno = dno; 941*1da177e4SLinus Torvalds while (1) { 942*1da177e4SLinus Torvalds if (!(dnode = hpfs_map_dnode(s, dno, &qbh))) return; 943*1da177e4SLinus Torvalds de = dnode_first_de(dnode); 944*1da177e4SLinus Torvalds if (de->last) { 945*1da177e4SLinus Torvalds if (de->down) d1 = de_down_pointer(de); 946*1da177e4SLinus Torvalds else goto error; 947*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 948*1da177e4SLinus Torvalds hpfs_free_dnode(s, dno); 949*1da177e4SLinus Torvalds dno = d1; 950*1da177e4SLinus Torvalds } else break; 951*1da177e4SLinus Torvalds } 952*1da177e4SLinus Torvalds if (!de->first) goto error; 953*1da177e4SLinus Torvalds d1 = de->down ? de_down_pointer(de) : 0; 954*1da177e4SLinus Torvalds de = de_next_de(de); 955*1da177e4SLinus Torvalds if (!de->last) goto error; 956*1da177e4SLinus Torvalds d2 = de->down ? de_down_pointer(de) : 0; 957*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 958*1da177e4SLinus Torvalds hpfs_free_dnode(s, dno); 959*1da177e4SLinus Torvalds do { 960*1da177e4SLinus Torvalds while (d1) { 961*1da177e4SLinus Torvalds if (!(dnode = hpfs_map_dnode(s, dno = d1, &qbh))) return; 962*1da177e4SLinus Torvalds de = dnode_first_de(dnode); 963*1da177e4SLinus Torvalds if (!de->last) goto error; 964*1da177e4SLinus Torvalds d1 = de->down ? de_down_pointer(de) : 0; 965*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 966*1da177e4SLinus Torvalds hpfs_free_dnode(s, dno); 967*1da177e4SLinus Torvalds } 968*1da177e4SLinus Torvalds d1 = d2; 969*1da177e4SLinus Torvalds d2 = 0; 970*1da177e4SLinus Torvalds } while (d1); 971*1da177e4SLinus Torvalds return; 972*1da177e4SLinus Torvalds error: 973*1da177e4SLinus Torvalds hpfs_brelse4(&qbh); 974*1da177e4SLinus Torvalds hpfs_free_dnode(s, dno); 975*1da177e4SLinus Torvalds hpfs_error(s, "directory %08x is corrupted or not empty", rdno); 976*1da177e4SLinus Torvalds } 977*1da177e4SLinus Torvalds 978*1da177e4SLinus Torvalds /* 979*1da177e4SLinus Torvalds * Find dirent for specified fnode. Use truncated 15-char name in fnode as 980*1da177e4SLinus Torvalds * a help for searching. 981*1da177e4SLinus Torvalds */ 982*1da177e4SLinus Torvalds 983*1da177e4SLinus Torvalds struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno, 984*1da177e4SLinus Torvalds struct fnode *f, struct quad_buffer_head *qbh) 985*1da177e4SLinus Torvalds { 986*1da177e4SLinus Torvalds char *name1; 987*1da177e4SLinus Torvalds char *name2; 988*1da177e4SLinus Torvalds int name1len, name2len; 989*1da177e4SLinus Torvalds struct dnode *d; 990*1da177e4SLinus Torvalds dnode_secno dno, downd; 991*1da177e4SLinus Torvalds struct fnode *upf; 992*1da177e4SLinus Torvalds struct buffer_head *bh; 993*1da177e4SLinus Torvalds struct hpfs_dirent *de, *de_end; 994*1da177e4SLinus Torvalds int c; 995*1da177e4SLinus Torvalds int c1, c2 = 0; 996*1da177e4SLinus Torvalds int d1, d2 = 0; 997*1da177e4SLinus Torvalds name1 = f->name; 998*1da177e4SLinus Torvalds if (!(name2 = kmalloc(256, GFP_NOFS))) { 999*1da177e4SLinus Torvalds printk("HPFS: out of memory, can't map dirent\n"); 1000*1da177e4SLinus Torvalds return NULL; 1001*1da177e4SLinus Torvalds } 1002*1da177e4SLinus Torvalds if (f->len <= 15) 1003*1da177e4SLinus Torvalds memcpy(name2, name1, name1len = name2len = f->len); 1004*1da177e4SLinus Torvalds else { 1005*1da177e4SLinus Torvalds memcpy(name2, name1, 15); 1006*1da177e4SLinus Torvalds memset(name2 + 15, 0xff, 256 - 15); 1007*1da177e4SLinus Torvalds /*name2[15] = 0xff;*/ 1008*1da177e4SLinus Torvalds name1len = 15; name2len = 256; 1009*1da177e4SLinus Torvalds } 1010*1da177e4SLinus Torvalds if (!(upf = hpfs_map_fnode(s, f->up, &bh))) { 1011*1da177e4SLinus Torvalds kfree(name2); 1012*1da177e4SLinus Torvalds return NULL; 1013*1da177e4SLinus Torvalds } 1014*1da177e4SLinus Torvalds if (!upf->dirflag) { 1015*1da177e4SLinus Torvalds brelse(bh); 1016*1da177e4SLinus Torvalds hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, f->up); 1017*1da177e4SLinus Torvalds kfree(name2); 1018*1da177e4SLinus Torvalds return NULL; 1019*1da177e4SLinus Torvalds } 1020*1da177e4SLinus Torvalds dno = upf->u.external[0].disk_secno; 1021*1da177e4SLinus Torvalds brelse(bh); 1022*1da177e4SLinus Torvalds go_down: 1023*1da177e4SLinus Torvalds downd = 0; 1024*1da177e4SLinus Torvalds go_up: 1025*1da177e4SLinus Torvalds if (!(d = hpfs_map_dnode(s, dno, qbh))) { 1026*1da177e4SLinus Torvalds kfree(name2); 1027*1da177e4SLinus Torvalds return NULL; 1028*1da177e4SLinus Torvalds } 1029*1da177e4SLinus Torvalds de_end = dnode_end_de(d); 1030*1da177e4SLinus Torvalds de = dnode_first_de(d); 1031*1da177e4SLinus Torvalds if (downd) { 1032*1da177e4SLinus Torvalds while (de < de_end) { 1033*1da177e4SLinus Torvalds if (de->down) if (de_down_pointer(de) == downd) goto f; 1034*1da177e4SLinus Torvalds de = de_next_de(de); 1035*1da177e4SLinus Torvalds } 1036*1da177e4SLinus Torvalds hpfs_error(s, "pointer to dnode %08x not found in dnode %08x", downd, dno); 1037*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 1038*1da177e4SLinus Torvalds kfree(name2); 1039*1da177e4SLinus Torvalds return NULL; 1040*1da177e4SLinus Torvalds } 1041*1da177e4SLinus Torvalds next_de: 1042*1da177e4SLinus Torvalds if (de->fnode == fno) { 1043*1da177e4SLinus Torvalds kfree(name2); 1044*1da177e4SLinus Torvalds return de; 1045*1da177e4SLinus Torvalds } 1046*1da177e4SLinus Torvalds c = hpfs_compare_names(s, name1, name1len, de->name, de->namelen, de->last); 1047*1da177e4SLinus Torvalds if (c < 0 && de->down) { 1048*1da177e4SLinus Torvalds dno = de_down_pointer(de); 1049*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 1050*1da177e4SLinus Torvalds if (hpfs_sb(s)->sb_chk) 1051*1da177e4SLinus Torvalds if (hpfs_stop_cycles(s, dno, &c1, &c2, "map_fnode_dirent #1")) { 1052*1da177e4SLinus Torvalds kfree(name2); 1053*1da177e4SLinus Torvalds return NULL; 1054*1da177e4SLinus Torvalds } 1055*1da177e4SLinus Torvalds goto go_down; 1056*1da177e4SLinus Torvalds } 1057*1da177e4SLinus Torvalds f: 1058*1da177e4SLinus Torvalds if (de->fnode == fno) { 1059*1da177e4SLinus Torvalds kfree(name2); 1060*1da177e4SLinus Torvalds return de; 1061*1da177e4SLinus Torvalds } 1062*1da177e4SLinus Torvalds c = hpfs_compare_names(s, name2, name2len, de->name, de->namelen, de->last); 1063*1da177e4SLinus Torvalds if (c < 0 && !de->last) goto not_found; 1064*1da177e4SLinus Torvalds if ((de = de_next_de(de)) < de_end) goto next_de; 1065*1da177e4SLinus Torvalds if (d->root_dnode) goto not_found; 1066*1da177e4SLinus Torvalds downd = dno; 1067*1da177e4SLinus Torvalds dno = d->up; 1068*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 1069*1da177e4SLinus Torvalds if (hpfs_sb(s)->sb_chk) 1070*1da177e4SLinus Torvalds if (hpfs_stop_cycles(s, downd, &d1, &d2, "map_fnode_dirent #2")) { 1071*1da177e4SLinus Torvalds kfree(name2); 1072*1da177e4SLinus Torvalds return NULL; 1073*1da177e4SLinus Torvalds } 1074*1da177e4SLinus Torvalds goto go_up; 1075*1da177e4SLinus Torvalds not_found: 1076*1da177e4SLinus Torvalds hpfs_brelse4(qbh); 1077*1da177e4SLinus Torvalds hpfs_error(s, "dirent for fnode %08x not found", fno); 1078*1da177e4SLinus Torvalds kfree(name2); 1079*1da177e4SLinus Torvalds return NULL; 1080*1da177e4SLinus Torvalds } 1081