您的位置:首页 > 其它

UBIFS文件系统分析4 - 目录项管理 .

2013-07-23 15:55 337 查看
传统文件系统,多个目录项集中存放在同一物理块,读取目录项就像读取文件内容一样,物理块内容是连续的目录项,因此目录文件也是有大小区分的,子目录和文件数目越多,那么目录文件尺寸越大。

而ubifs每当增加一个新的目录项,ubifs在master area中生成一个directory entry node,并把这个node插到wandering tree的某个位置,通过wandering tree保持同意目录下目录项在逻辑上的相邻。

这种特性也带来了ubifs在一些目录操作接口上的怪异行为,比如readdir和stat。

78 /**

79 * ubifs_new_inode - allocate new UBIFS inode object.

80 * @c: UBIFS file-system description object

81 * @dir: parent directory inode

82 * @mode: inode mode flags

83 *

84 * This function finds an unused inode number, allocates new inode and

85 * initializes it. Returns new inode in case of success and an error code in

86 * case of failure.

87 */

88 struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,

89 int mode)

90 {

91 struct inode *inode;

92 struct ubifs_inode *ui;

93

94 inode = new_inode(c->vfs_sb);

95 ui = ubifs_inode(inode);

96 if (!inode)

97 return ERR_PTR(-ENOMEM);

98

99 /*

100 * Set 'S_NOCMTIME' to prevent VFS form updating [mc]time of inodes and

101 * marking them dirty in file write path (see 'file_update_time()').

102 * UBIFS has to fully control "clean <-> dirty" transitions of inodes

103 * to make budgeting work.

104 */

105 inode->i_flags |= (S_NOCMTIME);

106

107 inode_init_owner(inode, dir, mode);

108 inode->i_mtime = inode->i_atime = inode->i_ctime =

109 ubifs_current_time(inode);

110 inode->i_mapping->nrpages = 0;

111 /* Disable readahead */

112 inode->i_mapping->backing_dev_info = &c->bdi;

113

114 switch (mode & S_IFMT) {

115 case S_IFREG:

116 inode->i_mapping->a_ops = &ubifs_file_address_operations;

117 inode->i_op = &ubifs_file_inode_operations;

118 inode->i_fop = &ubifs_file_operations;

119 break;

120 case S_IFDIR:

121 inode->i_op = &ubifs_dir_inode_operations;

122 inode->i_fop = &ubifs_dir_operations;

123 inode->i_size = ui->ui_size = UBIFS_INO_NODE_SZ;

124 break;

125 case S_IFLNK:

126 inode->i_op = &ubifs_symlink_inode_operations;

127 break;

128 case S_IFSOCK:

129 case S_IFIFO:

130 case S_IFBLK:

131 case S_IFCHR:

132 inode->i_op = &ubifs_file_inode_operations;

133 break;

134 default:

135 BUG();

136 }

137

138 ui->flags = inherit_flags(dir, mode);

139 ubifs_set_inode_flags(inode);

140 if (S_ISREG(mode))

141 ui->compr_type = c->default_compr;

142 else

143 ui->compr_type = UBIFS_COMPR_NONE;

144 ui->synced_i_size = 0;

145

146 spin_lock(&c->cnt_lock);

147 /* Inode number overflow is currently not supported */

148 if (c->highest_inum >= INUM_WARN_WATERMARK) {

149 if (c->highest_inum >= INUM_WATERMARK) {

150 spin_unlock(&c->cnt_lock);

151 ubifs_err("out of inode numbers");

152 make_bad_inode(inode);

153 iput(inode);

154 return ERR_PTR(-EINVAL);

155 }

156 ubifs_warn("running out of inode numbers (current %lu, max %d)",

157 (unsigned long)c->highest_inum, INUM_WATERMARK);

158 }

159

160 inode->i_ino = ++c->highest_inum;

161 /*

162 * The creation sequence number remains with this inode for its

163 * lifetime. All nodes for this inode have a greater sequence number,

164 * and so it is possible to distinguish obsolete nodes belonging to a

165 * previous incarnation of the same inode number - for example, for the

166 * purpose of rebuilding the index.

167 */

168 ui->creat_sqnum = ++c->max_sqnum;

169 spin_unlock(&c->cnt_lock);

170 return inode;

171 }

138 ~ 139 UBIFS有些inode flag是可以从父目录继承到子目录项的,比如UBIFS_COMPR_FL, UBIFS_SYNC_FL以及UBIFS_DIRSYNC_FL.

UBIFS_COMPR_FL是compression打开关闭标记

UBIFS_SYNC_FL是文件同步标记

UBIFS_DIRSYNC_FL是 是目录内容修改同步标记,这个标记只有子目录项还是目录时才会继承

147~160 UBIFS使用highest_inum记录已经使用过的inode number的最大值,UBIFS使用过的ino不能重复使用

168 creat_sqnum记录这个inode的sequence number,在unclean unmount发生时,ubifs可以通过这个sequence number来确定哪个inode是最新的.

192 static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,

193 struct nameidata *nd)

