diff --git a/[refs] b/[refs] index 9c7dfbb0dd0c..dcc1c96646ce 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cedabed49b39b4319bccc059a63344b6232b619c +refs/heads/master: 1373411ae4cd0caf2e1a35fb801dd9a00b64dea2 diff --git a/trunk/fs/fcntl.c b/trunk/fs/fcntl.c index 97e01dc0d95f..2cf93ec40a67 100644 --- a/trunk/fs/fcntl.c +++ b/trunk/fs/fcntl.c @@ -618,90 +618,60 @@ static DEFINE_RWLOCK(fasync_lock); static struct kmem_cache *fasync_cache __read_mostly; /* - * Remove a fasync entry. If successfully removed, return - * positive and clear the FASYNC flag. If no entry exists, - * do nothing and return 0. - * - * NOTE! It is very important that the FASYNC flag always - * match the state "is the filp on a fasync list". - * - * We always take the 'filp->f_lock', in since fasync_lock - * needs to be irq-safe. + * fasync_helper() is used by almost all character device drivers + * to set up the fasync queue. It returns negative on error, 0 if it did + * no changes and positive if it added/deleted the entry. */ -static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp) +int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) { struct fasync_struct *fa, **fp; + struct fasync_struct *new = NULL; int result = 0; - spin_lock(&filp->f_lock); - write_lock_irq(&fasync_lock); - for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { - if (fa->fa_file != filp) - continue; - *fp = fa->fa_next; - kmem_cache_free(fasync_cache, fa); - filp->f_flags &= ~FASYNC; - result = 1; - break; + if (on) { + new = kmem_cache_alloc(fasync_cache, GFP_KERNEL); + if (!new) + return -ENOMEM; } - write_unlock_irq(&fasync_lock); - spin_unlock(&filp->f_lock); - return result; -} - -/* - * Add a fasync entry. Return negative on error, positive if - * added, and zero if did nothing but change an existing one. - * - * NOTE! It is very important that the FASYNC flag always - * match the state "is the filp on a fasync list". - */ -static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp) -{ - struct fasync_struct *new, *fa, **fp; - int result = 0; - - new = kmem_cache_alloc(fasync_cache, GFP_KERNEL); - if (!new) - return -ENOMEM; + /* + * We need to take f_lock first since it's not an IRQ-safe + * lock. + */ spin_lock(&filp->f_lock); write_lock_irq(&fasync_lock); for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { - if (fa->fa_file != filp) - continue; - fa->fa_fd = fd; - kmem_cache_free(fasync_cache, new); - goto out; + if (fa->fa_file == filp) { + if(on) { + fa->fa_fd = fd; + kmem_cache_free(fasync_cache, new); + } else { + *fp = fa->fa_next; + kmem_cache_free(fasync_cache, fa); + result = 1; + } + goto out; + } } - new->magic = FASYNC_MAGIC; - new->fa_file = filp; - new->fa_fd = fd; - new->fa_next = *fapp; - *fapp = new; - result = 1; - filp->f_flags |= FASYNC; - + if (on) { + new->magic = FASYNC_MAGIC; + new->fa_file = filp; + new->fa_fd = fd; + new->fa_next = *fapp; + *fapp = new; + result = 1; + } out: + if (on) + filp->f_flags |= FASYNC; + else + filp->f_flags &= ~FASYNC; write_unlock_irq(&fasync_lock); spin_unlock(&filp->f_lock); return result; } -/* - * fasync_helper() is used by almost all character device drivers - * to set up the fasync queue, and for regular files by the file - * lease code. It returns negative on error, 0 if it did no changes - * and positive if it added/deleted the entry. - */ -int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) -{ - if (!on) - return fasync_remove_entry(filp, fapp); - return fasync_add_entry(fd, filp, fapp); -} - EXPORT_SYMBOL(fasync_helper); void __kill_fasync(struct fasync_struct *fa, int sig, int band) diff --git a/trunk/mm/truncate.c b/trunk/mm/truncate.c index e87e37244829..342deee22684 100644 --- a/trunk/mm/truncate.c +++ b/trunk/mm/truncate.c @@ -522,20 +522,22 @@ EXPORT_SYMBOL_GPL(invalidate_inode_pages2); */ void truncate_pagecache(struct inode *inode, loff_t old, loff_t new) { - struct address_space *mapping = inode->i_mapping; - - /* - * unmap_mapping_range is called twice, first simply for - * efficiency so that truncate_inode_pages does fewer - * single-page unmaps. However after this first call, and - * before truncate_inode_pages finishes, it is possible for - * private pages to be COWed, which remain after - * truncate_inode_pages finishes, hence the second - * unmap_mapping_range call must be made for correctness. - */ - unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); - truncate_inode_pages(mapping, new); - unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); + if (new < old) { + struct address_space *mapping = inode->i_mapping; + + /* + * unmap_mapping_range is called twice, first simply for + * efficiency so that truncate_inode_pages does fewer + * single-page unmaps. However after this first call, and + * before truncate_inode_pages finishes, it is possible for + * private pages to be COWed, which remain after + * truncate_inode_pages finishes, hence the second + * unmap_mapping_range call must be made for correctness. + */ + unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); + truncate_inode_pages(mapping, new); + unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); + } } EXPORT_SYMBOL(truncate_pagecache); diff --git a/trunk/scripts/Makefile.lib b/trunk/scripts/Makefile.lib index 0fe48cd91ffa..f9bdf264473d 100644 --- a/trunk/scripts/Makefile.lib +++ b/trunk/scripts/Makefile.lib @@ -219,8 +219,13 @@ for F in $1; do \ fsize=$$(stat -c "%s" $$F); \ dec_size=$$(expr $$dec_size + $$fsize); \ done; \ -printf "%08x" $$dec_size | \ - sed 's/\(..\)\(..\)\(..\)\(..\)/\\\\x\4\\\\x\3\\\\x\2\\\\x\1/g' \ +printf "%08x\n" $$dec_size | \ + sed 's/\(..\)/\1 /g' | { \ + read ch0 ch1 ch2 ch3; \ + for ch in $$ch3 $$ch2 $$ch1 $$ch0; do \ + printf '%s%03o' '\\' $$((0x$$ch)); \ + done; \ + } \ ) quiet_cmd_bzip2 = BZIP2 $@