cp & vfs & ubifs & ubi & mtd & nand driver 总结贴
来源:互联网 发布:海岛大亨mac汉化补丁 编辑:程序博客网 时间:2024/05/18 20:36
前段时间项目需要一直研究 ubifs ,作为流程的总结,学习了 cp 命令的实现【http://blog.csdn.net/chenqiang0721/article/details/8921613】, VFS 虚拟文件系统及其代码,ubifs 文件系统, ubi 设备层, mtd 设备层,以及最底层的nand flash driver.
马上就要开展新的项目了,作为总结,把之前看的东西在整理到CSDN 博客上,留做备忘。之前零散的东西动在之前的帖子上写过了,现在主要写一下从cp 到 nand flash driver 贯穿上下的流程。
首先,准备工作需要做好,包括使用 mtd-utils 的工具查看一个mtd partition (mtdinfo /dev/mtdx, eg: mtdinfo /dev/mtd10), 擦除一个 MTD device(flash_eraseall /dev/mtd10), 将UBI device 关联到MTD device(ubiattach /dev/ubi_ctrl -m 10), 这样就会在/dev/ 下面生成 UBI device的设备节点,如果以前没有的话,从0开始编号: /dev/ubi0,这是一个UBI device,然后可以在UBI device上面 创建 Volumn 卷(ubimkvol /dev/ubi0 -N test -s 8MiB),如果/dev 下面的设备节点没有自动创建的话,需要查看sys 文件系统下面的ubi 主从设备号,然后使用mknod 手动在/dev 下面创建就行了【http://blog.csdn.net/chenqiang0721/article/details/8825458】。
接下来就可以mount 文件系统了, 创建 mount 节点, $mkdir -p /mnt/ubifs, mount -t ubifs ubi0_0 /mnt/ubifs。 当然ubifs mount 的时候可以加上一些mount选项如 bulk_read 【http://blog.csdn.net/chenqiang0721/article/details/8906071#t6】。
这样就可以使用我们的ubifs 了,分析一个简单的例子,
$ cp ~/1.txt /mnt/ubifs (~/ 不是ubifs)
在之前的cp 命令分析中已经知道cp 使用到的文件操作相关的系统调用,包括 open, read, write。
在现在这个例子中我们先分析一下过程(不分析ubifs 以外的文件系统),cp 系统调用需要在 /mnt/ubifs 上面创建create 一个文件, VFS 的流程需要先检查这个文件是否存在(lookup),如果不存在的话,执行创建create 流程,其中VFS lookup, create 都要执行具体文件系统的方法,即 VFS 使用函数指针的形式执行lookup, create。在这个case 中使用ubifs 的lookup, create 方法,ubifs lookup 会在wandering tree (B+ tree) 中查找这样的node, 在读node 的过程中通过 I/O 接口调用的UBI 读LEB,UBI 层再通过mtd 接口调用nand flash driver 的PEB 读方法获取数据。
打开 ubifs 的debug config,看到上面描述的 lookup 过程:
5791 UBIFS DBG (pid 631): ubifs_lookup: '1.txt' in dir ino 1
5792 UBIFS DBG (pid 631): ubifs_lookup_level0: search key (1, direntry, 0x85c9644)
5793 UBIFS DBG (pid 631): ubifs_lookup_level0: found 0, lvl 0, n 0
5794 UBIFS DBG (pid 631): ubifs_lookup: not found
5795 UBIFS DBG (pid 631): ubifs_create: dent '1.txt', mode 0x81a4 in dir ino 1
下面看下代码流程:
1071 SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
1072 {
1073 long ret;
1074
1075 if (force_o_largefile())
1076 flags |= O_LARGEFILE;
1077
1078 ret = do_sys_open(AT_FDCWD, filename, flags, mode);
1048 long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
1049 {
1050 char *tmp = getname(filename);
1051 int fd = PTR_ERR(tmp);
1052
1053 if (!IS_ERR(tmp)) {
1054 fd = get_unused_fd_flags(flags);
1055 if (fd >= 0) {
1056 struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
1057 if (IS_ERR(f)) {
1058 put_unused_fd(fd);
1059 fd = PTR_ERR(f);
1060 } else {
1061 fsnotify_open(f->f_path.dentry);
1062 fd_install(fd, f);
1063 }
1761 struct file *do_filp_open(int dfd, const char *pathname,
1762 int open_flag, int mode, int acc_mode)
1763 {
1764 struct file *filp;
1765 struct nameidata nd;
1832 if (open_flag & O_DIRECTORY)
1833 nd.flags |= LOOKUP_DIRECTORY;
1834 if (!(open_flag & O_NOFOLLOW))
1835 nd.flags |= LOOKUP_FOLLOW;
1836 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
lookup 和 create 的分支发生在这个函数中,先lookup 文件,如果不存在的话,执行create.
1612 static struct file *do_last(struct nameidata *nd, struct path *path,
1613 int open_flag, int acc_mode,
1614 int mode, const char *pathname)
1615 {
1616 struct dentry *dir = nd->path.dentry;
1617 struct file *filp;
1618 int error = -EISDIR;
1648 /* just plain open? */
1649 if (!(open_flag & O_CREAT)) {
1650 error = do_lookup(nd, &nd->last, path);
1651 if (error)
1652 goto exit;
1653 error = -ENOENT;
1654 if (!path->dentry->d_inode)
1655 goto exit_dput;
1656 if (path->dentry->d_inode->i_op->follow_link)
1657 return NULL;
1658 error = -ENOTDIR;
1659 if (nd->flags & LOOKUP_DIRECTORY) {
1660 if (!path->dentry->d_inode->i_op->lookup)
1661 goto exit_dput;
1662 }
1663 path_to_nameidata(path, nd);
1664 audit_inode(pathname, nd->path.dentry);
1665 goto ok;
1666 }
1667
1668 /* OK, it's O_CREAT */
1669 mutex_lock(&dir->d_inode->i_mutex);
1670
1671 path->dentry = lookup_hash(nd);
1672 path->mnt = nd->path.mnt;
1673
1674 error = PTR_ERR(path->dentry);
1675 if (IS_ERR(path->dentry)) {
1676 mutex_unlock(&dir->d_inode->i_mutex);
1677 goto exit;
1678 }
1679
1680 if (IS_ERR(nd->intent.open.file)) {
1681 error = PTR_ERR(nd->intent.open.file);
1682 goto exit_mutex_unlock;
1683 }
1684
1685 /* Negative dentry, just create the file */
1686 if (!path->dentry->d_inode) {
1687 /*
1688 * This write is needed to ensure that a
1689 * ro->rw transition does not occur between
1690 * the time when the file is created and when
1691 * a permanent write count is taken through
1692 * the 'struct file' in nameidata_to_filp().
1693 */
1694 error = mnt_want_write(nd->path.mnt);
1695 if (error)
1696 goto exit_mutex_unlock;
1697 error = __open_namei_create(nd, path, open_flag, mode);
1698 if (error) {
1699 mnt_drop_write(nd->path.mnt);
1700 goto exit;
1701 }
1702 filp = nameidata_to_filp(nd);
1703 mnt_drop_write(nd->path.mnt);
1704 if (!IS_ERR(filp)) {
1705 error = ima_file_check(filp, acc_mode);
1706 if (error) {
1707 fput(filp);
1708 filp = ERR_PTR(error);
1709 }
1710 }
1711 return filp;
1712 }
1181 static struct dentry *lookup_hash(struct nameidata *nd)
1182 {
1183 int err;
1184
1185 err = exec_permission(nd->path.dentry->d_inode);
1186 if (err)
1187 return ERR_PTR(err);
1188 return __lookup_hash(&nd->last, nd->path.dentry, nd);
1189 }
1123 static struct dentry *__lookup_hash(struct qstr *name,
1124 struct dentry *base, struct nameidata *nd)
1125 {
1126 struct dentry *dentry;
1127 struct inode *inode;
1128 int err;
1129
1130 inode = base->d_inode;
1131
1132 /*
1133 * See if the low-level filesystem might want
1134 * to use its own hash..
1135 */
1136 if (base->d_op && base->d_op->d_hash) {
1137 err = base->d_op->d_hash(base, name);
1138 dentry = ERR_PTR(err);
1139 if (err < 0)
1140 goto out;
1141 }
1142
1143 dentry = __d_lookup(base, name);
1144
1145 /* lockess __d_lookup may fail due to concurrent d_move()
1146 * in some unrelated directory, so try with d_lookup
1147 */
1148 if (!dentry)
1149 dentry = d_lookup(base, name);
1150
1151 if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
1152 dentry = do_revalidate(dentry, nd);
1153
1154 if (!dentry) {
1155 struct dentry *new;
1156
1157 /* Don't create child dentry for a dead directory. */
1158 dentry = ERR_PTR(-ENOENT);
1159 if (IS_DEADDIR(inode))
1160 goto out;
1161
1162 new = d_alloc(base, name);
1163 dentry = ERR_PTR(-ENOMEM);
1164 if (!new)
1165 goto out;
1166 dentry = inode->i_op->lookup(inode, new, nd);
1167 if (!dentry)
1168 dentry = new;
1169 else
1170 dput(new);
1171 }
1172 out:
1173 return dentry;
1174 }
199 static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
200 struct nameidata *nd)
201 {
202 int err;
203 union ubifs_key key;
204 struct inode *inode = NULL;
205 struct ubifs_dent_node *dent;
206 struct ubifs_info *c = dir->i_sb->s_fs_info;
207
208 dbg_gen("'%.*s' in dir ino %lu",
209 dentry->d_name.len, dentry->d_name.name, dir->i_ino);
210
211 if (dentry->d_name.len > UBIFS_MAX_NLEN)
212 return ERR_PTR(-ENAMETOOLONG);
213
214 dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
215 if (!dent)
216 return ERR_PTR(-ENOMEM);
217
218 dent_key_init(c, &key, dir->i_ino, &dentry->d_name);
219
220 err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name);
1852 int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
1853 void *node, const struct qstr *nm)
1854 {
1855 int err, len;
1856 const struct ubifs_dent_node *dent = node;
1857
1858 /*
1859 * We assume that in most of the cases there are no name collisions and
1860 * 'ubifs_tnc_lookup()' returns us the right direntry.
1861 */
1862 err = ubifs_tnc_lookup(c, key, node);
1863 if (err)
1864 return err;
307 static inline int ubifs_tnc_lookup(struct ubifs_info *c,
308 const union ubifs_key *key, void *node)
309 {
310 return ubifs_tnc_locate(c, key, node, NULL, NULL);
311 }
1442 int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
1443 void *node, int *lnum, int *offs)
1444 {
1445 int found, n, err, safely = 0, gc_seq1;
1446 struct ubifs_znode *znode;
1447 struct ubifs_zbranch zbr, *zt;
1448
1449 again:
1450 mutex_lock(&c->tnc_mutex);
1451 found = ubifs_lookup_level0(c, key, &znode, &n);
1172 int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key,
1173 struct ubifs_znode **zn, int *n)
1174 {
1175 int err, exact;
1176 struct ubifs_znode *znode;
1177 unsigned long time = get_seconds();
1178
1179 dbg_tnc("search key %s", DBGKEY(key));
1180
1181 znode = c->zroot.znode;
1182 if (unlikely(!znode)) {
1183 znode = ubifs_load_znode(c, &c->zroot, NULL, 0);
1184 if (IS_ERR(znode))
1185 return PTR_ERR(znode);
1186 }
406 struct ubifs_znode *ubifs_load_znode(struct ubifs_info *c,
407 struct ubifs_zbranch *zbr,
408 struct ubifs_znode *parent, int iip)
409 {
410 int err;
411 struct ubifs_znode *znode;
412
413 ubifs_assert(!zbr->znode);
414 /*
415 * A slab cache is not presently used for znodes because the znode size
416 * depends on the fanout which is stored in the superblock.
417 */
418 znode = kzalloc(c->max_znode_sz, GFP_NOFS);
419 if (!znode)
420 return ERR_PTR(-ENOMEM);
421
422 err = read_znode(c, zbr->lnum, zbr->offs, zbr->len, znode);
273 static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
274 struct ubifs_znode *znode)
275 {
276 int i, err, type, cmp;
277 struct ubifs_idx_node *idx;
278
279 idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
280 if (!idx)
281 return -ENOMEM;
282
283 err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
777 int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
778 int lnum, int offs)
779 {
780 int err, l;
781 struct ubifs_ch *ch = buf;
782
783 dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
784 ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
785 ubifs_assert(len >= UBIFS_CH_SZ && offs + len <= c->leb_size);
786 ubifs_assert(!(offs & 7) && offs < c->leb_size);
787 ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
788
789 err = ubi_read(c->ubi, lnum, buf, offs, len);
200 static inline int ubi_read(struct ubi_volume_desc *desc, int lnum, char *buf,
201 int offset, int len)
202 {
203 return ubi_leb_read(desc, lnum, buf, offset, len, 0);
204 }
382 int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
383 int len, int check)
384 {
385 struct ubi_volume *vol = desc->vol;
386 struct ubi_device *ubi = vol->ubi;
387 int err, vol_id = vol->vol_id;
388
389 dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
390
391 if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
392 lnum >= vol->used_ebs || offset < 0 || len < 0 ||
393 offset + len > vol->usable_leb_size)
394 return -EINVAL;
395
396 if (vol->vol_type == UBI_STATIC_VOLUME) {
397 if (vol->used_ebs == 0)
398 /* Empty static UBI volume */
399 return 0;
400 if (lnum == vol->used_ebs - 1 &&
401 offset + len > vol->last_eb_bytes)
402 return -EINVAL;
403 }
404
405 if (vol->upd_marker)
406 return -EBADF;
407 if (len == 0)
408 return 0;
409
410 err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
370 int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
371 void *buf, int offset, int len, int check)
372 {
373 int err, pnum, scrub = 0, vol_id = vol->vol_id;
374 struct ubi_vid_hdr *vid_hdr;
375 uint32_t uninitialized_var(crc);
439
440 err = ubi_io_read_data(ubi, buf, pnum, offset, len);
632 static inline int ubi_io_read_data(const struct ubi_device *ubi, void *buf,
633 int pnum, int offset, int len)
634 {
635 ubi_assert(offset >= 0);
636 return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len);
637 }
132 int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
133 int len)
134 {
135 int err, retries = 0;
136 size_t read;
137 loff_t addr;
149 addr = (loff_t)pnum * ubi->peb_size + offset;
150 retry:
151 err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
1365 static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
1366 size_t *retlen, uint8_t *buf)
1367 {
1368 struct nand_chip *chip = mtd->priv;
1369 int ret;
1370
1371 /* Do not allow reads past end of device */
1372 if ((from + len) > mtd->size)
1373 return -EINVAL;
1374 if (!len)
1375 return 0;
1376
1377 nand_get_device(chip, mtd, FL_READING);
1378
1379 chip->ops.len = len;
1380 chip->ops.datbuf = buf;
1381 chip->ops.oobbuf = NULL;
1382
1383 ret = nand_do_read_ops(mtd, from, &chip->ops);
1224 static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1225 struct mtd_oob_ops *ops)
1226 {
1227 int chipnr, page, realpage, col, bytes, aligned;
1228 struct nand_chip *chip = mtd->priv;
1229 struct mtd_ecc_stats stats;
1230 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1231 int sndcmd = 1;
1232 int ret = 0;
1233 uint32_t readlen = ops->len;
1234 uint32_t oobreadlen = ops->ooblen;
1235 uint8_t *bufpoi, *oob, *buf;
1236
1237 stats = mtd->ecc_stats;
1238
1239 chipnr = (int)(from >> chip->chip_shift);
1240 chip->select_chip(mtd, chipnr);
1241
1242 realpage = (int)(from >> chip->page_shift);
1243 page = realpage & chip->pagemask;
1244
1245 col = (int)(from & (mtd->writesize - 1));
1246
1247 buf = ops->datbuf;
1248 oob = ops->oobbuf;
1249
1250 while(1) {
1251 bytes = min(mtd->writesize - col, readlen);
1252 aligned = (bytes == mtd->writesize);
1253
1254 /* Is the current page in the buffer ? */
1255 if (realpage != chip->pagebuf || oob) {
1256 bufpoi = aligned ? buf : chip->buffers->databuf;
1257
1258 if (likely(sndcmd)) {
1259 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
1260 sndcmd = 0;
1261 }
1262
1263 /* Now read the page into the buffer */
1264 if (unlikely(ops->mode == MTD_OOB_RAW))
1265 ret = chip->ecc.read_page_raw(mtd, chip,
1266 bufpoi, page);
1267 else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
1268 ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);
1269 else
1270 ret = chip->ecc.read_page(mtd, chip, bufpoi,
1271 page);
1272 if (ret < 0)
马上就要开展新的项目了,作为总结,把之前看的东西在整理到CSDN 博客上,留做备忘。之前零散的东西动在之前的帖子上写过了,现在主要写一下从cp 到 nand flash driver 贯穿上下的流程。
首先,准备工作需要做好,包括使用 mtd-utils 的工具查看一个mtd partition (mtdinfo /dev/mtdx, eg: mtdinfo /dev/mtd10), 擦除一个 MTD device(flash_eraseall /dev/mtd10), 将UBI device 关联到MTD device(ubiattach /dev/ubi_ctrl -m 10), 这样就会在/dev/ 下面生成 UBI device的设备节点,如果以前没有的话,从0开始编号: /dev/ubi0,这是一个UBI device,然后可以在UBI device上面 创建 Volumn 卷(ubimkvol /dev/ubi0 -N test -s 8MiB),如果/dev 下面的设备节点没有自动创建的话,需要查看sys 文件系统下面的ubi 主从设备号,然后使用mknod 手动在/dev 下面创建就行了【http://blog.csdn.net/chenqiang0721/article/details/8825458】。
接下来就可以mount 文件系统了, 创建 mount 节点, $mkdir -p /mnt/ubifs, mount -t ubifs ubi0_0 /mnt/ubifs。 当然ubifs mount 的时候可以加上一些mount选项如 bulk_read 【http://blog.csdn.net/chenqiang0721/article/details/8906071#t6】。
这样就可以使用我们的ubifs 了,分析一个简单的例子,
$ cp ~/1.txt /mnt/ubifs (~/ 不是ubifs)
在之前的cp 命令分析中已经知道cp 使用到的文件操作相关的系统调用,包括 open, read, write。
在现在这个例子中我们先分析一下过程(不分析ubifs 以外的文件系统),cp 系统调用需要在 /mnt/ubifs 上面创建create 一个文件, VFS 的流程需要先检查这个文件是否存在(lookup),如果不存在的话,执行创建create 流程,其中VFS lookup, create 都要执行具体文件系统的方法,即 VFS 使用函数指针的形式执行lookup, create。在这个case 中使用ubifs 的lookup, create 方法,ubifs lookup 会在wandering tree (B+ tree) 中查找这样的node, 在读node 的过程中通过 I/O 接口调用的UBI 读LEB,UBI 层再通过mtd 接口调用nand flash driver 的PEB 读方法获取数据。
打开 ubifs 的debug config,看到上面描述的 lookup 过程:
5791 UBIFS DBG (pid 631): ubifs_lookup: '1.txt' in dir ino 1
5792 UBIFS DBG (pid 631): ubifs_lookup_level0: search key (1, direntry, 0x85c9644)
5793 UBIFS DBG (pid 631): ubifs_lookup_level0: found 0, lvl 0, n 0
5794 UBIFS DBG (pid 631): ubifs_lookup: not found
5795 UBIFS DBG (pid 631): ubifs_create: dent '1.txt', mode 0x81a4 in dir ino 1
下面看下代码流程:
1071 SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
1072 {
1073 long ret;
1074
1075 if (force_o_largefile())
1076 flags |= O_LARGEFILE;
1077
1078 ret = do_sys_open(AT_FDCWD, filename, flags, mode);
1048 long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
1049 {
1050 char *tmp = getname(filename);
1051 int fd = PTR_ERR(tmp);
1052
1053 if (!IS_ERR(tmp)) {
1054 fd = get_unused_fd_flags(flags);
1055 if (fd >= 0) {
1056 struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
1057 if (IS_ERR(f)) {
1058 put_unused_fd(fd);
1059 fd = PTR_ERR(f);
1060 } else {
1061 fsnotify_open(f->f_path.dentry);
1062 fd_install(fd, f);
1063 }
1761 struct file *do_filp_open(int dfd, const char *pathname,
1762 int open_flag, int mode, int acc_mode)
1763 {
1764 struct file *filp;
1765 struct nameidata nd;
1832 if (open_flag & O_DIRECTORY)
1833 nd.flags |= LOOKUP_DIRECTORY;
1834 if (!(open_flag & O_NOFOLLOW))
1835 nd.flags |= LOOKUP_FOLLOW;
1836 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
lookup 和 create 的分支发生在这个函数中,先lookup 文件,如果不存在的话,执行create.
1612 static struct file *do_last(struct nameidata *nd, struct path *path,
1613 int open_flag, int acc_mode,
1614 int mode, const char *pathname)
1615 {
1616 struct dentry *dir = nd->path.dentry;
1617 struct file *filp;
1618 int error = -EISDIR;
1648 /* just plain open? */
1649 if (!(open_flag & O_CREAT)) {
1650 error = do_lookup(nd, &nd->last, path);
1651 if (error)
1652 goto exit;
1653 error = -ENOENT;
1654 if (!path->dentry->d_inode)
1655 goto exit_dput;
1656 if (path->dentry->d_inode->i_op->follow_link)
1657 return NULL;
1658 error = -ENOTDIR;
1659 if (nd->flags & LOOKUP_DIRECTORY) {
1660 if (!path->dentry->d_inode->i_op->lookup)
1661 goto exit_dput;
1662 }
1663 path_to_nameidata(path, nd);
1664 audit_inode(pathname, nd->path.dentry);
1665 goto ok;
1666 }
1667
1668 /* OK, it's O_CREAT */
1669 mutex_lock(&dir->d_inode->i_mutex);
1670
1671 path->dentry = lookup_hash(nd);
1672 path->mnt = nd->path.mnt;
1673
1674 error = PTR_ERR(path->dentry);
1675 if (IS_ERR(path->dentry)) {
1676 mutex_unlock(&dir->d_inode->i_mutex);
1677 goto exit;
1678 }
1679
1680 if (IS_ERR(nd->intent.open.file)) {
1681 error = PTR_ERR(nd->intent.open.file);
1682 goto exit_mutex_unlock;
1683 }
1684
1685 /* Negative dentry, just create the file */
1686 if (!path->dentry->d_inode) {
1687 /*
1688 * This write is needed to ensure that a
1689 * ro->rw transition does not occur between
1690 * the time when the file is created and when
1691 * a permanent write count is taken through
1692 * the 'struct file' in nameidata_to_filp().
1693 */
1694 error = mnt_want_write(nd->path.mnt);
1695 if (error)
1696 goto exit_mutex_unlock;
1697 error = __open_namei_create(nd, path, open_flag, mode);
1698 if (error) {
1699 mnt_drop_write(nd->path.mnt);
1700 goto exit;
1701 }
1702 filp = nameidata_to_filp(nd);
1703 mnt_drop_write(nd->path.mnt);
1704 if (!IS_ERR(filp)) {
1705 error = ima_file_check(filp, acc_mode);
1706 if (error) {
1707 fput(filp);
1708 filp = ERR_PTR(error);
1709 }
1710 }
1711 return filp;
1712 }
1181 static struct dentry *lookup_hash(struct nameidata *nd)
1182 {
1183 int err;
1184
1185 err = exec_permission(nd->path.dentry->d_inode);
1186 if (err)
1187 return ERR_PTR(err);
1188 return __lookup_hash(&nd->last, nd->path.dentry, nd);
1189 }
1123 static struct dentry *__lookup_hash(struct qstr *name,
1124 struct dentry *base, struct nameidata *nd)
1125 {
1126 struct dentry *dentry;
1127 struct inode *inode;
1128 int err;
1129
1130 inode = base->d_inode;
1131
1132 /*
1133 * See if the low-level filesystem might want
1134 * to use its own hash..
1135 */
1136 if (base->d_op && base->d_op->d_hash) {
1137 err = base->d_op->d_hash(base, name);
1138 dentry = ERR_PTR(err);
1139 if (err < 0)
1140 goto out;
1141 }
1142
1143 dentry = __d_lookup(base, name);
1144
1145 /* lockess __d_lookup may fail due to concurrent d_move()
1146 * in some unrelated directory, so try with d_lookup
1147 */
1148 if (!dentry)
1149 dentry = d_lookup(base, name);
1150
1151 if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
1152 dentry = do_revalidate(dentry, nd);
1153
1154 if (!dentry) {
1155 struct dentry *new;
1156
1157 /* Don't create child dentry for a dead directory. */
1158 dentry = ERR_PTR(-ENOENT);
1159 if (IS_DEADDIR(inode))
1160 goto out;
1161
1162 new = d_alloc(base, name);
1163 dentry = ERR_PTR(-ENOMEM);
1164 if (!new)
1165 goto out;
1166 dentry = inode->i_op->lookup(inode, new, nd);
1167 if (!dentry)
1168 dentry = new;
1169 else
1170 dput(new);
1171 }
1172 out:
1173 return dentry;
1174 }
199 static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
200 struct nameidata *nd)
201 {
202 int err;
203 union ubifs_key key;
204 struct inode *inode = NULL;
205 struct ubifs_dent_node *dent;
206 struct ubifs_info *c = dir->i_sb->s_fs_info;
207
208 dbg_gen("'%.*s' in dir ino %lu",
209 dentry->d_name.len, dentry->d_name.name, dir->i_ino);
210
211 if (dentry->d_name.len > UBIFS_MAX_NLEN)
212 return ERR_PTR(-ENAMETOOLONG);
213
214 dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
215 if (!dent)
216 return ERR_PTR(-ENOMEM);
217
218 dent_key_init(c, &key, dir->i_ino, &dentry->d_name);
219
220 err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name);
1852 int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
1853 void *node, const struct qstr *nm)
1854 {
1855 int err, len;
1856 const struct ubifs_dent_node *dent = node;
1857
1858 /*
1859 * We assume that in most of the cases there are no name collisions and
1860 * 'ubifs_tnc_lookup()' returns us the right direntry.
1861 */
1862 err = ubifs_tnc_lookup(c, key, node);
1863 if (err)
1864 return err;
307 static inline int ubifs_tnc_lookup(struct ubifs_info *c,
308 const union ubifs_key *key, void *node)
309 {
310 return ubifs_tnc_locate(c, key, node, NULL, NULL);
311 }
1442 int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key,
1443 void *node, int *lnum, int *offs)
1444 {
1445 int found, n, err, safely = 0, gc_seq1;
1446 struct ubifs_znode *znode;
1447 struct ubifs_zbranch zbr, *zt;
1448
1449 again:
1450 mutex_lock(&c->tnc_mutex);
1451 found = ubifs_lookup_level0(c, key, &znode, &n);
1172 int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key,
1173 struct ubifs_znode **zn, int *n)
1174 {
1175 int err, exact;
1176 struct ubifs_znode *znode;
1177 unsigned long time = get_seconds();
1178
1179 dbg_tnc("search key %s", DBGKEY(key));
1180
1181 znode = c->zroot.znode;
1182 if (unlikely(!znode)) {
1183 znode = ubifs_load_znode(c, &c->zroot, NULL, 0);
1184 if (IS_ERR(znode))
1185 return PTR_ERR(znode);
1186 }
406 struct ubifs_znode *ubifs_load_znode(struct ubifs_info *c,
407 struct ubifs_zbranch *zbr,
408 struct ubifs_znode *parent, int iip)
409 {
410 int err;
411 struct ubifs_znode *znode;
412
413 ubifs_assert(!zbr->znode);
414 /*
415 * A slab cache is not presently used for znodes because the znode size
416 * depends on the fanout which is stored in the superblock.
417 */
418 znode = kzalloc(c->max_znode_sz, GFP_NOFS);
419 if (!znode)
420 return ERR_PTR(-ENOMEM);
421
422 err = read_znode(c, zbr->lnum, zbr->offs, zbr->len, znode);
273 static int read_znode(struct ubifs_info *c, int lnum, int offs, int len,
274 struct ubifs_znode *znode)
275 {
276 int i, err, type, cmp;
277 struct ubifs_idx_node *idx;
278
279 idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
280 if (!idx)
281 return -ENOMEM;
282
283 err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
777 int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
778 int lnum, int offs)
779 {
780 int err, l;
781 struct ubifs_ch *ch = buf;
782
783 dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
784 ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
785 ubifs_assert(len >= UBIFS_CH_SZ && offs + len <= c->leb_size);
786 ubifs_assert(!(offs & 7) && offs < c->leb_size);
787 ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
788
789 err = ubi_read(c->ubi, lnum, buf, offs, len);
200 static inline int ubi_read(struct ubi_volume_desc *desc, int lnum, char *buf,
201 int offset, int len)
202 {
203 return ubi_leb_read(desc, lnum, buf, offset, len, 0);
204 }
382 int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
383 int len, int check)
384 {
385 struct ubi_volume *vol = desc->vol;
386 struct ubi_device *ubi = vol->ubi;
387 int err, vol_id = vol->vol_id;
388
389 dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
390
391 if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
392 lnum >= vol->used_ebs || offset < 0 || len < 0 ||
393 offset + len > vol->usable_leb_size)
394 return -EINVAL;
395
396 if (vol->vol_type == UBI_STATIC_VOLUME) {
397 if (vol->used_ebs == 0)
398 /* Empty static UBI volume */
399 return 0;
400 if (lnum == vol->used_ebs - 1 &&
401 offset + len > vol->last_eb_bytes)
402 return -EINVAL;
403 }
404
405 if (vol->upd_marker)
406 return -EBADF;
407 if (len == 0)
408 return 0;
409
410 err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
370 int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
371 void *buf, int offset, int len, int check)
372 {
373 int err, pnum, scrub = 0, vol_id = vol->vol_id;
374 struct ubi_vid_hdr *vid_hdr;
375 uint32_t uninitialized_var(crc);
439
440 err = ubi_io_read_data(ubi, buf, pnum, offset, len);
632 static inline int ubi_io_read_data(const struct ubi_device *ubi, void *buf,
633 int pnum, int offset, int len)
634 {
635 ubi_assert(offset >= 0);
636 return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len);
637 }
132 int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
133 int len)
134 {
135 int err, retries = 0;
136 size_t read;
137 loff_t addr;
149 addr = (loff_t)pnum * ubi->peb_size + offset;
150 retry:
151 err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
1365 static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
1366 size_t *retlen, uint8_t *buf)
1367 {
1368 struct nand_chip *chip = mtd->priv;
1369 int ret;
1370
1371 /* Do not allow reads past end of device */
1372 if ((from + len) > mtd->size)
1373 return -EINVAL;
1374 if (!len)
1375 return 0;
1376
1377 nand_get_device(chip, mtd, FL_READING);
1378
1379 chip->ops.len = len;
1380 chip->ops.datbuf = buf;
1381 chip->ops.oobbuf = NULL;
1382
1383 ret = nand_do_read_ops(mtd, from, &chip->ops);
1224 static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
1225 struct mtd_oob_ops *ops)
1226 {
1227 int chipnr, page, realpage, col, bytes, aligned;
1228 struct nand_chip *chip = mtd->priv;
1229 struct mtd_ecc_stats stats;
1230 int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
1231 int sndcmd = 1;
1232 int ret = 0;
1233 uint32_t readlen = ops->len;
1234 uint32_t oobreadlen = ops->ooblen;
1235 uint8_t *bufpoi, *oob, *buf;
1236
1237 stats = mtd->ecc_stats;
1238
1239 chipnr = (int)(from >> chip->chip_shift);
1240 chip->select_chip(mtd, chipnr);
1241
1242 realpage = (int)(from >> chip->page_shift);
1243 page = realpage & chip->pagemask;
1244
1245 col = (int)(from & (mtd->writesize - 1));
1246
1247 buf = ops->datbuf;
1248 oob = ops->oobbuf;
1249
1250 while(1) {
1251 bytes = min(mtd->writesize - col, readlen);
1252 aligned = (bytes == mtd->writesize);
1253
1254 /* Is the current page in the buffer ? */
1255 if (realpage != chip->pagebuf || oob) {
1256 bufpoi = aligned ? buf : chip->buffers->databuf;
1257
1258 if (likely(sndcmd)) {
1259 chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
1260 sndcmd = 0;
1261 }
1262
1263 /* Now read the page into the buffer */
1264 if (unlikely(ops->mode == MTD_OOB_RAW))
1265 ret = chip->ecc.read_page_raw(mtd, chip,
1266 bufpoi, page);
1267 else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
1268 ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);
1269 else
1270 ret = chip->ecc.read_page(mtd, chip, bufpoi,
1271 page);
1272 if (ret < 0)
1273 break;
chip->ecc.read_page 方法一般都是在特定的nand flash driver 的init 初始化函数中(probe 流程中)进行注册,使用特定nand flash driver 私有的page read 方法。
很重要的一点就是要理解 抽象层的概念以及意义,这样看起代码来才会比较顺利!
- cp & vfs & ubifs & ubi & mtd & nand driver 总结贴
- ubifs and ubi and mtd
- Linux MTD&Nand Driver
- Nand driver in mtd.
- nand ubi -4 kernel和mtd
- MTD NAND Driver Programming Interface
- ubifs & mtd
- ubifs & mtd
- ubifs & mtd
- ubifs & mtd
- ubifs & mtd
- ubifs[ubi文件系统]
- UBIFS - UBI File-System
- UBIFS介绍 - MTD网站
- UBIFS介绍 - MTD网站 .
- UBIFS介绍 - MTD网站
- UBIFS介绍 - MTD网站
- ubifs mtd分区
- struts2+hibernate 实现B2C电子商务网站的登录 、注册中验证码的实现(源码)
- hibernate的主键生成策略包括那些
- Unicode的一些类型转换问题
- 用java正则表达式验证字符串(邮箱与网址)
- 判断一个整数中是否有重复数字(0~9),该数字不以0开头--------方法1
- cp & vfs & ubifs & ubi & mtd & nand driver 总结贴
- SVN常用命令
- C++ new & delete
- Hibernate高效查询,只查询部分/指定字段
- android权限大全
- Linux-0.00运行环境搭建
- 串口驱动卸载/加载与 GSM 模块电源控制
- 解析 H.264 NAL Unit 帧类型
- Python import细节探索