194 {

195 int err;

196 union ubifs_key key;

197 struct inode *inode = NULL;

198 struct ubifs_dent_node *dent;

199 struct ubifs_info *c = dir->i_sb->s_fs_info;

200

201 dbg_gen("'%.*s' in dir ino %lu",

202 dentry->d_name.len, dentry->d_name.name, dir->i_ino);

203

204 if (dentry->d_name.len > UBIFS_MAX_NLEN)

205 return ERR_PTR(-ENAMETOOLONG);

206

207 dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);

208 if (!dent)

209 return ERR_PTR(-ENOMEM);

210

211 dent_key_init(c, &key, dir->i_ino, &dentry->d_name);

212

213 err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name);

214 if (err) {

215 if (err == -ENOENT) {

216 dbg_gen("not found");

217 goto done;

218 }

219 goto out;

220 }

221

222 if (dbg_check_name(dent, &dentry->d_name)) {

223 err = -EINVAL;

224 goto out;

225 }

226

227 inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum));

228 if (IS_ERR(inode)) {

229 /*

230 * This should not happen. Probably the file-system needs

231 * checking.

232 */

233 err = PTR_ERR(inode);

234 ubifs_err("dead directory entry '%.*s', error %d",

235 dentry->d_name.len, dentry->d_name.name, err);

236 ubifs_ro_mode(c, err);

237 goto out;

238 }

239

240 done:

241 kfree(dent);

242 /*

243 * Note, d_splice_alias() would be required instead if we supported

244 * NFS.

245 */

246 d_add(dentry, inode);

247 return NULL;

248

249 out:

250 kfree(dent);

251 return ERR_PTR(err);

252 }

211 ~ 213 生成目录项的key,然后在tnc tree中查找符合这个key的node, dentry node可能已经在tnc中,那么直接返回就可以了,如果没在tnc中,则会从flash读取并加到tnc

247 不知道为什么成功了也返回NULL

254 static int ubifs_create(struct inode *dir, struct dentry *dentry, int mode,

255 struct nameidata *nd)

256 {

257 struct inode *inode;

258 struct ubifs_info *c = dir->i_sb->s_fs_info;

259 int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);

260 struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,

261 .dirtied_ino = 1 };

262 struct ubifs_inode *dir_ui = ubifs_inode(dir);

263

264 /*

265 * Budget request settings: new inode, new direntry, changing the

266 * parent directory inode.

267 */

268

269 dbg_gen("dent '%.*s', mode %#x in dir ino %lu",

270 dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);

271

272 err = ubifs_budget_space(c, &req);

273 if (err)

274 return err;

275

276 inode = ubifs_new_inode(c, dir, mode);

277 if (IS_ERR(inode)) {

278 err = PTR_ERR(inode);

279 goto out_budg;

280 }

281

282 mutex_lock(&dir_ui->ui_mutex);

283 dir->i_size += sz_change;

284 dir_ui->ui_size = dir->i_size;

285 dir->i_mtime = dir->i_ctime = inode->i_ctime;

286 err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);

287 if (err)

288 goto out_cancel;

289 mutex_unlock(&dir_ui->ui_mutex);

290

291 ubifs_release_budget(c, &req);

292 insert_inode_hash(inode);

293 d_instantiate(dentry, inode);

294 return 0;

295

296 out_cancel:

297 dir->i_size -= sz_change;

298 dir_ui->ui_size = dir->i_size;

299 mutex_unlock(&dir_ui->ui_mutex);

300 make_bad_inode(inode);

301 iput(inode);

302 out_budg:

303 ubifs_release_budget(c, &req);

304 ubifs_err("cannot create regular file, error %d", err);

305 return err;

306 }

在调用ubifs_create前,已经创建了这个文件对应的dentry,但是相应的inode以及目录项还不存在

272 确保足够的空间进行下面的操作, 创建一个文件节点需要修改:parent inode的ctime和size, 新文件的inode和新文件对应的目录项

286 ubifs_jnl_update写新目录项,inode以及parent inode到journal

338 /*

339 * The classical Unix view for directory is that it is a linear array of

340 * (name, inode number) entries. Linux/VFS assumes this model as well.

341 * Particularly, 'readdir()' call wants us to return a directory entry offset

342 * which later may be used to continue 'readdir()'ing the directory or to

343 * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this

344 * model because directory entries are identified by keys, which may collide.

345 *

346 * UBIFS uses directory entry hash value for directory offsets, so

347 * 'seekdir()'/'telldir()' may not always work because of possible key

348 * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work

349 * properly by means of saving full directory entry name in the private field

350 * of the file description object.

351 *

352 * This means that UBIFS cannot support NFS which requires full

353 * 'seekdir()'/'telldir()' support.

354 */

355 static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)

356 {

357 int err, over = 0;

358 struct qstr nm;

359 union ubifs_key key;

360 struct ubifs_dent_node *dent;

361 struct inode *dir = file->f_path.dentry->d_inode;

362 struct ubifs_info *c = dir->i_sb->s_fs_info;

363

364 dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);

365

366 if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)

367 /*

368 * The directory was seek'ed to a senseless position or there

369 * are no more entries.

370 */

371 return 0;

372

373 /* File positions 0 and 1 correspond to "." and ".." */

374 if (file->f_pos == 0) {

375 ubifs_assert(!file->private_data);

376 over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR);

377 if (over)

