Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 179212
b: refs/heads/master
c: 1373411
h: refs/heads/master
v: v3
  • Loading branch information
Jonathan Nieder authored and Michal Marek committed Jan 13, 2010
1 parent 97fc756 commit 104715e
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 83 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cedabed49b39b4319bccc059a63344b6232b619c
refs/heads/master: 1373411ae4cd0caf2e1a35fb801dd9a00b64dea2
102 changes: 36 additions & 66 deletions trunk/fs/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
30 changes: 16 additions & 14 deletions trunk/mm/truncate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
9 changes: 7 additions & 2 deletions trunk/scripts/Makefile.lib
Original file line number Diff line number Diff line change
Expand Up @@ -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 $@
Expand Down

0 comments on commit 104715e

Please sign in to comment.