From 2b1e300a9dfc3196ccddf6f1d74b91b7af55e416 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 2 Dec 2007 00:33:17 +1100 Subject: [NETNS]: Fix /proc/net breakage Well I clearly goofed when I added the initial network namespace support for /proc/net. Currently things work but there are odd details visible to user space, even when we have a single network namespace. Since we do not cache proc_dir_entry dentries at the moment we can just modify ->lookup to return a different directory inode depending on the network namespace of the process looking at /proc/net, replacing the current technique of using a magic and fragile follow_link method. To accomplish that this patch: - introduces a shadow_proc method to allow different dentries to be returned from proc_lookup. - Removes the old /proc/net follow_link magic - Fixes a weakness in our not caching of proc generic dentries. As shadow_proc uses a task struct to decided which dentry to return we can go back later and fix the proc generic caching without modifying any code that uses the shadow_proc method. Signed-off-by: Eric W. Biederman Cc: "Rafael J. Wysocki" Cc: Pavel Machek Cc: Pavel Emelyanov Cc: "David S. Miller" Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Herbert Xu --- fs/proc/generic.c | 12 +++++++- fs/proc/proc_net.c | 86 ++++-------------------------------------------------- 2 files changed, 16 insertions(+), 82 deletions(-) (limited to 'fs') diff --git a/fs/proc/generic.c b/fs/proc/generic.c index a9806bc21ec3..c2b752341f89 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -374,9 +374,16 @@ static int proc_delete_dentry(struct dentry * dentry) return 1; } +static int proc_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) +{ + d_drop(dentry); + return 0; +} + static struct dentry_operations proc_dentry_operations = { .d_delete = proc_delete_dentry, + .d_revalidate = proc_revalidate_dentry, }; /* @@ -397,8 +404,11 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam if (de->namelen != dentry->d_name.len) continue; if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { - unsigned int ino = de->low_ino; + unsigned int ino; + if (de->shadow_proc) + de = de->shadow_proc(current, de); + ino = de->low_ino; de_get(de); spin_unlock(&proc_subdir_lock); error = -EINVAL; diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 131f9c68be5f..0afe21ee0607 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c @@ -50,89 +50,14 @@ struct net *get_proc_net(const struct inode *inode) } EXPORT_SYMBOL_GPL(get_proc_net); -static struct proc_dir_entry *proc_net_shadow; +static struct proc_dir_entry *shadow_pde; -static struct dentry *proc_net_shadow_dentry(struct dentry *parent, +static struct proc_dir_entry *proc_net_shadow(struct task_struct *task, struct proc_dir_entry *de) { - struct dentry *shadow = NULL; - struct inode *inode; - if (!de) - goto out; - de_get(de); - inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de); - if (!inode) - goto out_de_put; - shadow = d_alloc_name(parent, de->name); - if (!shadow) - goto out_iput; - shadow->d_op = parent->d_op; /* proc_dentry_operations */ - d_instantiate(shadow, inode); -out: - return shadow; -out_iput: - iput(inode); -out_de_put: - de_put(de); - goto out; -} - -static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd) -{ - struct net *net = current->nsproxy->net_ns; - struct dentry *shadow; - shadow = proc_net_shadow_dentry(parent, net->proc_net); - if (!shadow) - return ERR_PTR(-ENOENT); - - dput(nd->dentry); - /* My dentry count is 1 and that should be enough as the - * shadow dentry is thrown away immediately. - */ - nd->dentry = shadow; - return NULL; + return task->nsproxy->net_ns->proc_net; } -static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *nd) -{ - struct net *net = current->nsproxy->net_ns; - struct dentry *shadow; - - shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net); - if (!shadow) - return ERR_PTR(-ENOENT); - - dput(nd->dentry); - nd->dentry = shadow; - - return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd); -} - -static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr) -{ - struct net *net = current->nsproxy->net_ns; - struct dentry *shadow; - int ret; - - shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net); - if (!shadow) - return -ENOENT; - ret = shadow->d_inode->i_op->setattr(shadow, iattr); - dput(shadow); - return ret; -} - -static const struct file_operations proc_net_dir_operations = { - .read = generic_read_dir, -}; - -static struct inode_operations proc_net_dir_inode_operations = { - .follow_link = proc_net_follow_link, - .lookup = proc_net_lookup, - .setattr = proc_net_setattr, -}; - static __net_init int proc_net_ns_init(struct net *net) { struct proc_dir_entry *root, *netd, *net_statd; @@ -185,9 +110,8 @@ static struct pernet_operations __net_initdata proc_net_ns_ops = { int __init proc_net_init(void) { - proc_net_shadow = proc_mkdir("net", NULL); - proc_net_shadow->proc_iops = &proc_net_dir_inode_operations; - proc_net_shadow->proc_fops = &proc_net_dir_operations; + shadow_pde = proc_mkdir("net", NULL); + shadow_pde->shadow_proc = proc_net_shadow; return register_pernet_subsys(&proc_net_ns_ops); } -- cgit v1.2.2 From e136e769d471e7f3d24a8f6bf9c91dcb372bd0ab Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 4 Dec 2007 01:11:09 +0100 Subject: Freezer: Fix JFFS2 garbage collector freezing issue (rev. 2) Fix breakage caused by commit d5d8c5976d6adeddb8208c240460411e2198b393 "freezer: do not send signals to kernel threads" in jffs2_garbage_collect_thread() that assumed it would be sent signals by the freezer. Signed-off-by: Rafael J. Wysocki Cc: David Woodhouse Cc: Pete MacKay Signed-off-by: Len Brown --- fs/jffs2/background.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index d568ae846741..8adebd3e43c6 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -105,7 +105,7 @@ static int jffs2_garbage_collect_thread(void *_c) /* Put_super will send a SIGKILL and then wait on the sem. */ - while (signal_pending(current)) { + while (signal_pending(current) || freezing(current)) { siginfo_t info; unsigned long signr; -- cgit v1.2.2 From e00ba3dae077f54cfd2af42e939a618caa7a3bca Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Tue, 4 Dec 2007 23:45:02 -0800 Subject: aio: only account I/O wait time in read_events if there are active requests On 2.6.24, top started showing 100% iowait on one CPU when a UML instance was running (but completely idle). The UML code sits in io_getevents waiting for an event to be submitted and completed. Fix this by checking ctx->reqs_active before scheduling to determine whether or not we are waiting for I/O. Signed-off-by: Jeff Moyer Cc: Zach Brown Cc: Miklos Szeredi Cc: Jeff Dike Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index f12db415c0f6..9dec7d2d546e 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1161,7 +1161,12 @@ retry: ret = 0; if (to.timed_out) /* Only check after read evt */ break; - io_schedule(); + /* Try to only show up in io wait if there are ops + * in flight */ + if (ctx->reqs_active) + io_schedule(); + else + schedule(); if (signal_pending(tsk)) { ret = -EINTR; break; -- cgit v1.2.2 From 0c664f974269bb4c3d38ba900c91a9a5d4cee5b1 Mon Sep 17 00:00:00 2001 From: Evgeniy Dushistov Date: Tue, 4 Dec 2007 23:45:06 -0800 Subject: ufs: fix nexstep dir block size This patch fixes regression, introduced since 2.6.16. NextStep variant of UFS as OpenStep uses directory block size equals to 1024. Without this change, ufs_check_page fails in many cases. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Evgeniy Dushistov Cc: Dave Bailey Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ufs/dir.c | 2 +- fs/ufs/super.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 30f8c2bb0c3e..aaf2878305ce 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -179,7 +179,7 @@ bad_entry: goto fail; Eend: p = (struct ufs_dir_entry *)(kaddr + offs); - ufs_error (sb, "ext2_check_page", + ufs_error(sb, __FUNCTION__, "entry in directory #%lu spans the page boundary" "offset=%lu", dir->i_ino, (page->index<s_fsize = block_size = 1024; uspi->s_fmask = ~(1024 - 1); uspi->s_fshift = 10; uspi->s_sbsize = super_block_size = 2048; uspi->s_sbbase = 0; + uspi->s_dirblksize = 1024; flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; if (!(sb->s_flags & MS_RDONLY)) { if (!silent) @@ -771,13 +771,13 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) break; case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD: - /*TODO: check may be we need set special dir block size?*/ UFSD("ufstype=nextstep-cd\n"); uspi->s_fsize = block_size = 2048; uspi->s_fmask = ~(2048 - 1); uspi->s_fshift = 11; uspi->s_sbsize = super_block_size = 2048; uspi->s_sbbase = 0; + uspi->s_dirblksize = 1024; flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; if (!(sb->s_flags & MS_RDONLY)) { if (!silent) -- cgit v1.2.2 From d4beaf4ab5f89496f2bcf67db62ad95d99bfeff6 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 4 Dec 2007 23:45:27 -0800 Subject: jbd: Fix assertion failure in fs/jbd/checkpoint.c Before we start committing a transaction, we call __journal_clean_checkpoint_list() to cleanup transaction's written-back buffers. If this call happens to remove all of them (and there were already some buffers), __journal_remove_checkpoint() will decide to free the transaction because it isn't (yet) a committing transaction and soon we fail some assertion - the transaction really isn't ready to be freed :). We change the check in __journal_remove_checkpoint() to free only a transaction in T_FINISHED state. The locking there is subtle though (as everywhere in JBD ;(). We use j_list_lock to protect the check and a subsequent call to __journal_drop_transaction() and do the same in the end of journal_commit_transaction() which is the only place where a transaction can get to T_FINISHED state. Probably I'm too paranoid here and such locking is not really necessary - checkpoint lists are processed only from log_do_checkpoint() where a transaction must be already committed to be processed or from __journal_clean_checkpoint_list() where kjournald itself calls it and thus transaction cannot change state either. Better be safe if something changes in future... Signed-off-by: Jan Kara Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/jbd/checkpoint.c | 12 ++++++------ fs/jbd/commit.c | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 47552d4a6324..0f69c416eebc 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -602,15 +602,15 @@ int __journal_remove_checkpoint(struct journal_head *jh) /* * There is one special case to worry about: if we have just pulled the - * buffer off a committing transaction's forget list, then even if the - * checkpoint list is empty, the transaction obviously cannot be - * dropped! + * buffer off a running or committing transaction's checkpoing list, + * then even if the checkpoint list is empty, the transaction obviously + * cannot be dropped! * - * The locking here around j_committing_transaction is a bit sleazy. + * The locking here around t_state is a bit sleazy. * See the comment at the end of journal_commit_transaction(). */ - if (transaction == journal->j_committing_transaction) { - JBUFFER_TRACE(jh, "belongs to committing transaction"); + if (transaction->t_state != T_FINISHED) { + JBUFFER_TRACE(jh, "belongs to running/committing transaction"); goto out; } diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 8f1f2aa5fb39..610264b99a8e 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -858,10 +858,10 @@ restart_loop: } spin_unlock(&journal->j_list_lock); /* - * This is a bit sleazy. We borrow j_list_lock to protect - * journal->j_committing_transaction in __journal_remove_checkpoint. - * Really, __journal_remove_checkpoint should be using j_state_lock but - * it's a bit hassle to hold that across __journal_remove_checkpoint + * This is a bit sleazy. We use j_list_lock to protect transition + * of a transaction into T_FINISHED state and calling + * __journal_drop_transaction(). Otherwise we could race with + * other checkpointing code processing the transaction... */ spin_lock(&journal->j_state_lock); spin_lock(&journal->j_list_lock); -- cgit v1.2.2 From 5a622f2d0f86b316b07b55a4866ecb5518dd1cf7 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 4 Dec 2007 23:45:28 -0800 Subject: proc: fix proc_dir_entry refcounting Creating PDEs with refcount 0 and "deleted" flag has problems (see below). Switch to usual scheme: * PDE is created with refcount 1 * every de_get does +1 * every de_put() and remove_proc_entry() do -1 * once refcount reaches 0, PDE is freed. This elegantly fixes at least two following races (both observed) without introducing new locks, without abusing old locks, without spreading lock_kernel(): 1) PDE leak remove_proc_entry de_put ----------------- ------ [refcnt = 1] if (atomic_read(&de->count) == 0) if (atomic_dec_and_test(&de->count)) if (de->deleted) /* also not taken! */ free_proc_entry(de); else de->deleted = 1; [refcount=0, deleted=1] 2) use after free remove_proc_entry de_put ----------------- ------ [refcnt = 1] if (atomic_dec_and_test(&de->count)) if (atomic_read(&de->count) == 0) free_proc_entry(de); /* boom! */ if (de->deleted) free_proc_entry(de); BUG: unable to handle kernel paging request at virtual address 6b6b6b6b printing eip: c10acdda *pdpt = 00000000338f8001 *pde = 0000000000000000 Oops: 0000 [#1] PREEMPT SMP Modules linked in: af_packet ipv6 cpufreq_ondemand loop serio_raw psmouse k8temp hwmon sr_mod cdrom Pid: 23161, comm: cat Not tainted (2.6.24-rc2-8c0863403f109a43d7000b4646da4818220d501f #4) EIP: 0060:[] EFLAGS: 00210097 CPU: 1 EIP is at strnlen+0x6/0x18 EAX: 6b6b6b6b EBX: 6b6b6b6b ECX: 6b6b6b6b EDX: fffffffe ESI: c128fa3b EDI: f380bf34 EBP: ffffffff ESP: f380be44 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Process cat (pid: 23161, ti=f380b000 task=f38f2570 task.ti=f380b000) Stack: c10ac4f0 00000278 c12ce000 f43cd2a8 00000163 00000000 7da86067 00000400 c128fa20 00896b18 f38325a8 c128fe20 ffffffff 00000000 c11f291e 00000400 f75be300 c128fa20 f769c9a0 c10ac779 f380bf34 f7bfee70 c1018e6b f380bf34 Call Trace: [] vsnprintf+0x2ad/0x49b [] vscnprintf+0x14/0x1f [] vprintk+0xc5/0x2f9 [] handle_fasteoi_irq+0x0/0xab [] do_IRQ+0x9f/0xb7 [] preempt_schedule_irq+0x3f/0x5b [] need_resched+0x1f/0x21 [] printk+0x1b/0x1f [] de_put+0x3d/0x50 [] proc_delete_inode+0x38/0x41 [] proc_delete_inode+0x0/0x41 [] generic_delete_inode+0x5e/0xc6 [] iput+0x60/0x62 [] d_kill+0x2d/0x46 [] dput+0xdc/0xe4 [] __fput+0xb0/0xcd [] filp_close+0x48/0x4f [] sys_close+0x67/0xa5 [] sysenter_past_esp+0x5f/0x85 ======================= Code: c9 74 0c f2 ae 74 05 bf 01 00 00 00 4f 89 fa 5f 89 d0 c3 85 c9 57 89 c7 89 d0 74 05 f2 ae 75 01 4f 89 f8 5f c3 89 c1 89 c8 eb 06 <80> 38 00 74 07 40 4a 83 fa ff 75 f4 29 c8 c3 90 90 90 57 83 c9 EIP: [] strnlen+0x6/0x18 SS:ESP 0068:f380be44 Also, remove broken usage of ->deleted from reiserfs: if sget() succeeds, module is already pinned and remove_proc_entry() can't happen => nobody can mark PDE deleted. Dummy proc root in netns code is not marked with refcount 1. AFAICS, we never get it, it's just for proper /proc/net removal. I double checked CLONE_NETNS continues to work. Patch survives many hours of modprobe/rmmod/cat loops without new bugs which can be attributed to refcounting. Signed-off-by: Alexey Dobriyan Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/generic.c | 9 ++------- fs/proc/inode.c | 9 ++------- fs/proc/root.c | 1 + fs/reiserfs/procfs.c | 6 ------ 4 files changed, 5 insertions(+), 20 deletions(-) (limited to 'fs') diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 5fccfe222a63..8d49838e5554 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -595,6 +595,7 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, ent->namelen = len; ent->mode = mode; ent->nlink = nlink; + atomic_set(&ent->count, 1); ent->pde_users = 0; spin_lock_init(&ent->pde_unload_lock); ent->pde_unload_completion = NULL; @@ -692,7 +693,6 @@ void free_proc_entry(struct proc_dir_entry *de) /* * Remove a /proc entry and free it if it's not currently in use. - * If it is in use, we set the 'deleted' flag. */ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) { @@ -741,13 +741,8 @@ continue_removing: parent->nlink--; de->nlink = 0; WARN_ON(de->subdir); - if (!atomic_read(&de->count)) + if (atomic_dec_and_test(&de->count)) free_proc_entry(de); - else { - de->deleted = 1; - printk("remove_proc_entry: %s/%s busy, count=%d\n", - parent->name, de->name, atomic_read(&de->count)); - } break; } spin_unlock(&proc_subdir_lock); diff --git a/fs/proc/inode.c b/fs/proc/inode.c index abe6a3f04368..1a551d92e1d8 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -43,13 +43,8 @@ void de_put(struct proc_dir_entry *de) return; } - if (atomic_dec_and_test(&de->count)) { - if (de->deleted) { - printk("de_put: deferred delete of %s\n", - de->name); - free_proc_entry(de); - } - } + if (atomic_dec_and_test(&de->count)) + free_proc_entry(de); unlock_kernel(); } } diff --git a/fs/proc/root.c b/fs/proc/root.c index ec9cb3b6c93b..81f99e691f99 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -207,6 +207,7 @@ struct proc_dir_entry proc_root = { .name = "/proc", .mode = S_IFDIR | S_IRUGO | S_IXUGO, .nlink = 2, + .count = ATOMIC_INIT(1), .proc_iops = &proc_root_inode_operations, .proc_fops = &proc_root_operations, .parent = &proc_root, diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index 9aa7a06e093f..001144621672 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c @@ -420,12 +420,6 @@ static void *r_start(struct seq_file *m, loff_t * pos) return NULL; up_write(&s->s_umount); - - if (de->deleted) { - deactivate_super(s); - return NULL; - } - return s; } -- cgit v1.2.2 From 9b5e6857b3f3acc8ab434e565b7ec87bf9f9b53c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 5 Dec 2007 08:24:38 +0000 Subject: regression: cifs endianness bug access_flags_to_mode() gets on-the-wire data (little-endian) and treats it as host-endian. Introduced in commit e01b64001359034d04c695388870936ed3d1b56b ("[CIFS] enable get mode from ACL when cifsacl mount option specified") Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/cifs/cifsacl.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index f02fdef463a7..c312adcba4fc 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -134,9 +134,10 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) pmode is the existing mode (we only want to overwrite part of this bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007 */ -static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode, +static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, umode_t *pbits_to_set) { + __u32 flags = le32_to_cpu(ace_flags); /* the order of ACEs is important. The canonical order is to begin with DENY entries followed by ALLOW, otherwise an allow entry could be encountered first, making the subsequent deny entry like "dead code" @@ -146,17 +147,17 @@ static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode, /* For deny ACEs we change the mask so that subsequent allow access control entries do not turn on the bits we are denying */ if (type == ACCESS_DENIED) { - if (ace_flags & GENERIC_ALL) { + if (flags & GENERIC_ALL) { *pbits_to_set &= ~S_IRWXUGO; } - if ((ace_flags & GENERIC_WRITE) || - ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) + if ((flags & GENERIC_WRITE) || + ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) *pbits_to_set &= ~S_IWUGO; - if ((ace_flags & GENERIC_READ) || - ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) + if ((flags & GENERIC_READ) || + ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) *pbits_to_set &= ~S_IRUGO; - if ((ace_flags & GENERIC_EXECUTE) || - ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) + if ((flags & GENERIC_EXECUTE) || + ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) *pbits_to_set &= ~S_IXUGO; return; } else if (type != ACCESS_ALLOWED) { @@ -165,25 +166,25 @@ static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode, } /* else ACCESS_ALLOWED type */ - if (ace_flags & GENERIC_ALL) { + if (flags & GENERIC_ALL) { *pmode |= (S_IRWXUGO & (*pbits_to_set)); #ifdef CONFIG_CIFS_DEBUG2 cFYI(1, ("all perms")); #endif return; } - if ((ace_flags & GENERIC_WRITE) || - ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) + if ((flags & GENERIC_WRITE) || + ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) *pmode |= (S_IWUGO & (*pbits_to_set)); - if ((ace_flags & GENERIC_READ) || - ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) + if ((flags & GENERIC_READ) || + ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) *pmode |= (S_IRUGO & (*pbits_to_set)); - if ((ace_flags & GENERIC_EXECUTE) || - ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) + if ((flags & GENERIC_EXECUTE) || + ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) *pmode |= (S_IXUGO & (*pbits_to_set)); #ifdef CONFIG_CIFS_DEBUG2 - cFYI(1, ("access flags 0x%x mode now 0x%x", ace_flags, *pmode)); + cFYI(1, ("access flags 0x%x mode now 0x%x", flags, *pmode)); #endif return; } -- cgit v1.2.2 From 7e46aa5c8cb1347853de9ec86f3fa440f9dc9d77 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 5 Dec 2007 08:32:52 +0000 Subject: regression: bfs endianness bug BFS_FILEBLOCKS() expects struct bfs_inode * (on-disk data, with little- endian fields), not struct bfs_inode_info * (in-core stuff, with host- endian ones). It's a macro and fields with the right names are present in bfs_inode_info, so it compiles, but on big-endian host it gives bogus results. Introduced in commit f433dc56344cb72cc3de5ba0819021cec3aef807 ("Fixes to the BFS filesystem driver"). Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/bfs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 294c41baef6e..a64a71d444f5 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -178,7 +178,8 @@ static void bfs_delete_inode(struct inode *inode) brelse(bh); if (bi->i_dsk_ino) { - info->si_freeb += BFS_FILEBLOCKS(bi); + if (bi->i_sblock) + info->si_freeb += bi->i_eblock + 1 - bi->i_sblock; info->si_freei++; clear_bit(ino, info->si_imap); dump_imap("delete_inode", s); -- cgit v1.2.2 From 97bd7919e2c1445dabbcc2686795dbb52316b923 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 5 Dec 2007 08:46:47 +0000 Subject: remove nonsense force-casts from ocfs2 endianness annotations in networking code had been in place for quite a while; in particular, sin_port and s_addr are annotated as big-endian. Code in ocfs2 had __force casts added apparently to shut the sparse warnings up; of course, these days they only serve to *produce* warnings for no reason whatsoever... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/ocfs2/cluster/tcp.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index d84bd155997b..ee50c9610e7f 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -72,14 +72,6 @@ #include "tcp_internal.h" -/* - * The linux network stack isn't sparse endian clean.. It has macros like - * ntohs() which perform the endian checks and structs like sockaddr_in - * which aren't annotated. So __force is found here to get the build - * clean. When they emerge from the dark ages and annotate the code - * we can remove these. - */ - #define SC_NODEF_FMT "node %s (num %u) at %u.%u.%u.%u:%u" #define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num, \ NIPQUAD(sc->sc_node->nd_ipv4_address), \ @@ -1500,7 +1492,7 @@ static void o2net_start_connect(struct work_struct *work) myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = mynode->nd_ipv4_address; - myaddr.sin_port = (__force u16)htons(0); /* any port */ + myaddr.sin_port = htons(0); /* any port */ ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr)); @@ -1701,11 +1693,11 @@ static int o2net_accept_one(struct socket *sock) if (ret < 0) goto out; - node = o2nm_get_node_by_ip((__force __be32)sin.sin_addr.s_addr); + node = o2nm_get_node_by_ip(sin.sin_addr.s_addr); if (node == NULL) { mlog(ML_NOTICE, "attempt to connect from unknown node at " "%u.%u.%u.%u:%d\n", NIPQUAD(sin.sin_addr.s_addr), - ntohs((__force __be16)sin.sin_port)); + ntohs(sin.sin_port)); ret = -EINVAL; goto out; } @@ -1714,7 +1706,7 @@ static int o2net_accept_one(struct socket *sock) mlog(ML_NOTICE, "unexpected connect attempted from a lower " "numbered node '%s' at " "%u.%u.%u.%u:%d with num %u\n", node->nd_name, NIPQUAD(sin.sin_addr.s_addr), - ntohs((__force __be16)sin.sin_port), node->nd_num); + ntohs(sin.sin_port), node->nd_num); ret = -EINVAL; goto out; } @@ -1725,7 +1717,7 @@ static int o2net_accept_one(struct socket *sock) mlog(ML_CONN, "attempt to connect from node '%s' at " "%u.%u.%u.%u:%d but it isn't heartbeating\n", node->nd_name, NIPQUAD(sin.sin_addr.s_addr), - ntohs((__force __be16)sin.sin_port)); + ntohs(sin.sin_port)); ret = -EINVAL; goto out; } @@ -1742,7 +1734,7 @@ static int o2net_accept_one(struct socket *sock) mlog(ML_NOTICE, "attempt to connect from node '%s' at " "%u.%u.%u.%u:%d but it already has an open connection\n", node->nd_name, NIPQUAD(sin.sin_addr.s_addr), - ntohs((__force __be16)sin.sin_port)); + ntohs(sin.sin_port)); goto out; } -- cgit v1.2.2