378 return 0;

379 file->f_pos = 1;

380 }

381

382 if (file->f_pos == 1) {

383 ubifs_assert(!file->private_data);

384 over = filldir(dirent, "..", 2, 1,

385 parent_ino(file->f_path.dentry), DT_DIR);

386 if (over)

387 return 0;

388

389 /* Find the first entry in TNC and save it */

390 lowest_dent_key(c, &key, dir->i_ino);

391 nm.name = NULL;

392 dent = ubifs_tnc_next_ent(c, &key, &nm);

393 if (IS_ERR(dent)) {

394 err = PTR_ERR(dent);

395 goto out;

396 }

397

398 file->f_pos = key_hash_flash(c, &dent->key);

399 file->private_data = dent;

400 }

401

402 dent = file->private_data;

403 if (!dent) {

404 /*

405 * The directory was seek'ed to and is now readdir'ed.

406 * Find the entry corresponding to @file->f_pos or the

407 * closest one.

408 */

409 dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);

410 nm.name = NULL;

411 dent = ubifs_tnc_next_ent(c, &key, &nm);

412 if (IS_ERR(dent)) {

413 err = PTR_ERR(dent);

414 goto out;

415 }

416 file->f_pos = key_hash_flash(c, &dent->key);

417 file->private_data = dent;

418 }

419

420 while (1) {

421 dbg_gen("feed '%s', ino %llu, new f_pos %#x",

422 dent->name, (unsigned long long)le64_to_cpu(dent->inum),

423 key_hash_flash(c, &dent->key));

424 ubifs_assert(le64_to_cpu(dent->ch.sqnum) >

425 ubifs_inode(dir)->creat_sqnum);

426

427 nm.len = le16_to_cpu(dent->nlen);

428 over = filldir(dirent, dent->name, nm.len, file->f_pos,

429 le64_to_cpu(dent->inum),

430 vfs_dent_type(dent->type));

431 if (over)

432 return 0;

433

434 /* Switch to the next entry */

435 key_read(c, &dent->key, &key);

436 nm.name = dent->name;

437 dent = ubifs_tnc_next_ent(c, &key, &nm);

438 if (IS_ERR(dent)) {

439 err = PTR_ERR(dent);

440 goto out;

441 }

442

443 kfree(file->private_data);

444 file->f_pos = key_hash_flash(c, &dent->key);

445 file->private_data = dent;

446 cond_resched();

447 }

448

449 out:

450 if (err != -ENOENT) {

451 ubifs_err("cannot find next direntry, error %d", err);

452 return err;

453 }

454

455 kfree(file->private_data);

456 file->private_data = NULL;

457 file->f_pos = 2;

458 return 0;

459 }

ubifs_readdir 读取目录@file下的目录项,内容放入@dirent,每读取一个目录项,由filldir填充@dirent,具体读取多少,由filldir的返回值决定

ubifs_readdir的问题是offset并不像传统文件系统的offset一样,因为ubifs的目录项并不是顺序排放的,dentry node没有offset,而是由key来决定在父目录中的排序位置。

从代码中可以看到,只有"."和".."目录项offset是传统的位置,其他目录项的offset就是名字的hash值

374 ~ 387 读取. 和..目录项

389 ~ 399 读取第一个目录项

403 ~ 418 由于读取的offset并不是常规的offset, 所以找一个最接近这个offset的目录项

420 ~477 ubifs_tnc_next_ent依次遍历所有的entry,直到filldir请求结束遍历

461 /* If a directory is seeked, we have to free saved readdir() state */

462 static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int origin)

463 {

464 kfree(file->private_data);

465 file->private_data = NULL;

466 return generic_file_llseek(file, offset, origin);

467 }

465 由于ubifs借用来file->private_data来模拟offset,所以llseek要先清空private_data,具体参见ubifs_readdir

static int ubifs_link(struct dentry *old_dentry, struct inode *dir,

504 struct dentry *dentry)

505 {

506 struct ubifs_info *c = dir->i_sb->s_fs_info;

507 struct inode *inode = old_dentry->d_inode;

508 struct ubifs_inode *ui = ubifs_inode(inode);

509 struct ubifs_inode *dir_ui = ubifs_inode(dir);

510 int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);

511 struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2,

512 .dirtied_ino_d = ALIGN(ui->data_len, 8) };

513

514 /*

515 * Budget request settings: new direntry, changing the target inode,

516 * changing the parent inode.

517 */

518

519 dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu",

520 dentry->d_name.len, dentry->d_name.name, inode->i_ino,

521 inode->i_nlink, dir->i_ino);

522 ubifs_assert(mutex_is_locked(&dir->i_mutex));

523 ubifs_assert(mutex_is_locked(&inode->i_mutex));

524

525 /*

526 * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing

527 * otherwise has the potential to corrupt the orphan inode list.

528 *

529 * Indeed, consider a scenario when 'vfs_link(dirA/fileA)' and

530 * 'vfs_unlink(dirA/fileA, dirB/fileB)' race. 'vfs_link()' does not

531 * lock 'dirA->i_mutex', so this is possible. Both of the functions

532 * lock 'fileA->i_mutex' though. Suppose 'vfs_unlink()' wins, and takes

533 * 'fileA->i_mutex' mutex first. Suppose 'fileA->i_nlink' is 1. In this

534 * case 'ubifs_unlink()' will drop the last reference, and put 'inodeA'

535 * to the list of orphans. After this, 'vfs_link()' will link

536 * 'dirB/fileB' to 'inodeA'. This is a problem because, for example,

537 * the subsequent 'vfs_unlink(dirB/fileB)' will add the same inode

538 * to the list of orphans.

539 */

540 if (inode->i_nlink == 0)

541 return -ENOENT;

542

543 err = dbg_check_synced_i_size(inode);

544 if (err)

545 return err;

546

547 err = ubifs_budget_space(c, &req);

548 if (err)

549 return err;

550

551 lock_2_inodes(dir, inode);

552 inc_nlink(inode);

554 inode->i_ctime = ubifs_current_time(inode);

555 dir->i_size += sz_change;

556 dir_ui->ui_size = dir->i_size;

557 dir->i_mtime = dir->i_ctime = inode->i_ctime;

558 err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);

559 if (err)

560 goto out_cancel;

561 unlock_2_inodes(dir, inode);

562

563 ubifs_release_budget(c, &req);

564 d_instantiate(dentry, inode);

565 return 0;

566

567 out_cancel:

568 dir->i_size -= sz_change;

569 dir_ui->ui_size = dir->i_size;

570 drop_nlink(inode);

571 unlock_2_inodes(dir, inode);

572 ubifs_release_budget(c, &req);

573 iput(inode);

574 return err;

575 }

ubifs_link用来把@old_dentry对应的文件,链接到@dentry这个目录项上,是文件系统硬链接的底层实现

ubifs_link和ubifs_create类似,都会修改parent inode,增加一个新的目录项。

ubifs_link不需要创建inode,因为inode已经存在了,但是需要修改inode的link和修改inode的ctime

552 增加inode的nlink,因为一个新的dentry指向了这个文件

577 static int ubifs_unlink(struct inode *dir, struct dentry *dentry)

578 {

579 struct ubifs_info *c = dir->i_sb->s_fs_info;

580 struct inode *inode = dentry->d_inode;

581 struct ubifs_inode *dir_ui = ubifs_inode(dir);

582 int sz_change = CALC_DENT_SIZE(dentry->d_name.len);

583 int err, budgeted = 1;

584 struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 };

585

586 /*

587 * Budget request settings: deletion direntry, deletion inode (+1 for

588 * @dirtied_ino), changing the parent directory inode. If budgeting

589 * fails, go ahead anyway because we have extra space reserved for

590 * deletions.

591 */

592

593 dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu",

594 dentry->d_name.len, dentry->d_name.name, inode->i_ino,

595 inode->i_nlink, dir->i_ino);

596 ubifs_assert(mutex_is_locked(&dir->i_mutex));

597 ubifs_assert(mutex_is_locked(&inode->i_mutex));

598 err = dbg_check_synced_i_size(inode);

599 if (err)

600 return err;

601

602 err = ubifs_budget_space(c, &req);

603 if (err) {

604 if (err != -ENOSPC)

605 return err;

606 budgeted = 0;

607 }

608

609 lock_2_inodes(dir, inode);

610 inode->i_ctime = ubifs_current_time(dir);

611 drop_nlink(inode);

612 dir->i_size -= sz_change;

613 dir_ui->ui_size = dir->i_size;

614 dir->i_mtime = dir->i_ctime = inode->i_ctime;

615 err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0);

616 if (err)

617 goto out_cancel;

618 unlock_2_inodes(dir, inode);

619

620 if (budgeted)

621 ubifs_release_budget(c, &req);

622 else {

623 /* We've deleted something - clean the "no space" flags */

624 c->nospace = c->nospace_rp = 0;

625 smp_wmb();

626 }

627 return 0;

628

629 out_cancel:

630 dir->i_size += sz_change;

631 dir_ui->ui_size = dir->i_size;

632 inc_nlink(inode);

633 unlock_2_inodes(dir, inode);

634 if (budgeted)

635 ubifs_release_budget(c, &req);

636 return err;

637 }

ubifs_unlink是ubifs_link的逆操作,把@dentry目录项从@dir中删除掉

这个操作涉及到一个目录项的删除,以及parent inode和child inode的修改

611 由于少了一个到child inode的目录项, 减少child inode的链接数

612 由于删除了目录项,父目录inode的尺寸减去目录项node的尺寸

615 ubifs_jnl_update第五个参数1 用来指定对目录项的删除

639 /**

640 * check_dir_empty - check if a directory is empty or not.

641 * @c: UBIFS file-system description object

642 * @dir: VFS inode object of the directory to check

643 *

644 * This function checks if directory @dir is empty. Returns zero if the

645 * directory is empty, %-ENOTEMPTY if it is not, and other negative error codes

646 * in case of of errors.

647 */

648 static int check_dir_empty(struct ubifs_info *c, struct inode *dir)

