📄 inode-v22.c
字号:
raw_inode.atime = CURRENT_TIME; raw_inode.mtime = raw_inode.atime; raw_inode.ctime = f->ctime; raw_inode.offset = 0; raw_inode.dsize = 0; raw_inode.rsize = 0; raw_inode.nsize = new_dentry->d_name.len; raw_inode.nlink = f->nlink; raw_inode.spare = 0; raw_inode.rename = 0; raw_inode.deleted = 0; /* See if there already exists a file with the same name as new_name. */ if ((del_f = jffs_find_child(new_dir_f, new_dentry->d_name.name, new_dentry->d_name.len))) { raw_inode.rename = 1; raw_inode.dsize = sizeof(__u32); rename_data = del_f->ino; } /* Write the new node to the flash memory. */ if ((result = jffs_write_node(c, node, &raw_inode, new_dentry->d_name.name, (unsigned char*)&rename_data, 0, f)) < 0) { D(printk("jffs_rename(): Failed to write node to flash.\n")); jffs_free_node(node); goto jffs_rename_end; } raw_inode.dsize = 0; if (raw_inode.rename) { /* The file with the same name must be deleted. */ //FIXME deadlock down(&c->fmc->gclock); if ((result = jffs_remove(new_dir, new_dentry, del_f->mode)) < 0) { /* This is really bad. */ printk(KERN_ERR "JFFS: An error occurred in " "rename().\n"); } // up(&c->fmc->gclock); } if (old_dir_f != new_dir_f) { /* Remove the file from its old position in the filesystem tree. */ jffs_unlink_file_from_tree(f); } /* Insert the new node into the file system. */ if ((result = jffs_insert_node(c, f, &raw_inode, new_dentry->d_name.name, node)) < 0) { D(printk(KERN_ERR "jffs_rename(): jffs_insert_node() " "failed!\n")); } if (old_dir_f != new_dir_f) { /* Insert the file to its new position in the file system. */ jffs_insert_file_into_tree(f); } /* This is a kind of update of the inode we're about to make here. This is what they do in ext2fs. Kind of. */ if ((inode = iget(new_dir->i_sb, f->ino))) { inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); iput(inode); } jffs_rename_end: D3(printk (KERN_NOTICE "rename(): up biglock\n")); up(&c->fmc->biglock); return result;} /* jffs_rename() *//* Read the contents of a directory. Used by programs like `ls' for instance. */static intjffs_readdir(struct file *filp, void *dirent, filldir_t filldir){ struct jffs_file *f; struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; struct jffs_control *c = (struct jffs_control *)inode->i_sb->u.generic_sbp; int j; int ddino; D3(printk (KERN_NOTICE "readdir(): down biglock\n")); down(&c->fmc->biglock); D2(printk("jffs_readdir(): inode: 0x%p, filp: 0x%p\n", inode, filp)); if (filp->f_pos == 0) { D3(printk("jffs_readdir(): \".\" %lu\n", inode->i_ino)); if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0) { D3(printk (KERN_NOTICE "readdir(): up biglock\n")); up(&c->fmc->biglock); return 0; } filp->f_pos = 1; } if (filp->f_pos == 1) { if (inode->i_ino == JFFS_MIN_INO) { ddino = JFFS_MIN_INO; } else { ddino = ((struct jffs_file *)inode->u.generic_ip)->pino; } D3(printk("jffs_readdir(): \"..\" %u\n", ddino)); if (filldir(dirent, "..", 2, filp->f_pos, ddino) < 0) { D3(printk (KERN_NOTICE "readdir(): up biglock\n")); up(&c->fmc->biglock); return 0; } filp->f_pos++; } f = ((struct jffs_file *)inode->u.generic_ip)->children; j=2; while(f && (f->deleted || j++ < filp->f_pos )) { f = f->sibling_next; } while (f) { D3(printk("jffs_readdir(): \"%s\" ino: %u\n", (f->name ? f->name : ""), f->ino)); if (filldir(dirent, f->name, f->nsize, filp->f_pos , f->ino) < 0) { D3(printk (KERN_NOTICE "readdir(): up biglock\n")); up(&c->fmc->biglock); return 0; } filp->f_pos++; do { f = f->sibling_next; } while(f && f->deleted); } D3(printk (KERN_NOTICE "readdir(): up biglock\n")); up(&c->fmc->biglock); return filp->f_pos;} /* jffs_readdir() *//* Find a file in a directory. If the file exists, return its corresponding dentry. */static struct dentry *jffs_lookup(struct inode *dir, struct dentry *dentry){ struct jffs_file *d; struct jffs_file *f; struct jffs_control *c = (struct jffs_control *)dir->i_sb->u.generic_sbp; int len; int r = 0; const char *name; struct inode *inode = NULL; len = dentry->d_name.len; name = dentry->d_name.name; D3({ char *s = (char *)kmalloc(len + 1, GFP_KERNEL); memcpy(s, name, len); s[len] = '\0'; printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s); kfree(s); }); D3(printk (KERN_NOTICE "lookup(): down biglock\n")); down(&c->fmc->biglock); r = -ENAMETOOLONG; if (len > JFFS_MAX_NAME_LEN) { goto jffs_lookup_end; } r = -EACCES; if (!(d = (struct jffs_file *)dir->u.generic_ip)) { D(printk("jffs_lookup(): No such inode! (%lu)\n", dir->i_ino)); goto jffs_lookup_end; } /* Get the corresponding inode to the file. */ /* iget calls jffs_read_inode, so we need to drop the biglock before calling iget. Unfortunately, the GC has a tendency to sneak in here, because iget sometimes calls schedule (). */ if ((len == 1) && (name[0] == '.')) { D3(printk (KERN_NOTICE "lookup(): up biglock\n")); up(&c->fmc->biglock); if (!(inode = iget(dir->i_sb, d->ino))) { D(printk("jffs_lookup(): . iget() ==> NULL\n")); goto jffs_lookup_end_no_biglock; } D3(printk (KERN_NOTICE "lookup(): down biglock\n")); down(&c->fmc->biglock); } else if ((len == 2) && (name[0] == '.') && (name[1] == '.')) { D3(printk (KERN_NOTICE "lookup(): up biglock\n")); up(&c->fmc->biglock); if (!(inode = iget(dir->i_sb, d->pino))) { D(printk("jffs_lookup(): .. iget() ==> NULL\n")); goto jffs_lookup_end_no_biglock; } D3(printk (KERN_NOTICE "lookup(): down biglock\n")); down(&c->fmc->biglock); } else if ((f = jffs_find_child(d, name, len))) { D3(printk (KERN_NOTICE "lookup(): up biglock\n")); up(&c->fmc->biglock); if (!(inode = iget(dir->i_sb, f->ino))) { D(printk("jffs_lookup(): iget() ==> NULL\n")); goto jffs_lookup_end_no_biglock; } D3(printk (KERN_NOTICE "lookup(): down biglock\n")); down(&c->fmc->biglock); } else { D3(printk("jffs_lookup(): Couldn't find the file. " "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n", f, name, d, d->ino)); inode = NULL; } d_add(dentry, inode); D3(printk (KERN_NOTICE "lookup(): up biglock\n")); up(&c->fmc->biglock); return NULL; jffs_lookup_end: D3(printk (KERN_NOTICE "lookup(): up biglock\n")); up(&c->fmc->biglock); jffs_lookup_end_no_biglock: return ERR_PTR(r);} /* jffs_lookup() *//* Try to read a page of data from a file. */static intjffs_readpage(struct file *file, struct page *page){ unsigned long buf; unsigned long read_len; int result = -EIO; struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; struct jffs_file *f = (struct jffs_file *)inode->u.generic_ip; struct jffs_control *c = (struct jffs_control *)inode->i_sb->u.generic_sbp; int r; D2(printk("***jffs_readpage(): file = \"%s\", page->offset = %lu\n", (f->name ? f->name : ""), page->offset)); atomic_inc(&page->count); set_bit(PG_locked, &page->flags); set_bit(PG_free_after, &page->flags); buf = page_address(page); clear_bit(PG_uptodate, &page->flags); clear_bit(PG_error, &page->flags); D3(printk (KERN_NOTICE "readpage(): down biglock\n")); down(&c->fmc->biglock); if (page->offset < inode->i_size) { read_len = min_t(long, inode->i_size - page->offset, PAGE_SIZE); r = jffs_read_data(f, (char *)buf, page->offset, read_len); if (r == read_len) { if (read_len < PAGE_SIZE) { memset((void *)(buf + read_len), 0, PAGE_SIZE - read_len); } set_bit(PG_uptodate, &page->flags); result = 0; } D(else { printk("***jffs_readpage(): Read error! " "Wanted to read %lu bytes but only " "read %d bytes.\n", read_len, r); }); } D3(printk (KERN_NOTICE "readpage(): up biglock\n")); up(&c->fmc->biglock); if (result) { set_bit(PG_error, &page->flags); memset((void *)buf, 0, PAGE_SIZE); } clear_bit(PG_locked, &page->flags); wake_up(&page->wait); free_page(buf); D3(printk("jffs_readpage(): Leaving...\n")); return result;} /* jffs_readpage() *//* Create a new directory. */static intjffs_mkdir(struct inode *dir, struct dentry *dentry, int mode){ struct jffs_raw_inode raw_inode; struct jffs_control *c; struct jffs_node *node; struct jffs_file *dir_f; struct inode *inode; int dir_mode; int result = 0; int err; D1({ int len = dentry->d_name.len; char *_name = (char *) kmalloc(len + 1, GFP_KERNEL); memcpy(_name, dentry->d_name.name, len); _name[len] = '\0'; printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", " "len = %d, mode = 0x%08x\n", dir, _name, len, mode); kfree(_name); }); if (!dir->i_nlink) { D(printk("jffs_mkdir(): dir->i_nlink is zero\n")); return -ENOENT; } dir_f = (struct jffs_file *)dir->u.generic_ip; ASSERT(if (!dir_f) { printk(KERN_ERR "jffs_mkdir(): No reference to a " "jffs_file struct in inode.\n"); return -EIO; }); c = dir_f->c; D3(printk (KERN_NOTICE "mkdir(): down biglock\n")); down(&c->fmc->biglock); dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask); if (dir->i_mode & S_ISGID) { dir_mode |= S_ISGID; } /* Create a node and initialize it as much as needed. */ if (!(node = jffs_alloc_node())) { D(printk("jffs_mkdir(): Allocation failed: node == 0\n")); result = -ENOMEM; goto jffs_mkdir_end; } node->data_offset = 0; node->removed_size = 0; /* Initialize the raw inode. */ raw_inode.magic = JFFS_MAGIC_BITMASK; raw_inode.ino = c->next_ino++; raw_inode.pino = dir_f->ino; raw_inode.version = 1; raw_inode.mode = dir_mode; raw_inode.uid = current->fsuid; raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; /* raw_inode.gid = current->fsgid; */ raw_inode.atime = CURRENT_TIME; raw_inode.mtime = raw_inode.atime; raw_inode.ctime = raw_inode.atime; raw_inode.offset = 0; raw_inode.dsize = 0; raw_inode.rsize = 0; raw_inode.nsize = dentry->d_name.len; raw_inode.nlink = 1; raw_inode.spare = 0; raw_inode.rename = 0; raw_inode.deleted = 0; /* Write the new node to the flash. */ if ((result = jffs_write_node(c, node, &raw_inode, dentry->d_name.name, 0, 0, NULL)) < 0) { D(printk("jffs_mkdir(): jffs_write_node() failed.\n")); jffs_free_node(node); goto jffs_mkdir_end; } /* Insert the new node into the file system. */ if ((result = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, node)) < 0) { goto jffs_mkdir_end; } inode = jffs_new_inode(dir, &raw_inode, &err); if (inode == NULL) { result = err; goto jffs_mkdir_end; } inode->i_op = &jffs_dir_inode_operations; inode->i_op->default_file_ops = &jffs_dir_operations; mark_inode_dirty(dir); d_instantiate(dentry, inode); result = 0; jffs_mkdir_end: D3(printk (KERN_NOTICE "mkdir(): up biglock\n")); up(&c->fmc->biglock); return result;} /* jffs_mkdir() *//* Remove a directory. */static intjffs_rmdir(struct inode *dir, struct dentry *dentry){ struct jffs_control *c = (struct jffs_control *)dir->i_sb->u.generic_sbp; int ret; D3(printk("***jffs_rmdir()\n")); D3(printk (KERN_NOTICE "rmdir(): down biglock\n")); down(&c->fmc->biglock); ret = jffs_remove(dir, dentry, S_IFDIR); D3(printk (KERN_NOTICE "rmdir(): up biglock\n")); up(&c->fmc->biglock); return ret;}/* Remove any kind of file except for directories. */static intjffs_unlink(struct inode *dir, struct dentry *dentry){ struct jffs_control *c = (struct jffs_control *)dir->i_sb->u.generic_sbp; int ret; D3(printk("***jffs_unlink()\n")); D3(printk (KERN_NOTICE "unlink(): down biglock\n")); down(&c->fmc->biglock); ret = jffs_remove(dir, dentry, 0); D3(printk (KERN_NOTICE "unlink(): up biglock\n")); up(&c->fmc->biglock); return ret;}/* Remove a JFFS entry, i.e. plain files, directories, etc. Here we shouldn't test for free space on the device. */static intjffs_remove(struct inode *dir, struct dentry *dentry, int type){ struct jffs_raw_inode raw_inode; struct jffs_control *c; struct jffs_file *dir_f; /* The file-to-remove's parent. */ struct jffs_file *del_f; /* The file to remove. */ struct jffs_node *del_node; struct inode *inode = 0; int result = 0; D1({ int len = dentry->d_name.len; const char *name = dentry->d_name.name; char *_name = (char *) kmalloc(len + 1, GFP_KERNEL); memcpy(_name, name, len); _name[len] = '\0'; printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino); kfree(_name); }); dir_f = (struct jffs_file *) dir->u.generic_ip; c = dir_f->c; result = -ENOENT; if (!(del_f = jffs_find_child(dir_f, dentry->d_name.name, dentry->d_name.len))) { D(printk("jffs_remove(): jffs_find_child() failed.\n")); goto jffs_remove_end; } if (S_ISDIR(type)) { struct jffs_file *child = del_f->children; result = -ENOTDIR; if (!S_ISDIR(del_f->mode)) { /* Is this really needed for 2.2? */ D(printk("jffs_remove(): S_ISDIR but isn't\n")); goto jffs_remove_end; } while(child) { if( !child->deleted ) { result = -ENOTEMPTY; goto jffs_remove_end; } child = child->sibling_next; } } else if (S_ISDIR(del_f->mode)) { D(printk("jffs_remove(): node is a directory " "but it shouldn't be.\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -