aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/acl.c6
-rw-r--r--fs/jffs2/acl.h2
-rw-r--r--fs/jffs2/fs.c6
-rw-r--r--fs/jffs2/nodelist.c9
-rw-r--r--fs/jffs2/readinode.c31
-rw-r--r--fs/jffs2/write.c28
6 files changed, 42 insertions, 40 deletions
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 77fc5838609c..4c80404a9aba 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -176,7 +176,7 @@ static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct
176 spin_unlock(&inode->i_lock); 176 spin_unlock(&inode->i_lock);
177} 177}
178 178
179struct posix_acl *jffs2_get_acl(struct inode *inode, int type) 179static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
180{ 180{
181 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 181 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
182 struct posix_acl *acl; 182 struct posix_acl *acl;
@@ -345,8 +345,10 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
345 if (!clone) 345 if (!clone)
346 return -ENOMEM; 346 return -ENOMEM;
347 rc = posix_acl_create_masq(clone, (mode_t *)i_mode); 347 rc = posix_acl_create_masq(clone, (mode_t *)i_mode);
348 if (rc < 0) 348 if (rc < 0) {
349 posix_acl_release(clone);
349 return rc; 350 return rc;
351 }
350 if (rc > 0) 352 if (rc > 0)
351 jffs2_iset_acl(inode, &f->i_acl_access, clone); 353 jffs2_iset_acl(inode, &f->i_acl_access, clone);
352 354
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 76c6ebd1acd9..0bb7f003fd80 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -28,7 +28,6 @@ struct jffs2_acl_header {
28 28
29#define JFFS2_ACL_NOT_CACHED ((void *)-1) 29#define JFFS2_ACL_NOT_CACHED ((void *)-1)
30 30
31extern struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
32extern int jffs2_permission(struct inode *, int, struct nameidata *); 31extern int jffs2_permission(struct inode *, int, struct nameidata *);
33extern int jffs2_acl_chmod(struct inode *); 32extern int jffs2_acl_chmod(struct inode *);
34extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *); 33extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *);
@@ -40,7 +39,6 @@ extern struct xattr_handler jffs2_acl_default_xattr_handler;
40 39
41#else 40#else
42 41
43#define jffs2_get_acl(inode, type) (NULL)
44#define jffs2_permission (NULL) 42#define jffs2_permission (NULL)
45#define jffs2_acl_chmod(inode) (0) 43#define jffs2_acl_chmod(inode) (0)
46#define jffs2_init_acl_pre(dir_i,inode,mode) (0) 44#define jffs2_init_acl_pre(dir_i,inode,mode) (0)
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 6d1eaddde0ec..e26ea78c7892 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -97,11 +97,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
97 ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid); 97 ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid);
98 98
99 if (ivalid & ATTR_MODE) 99 if (ivalid & ATTR_MODE)
100 if (iattr->ia_mode & S_ISGID && 100 ri->mode = cpu_to_jemode(iattr->ia_mode);
101 !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID))
102 ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID);
103 else
104 ri->mode = cpu_to_jemode(iattr->ia_mode);
105 else 101 else
106 ri->mode = cpu_to_jemode(inode->i_mode); 102 ri->mode = cpu_to_jemode(inode->i_mode);
107 103
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 4bf86088b3ae..87c6f555e1a0 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -32,15 +32,18 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new
32 if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) { 32 if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) {
33 /* Duplicate. Free one */ 33 /* Duplicate. Free one */
34 if (new->version < (*prev)->version) { 34 if (new->version < (*prev)->version) {
35 dbg_dentlist("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", 35 dbg_dentlist("Eep! Marking new dirent node obsolete, old is \"%s\", ino #%u\n",
36 (*prev)->name, (*prev)->ino); 36 (*prev)->name, (*prev)->ino);
37 jffs2_mark_node_obsolete(c, new->raw); 37 jffs2_mark_node_obsolete(c, new->raw);
38 jffs2_free_full_dirent(new); 38 jffs2_free_full_dirent(new);
39 } else { 39 } else {
40 dbg_dentlist("marking old dirent \"%s\", ino #%u bsolete\n", 40 dbg_dentlist("marking old dirent \"%s\", ino #%u obsolete\n",
41 (*prev)->name, (*prev)->ino); 41 (*prev)->name, (*prev)->ino);
42 new->next = (*prev)->next; 42 new->next = (*prev)->next;
43 jffs2_mark_node_obsolete(c, ((*prev)->raw)); 43 /* It may have been a 'placeholder' deletion dirent,
44 if jffs2_can_mark_obsolete() (see jffs2_do_unlink()) */
45 if ((*prev)->raw)
46 jffs2_mark_node_obsolete(c, ((*prev)->raw));
44 jffs2_free_full_dirent(*prev); 47 jffs2_free_full_dirent(*prev);
45 *prev = new; 48 *prev = new;
46 } 49 }
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 6c1ba3566f58..e512a93d6249 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -37,23 +37,24 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
37 37
38 BUG_ON(tn->csize == 0); 38 BUG_ON(tn->csize == 0);
39 39
40 if (!jffs2_is_writebuffered(c))
41 goto adj_acc;
42
43 /* Calculate how many bytes were already checked */ 40 /* Calculate how many bytes were already checked */
44 ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); 41 ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode);
45 len = ofs % c->wbuf_pagesize; 42 len = tn->csize;
46 if (likely(len)) 43
47 len = c->wbuf_pagesize - len; 44 if (jffs2_is_writebuffered(c)) {
48 45 int adj = ofs % c->wbuf_pagesize;
49 if (len >= tn->csize) { 46 if (likely(adj))
50 dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", 47 adj = c->wbuf_pagesize - adj;
51 ref_offset(ref), tn->csize, ofs); 48
52 goto adj_acc; 49 if (adj >= tn->csize) {
53 } 50 dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n",
51 ref_offset(ref), tn->csize, ofs);
52 goto adj_acc;
53 }
54 54
55 ofs += len; 55 ofs += adj;
56 len = tn->csize - len; 56 len -= adj;
57 }
57 58
58 dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", 59 dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n",
59 ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); 60 ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len);
@@ -63,7 +64,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
63 * adding and jffs2_flash_read_end() interface. */ 64 * adding and jffs2_flash_read_end() interface. */
64 if (c->mtd->point) { 65 if (c->mtd->point) {
65 err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); 66 err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
66 if (!err && retlen < tn->csize) { 67 if (!err && retlen < len) {
67 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); 68 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
68 c->mtd->unpoint(c->mtd, buffer, ofs, retlen); 69 c->mtd->unpoint(c->mtd, buffer, ofs, retlen);
69 } else if (err) 70 } else if (err)
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 1b88e6e734ef..776f13cbf2b5 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -582,7 +582,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
582 jffs2_add_fd_to_list(c, fd, &dir_f->dents); 582 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
583 up(&dir_f->sem); 583 up(&dir_f->sem);
584 } else { 584 } else {
585 struct jffs2_full_dirent **prev = &dir_f->dents; 585 struct jffs2_full_dirent *fd = dir_f->dents;
586 uint32_t nhash = full_name_hash(name, namelen); 586 uint32_t nhash = full_name_hash(name, namelen);
587 587
588 /* We don't actually want to reserve any space, but we do 588 /* We don't actually want to reserve any space, but we do
@@ -590,21 +590,22 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
590 down(&c->alloc_sem); 590 down(&c->alloc_sem);
591 down(&dir_f->sem); 591 down(&dir_f->sem);
592 592
593 while ((*prev) && (*prev)->nhash <= nhash) { 593 for (fd = dir_f->dents; fd; fd = fd->next) {
594 if ((*prev)->nhash == nhash && 594 if (fd->nhash == nhash &&
595 !memcmp((*prev)->name, name, namelen) && 595 !memcmp(fd->name, name, namelen) &&
596 !(*prev)->name[namelen]) { 596 !fd->name[namelen]) {
597 struct jffs2_full_dirent *this = *prev;
598 597
599 D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n", 598 D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n",
600 this->ino, ref_offset(this->raw))); 599 fd->ino, ref_offset(fd->raw)));
601 600 jffs2_mark_node_obsolete(c, fd->raw);
602 *prev = this->next; 601 /* We don't want to remove it from the list immediately,
603 jffs2_mark_node_obsolete(c, (this->raw)); 602 because that screws up getdents()/seek() semantics even
604 jffs2_free_full_dirent(this); 603 more than they're screwed already. Turn it into a
604 node-less deletion dirent instead -- a placeholder */
605 fd->raw = NULL;
606 fd->ino = 0;
605 break; 607 break;
606 } 608 }
607 prev = &((*prev)->next);
608 } 609 }
609 up(&dir_f->sem); 610 up(&dir_f->sem);
610 } 611 }
@@ -630,7 +631,8 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
630 D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", 631 D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n",
631 fd->name, dead_f->inocache->ino)); 632 fd->name, dead_f->inocache->ino));
632 } 633 }
633 jffs2_mark_node_obsolete(c, fd->raw); 634 if (fd->raw)
635 jffs2_mark_node_obsolete(c, fd->raw);
634 jffs2_free_full_dirent(fd); 636 jffs2_free_full_dirent(fd);
635 } 637 }
636 } 638 }