649 {

650 struct qstr nm = { .name = NULL };

651 struct ubifs_dent_node *dent;

652 union ubifs_key key;

653 int err;

654

655 lowest_dent_key(c, &key, dir->i_ino);

656 dent = ubifs_tnc_next_ent(c, &key, &nm);

657 if (IS_ERR(dent)) {

658 err = PTR_ERR(dent);

659 if (err == -ENOENT)

660 err = 0;

661 } else {

662 kfree(dent);

663 err = -ENOTEMPTY;

664 }

665 return err;

666 }

这个函数检测给定的目录@dir是否为空

655 首先计算出这个目录下最小的dentry key

656 ubifs_tnc_next_ent 找到并返回@key后面的一个目录项,如果不存在,说明没有目录项,否则有

668 static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)

669 {

670 struct ubifs_info *c = dir->i_sb->s_fs_info;

671 struct inode *inode = dentry->d_inode;

672 int sz_change = CALC_DENT_SIZE(dentry->d_name.len);

673 int err, budgeted = 1;

674 struct ubifs_inode *dir_ui = ubifs_inode(dir);

675 struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 };

676

677 /*

678 * Budget request settings: deletion direntry, deletion inode and

679 * changing the parent inode. If budgeting fails, go ahead anyway

680 * because we have extra space reserved for deletions.

681 */

682

683 dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len,

684 dentry->d_name.name, inode->i_ino, dir->i_ino);

685 ubifs_assert(mutex_is_locked(&dir->i_mutex));

686 ubifs_assert(mutex_is_locked(&inode->i_mutex));

687 err = check_dir_empty(c, dentry->d_inode);

688 if (err)

689 return err;

690

691 err = ubifs_budget_space(c, &req);

692 if (err) {

693 if (err != -ENOSPC)

694 return err;

695 budgeted = 0;

696 }

697

698 lock_2_inodes(dir, inode);

699 inode->i_ctime = ubifs_current_time(dir);

700 clear_nlink(inode);

701 drop_nlink(dir);

702 dir->i_size -= sz_change;

703 dir_ui->ui_size = dir->i_size;

704 dir->i_mtime = dir->i_ctime = inode->i_ctime;

705 err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0);

706 if (err)

707 goto out_cancel;

708 unlock_2_inodes(dir, inode);

709

710 if (budgeted)

711 ubifs_release_budget(c, &req);

712 else {

713 /* We've deleted something - clean the "no space" flags */

714 c->nospace = c->nospace_rp = 0;

715 smp_wmb();

716 }

717 return 0;

718

719 out_cancel:

720 dir->i_size += sz_change;

721 dir_ui->ui_size = dir->i_size;

722 inc_nlink(dir);

723 inc_nlink(inode);

724 inc_nlink(inode);

725 unlock_2_inodes(dir, inode);

726 if (budgeted)

727 ubifs_release_budget(c, &req);

728 return err;

729 }

ubifs_rmdir删除@dir下的目录项@dentry,这个函数和ubifs_unlink的区别是前者删除的是子目录,后者删除的是非子目录

677 ~ 681 该操作涉及到删除目录项,删除子目录的inode,更改父目录的inode

687 判断待删除目录是否包含除"." ".."外的目录项,非空目录是不能删除的。

700 clear_nlink直接设置inode的nlink为0,事实上我觉得使用drop_nlink也可

701 减少父目录inode的nlink

731 static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, int mode)

732 {

733 struct inode *inode;

734 struct ubifs_inode *dir_ui = ubifs_inode(dir);

735 struct ubifs_info *c = dir->i_sb->s_fs_info;

736 int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);

737 struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };

738

739 /*

740 * Budget request settings: new inode, new direntry and changing parent

741 * directory inode.

742 */

743

744 dbg_gen("dent '%.*s', mode %#x in dir ino %lu",

745 dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);

746

747 err = ubifs_budget_space(c, &req);

748 if (err)

749 return err;

750

751 inode = ubifs_new_inode(c, dir, S_IFDIR | mode);

752 if (IS_ERR(inode)) {

753 err = PTR_ERR(inode);

754 goto out_budg;

755 }

756

757 mutex_lock(&dir_ui->ui_mutex);

758 insert_inode_hash(inode);

759 inc_nlink(inode);

760 inc_nlink(dir);

761 dir->i_size += sz_change;

762 dir_ui->ui_size = dir->i_size;

763 dir->i_mtime = dir->i_ctime = inode->i_ctime;

764 err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);

765 if (err) {

766 ubifs_err("cannot create directory, error %d", err);

767 goto out_cancel;

768 }

769 mutex_unlock(&dir_ui->ui_mutex);

770

771 ubifs_release_budget(c, &req);

772 d_instantiate(dentry, inode);

773 return 0;

774

775 out_cancel:

776 dir->i_size -= sz_change;

777 dir_ui->ui_size = dir->i_size;

778 drop_nlink(dir);

779 mutex_unlock(&dir_ui->ui_mutex);

780 make_bad_inode(inode);

781 iput(inode);

782 out_budg:

783 ubifs_release_budget(c, &req);

784 return err;

785 }

ubifs_mkdir 在父目录@dir下创建@dentry对应的子目录,该函数需要分配子目录的inode

ubifs涉及到新目录项的添加,子inode的创建以及父inode的修改

751 为子目录创建inode

758 把新创建的inode加到hash table中

759 ~ 760 增加父子inode的nlink

772 把dentry和新创建的inode关联起来

787 static int ubifs_mknod(struct inode *dir, struct dentry *dentry,

788 int mode, dev_t rdev)

789 {

790 struct inode *inode;

791 struct ubifs_inode *ui;

792 struct ubifs_inode *dir_ui = ubifs_inode(dir);

793 struct ubifs_info *c = dir->i_sb->s_fs_info;

794 union ubifs_dev_desc *dev = NULL;

795 int sz_change = CALC_DENT_SIZE(dentry->d_name.len);

796 int err, devlen = 0;

797 struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,

798 .new_ino_d = ALIGN(devlen, 8),

799 .dirtied_ino = 1 };

800

801 /*

802 * Budget request settings: new inode, new direntry and changing parent

803 * directory inode.

804 */

805

806 dbg_gen("dent '%.*s' in dir ino %lu",

807 dentry->d_name.len, dentry->d_name.name, dir->i_ino);

808

809 if (!new_valid_dev(rdev))

810 return -EINVAL;

811

812 if (S_ISBLK(mode) || S_ISCHR(mode)) {

813 dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);

814 if (!dev)

815 return -ENOMEM;

816 devlen = ubifs_encode_dev(dev, rdev);

817 }

818

819 err = ubifs_budget_space(c, &req);

820 if (err) {

821 kfree(dev);

822 return err;

823 }

824

825 inode = ubifs_new_inode(c, dir, mode);

826 if (IS_ERR(inode)) {

827 kfree(dev);

828 err = PTR_ERR(inode);

829 goto out_budg;

830 }

831

832 init_special_inode(inode, inode->i_mode, rdev);

833 inode->i_size = ubifs_inode(inode)->ui_size = devlen;

834 ui = ubifs_inode(inode);

835 ui->data = dev;

836 ui->data_len = devlen;

837

838 mutex_lock(&dir_ui->ui_mutex);

839 dir->i_size += sz_change;

840 dir_ui->ui_size = dir->i_size;

841 dir->i_mtime = dir->i_ctime = inode->i_ctime;

842 err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);

843 if (err)

844 goto out_cancel;

845 mutex_unlock(&dir_ui->ui_mutex);

846

847 ubifs_release_budget(c, &req);

848 insert_inode_hash(inode);

849 d_instantiate(dentry, inode);

850 return 0;

851

852 out_cancel:

853 dir->i_size -= sz_change;

854 dir_ui->ui_size = dir->i_size;

855 mutex_unlock(&dir_ui->ui_mutex);

856 make_bad_inode(inode);

857 iput(inode);

858 out_budg:

859 ubifs_release_budget(c, &req);

860 return err;

861 }

ubifs_mknod和ubifs_mkdir非常类似,只是前者创建的是设备节点而后者创建的是子目录,ubifs_mknod不会增加父母录的连接数

863 static int ubifs_symlink(struct inode *dir, struct dentry *dentry,

864 const char *symname)

865 {

866 struct inode *inode;

867 struct ubifs_inode *ui;

868 struct ubifs_inode *dir_ui = ubifs_inode(dir);

869 struct ubifs_info *c = dir->i_sb->s_fs_info;

870 int err, len = strlen(symname);

871 int sz_change = CALC_DENT_SIZE(dentry->d_name.len);

872 struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,

873 .new_ino_d = ALIGN(len, 8),

874 .dirtied_ino = 1 };

875

876 /*

877 * Budget request settings: new inode, new direntry and changing parent

878 * directory inode.

879 */

880

881 dbg_gen("dent '%.*s', target '%s' in dir ino %lu", dentry->d_name.len,

882 dentry->d_name.name, symname, dir->i_ino);

883

884 if (len > UBIFS_MAX_INO_DATA)

885 return -ENAMETOOLONG;

886

887 err = ubifs_budget_space(c, &req);

888 if (err)

889 return err;

890

891 inode = ubifs_new_inode(c, dir, S_IFLNK | S_IRWXUGO);

892 if (IS_ERR(inode)) {

893 err = PTR_ERR(inode);

894 goto out_budg;

895 }

896

897 ui = ubifs_inode(inode);

898 ui->data = kmalloc(len + 1, GFP_NOFS);

899 if (!ui->data) {

900 err = -ENOMEM;

901 goto out_inode;

902 }

903

904 memcpy(ui->data, symname, len);

905 ((char *)ui->data)[len] = '\0';

906 /*

907 * The terminating zero byte is not written to the flash media and it

908 * is put just to make later in-memory string processing simpler. Thus,

909 * data length is @len, not @len + %1.

910 */

911 ui->data_len = len;

912 inode->i_size = ubifs_inode(inode)->ui_size = len;

913

914 mutex_lock(&dir_ui->ui_mutex);

915 dir->i_size += sz_change;

916 dir_ui->ui_size = dir->i_size;

917 dir->i_mtime = dir->i_ctime = inode->i_ctime;

918 err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);

919 if (err)

920 goto out_cancel;

921 mutex_unlock(&dir_ui->ui_mutex);

922

923 ubifs_release_budget(c, &req);

924 insert_inode_hash(inode);

925 d_instantiate(dentry, inode);

926 return 0;

927

928 out_cancel:

929 dir->i_size -= sz_change;

930 dir_ui->ui_size = dir->i_size;

931 mutex_unlock(&dir_ui->ui_mutex);

932 out_inode:

933 make_bad_inode(inode);

934 iput(inode);

935 out_budg:

936 ubifs_release_budget(c, &req);

937 return err;

938 }

ubifs_symlink在父目录@dir下增加@dentry指定的目录项,这个函数需要创建一个新的inode,增加一个新的目录项,修改parent inode

新创建的inode数据内容为@symname指定的路径,放在ui->data内,由ui->data_len指定长度

该函数不增加parent inode和child inode的nlink

884 该行限制了符号链接的最大长度不能超过UBIFS_MAX_INO_DATA,注意这只是存储方面的限制,对symlink名最大长度的限制来自多方面

979 static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,

980 struct inode *new_dir, struct dentry *new_dentry)

981 {

982 struct ubifs_info *c = old_dir->i_sb->s_fs_info;

983 struct inode *old_inode = old_dentry->d_inode;

984 struct inode *new_inode = new_dentry->d_inode;

985 struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode);

986 int err, release, sync = 0, move = (new_dir != old_dir);

987 int is_dir = S_ISDIR(old_inode->i_mode);

988 int unlink = !!new_inode;

989 int new_sz = CALC_DENT_SIZE(new_dentry->d_name.len);

990 int old_sz = CALC_DENT_SIZE(old_dentry->d_name.len);

991 struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1,

992 .dirtied_ino = 3 };

993 struct ubifs_budget_req ino_req = { .dirtied_ino = 1,

994 .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };

995 struct timespec time;

996

997 /*

998 * Budget request settings: deletion direntry, new direntry, removing

999 * the old inode, and changing old and new parent directory inodes.

1000 *

1001 * However, this operation also marks the target inode as dirty and

1002 * does not write it, so we allocate budget for the target inode

1003 * separately.

1004 */

1005

1006 dbg_gen("dent '%.*s' ino %lu in dir ino %lu to dent '%.*s' in "

1007 "dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name,

1008 old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len,

1009 new_dentry->d_name.name, new_dir->i_ino);

1010 ubifs_assert(mutex_is_locked(&old_dir->i_mutex));

1011 ubifs_assert(mutex_is_locked(&new_dir->i_mutex));

1012 if (unlink)

1013 ubifs_assert(mutex_is_locked(&new_inode->i_mutex));

1014

1015

1016 if (unlink && is_dir) {

1017 err = check_dir_empty(c, new_inode);

1018 if (err)

1019 return err;

1020 }

1021

1022 err = ubifs_budget_space(c, &req);

1023 if (err)

1024 return err;

1025 err = ubifs_budget_space(c, &ino_req);

1026 if (err) {

1027 ubifs_release_budget(c, &req);

1028 return err;

1029 }

1030

1031 lock_3_inodes(old_dir, new_dir, new_inode);

1032

1033 /*

1034 * Like most other Unix systems, set the @i_ctime for inodes on a

1035 * rename.

1036 */

1037 time = ubifs_current_time(old_dir);

1038 old_inode->i_ctime = time;

1039

1040 /* We must adjust parent link count when renaming directories */

1041 if (is_dir) {

1042 if (move) {

1043 /*

1044 * @old_dir loses a link because we are moving

1045 * @old_inode to a different directory.

1046 */

1047 drop_nlink(old_dir);

1048 /*

1049 * @new_dir only gains a link if we are not also

1050 * overwriting an existing directory.

1051 */

1052 if (!unlink)

1053 inc_nlink(new_dir);

1054 } else {

1055 /*

1056 * @old_inode is not moving to a different directory,

1057 * but @old_dir still loses a link if we are

1058 * overwriting an existing directory.

1059 */

1060 if (unlink)

1061 drop_nlink(old_dir);

1062 }

1063 }

1064

1065 old_dir->i_size -= old_sz;

1066 ubifs_inode(old_dir)->ui_size = old_dir->i_size;

1067 old_dir->i_mtime = old_dir->i_ctime = time;

1068 new_dir->i_mtime = new_dir->i_ctime = time;

1069

1070 /*

1071 * And finally, if we unlinked a direntry which happened to have the

1072 * same name as the moved direntry, we have to decrement @i_nlink of

1073 * the unlinked inode and change its ctime.

1074 */

1075 if (unlink) {

1076 /*

1077 * Directories cannot have hard-links, so if this is a

1078 * directory, decrement its @i_nlink twice because an empty

1079 * directory has @i_nlink 2.

1080 */

1081 if (is_dir)

1082 drop_nlink(new_inode);

1083 new_inode->i_ctime = time;

1084 drop_nlink(new_inode);

1085 } else {

1086 new_dir->i_size += new_sz;

1087 ubifs_inode(new_dir)->ui_size = new_dir->i_size;

1088 }

1089

1090 /*

1091 * Do not ask 'ubifs_jnl_rename()' to flush write-buffer if @old_inode

1092 * is dirty, because this will be done later on at the end of

1093 * 'ubifs_rename()'.

1094 */

1095 if (IS_SYNC(old_inode)) {

1096 sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir);

1097 if (unlink && IS_SYNC(new_inode))

1098 sync = 1;

1099 }

1100 err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry,

1101 sync);

1102 if (err)

1103 goto out_cancel;

1104

1105 unlock_3_inodes(old_dir, new_dir, new_inode);

1106 ubifs_release_budget(c, &req);

1107

1108 mutex_lock(&old_inode_ui->ui_mutex);

1109 release = old_inode_ui->dirty;

1110 mark_inode_dirty_sync(old_inode);

1111 mutex_unlock(&old_inode_ui->ui_mutex);

1112

1113 if (release)

1114 ubifs_release_budget(c, &ino_req);

1115 if (IS_SYNC(old_inode))

1116 err = old_inode->i_sb->s_op->write_inode(old_inode, NULL);

1117 return err;

1118

1119 out_cancel:

1120 if (unlink) {

1121 if (is_dir)

1122 inc_nlink(new_inode);

1123 inc_nlink(new_inode);

1124 } else {

1125 new_dir->i_size -= new_sz;

1126 ubifs_inode(new_dir)->ui_size = new_dir->i_size;

1127 }

1128 old_dir->i_size += old_sz;

1129 ubifs_inode(old_dir)->ui_size = old_dir->i_size;

1130 if (is_dir) {

1131 if (move) {

1132 inc_nlink(old_dir);

1133 if (!unlink)

1134 drop_nlink(new_dir);

1135 } else {

1136 if (unlink)

1137 inc_nlink(old_dir);

1138 }

1139 }

1140 unlock_3_inodes(old_dir, new_dir, new_inode);

1141 ubifs_release_budget(c, &ino_req);

1142 ubifs_release_budget(c, &req);

1143 return err;

1144 }

ubifs_rename 重命名@old_dentry为@new_dentry,@old_dir为原目录,@new_dir为新目录

注意@new_dentry可能在改名前就对应着一个文件或目录,因此改名后相当于减少了这个inode的nlink

984 new_inode可能为空或者不为空,为空表明这个文件名原本就不存在,处理起来要简单一些;不为空,表明这个文件名原来就存在,那么rename会覆盖掉@new_dentry原来指向的文件。

1016 ~ 1020 ubifs要求@new_dentry不能对应一个不为空的目录,即rename禁止非空目录覆盖

1041 ~ 1042 is_dir表示@new_dentry是一个目录,move表明old_dir new_dir不是相同的目录(跨目录rename)

1043 ~ 1061 处理nlink

1065 ~ 1068 修改@old_dir的尺寸

1070 ~ 1088 如果@new_dentry本来就对应着一个文件或目录,如果是目录nlink -= 2来释放这个目录inode(前面已经确保这个目录肯定为空);如果是文件,只需-1

rename 看起来稍微复杂,主要有以下几种分支情况需要仔细处理

1. old_dir new_dir是不是同一个目录

2. new_dentry, old_dentry是不是同一个路径

3. new_dentry old_dentry是目录还是文件

1146 int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,

1147 struct kstat *stat)

1148 {

1149 loff_t size;

1150 struct inode *inode = dentry->d_inode;

1151 struct ubifs_inode *ui = ubifs_inode(inode);

1152

1153 mutex_lock(&ui->ui_mutex);

1154 stat->dev = inode->i_sb->s_dev;

1155 stat->ino = inode->i_ino;

1156 stat->mode = inode->i_mode;

1157 stat->nlink = inode->i_nlink;

1158 stat->uid = inode->i_uid;

1159 stat->gid = inode->i_gid;

1160 stat->rdev = inode->i_rdev;

1161 stat->atime = inode->i_atime;

1162 stat->mtime = inode->i_mtime;

1163 stat->ctime = inode->i_ctime;

1164 stat->blksize = UBIFS_BLOCK_SIZE;

1165 stat->size = ui->ui_size;

1166

1167 /*

1168 * Unfortunately, the 'stat()' system call was designed for block

1169 * device based file systems, and it is not appropriate for UBIFS,

1170 * because UBIFS does not have notion of "block". For example, it is

1171 * difficult to tell how many block a directory takes - it actually

1172 * takes less than 300 bytes, but we have to round it to block size,

1173 * which introduces large mistake. This makes utilities like 'du' to

1174 * report completely senseless numbers. This is the reason why UBIFS

1175 * goes the same way as JFFS2 - it reports zero blocks for everything

1176 * but regular files, which makes more sense than reporting completely

1177 * wrong sizes.

1178 */

1179 if (S_ISREG(inode->i_mode)) {

1180 size = ui->xattr_size;

1181 size += stat->size;

1182 size = ALIGN(size, UBIFS_BLOCK_SIZE);

1183 /*

1184 * Note, user-space expects 512-byte blocks count irrespectively

1185 * of what was reported in @stat->size.

1186 */

1187 stat->blocks = size >> 9;

1188 } else

1189 stat->blocks = 0;

1190 mutex_unlock(&ui->ui_mutex);

1191 return 0;

1192 }

这个函数需要注意1168行开始的代码注释部分,ubifs不像传统的block filesystem,因此在汇报stat->blocks时有些问题,需要应用程序小心使用stat在ubifs文件系统的返回值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: