From 00be3e7e5cc3ca80e035b387e883d5ec10d7b897 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Thu, 14 Jul 2005 15:15:39 -0500 Subject: JFS: Remove bogus WARN_ON statement and some dead code Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_metapage.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 6c5485d16c39..8cb803b54bc1 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -561,7 +561,6 @@ static int metapage_releasepage(struct page *page, int gfp_mask) dump_mem("page", page, sizeof(struct page)); dump_stack(); } - WARN_ON(mp->lsn); if (mp->lsn) remove_from_logsync(mp); remove_metapage(page, mp); @@ -783,14 +782,6 @@ void release_metapage(struct metapage * mp) if (test_bit(META_discard, &mp->flag) && !mp->count) { clear_page_dirty(page); ClearPageUptodate(page); -#ifdef _NOT_YET - if (page->mapping) { - /* Remove from page cache and page cache reference */ - remove_from_page_cache(page); - page_cache_release(page); - metapage_releasepage(page, 0); - } -#endif } #else /* Try to keep metapages from using up too much memory */ -- cgit v1.2.2 From 56d1254917d9f301a8e24155cd3f2236e642cb7d Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Fri, 15 Jul 2005 09:43:36 -0500 Subject: JFS: Remove assert statement in dbJoin & return -EIO instead Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_dmap.c | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 0732f206ca60..c739626f5bf1 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -75,7 +75,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks); static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval); static void dbBackSplit(dmtree_t * tp, int leafno); -static void dbJoin(dmtree_t * tp, int leafno, int newval); +static int dbJoin(dmtree_t * tp, int leafno, int newval); static void dbAdjTree(dmtree_t * tp, int leafno, int newval); static int dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level); @@ -98,8 +98,8 @@ static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks); static int dbFindBits(u32 word, int l2nb); static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno); static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx); -static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, - int nblocks); +static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, + int nblocks); static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks); static int dbMaxBud(u8 * cp); @@ -378,6 +378,7 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks) /* free the blocks. */ if ((rc = dbFreeDmap(bmp, dp, blkno, nb))) { + jfs_error(ip->i_sb, "dbFree: error in block map\n"); release_metapage(mp); IREAD_UNLOCK(ipbmap); return (rc); @@ -2020,7 +2021,7 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks) { s8 oldroot; - int rc, word; + int rc = 0, word; /* save the current value of the root (i.e. maximum free string) * of the dmap tree. @@ -2028,11 +2029,11 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, oldroot = dp->tree.stree[ROOT]; /* free the specified (blocks) bits */ - dbFreeBits(bmp, dp, blkno, nblocks); + rc = dbFreeBits(bmp, dp, blkno, nblocks); - /* if the root has not changed, done. */ - if (dp->tree.stree[ROOT] == oldroot) - return (0); + /* if error or the root has not changed, done. */ + if (rc || (dp->tree.stree[ROOT] == oldroot)) + return (rc); /* root changed. bubble the change up to the dmap control pages. * if the adjustment of the upper level control pages fails, @@ -2221,15 +2222,16 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, * blkno - starting block number of the bits to be freed. * nblocks - number of bits to be freed. * - * RETURN VALUES: none + * RETURN VALUES: 0 for success * * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit; */ -static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, +static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks) { int dbitno, word, rembits, nb, nwords, wbitno, nw, agno; dmtree_t *tp = (dmtree_t *) & dp->tree; + int rc = 0; int size; /* determine the bit number and word within the dmap of the @@ -2278,8 +2280,10 @@ static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, /* update the leaf for this dmap word. */ - dbJoin(tp, word, - dbMaxBud((u8 *) & dp->wmap[word])); + rc = dbJoin(tp, word, + dbMaxBud((u8 *) & dp->wmap[word])); + if (rc) + return rc; word += 1; } else { @@ -2310,7 +2314,9 @@ static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, /* update the leaf. */ - dbJoin(tp, word, size); + rc = dbJoin(tp, word, size); + if (rc) + return rc; /* get the number of dmap words handled. */ @@ -2357,6 +2363,8 @@ static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, } BMAP_UNLOCK(bmp); + + return 0; } @@ -2464,7 +2472,9 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) } dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval); } else { - dbJoin((dmtree_t *) dcp, leafno, newval); + rc = dbJoin((dmtree_t *) dcp, leafno, newval); + if (rc) + return rc; } /* check if the root of the current dmap control page changed due @@ -2689,7 +2699,7 @@ static void dbBackSplit(dmtree_t * tp, int leafno) * * RETURN VALUES: none */ -static void dbJoin(dmtree_t * tp, int leafno, int newval) +static int dbJoin(dmtree_t * tp, int leafno, int newval) { int budsz, buddy; s8 *leaf; @@ -2729,7 +2739,9 @@ static void dbJoin(dmtree_t * tp, int leafno, int newval) if (newval > leaf[buddy]) break; - assert(newval == leaf[buddy]); + /* It shouldn't be less */ + if (newval < leaf[buddy]) + return -EIO; /* check which (leafno or buddy) is the left buddy. * the left buddy gets to claim the blocks resulting @@ -2761,6 +2773,8 @@ static void dbJoin(dmtree_t * tp, int leafno, int newval) /* update the leaf value. */ dbAdjTree(tp, leafno, newval); + + return 0; } -- cgit v1.2.2 From 3d9b1cdd2455017c6aa25bc2442092b81438981f Mon Sep 17 00:00:00 2001 From: Qu Fuping Date: Fri, 15 Jul 2005 10:36:08 -0500 Subject: JFS: fsync wrong behavior when I/O failure occurs This is half of a patch that Qu Fuping submitted in April. The first part was applied to fs/mpage.c in 2.6.12-rc4. jfs_fsync should return error, but it doesn't wait for the metadata page to be uptodate, e.g.: jfs_fsync->jfs_commit_inode->txCommit->diWrite->read_metapage-> __get_metapage->read_cache_page reads a page from disk. Because read is async, when read_cache_page: err = filler(data, page), filler will not return error, it just submits I/O request and returns. So, page is not uptodate. Checking only if(IS_ERROR(mp->page)) is not enough, we should add "|| !PageUptodate(mp->page)" Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_metapage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 8cb803b54bc1..02add5d8ff89 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -640,7 +640,7 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, } else { page = read_cache_page(mapping, page_index, (filler_t *)mapping->a_ops->readpage, NULL); - if (IS_ERR(page)) { + if (IS_ERR(page) || !PageUptodate(mp->page)) { jfs_err("read_cache_page failed!"); return NULL; } -- cgit v1.2.2 From c40c202493d18de42fcd0b8b5d68c22aefb70f03 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Fri, 22 Jul 2005 11:08:44 -0500 Subject: JFS: Fix typo in last patch Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_metapage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 02add5d8ff89..13d7e3f1feb4 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -640,7 +640,7 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, } else { page = read_cache_page(mapping, page_index, (filler_t *)mapping->a_ops->readpage, NULL); - if (IS_ERR(page) || !PageUptodate(mp->page)) { + if (IS_ERR(page) || !PageUptodate(page)) { jfs_err("read_cache_page failed!"); return NULL; } -- cgit v1.2.2 From c2783f3a625b2aba943ef94623e277557a91a448 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 25 Jul 2005 08:58:54 -0500 Subject: JFS: Don't set log_SYNCBARRIER when log->active == 0 If a metadata page is kept active, it is possible that the sync barrier logic continues to trigger, even if all active transactions have been phyically written to the journal. This can cause a hang, since the completion of the journal I/O is what unsets the sync barrier flag to allow new transactions to be created. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_logmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 79d07624bfe1..22815e88e7cc 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1030,7 +1030,8 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) * starting until all current transactions are completed * by setting syncbarrier flag. */ - if (written > LOGSYNC_BARRIER(logsize) && logsize > 32 * LOGPSIZE) { + if (!test_bit(log_SYNCBARRIER, &log->flag) && + (written > LOGSYNC_BARRIER(logsize)) && log->active) { set_bit(log_SYNCBARRIER, &log->flag); jfs_info("log barrier on: lsn=0x%x syncpt=0x%x", lsn, log->syncpt); -- cgit v1.2.2 From 18190cc08d70a6ec8ef69f0f6ede021f7cb3f9b8 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Tue, 26 Jul 2005 09:29:13 -0500 Subject: JFS: Fix i_blocks accounting when allocation fails A failure in dbAlloc caused a directory's i_blocks to be incorrectly incremented, causing jfs_fsck to find the inode to be corrupt. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_dtree.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 73b5fc7eda80..404f33eae507 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -381,9 +381,12 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot) * It's time to move the inline table to an external * page and begin to build the xtree */ - if (DQUOT_ALLOC_BLOCK(ip, sbi->nbperpage) || - dbAlloc(ip, 0, sbi->nbperpage, &xaddr)) - goto clean_up; /* No space */ + if (DQUOT_ALLOC_BLOCK(ip, sbi->nbperpage)) + goto clean_up; + if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr)) { + DQUOT_FREE_BLOCK(ip, sbi->nbperpage); + goto clean_up; + } /* * Save the table, we're going to overwrite it with the @@ -397,13 +400,15 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot) xtInitRoot(tid, ip); /* - * Allocate the first block & add it to the xtree + * Add the first block to the xtree */ if (xtInsert(tid, ip, 0, 0, sbi->nbperpage, &xaddr, 0)) { /* This really shouldn't fail */ jfs_warn("add_index: xtInsert failed!"); memcpy(&jfs_ip->i_dirtable, temp_table, sizeof (temp_table)); + dbFree(ip, xaddr, sbi->nbperpage); + DQUOT_FREE_BLOCK(ip, sbi->nbperpage); goto clean_up; } ip->i_size = PSIZE; -- cgit v1.2.2 From b680716ed28baf549f777fb125fc23ba975985c5 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Mon, 25 Jul 2005 15:07:13 -0400 Subject: [PATCH] inotify: misc. cleanup Miscellaneous invariant clean up, comment fixes, and so on. Trivial stuff. Signed-off-by: Robert Love Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/inotify.c | 66 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 32 insertions(+), 34 deletions(-) (limited to 'fs') diff --git a/fs/inotify.c b/fs/inotify.c index 54757be888b6..a87926584cd2 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -62,8 +62,8 @@ int inotify_max_queued_events; * Lifetimes of the three main data structures--inotify_device, inode, and * inotify_watch--are managed by reference count. * - * inotify_device: Lifetime is from open until release. Additional references - * can bump the count via get_inotify_dev() and drop the count via + * inotify_device: Lifetime is from inotify_init() until release. Additional + * references can bump the count via get_inotify_dev() and drop the count via * put_inotify_dev(). * * inotify_watch: Lifetime is from create_watch() to destory_watch(). @@ -75,7 +75,7 @@ int inotify_max_queued_events; */ /* - * struct inotify_device - represents an open instance of an inotify device + * struct inotify_device - represents an inotify instance * * This structure is protected by the semaphore 'sem'. */ @@ -371,7 +371,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd) /* you can only watch an inode if you have read permissions on it */ error = permission(nd->dentry->d_inode, MAY_READ, NULL); if (error) - path_release (nd); + path_release(nd); return error; } @@ -387,7 +387,8 @@ static struct inotify_watch *create_watch(struct inotify_device *dev, struct inotify_watch *watch; int ret; - if (atomic_read(&dev->user->inotify_watches) >= inotify_max_user_watches) + if (atomic_read(&dev->user->inotify_watches) >= + inotify_max_user_watches) return ERR_PTR(-ENOSPC); watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL); @@ -783,15 +784,14 @@ static int inotify_release(struct inode *ignored, struct file *file) inotify_dev_event_dequeue(dev); up(&dev->sem); - /* free this device: the put matching the get in inotify_open() */ + /* free this device: the put matching the get in inotify_init() */ put_inotify_dev(dev); return 0; } /* - * inotify_ignore - handle the INOTIFY_IGNORE ioctl, asking that a given wd be - * removed from the device. + * inotify_ignore - remove a given wd from this inotify instance. * * Can sleep. */ @@ -856,15 +856,12 @@ asmlinkage long sys_inotify_init(void) { struct inotify_device *dev; struct user_struct *user; - int ret = -ENOTTY; - int fd; - struct file *filp; + struct file *filp; + int fd, ret; fd = get_unused_fd(); - if (fd < 0) { - ret = fd; - goto out; - } + if (fd < 0) + return fd; filp = get_empty_filp(); if (!filp) { @@ -872,16 +869,11 @@ asmlinkage long sys_inotify_init(void) ret = -ENFILE; goto out; } - filp->f_op = &inotify_fops; - filp->f_vfsmnt = mntget(inotify_mnt); - filp->f_dentry = dget(inotify_mnt->mnt_root); - filp->f_mapping = filp->f_dentry->d_inode->i_mapping; - filp->f_mode = FMODE_READ; - filp->f_flags = O_RDONLY; user = get_uid(current->user); - if (unlikely(atomic_read(&user->inotify_devs) >= inotify_max_user_instances)) { + if (unlikely(atomic_read(&user->inotify_devs) >= + inotify_max_user_instances)) { ret = -EMFILE; goto out_err; } @@ -892,6 +884,14 @@ asmlinkage long sys_inotify_init(void) goto out_err; } + filp->f_op = &inotify_fops; + filp->f_vfsmnt = mntget(inotify_mnt); + filp->f_dentry = dget(inotify_mnt->mnt_root); + filp->f_mapping = filp->f_dentry->d_inode->i_mapping; + filp->f_mode = FMODE_READ; + filp->f_flags = O_RDONLY; + filp->private_data = dev; + idr_init(&dev->idr); INIT_LIST_HEAD(&dev->events); INIT_LIST_HEAD(&dev->watches); @@ -905,9 +905,8 @@ asmlinkage long sys_inotify_init(void) get_inotify_dev(dev); atomic_inc(&user->inotify_devs); + fd_install(fd, filp); - filp->private_data = dev; - fd_install (fd, filp); return fd; out_err: put_unused_fd (fd); @@ -917,7 +916,7 @@ out: return ret; } -asmlinkage long sys_inotify_add_watch(int fd, const char *path, u32 mask) +asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) { struct inotify_watch *watch, *old; struct inode *inode; @@ -930,21 +929,20 @@ asmlinkage long sys_inotify_add_watch(int fd, const char *path, u32 mask) if (!filp) return -EBADF; - dev = filp->private_data; - - ret = find_inode((const char __user*) path, &nd); - if (ret) + ret = find_inode(path, &nd); + if (unlikely(ret)) goto fput_and_out; - /* Held in place by reference in nd */ + /* inode held in place by reference to nd; dev by fget on fd */ inode = nd.dentry->d_inode; + dev = filp->private_data; down(&inode->inotify_sem); down(&dev->sem); /* don't let user-space set invalid bits: we don't want flags set */ mask &= IN_ALL_EVENTS; - if (!mask) { + if (unlikely(!mask)) { ret = -EINVAL; goto out; } @@ -1009,11 +1007,11 @@ static struct file_system_type inotify_fs_type = { }; /* - * inotify_init - Our initialization function. Note that we cannnot return + * inotify_setup - Our initialization function. Note that we cannnot return * error because we have compiled-in VFS hooks. So an (unlikely) failure here * must result in panic(). */ -static int __init inotify_init(void) +static int __init inotify_setup(void) { register_filesystem(&inotify_fs_type); inotify_mnt = kern_mount(&inotify_fs_type); @@ -1034,4 +1032,4 @@ static int __init inotify_init(void) return 0; } -module_init(inotify_init); +module_init(inotify_setup); -- cgit v1.2.2 From 33ea2f52b8758ef62ae4a9d2f91821c47d999ee9 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Mon, 25 Jul 2005 15:08:37 -0400 Subject: [PATCH] inotify: use fget_light As an optimization, use fget_light() and fput_light() where possible. Signed-off-by: Robert Love Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/inotify.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/inotify.c b/fs/inotify.c index a87926584cd2..807209f0bcda 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -923,10 +923,10 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) struct inotify_device *dev; struct nameidata nd; struct file *filp; - int ret; + int ret, fput_needed; - filp = fget(fd); - if (!filp) + filp = fget_light(fd, &fput_needed); + if (unlikely(!filp)) return -EBADF; ret = find_inode(path, &nd); @@ -973,7 +973,7 @@ out: up(&dev->sem); up(&inode->inotify_sem); fput_and_out: - fput(filp); + fput_light(filp, fput_needed); return ret; } @@ -981,14 +981,14 @@ asmlinkage long sys_inotify_rm_watch(int fd, u32 wd) { struct file *filp; struct inotify_device *dev; - int ret; + int ret, fput_needed; - filp = fget(fd); - if (!filp) + filp = fget_light(fd, &fput_needed); + if (unlikely(!filp)) return -EBADF; dev = filp->private_data; ret = inotify_ignore(dev, wd); - fput(filp); + fput_light(filp, fput_needed); return ret; } -- cgit v1.2.2 From 783bc29bbc5d6625a4669d3eb1d989a8fb275d43 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Mon, 25 Jul 2005 15:10:08 -0400 Subject: [PATCH] inotify: oops fix Bug fix: Ensure that the fd passed to inotify_add_watch() and inotify_rm_watch() belongs to inotify. Signed-off-by: Robert Love Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/inotify.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/inotify.c b/fs/inotify.c index 807209f0bcda..b55d6e4a0911 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -929,6 +929,12 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) if (unlikely(!filp)) return -EBADF; + /* verify that this is indeed an inotify instance */ + if (unlikely(filp->f_op != &inotify_fops)) { + ret = -EINVAL; + goto fput_and_out; + } + ret = find_inode(path, &nd); if (unlikely(ret)) goto fput_and_out; @@ -986,10 +992,18 @@ asmlinkage long sys_inotify_rm_watch(int fd, u32 wd) filp = fget_light(fd, &fput_needed); if (unlikely(!filp)) return -EBADF; + + /* verify that this is indeed an inotify instance */ + if (unlikely(filp->f_op != &inotify_fops)) { + ret = -EINVAL; + goto out; + } + dev = filp->private_data; ret = inotify_ignore(dev, wd); - fput_light(filp, fput_needed); +out: + fput_light(filp, fput_needed); return ret; } -- cgit v1.2.2 From 5eb22cbcdb849886c2584389faff5afb56c23876 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Mon, 25 Jul 2005 15:12:19 -0400 Subject: [PATCH] inotify: exit path cleanups Handle error out paths better. Signed-off-by: Robert Love Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/inotify.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/inotify.c b/fs/inotify.c index b55d6e4a0911..d41c53c8dfd0 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -865,23 +865,21 @@ asmlinkage long sys_inotify_init(void) filp = get_empty_filp(); if (!filp) { - put_unused_fd(fd); ret = -ENFILE; - goto out; + goto out_put_fd; } user = get_uid(current->user); - if (unlikely(atomic_read(&user->inotify_devs) >= inotify_max_user_instances)) { ret = -EMFILE; - goto out_err; + goto out_free_uid; } dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL); if (unlikely(!dev)) { ret = -ENOMEM; - goto out_err; + goto out_free_uid; } filp->f_op = &inotify_fops; @@ -908,11 +906,11 @@ asmlinkage long sys_inotify_init(void) fd_install(fd, filp); return fd; -out_err: - put_unused_fd (fd); - put_filp (filp); +out_free_uid: free_uid(user); -out: + put_filp(filp); +out_put_fd: + put_unused_fd(fd); return ret; } @@ -975,9 +973,9 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) list_add(&watch->i_list, &inode->inotify_watches); ret = watch->wd; out: - path_release (&nd); up(&dev->sem); up(&inode->inotify_sem); + path_release(&nd); fput_and_out: fput_light(filp, fput_needed); return ret; -- cgit v1.2.2 From 1b2ccf0cc15af717263c7cfe5d0aaf5ac057489e Mon Sep 17 00:00:00 2001 From: Robert Love Date: Mon, 25 Jul 2005 15:13:43 -0400 Subject: [PATCH] inotify: change default limits Change default inotify limits: Maximum instances per user to 128 and maximum events per queue to 16k. The max instances used to be 128; the change to 8 was a mistake. Memory consumption is fine. Signed-off-by: Robert Love Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/inotify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/inotify.c b/fs/inotify.c index d41c53c8dfd0..6a0ba2c858e6 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -1028,8 +1028,8 @@ static int __init inotify_setup(void) register_filesystem(&inotify_fs_type); inotify_mnt = kern_mount(&inotify_fs_type); - inotify_max_queued_events = 8192; - inotify_max_user_instances = 8; + inotify_max_queued_events = 16384; + inotify_max_user_instances = 128; inotify_max_user_watches = 8192; atomic_set(&inotify_cookie, 0); -- cgit v1.2.2 From e5ca844a9d795e97c08bc7901c62a48c28469eb0 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Mon, 25 Jul 2005 15:17:34 -0400 Subject: [PATCH] inotify: check retval in init Check for (unlikely) errors in the filesystem initialization stuff in our module_init() function. Signed-off-by: Robert Love Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/inotify.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/inotify.c b/fs/inotify.c index 6a0ba2c858e6..cdfff9067149 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -1025,8 +1025,15 @@ static struct file_system_type inotify_fs_type = { */ static int __init inotify_setup(void) { - register_filesystem(&inotify_fs_type); + int ret; + + ret = register_filesystem(&inotify_fs_type); + if (unlikely(ret)) + panic("inotify: register_filesystem returned %d!\n", ret); + inotify_mnt = kern_mount(&inotify_fs_type); + if (unlikely(PTR_ERR(inotify_mnt))) + panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt)); inotify_max_queued_events = 16384; inotify_max_user_instances = 128; -- cgit v1.2.2 From 89373de7dd010832d8b68cb37dabb33ff5a688bb Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 26 Jul 2005 14:08:38 -0700 Subject: [PATCH] inotify: fix oops fix Cc: Robert Love Cc: John McCutchan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/inotify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/inotify.c b/fs/inotify.c index cdfff9067149..a8a714e48140 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -1032,7 +1032,7 @@ static int __init inotify_setup(void) panic("inotify: register_filesystem returned %d!\n", ret); inotify_mnt = kern_mount(&inotify_fs_type); - if (unlikely(PTR_ERR(inotify_mnt))) + if (IS_ERR(inotify_mnt)) panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt)); inotify_max_queued_events = 16384; -- cgit v1.2.2 From cbc3d65ebcb0c494183d45cf202a53352cbf3871 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Wed, 27 Jul 2005 09:17:57 -0500 Subject: JFS: Improve sync barrier processing Under heavy load, hot metadata pages are often locked by non-committed transactions, making them difficult to flush to disk. This prevents the sync point from advancing past a transaction that had modified the page. There is a point during the sync barrier processing where all outstanding transactions have been committed to disk, but no new transaction have been allowed to proceed. This is the best time to write the metadata. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_logmgr.c | 36 +++++++++++++++++++----------------- fs/jfs/jfs_logmgr.h | 2 +- fs/jfs/jfs_txnmgr.c | 10 +++++----- fs/jfs/super.c | 2 +- 4 files changed, 26 insertions(+), 24 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 22815e88e7cc..d27bac6acaa3 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -191,7 +191,7 @@ static int lbmIOWait(struct lbuf * bp, int flag); static bio_end_io_t lbmIODone; static void lbmStartIO(struct lbuf * bp); static void lmGCwrite(struct jfs_log * log, int cant_block); -static int lmLogSync(struct jfs_log * log, int nosyncwait); +static int lmLogSync(struct jfs_log * log, int hard_sync); @@ -915,19 +915,17 @@ static void lmPostGC(struct lbuf * bp) * if new sync address is available * (normally the case if sync() is executed by back-ground * process). - * if not, explicitly run jfs_blogsync() to initiate - * getting of new sync address. * calculate new value of i_nextsync which determines when * this code is called again. * * PARAMETERS: log - log structure - * nosyncwait - 1 if called asynchronously + * hard_sync - 1 to force all metadata to be written * * RETURN: 0 * * serialization: LOG_LOCK() held on entry/exit */ -static int lmLogSync(struct jfs_log * log, int nosyncwait) +static int lmLogSync(struct jfs_log * log, int hard_sync) { int logsize; int written; /* written since last syncpt */ @@ -941,11 +939,18 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) unsigned long flags; /* push dirty metapages out to disk */ - list_for_each_entry(sbi, &log->sb_list, log_list) { - filemap_flush(sbi->ipbmap->i_mapping); - filemap_flush(sbi->ipimap->i_mapping); - filemap_flush(sbi->direct_inode->i_mapping); - } + if (hard_sync) + list_for_each_entry(sbi, &log->sb_list, log_list) { + filemap_fdatawrite(sbi->ipbmap->i_mapping); + filemap_fdatawrite(sbi->ipimap->i_mapping); + filemap_fdatawrite(sbi->direct_inode->i_mapping); + } + else + list_for_each_entry(sbi, &log->sb_list, log_list) { + filemap_flush(sbi->ipbmap->i_mapping); + filemap_flush(sbi->ipimap->i_mapping); + filemap_flush(sbi->direct_inode->i_mapping); + } /* * forward syncpt @@ -1021,10 +1026,6 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) /* next syncpt trigger = written + more */ log->nextsync = written + more; - /* return if lmLogSync() from outside of transaction, e.g., sync() */ - if (nosyncwait) - return lsn; - /* if number of bytes written from last sync point is more * than 1/4 of the log size, stop new transactions from * starting until all current transactions are completed @@ -1049,11 +1050,12 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) * * FUNCTION: write log SYNCPT record for specified log * - * PARAMETERS: log - log structure + * PARAMETERS: log - log structure + * hard_sync - set to 1 to force metadata to be written */ -void jfs_syncpt(struct jfs_log *log) +void jfs_syncpt(struct jfs_log *log, int hard_sync) { LOG_LOCK(log); - lmLogSync(log, 1); + lmLogSync(log, hard_sync); LOG_UNLOCK(log); } diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h index 747114cd38b8..e4978b5b65ee 100644 --- a/fs/jfs/jfs_logmgr.h +++ b/fs/jfs/jfs_logmgr.h @@ -510,6 +510,6 @@ extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize); extern int lmGroupCommit(struct jfs_log *, struct tblock *); extern int jfsIOWait(void *); extern void jfs_flush_journal(struct jfs_log * log, int wait); -extern void jfs_syncpt(struct jfs_log *log); +extern void jfs_syncpt(struct jfs_log *log, int hard_sync); #endif /* _H_JFS_LOGMGR */ diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 121c981ff453..3555acff12d0 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -552,6 +552,11 @@ void txEnd(tid_t tid) * synchronize with logsync barrier */ if (test_bit(log_SYNCBARRIER, &log->flag)) { + TXN_UNLOCK(); + + /* write dirty metadata & forward log syncpt */ + jfs_syncpt(log, 1); + jfs_info("log barrier off: 0x%x", log->lsn); /* enable new transactions start */ @@ -560,11 +565,6 @@ void txEnd(tid_t tid) /* wakeup all waitors for logsync barrier */ TXN_WAKEUP(&log->syncwait); - TXN_UNLOCK(); - - /* forward log syncpt */ - jfs_syncpt(log); - goto wakeup; } } diff --git a/fs/jfs/super.c b/fs/jfs/super.c index ee32211288ce..c2abdaee0c0b 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -531,7 +531,7 @@ static int jfs_sync_fs(struct super_block *sb, int wait) /* log == NULL indicates read-only mount */ if (log) { jfs_flush_journal(log, wait); - jfs_syncpt(log); + jfs_syncpt(log, 0); } return 0; -- cgit v1.2.2 From ef2a701d444a4ea9790146e92756b0dde5070a15 Mon Sep 17 00:00:00 2001 From: Nigel Cunningham Date: Wed, 27 Jul 2005 11:43:36 -0700 Subject: [PATCH] Fix missing refrigerator invocation in jffs2 Here's a patch to fix a missing refrigerator call in jffs2. Signed-off-by: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/jffs/intrep.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index fc589ddd0762..456d7e6e29c2 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c @@ -3397,6 +3397,9 @@ jffs_garbage_collect_thread(void *ptr) siginfo_t info; unsigned long signr = 0; + if (try_to_freeze()) + continue; + spin_lock_irq(¤t->sighand->siglock); signr = dequeue_signal(current, ¤t->blocked, &info); spin_unlock_irq(¤t->sighand->siglock); -- cgit v1.2.2 From b3bb8afd965159f155d4f629cbea158cbcc69275 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Wed, 27 Jul 2005 11:43:38 -0700 Subject: [PATCH] reiserfs: fix deadlock in inode creation failure path w/ default ACL reiserfs_new_inode() can call iput() with the xattr lock held. This will cause a deadlock to occur when reiserfs_delete_xattrs() is called to clean up. The following patch releases the lock and reacquires it after the iput. This is safe because interaction with xattrs is complete, and the relock is just to balance out the release in the caller. The locking needs some reworking to be more sane, but that's more intrusive and I was just looking to fix this bug. Signed-off-by: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/inode.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 1aaf2c7d44e6..d9f614a57731 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1980,7 +1980,17 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, out_inserted_sd: inode->i_nlink = 0; th->t_trans_id = 0; /* so the caller can't use this handle later */ - iput(inode); + + /* If we were inheriting an ACL, we need to release the lock so that + * iput doesn't deadlock in reiserfs_delete_xattrs. The locking + * code really needs to be reworked, but this will take care of it + * for now. -jeffm */ + if (REISERFS_I(dir)->i_acl_default) { + reiserfs_write_unlock_xattrs(dir->i_sb); + iput(inode); + reiserfs_write_lock_xattrs(dir->i_sb); + } else + iput(inode); return err; } -- cgit v1.2.2 From c7e9a52ef0089492bba457dfb8eba1a54e19f24a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 27 Jul 2005 11:43:39 -0700 Subject: [PATCH] ext2: drop quota reference before releasing inode We must drop references to quota structures before releasing the inode. Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/ialloc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 77e059149212..161f156d98c8 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -612,6 +612,7 @@ got: err = ext2_init_acl(inode, dir); if (err) { DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); goto fail2; } mark_inode_dirty(inode); -- cgit v1.2.2 From ab6862e6dab813ecde9ae7da506188dc1e9f11bb Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 27 Jul 2005 11:43:40 -0700 Subject: [PATCH] ext3: drop quota references before releasing inode We must drop references to quota structures before releasing the inode. Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/ialloc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 1e6f3ea28713..6981bd014ede 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -604,12 +604,14 @@ got: err = ext3_init_acl(handle, inode, dir); if (err) { DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); goto fail2; } err = ext3_mark_inode_dirty(handle, inode); if (err) { ext3_std_error(sb, err); DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); goto fail2; } -- cgit v1.2.2 From 104e49fc1e1656142869fab0e75d7df52b72eed9 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Wed, 27 Jul 2005 11:43:45 -0700 Subject: [PATCH] autofs4: fix infamous "Busy inodes after umount ..." message If the automount daemon receives a signal which causes it to sumarily terminate the autofs4 module leaks dentries. The same problem exists with detached mount requests without the warning. This patch cleans these dentries at umount. Signed-off-by: Ian Kent Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/autofs4/autofs_i.h | 1 + fs/autofs4/inode.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'fs') diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 9c09641ce907..fca83e28edcf 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -92,6 +92,7 @@ struct autofs_wait_queue { struct autofs_sb_info { u32 magic; + struct dentry *root; struct file *pipe; pid_t oz_pgrp; int catatonic; diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 4bb14cc68040..0a3c05d10167 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "autofs_i.h" #include @@ -76,6 +77,66 @@ void autofs4_free_ino(struct autofs_info *ino) kfree(ino); } +/* + * Deal with the infamous "Busy inodes after umount ..." message. + * + * Clean up the dentry tree. This happens with autofs if the user + * space program goes away due to a SIGKILL, SIGSEGV etc. + */ +static void autofs4_force_release(struct autofs_sb_info *sbi) +{ + struct dentry *this_parent = sbi->root; + struct list_head *next; + + spin_lock(&dcache_lock); +repeat: + next = this_parent->d_subdirs.next; +resume: + while (next != &this_parent->d_subdirs) { + struct dentry *dentry = list_entry(next, struct dentry, d_child); + + /* Negative dentry - don`t care */ + if (!simple_positive(dentry)) { + next = next->next; + continue; + } + + if (!list_empty(&dentry->d_subdirs)) { + this_parent = dentry; + goto repeat; + } + + next = next->next; + spin_unlock(&dcache_lock); + + DPRINTK("dentry %p %.*s", + dentry, (int)dentry->d_name.len, dentry->d_name.name); + + dput(dentry); + spin_lock(&dcache_lock); + } + + if (this_parent != sbi->root) { + struct dentry *dentry = this_parent; + + next = this_parent->d_child.next; + this_parent = this_parent->d_parent; + spin_unlock(&dcache_lock); + DPRINTK("parent dentry %p %.*s", + dentry, (int)dentry->d_name.len, dentry->d_name.name); + dput(dentry); + spin_lock(&dcache_lock); + goto resume; + } + spin_unlock(&dcache_lock); + + dput(sbi->root); + sbi->root = NULL; + shrink_dcache_sb(sbi->sb); + + return; +} + static void autofs4_put_super(struct super_block *sb) { struct autofs_sb_info *sbi = autofs4_sbi(sb); @@ -85,6 +146,10 @@ static void autofs4_put_super(struct super_block *sb) if ( !sbi->catatonic ) autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ + /* Clean up and release dangling references */ + if (sbi) + autofs4_force_release(sbi); + kfree(sbi); DPRINTK("shutting down"); @@ -199,6 +264,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) s->s_fs_info = sbi; sbi->magic = AUTOFS_SBI_MAGIC; + sbi->root = NULL; sbi->catatonic = 0; sbi->exp_timeout = 0; sbi->oz_pgrp = process_group(current); @@ -266,6 +332,13 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) goto fail_fput; sbi->pipe = pipe; + /* + * Take a reference to the root dentry so we get a chance to + * clean up the dentry tree on umount. + * See autofs4_force_release. + */ + sbi->root = dget(root); + /* * Success! Install the root dentry now to indicate completion. */ -- cgit v1.2.2 From 0cfc11ed45e4c00750039e5a18c0fc0d681e19db Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Wed, 27 Jul 2005 11:43:52 -0700 Subject: [PATCH] fix xip sparse file handling in ext2 Oliver Paukstadt from our test department is testing the xip patches in Linus' git-tree. He found a problem that shows when reading a file that contains sparse blocks (holes) on a -o xip mounted ext2 filesystem: the BUG_ON() in fs/ext2/xip.c:40 triggers where it should not. The problem was introduced by a cleanup in my previous patch, this patch fixes it. Signed-off-by: Carsten Otte Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/xip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c index 0aa5ac159c09..ca7f00312388 100644 --- a/fs/ext2/xip.c +++ b/fs/ext2/xip.c @@ -36,7 +36,7 @@ __ext2_get_sector(struct inode *inode, sector_t offset, int create, *result = tmp.b_blocknr; /* did we get a sparse block (hole in the file)? */ - if (!(*result)) { + if (!tmp.b_blocknr && !rc) { BUG_ON(create); rc = -ENODATA; } -- cgit v1.2.2 From c293621bbf678a3d85e3ed721c3921c8a670610d Mon Sep 17 00:00:00 2001 From: Peter Staubach Date: Wed, 27 Jul 2005 11:45:09 -0700 Subject: [PATCH] stale POSIX lock handling I believe that there is a problem with the handling of POSIX locks, which the attached patch should address. The problem appears to be a race between fcntl(2) and close(2). A multithreaded application could close a file descriptor at the same time as it is trying to acquire a lock using the same file descriptor. I would suggest that that multithreaded application is not providing the proper synchronization for itself, but the OS should still behave correctly. SUS3 (Single UNIX Specification Version 3, read: POSIX) indicates that when a file descriptor is closed, that all POSIX locks on the file, owned by the process which closed the file descriptor, should be released. The trick here is when those locks are released. The current code releases all locks which exist when close is processing, but any locks in progress are handled when the last reference to the open file is released. There are three cases to consider. One is the simple case, a multithreaded (mt) process has a file open and races to close it and acquire a lock on it. In this case, the close will release one reference to the open file and when the fcntl is done, it will release the other reference. For this situation, no locks should exist on the file when both the close and fcntl operations are done. The current system will handle this case because the last reference to the open file is being released. The second case is when the mt process has dup(2)'d the file descriptor. The close will release one reference to the file and the fcntl, when done, will release another, but there will still be at least one more reference to the open file. One could argue that the existence of a lock on the file after the close has completed is okay, because it was acquired after the close operation and there is still a way for the application to release the lock on the file, using an existing file descriptor. The third case is when the mt process has forked, after opening the file and either before or after becoming an mt process. In this case, each process would hold a reference to the open file. For each process, this degenerates to first case above. However, the lock continues to exist until both processes have released their references to the open file. This lock could block other lock requests. The changes to release the lock when the last reference to the open file aren't quite right because they would allow the lock to exist as long as there was a reference to the open file. This is too long. The new proposed solution is to add support in the fcntl code path to detect a race with close and then to release the lock which was just acquired when such as race is detected. This causes locks to be released in a timely fashion and for the system to conform to the POSIX semantic specification. This was tested by instrumenting a kernel to detect the handling locks and then running a program which generates case #3 above. A dangling lock could be reliably generated. When the changes to detect the close/fcntl race were added, a dangling lock could no longer be generated. Cc: Matthew Wilcox Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fcntl.c | 5 ++-- fs/locks.c | 81 +++++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 51 insertions(+), 35 deletions(-) (limited to 'fs') diff --git a/fs/fcntl.c b/fs/fcntl.c index 286a9f8f3d49..6fbc9d8fcc36 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -288,7 +288,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, break; case F_SETLK: case F_SETLKW: - err = fcntl_setlk(filp, cmd, (struct flock __user *) arg); + err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg); break; case F_GETOWN: /* @@ -376,7 +376,8 @@ asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg break; case F_SETLK64: case F_SETLKW64: - err = fcntl_setlk64(filp, cmd, (struct flock64 __user *) arg); + err = fcntl_setlk64(fd, filp, cmd, + (struct flock64 __user *) arg); break; default: err = do_fcntl(fd, cmd, arg, filp); diff --git a/fs/locks.c b/fs/locks.c index 29fa5da6c117..11956b6179ff 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1591,7 +1591,8 @@ out: /* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ -int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l) +int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, + struct flock __user *l) { struct file_lock *file_lock = locks_alloc_lock(); struct flock flock; @@ -1620,6 +1621,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l) goto out; } +again: error = flock_to_posix_lock(filp, file_lock, &flock); if (error) goto out; @@ -1648,25 +1650,33 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l) if (error) goto out; - if (filp->f_op && filp->f_op->lock != NULL) { + if (filp->f_op && filp->f_op->lock != NULL) error = filp->f_op->lock(filp, cmd, file_lock); - goto out; - } + else { + for (;;) { + error = __posix_lock_file(inode, file_lock); + if ((error != -EAGAIN) || (cmd == F_SETLK)) + break; + error = wait_event_interruptible(file_lock->fl_wait, + !file_lock->fl_next); + if (!error) + continue; - for (;;) { - error = __posix_lock_file(inode, file_lock); - if ((error != -EAGAIN) || (cmd == F_SETLK)) + locks_delete_block(file_lock); break; - error = wait_event_interruptible(file_lock->fl_wait, - !file_lock->fl_next); - if (!error) - continue; + } + } - locks_delete_block(file_lock); - break; + /* + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ + if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) { + flock.l_type = F_UNLCK; + goto again; } - out: +out: locks_free_lock(file_lock); return error; } @@ -1724,7 +1734,8 @@ out: /* Apply the lock described by l to an open file descriptor. * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ -int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) +int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, + struct flock64 __user *l) { struct file_lock *file_lock = locks_alloc_lock(); struct flock64 flock; @@ -1753,6 +1764,7 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) goto out; } +again: error = flock64_to_posix_lock(filp, file_lock, &flock); if (error) goto out; @@ -1781,22 +1793,30 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) if (error) goto out; - if (filp->f_op && filp->f_op->lock != NULL) { + if (filp->f_op && filp->f_op->lock != NULL) error = filp->f_op->lock(filp, cmd, file_lock); - goto out; - } + else { + for (;;) { + error = __posix_lock_file(inode, file_lock); + if ((error != -EAGAIN) || (cmd == F_SETLK64)) + break; + error = wait_event_interruptible(file_lock->fl_wait, + !file_lock->fl_next); + if (!error) + continue; - for (;;) { - error = __posix_lock_file(inode, file_lock); - if ((error != -EAGAIN) || (cmd == F_SETLK64)) + locks_delete_block(file_lock); break; - error = wait_event_interruptible(file_lock->fl_wait, - !file_lock->fl_next); - if (!error) - continue; + } + } - locks_delete_block(file_lock); - break; + /* + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ + if (!error && fcheck(fd) != filp && flock.l_type != F_UNLCK) { + flock.l_type = F_UNLCK; + goto again; } out: @@ -1888,12 +1908,7 @@ void locks_remove_flock(struct file *filp) while ((fl = *before) != NULL) { if (fl->fl_file == filp) { - /* - * We might have a POSIX lock that was created at the same time - * the filp was closed for the last time. Just remove that too, - * regardless of ownership, since nobody can own it. - */ - if (IS_FLOCK(fl) || IS_POSIX(fl)) { + if (IS_FLOCK(fl)) { locks_delete_lock(before); continue; } -- cgit v1.2.2 From 8c52ab42c11b5a7fb44bb84c954d09968e90e9e7 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 27 Jul 2005 11:45:15 -0700 Subject: [PATCH] mbcache: Remove unused mb_cache_shrink parameter The cache parameter to mb_cache_shrink isn't used. We may as well remove it. Signed-off-by: Andreas Gruenbacher Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/xattr.c | 2 +- fs/ext3/xattr.c | 2 +- fs/mbcache.c | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 27982b500e84..0099462d4271 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -823,7 +823,7 @@ cleanup: void ext2_xattr_put_super(struct super_block *sb) { - mb_cache_shrink(ext2_xattr_cache, sb->s_bdev); + mb_cache_shrink(sb->s_bdev); } diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 3f9dfa643b19..269c7b92db9a 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -1106,7 +1106,7 @@ cleanup: void ext3_xattr_put_super(struct super_block *sb) { - mb_cache_shrink(ext3_xattr_cache, sb->s_bdev); + mb_cache_shrink(sb->s_bdev); } /* diff --git a/fs/mbcache.c b/fs/mbcache.c index c7170b9221a3..b002a088857d 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -316,11 +316,10 @@ fail: * currently in use cannot be freed, and thus remain in the cache. All others * are freed. * - * @cache: which cache to shrink * @bdev: which device's cache entries to shrink */ void -mb_cache_shrink(struct mb_cache *cache, struct block_device *bdev) +mb_cache_shrink(struct block_device *bdev) { LIST_HEAD(free_list); struct list_head *l, *ltmp; -- cgit v1.2.2 From 02b775696fee75a04041d8d94db26a9462216d24 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 27 Jul 2005 11:45:16 -0700 Subject: [PATCH] reiserfs doesn't use mbcache reiserfs doesn't use the mbcache, so this can go. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/xattr.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index e386d3db3051..87ac9dc8b381 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.2 From 44456d37b59d8e541936ed26d8b6e08d27e88ac1 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Wed, 27 Jul 2005 11:45:17 -0700 Subject: [PATCH] turn many #if $undefined_string into #ifdef $undefined_string turn many #if $undefined_string into #ifdef $undefined_string to fix some warnings after -Wno-def was added to global CFLAGS Signed-off-by: Olaf Hering Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ntfs/sysctl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ntfs/sysctl.h b/fs/ntfs/sysctl.h index df749cc0aac8..c8064cae8f17 100644 --- a/fs/ntfs/sysctl.h +++ b/fs/ntfs/sysctl.h @@ -26,7 +26,7 @@ #include -#if (DEBUG && CONFIG_SYSCTL) +#if defined(DEBUG) && defined(CONFIG_SYSCTL) extern int ntfs_sysctl(int add); -- cgit v1.2.2 From 77933d7276ee8fa0e2947641941a6f7a100a327b Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Wed, 27 Jul 2005 11:46:09 -0700 Subject: [PATCH] clean up inline static vs static inline `gcc -W' likes to complain if the static keyword is not at the beginning of the declaration. This patch fixes all remaining occurrences of "inline static" up with "static inline" in the entire kernel tree (140 occurrences in 47 files). While making this change I came across a few lines with trailing whitespace that I also fixed up, I have also added or removed a blank line or two here and there, but there are no functional changes in the patch. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/journal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index c66c27ec4100..ca7989b04be3 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -556,14 +556,14 @@ static inline void insert_journal_hash(struct reiserfs_journal_cnode **table, } /* lock the current transaction */ -inline static void lock_journal(struct super_block *p_s_sb) +static inline void lock_journal(struct super_block *p_s_sb) { PROC_INFO_INC(p_s_sb, journal.lock_journal); down(&SB_JOURNAL(p_s_sb)->j_lock); } /* unlock the current transaction */ -inline static void unlock_journal(struct super_block *p_s_sb) +static inline void unlock_journal(struct super_block *p_s_sb) { up(&SB_JOURNAL(p_s_sb)->j_lock); } -- cgit v1.2.2 From a5453be48e8def75a9c1b2177b82fa0e692c6e3a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 28 Jul 2005 01:07:18 -0700 Subject: [PATCH] bio_clone fix Fix bug introduced in 2.6.11-rc2: when we clone a BIO we need to copy over the current index into it as well. It corrupts data with some MD setups. See http://bugzilla.kernel.org/show_bug.cgi?id=4946 Huuuuuuuuge thanks to Matthew Stapleton for doggedly chasing this one down. Acked-by: Jens Axboe Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/bio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/bio.c b/fs/bio.c index ca8f7a850fe3..249dd6bb66c8 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -261,6 +261,7 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src) */ bio->bi_vcnt = bio_src->bi_vcnt; bio->bi_size = bio_src->bi_size; + bio->bi_idx = bio_src->bi_idx; bio_phys_segments(q, bio); bio_hw_segments(q, bio); } -- cgit v1.2.2 From a2d76bd8fa29f9b6dbf3ee8f6bc7bdda21bc5ce8 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 28 Jul 2005 21:16:15 -0700 Subject: [PATCH] uml: implement hostfs syncing Actually implement the hostfs "sync" method. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hostfs/hostfs.h | 1 + fs/hostfs/hostfs_kern.c | 2 +- fs/hostfs/hostfs_user.c | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index c1516d013bf6..67bca0d4a33b 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -69,6 +69,7 @@ extern int read_file(int fd, unsigned long long *offset, char *buf, int len); extern int write_file(int fd, unsigned long long *offset, const char *buf, int len); extern int lseek_file(int fd, long long offset, int whence); +extern int fsync_file(int fd, int datasync); extern int file_create(char *name, int ur, int uw, int ux, int gr, int gw, int gx, int or, int ow, int ox); extern int set_attr(const char *file, struct hostfs_iattr *attrs); diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 88e68caa3784..b2d18200a003 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -382,7 +382,7 @@ int hostfs_file_open(struct inode *ino, struct file *file) int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) { - return(0); + return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync); } static struct file_operations hostfs_file_fops = { diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index 4796e8490f7d..b97809deba66 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c @@ -153,10 +153,24 @@ int lseek_file(int fd, long long offset, int whence) int ret; ret = lseek64(fd, offset, whence); - if(ret < 0) return(-errno); + if(ret < 0) + return(-errno); return(0); } +int fsync_file(int fd, int datasync) +{ + int ret; + if (datasync) + ret = fdatasync(fd); + else + ret = fsync(fd); + + if (ret < 0) + return -errno; + return 0; +} + void close_file(void *stream) { close(*((int *) stream)); -- cgit v1.2.2 From bc062b1b5c6bef4e3a29c7fda57967251d12beb0 Mon Sep 17 00:00:00 2001 From: Maneesh Soni Date: Fri, 29 Jul 2005 12:13:35 -0700 Subject: [PATCH] sysfs: fix sysfs_chmod_file o sysfs_chmod_file() must update the new iattr field in sysfs_dirent else the mode change will not be persistent in case of inode evacuation from cache. Signed-off-by: Maneesh Soni Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- fs/sysfs/file.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 335288b9be0f..4013d7905e84 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -437,8 +437,8 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) { struct dentry *dir = kobj->dentry; struct dentry *victim; - struct sysfs_dirent *sd; - umode_t umode = (mode & S_IALLUGO) | S_IFREG; + struct inode * inode; + struct iattr newattrs; int res = -ENOENT; down(&dir->d_inode->i_sem); @@ -446,13 +446,15 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) if (!IS_ERR(victim)) { if (victim->d_inode && (victim->d_parent->d_inode == dir->d_inode)) { - sd = victim->d_fsdata; - attr->mode = mode; - sd->s_mode = umode; - victim->d_inode->i_mode = umode; - dput(victim); - res = 0; + inode = victim->d_inode; + down(&inode->i_sem); + newattrs.ia_mode = (mode & S_IALLUGO) | + (inode->i_mode & ~S_IALLUGO); + newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; + res = notify_change(victim, &newattrs); + up(&inode->i_sem); } + dput(victim); } up(&dir->d_inode->i_sem); -- cgit v1.2.2 From 9ca1eb3282b6050c295adb296761f8d26baf4ca5 Mon Sep 17 00:00:00 2001 From: Maneesh Soni Date: Fri, 29 Jul 2005 12:14:19 -0700 Subject: [PATCH] sysfs: fix sysfs_setattr o sysfs_dirent's s_mode field should also be updated in sysfs_setattr(), else there could be inconsistency in the two fields. s_mode is used while ->readdir so as not to bring in the inode to cache. Signed-off-by: Maneesh Soni Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- fs/sysfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 8de13bafaa76..d727dc960634 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -85,7 +85,7 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) mode &= ~S_ISGID; - sd_iattr->ia_mode = mode; + sd_iattr->ia_mode = sd->s_mode = mode; } return error; -- cgit v1.2.2 From 7544953685859875b5ac0260b6b1856066c092d6 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Mon, 1 Aug 2005 11:00:45 -0400 Subject: [PATCH] inotify: fix file deletion by rename detection When a file is moved over an existing file that you are watching, inotify won't send you a DELETE_SELF event and it won't unref the inode until the inotify instance is closed by the application. Signed-off-by: John McCutchan Signed-off-by: Robert Love Signed-off-by: Linus Torvalds --- fs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index 02a824cd3c5c..4a27eb798118 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2218,7 +2218,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); if (!error) { const char *new_name = old_dentry->d_name.name; - fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir); + fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, new_dentry->d_inode); } fsnotify_oldname_free(old_name); -- cgit v1.2.2 From b9c55d29e9fced1eb1b4c252b2efd4b55a0c3c7f Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Mon, 1 Aug 2005 11:00:45 -0400 Subject: [PATCH] inotify: fix race between the kernel and user space When you rm a watch, an IN_IGNORED event is sent down the event queue with the watch descriptor that you just rm'd. If you then add a watch you could get the ignored watch's wd and if you haven't read the entire event queue, user space will think that it's newly created watch was just ignored. To avoid this problem we just use idr_get_new_above instead of idr_get_new. Signed-off-by: John McCutchan Signed-off-by: Robert Love Signed-off-by: Linus Torvalds --- fs/inotify.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/inotify.c b/fs/inotify.c index a8a714e48140..27ebcac5e07f 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -90,6 +90,7 @@ struct inotify_device { unsigned int queue_size; /* size of the queue (bytes) */ unsigned int event_count; /* number of pending events */ unsigned int max_events; /* maximum number of events */ + u32 last_wd; /* the last wd allocated */ }; /* @@ -352,7 +353,7 @@ static int inotify_dev_get_wd(struct inotify_device *dev, do { if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL))) return -ENOSPC; - ret = idr_get_new(&dev->idr, watch, &watch->wd); + ret = idr_get_new_above(&dev->idr, watch, dev->last_wd, &watch->wd); } while (ret == -EAGAIN); return ret; @@ -401,6 +402,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev, return ERR_PTR(ret); } + dev->last_wd = ret; watch->mask = mask; atomic_set(&watch->count, 0); INIT_LIST_HEAD(&watch->d_list); @@ -899,6 +901,7 @@ asmlinkage long sys_inotify_init(void) dev->queue_size = 0; dev->max_events = inotify_max_queued_events; dev->user = user; + dev->last_wd = 0; atomic_set(&dev->count, 0); get_inotify_dev(dev); -- cgit v1.2.2 From 30db1ae8640d3527ca7ac8df4bcbf14ccc6ae9cd Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 1 Aug 2005 16:54:26 -0500 Subject: JFS: Check for invalid inodes in jfs_delete_inode Some error paths may iput an invalid inode with i_nlink=0. jfs should not try to actually delete such an inode. Signed-off-by: Dave Kleikamp --- fs/jfs/inode.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 2137138c59b0..767c7ecb429e 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -128,6 +128,10 @@ void jfs_delete_inode(struct inode *inode) { jfs_info("In jfs_delete_inode, inode = 0x%p", inode); + if (is_bad_inode(inode) || + (JFS_IP(inode)->fileset != cpu_to_le32(FILESYSTEM_I))) + return; + if (test_cflag(COMMIT_Freewmap, inode)) jfs_free_zero_link(inode); -- cgit v1.2.2 From f76d28d235cf777dd2e1c1d48c16ee10c1d1587f Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Mon, 1 Aug 2005 21:11:40 -0700 Subject: [PATCH] hfs: don't dirty unchanged inode If inode size hasn't changed, don't do anything further in truncate, which also prevents a dirty inode, what might upset some readonly devices quite badly. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hfs/extent.c | 3 ++- fs/hfsplus/extents.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c index cbc8510ad222..5ea6b3d45eaa 100644 --- a/fs/hfs/extent.c +++ b/fs/hfs/extent.c @@ -482,7 +482,8 @@ void hfs_file_truncate(struct inode *inode) page_cache_release(page); mark_inode_dirty(inode); return; - } + } else if (inode->i_size == HFS_I(inode)->phys_size) + return; size = inode->i_size + HFS_SB(sb)->alloc_blksz - 1; blk_cnt = size / HFS_SB(sb)->alloc_blksz; alloc_cnt = HFS_I(inode)->alloc_blocks; diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 376498cc64fd..e7235ca79a95 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -461,7 +461,9 @@ void hfsplus_file_truncate(struct inode *inode) page_cache_release(page); mark_inode_dirty(inode); return; - } + } else if (inode->i_size == HFSPLUS_I(inode).phys_size) + return; + blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift; alloc_cnt = HFSPLUS_I(inode).alloc_blocks; if (blk_cnt == alloc_cnt) -- cgit v1.2.2 From 74f9c9c258249fba3e2e78f70691528426a6c010 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Mon, 1 Aug 2005 21:11:41 -0700 Subject: [PATCH] hfs: don't reference missing page If there was a read error, the bnode might miss some pages, so skip them. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hfs/bnode.c | 2 ++ fs/hfsplus/bnode.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c index 6ad1211f84ed..a096c5a56664 100644 --- a/fs/hfs/bnode.c +++ b/fs/hfs/bnode.c @@ -480,6 +480,8 @@ void hfs_bnode_put(struct hfs_bnode *node) return; } for (i = 0; i < tree->pages_per_bnode; i++) { + if (!node->page[i]) + continue; mark_page_accessed(node->page[i]); #if REF_PAGES put_page(node->page[i]); diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index 267872e84d71..8868d3b766fd 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -643,6 +643,8 @@ void hfs_bnode_put(struct hfs_bnode *node) return; } for (i = 0; i < tree->pages_per_bnode; i++) { + if (!node->page[i]) + continue; mark_page_accessed(node->page[i]); #if REF_PAGES put_page(node->page[i]); -- cgit v1.2.2 From 3de11748c1b312833e8a148ab7ec47669ecc99dc Mon Sep 17 00:00:00 2001 From: Robert Love Date: Thu, 4 Aug 2005 13:07:08 -0700 Subject: [PATCH] inotify: update help text The inotify help text still refers to the character device. Update it. Fixes kernel bug #4993. Signed-off-by: Robert Love Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/Kconfig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/Kconfig b/fs/Kconfig index 5d0c4be43dba..e54be7058359 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -363,12 +363,15 @@ config INOTIFY bool "Inotify file change notification support" default y ---help--- - Say Y here to enable inotify support and the /dev/inotify character - device. Inotify is a file change notification system and a + Say Y here to enable inotify support and the associated system + calls. Inotify is a file change notification system and a replacement for dnotify. Inotify fixes numerous shortcomings in dnotify and introduces several new features. It allows monitoring - of both files and directories via a single open fd. Multiple file - events are supported. + of both files and directories via a single open fd. Other features + include multiple file events, one-shot support, and unmount + notification. + + For more information, see Documentation/filesystems/inotify.txt If unsure, say Y. -- cgit v1.2.2 From e234f35c54a30d040313e40833dcf623d14629b4 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Thu, 4 Aug 2005 13:07:08 -0700 Subject: [PATCH] inotify delete race fix The included patch fixes a problem where a inotify client would receive a delete event before the file was actually deleted. The bug affects both dnotify & inotify. Signed-off-by: John McCutchan Signed-off-by: Robert Love Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namei.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index 4a27eb798118..83559dce4286 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1801,8 +1801,8 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) } up(&dentry->d_inode->i_sem); if (!error) { - fsnotify_rmdir(dentry, dentry->d_inode, dir); d_delete(dentry); + fsnotify_rmdir(dentry, dentry->d_inode, dir); } dput(dentry); @@ -1874,8 +1874,14 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) /* We don't d_delete() NFS sillyrenamed files--they still exist. */ if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { +#if defined(CONFIG_INOTIFY) || defined(CONFIG_DNOTIFY) + dget(dentry); + d_delete(dentry); fsnotify_unlink(dentry, dir); + dput(dentry); +#else d_delete(dentry); +#endif } return error; -- cgit v1.2.2 From 0c3dba1534569734ba353afdf3f11def497ff2ac Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Thu, 4 Aug 2005 21:12:54 -0400 Subject: [PATCH] Clean up inotify delete race fix This avoids the whole #ifdef mess by just getting a copy of dentry->d_inode before d_delete is called - that makes the codepaths the same for the INOTIFY/DNOTIFY cases as for the regular no-notify case. I've been running this under a Gnome session for the last 10 minutes. Inotify is being used extensively. Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/namei.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index 83559dce4286..32accb6a672f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1874,14 +1874,9 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) /* We don't d_delete() NFS sillyrenamed files--they still exist. */ if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { -#if defined(CONFIG_INOTIFY) || defined(CONFIG_DNOTIFY) - dget(dentry); + struct inode *inode = dentry->d_inode; d_delete(dentry); - fsnotify_unlink(dentry, dir); - dput(dentry); -#else - d_delete(dentry); -#endif + fsnotify_unlink(dentry, inode, dir); } return error; -- cgit v1.2.2 From fab5a60a29f98f17256a4183e34a414f6db67569 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 6 Aug 2005 09:42:06 -0700 Subject: Check input buffer size in zisofs This uses the new deflateBound() thing to sanity-check the input to the zlib decompressor before we even bother to start reading in the blocks. Problem noted by Tim Yamin --- fs/isofs/compress.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs') diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index 34a44e451689..4917315db732 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c @@ -129,8 +129,14 @@ static int zisofs_readpage(struct file *file, struct page *page) cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask))); brelse(bh); + if (cstart > cend) + goto eio; + csize = cend-cstart; + if (csize > deflateBound(1UL << zisofs_block_shift)) + goto eio; + /* Now page[] contains an array of pages, any of which can be NULL, and the locks on which we hold. We should now read the data and release the pages. If the pages are NULL the decompressed data -- cgit v1.2.2 From e525e153c7a99fc64af68e7f50a2660babd6752b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 7 Aug 2005 09:42:12 -0700 Subject: [PATCH] __bio_clone() dead comment Remove a very wrong comment. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/bio.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/bio.c b/fs/bio.c index 249dd6bb66c8..1f2d4649b188 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -248,17 +248,13 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src) { request_queue_t *q = bdev_get_queue(bio_src->bi_bdev); - memcpy(bio->bi_io_vec, bio_src->bi_io_vec, bio_src->bi_max_vecs * sizeof(struct bio_vec)); + memcpy(bio->bi_io_vec, bio_src->bi_io_vec, + bio_src->bi_max_vecs * sizeof(struct bio_vec)); bio->bi_sector = bio_src->bi_sector; bio->bi_bdev = bio_src->bi_bdev; bio->bi_flags |= 1 << BIO_CLONED; bio->bi_rw = bio_src->bi_rw; - - /* - * notes -- maybe just leave bi_idx alone. assume identical mapping - * for the clone - */ bio->bi_vcnt = bio_src->bi_vcnt; bio->bi_size = bio_src->bi_size; bio->bi_idx = bio_src->bi_idx; -- cgit v1.2.2 From 68b47139ea94ab6d05e89c654db8daa99e9a232c Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Sun, 7 Aug 2005 09:42:25 -0700 Subject: [PATCH] namespace.c: fix bind mount from foreign namespace I'm resending this patch, because I still believe it's the correct fix. Tested before/after applying the patch with a test application available from: http://www.inf.bme.hu/~mszeredi/nstest.c Bind mount from a foreign namespace results in an un-removable mount. The reason is that mnt->mnt_namespace is copied from the old mount in clone_mnt(). Because of this check_mnt() in sys_umount() will fail. The solution is to set mnt->mnt_namespace to current->namespace in clone_mnt(). clone_mnt() is either called from do_loopback() or copy_tree(). copy_tree() is called from do_loopback() or copy_namespace(). When called (directly or indirectly) from do_loopback(), always current->namspace is being modified: check_mnt(nd->mnt). So setting mnt->mnt_namespace to current->namspace is the right thing to do. When called from copy_namespace(), the setting of mnt_namespace is irrelevant, since mnt_namespace is reset later in that function for all copied mounts. Jamie said: This patch is correct. The old code was buggy for more fundamental and serious reason: it broke the invariant that a tree of vfsmnts all have the same value of mnt_namespace (and the same for the mnt_list list). Signed-off-by: Miklos Szeredi Acked-by: Jamie Lokier Cc: Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/namespace.c b/fs/namespace.c index 587eb0d707ee..79bd8a46e1e7 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -160,7 +160,7 @@ clone_mnt(struct vfsmount *old, struct dentry *root) mnt->mnt_root = dget(root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - mnt->mnt_namespace = old->mnt_namespace; + mnt->mnt_namespace = current->namespace; /* stick the duplicate mount on the same expiry list * as the original if that was on one */ -- cgit v1.2.2 From 7a91bf7f5c22c8407a9991cbd9ce5bb87caa6b4a Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Mon, 8 Aug 2005 13:52:16 -0400 Subject: [PATCH] fsnotify_name/inoderemove The patch below unhooks fsnotify from vfs_unlink & vfs_rmdir. It introduces two new fsnotify calls, that are hooked in at the dcache level. This not only more closely matches how the VFS layer works, it also avoids the problem with locking and inode lifetimes. The two functions are - fsnotify_nameremove -- called when a directory entry is going away. It notifies the PARENT of the deletion. This is called from d_delete(). - inoderemove -- called when the files inode itself is going away. It notifies the inode that is being deleted. This is called from dentry_iput(). Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/dcache.c | 7 +++++++ fs/namei.c | 3 --- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/dcache.c b/fs/dcache.c index 3aa8a7e980d8..a15a2e1f5520 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -101,6 +102,7 @@ static inline void dentry_iput(struct dentry * dentry) list_del_init(&dentry->d_alias); spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); + fsnotify_inoderemove(inode); if (dentry->d_op && dentry->d_op->d_iput) dentry->d_op->d_iput(dentry, inode); else @@ -1165,13 +1167,16 @@ out: void d_delete(struct dentry * dentry) { + int isdir = 0; /* * Are we the only user? */ spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); + isdir = S_ISDIR(dentry->d_inode->i_mode); if (atomic_read(&dentry->d_count) == 1) { dentry_iput(dentry); + fsnotify_nameremove(dentry, isdir); return; } @@ -1180,6 +1185,8 @@ void d_delete(struct dentry * dentry) spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); + + fsnotify_nameremove(dentry, isdir); } static void __d_rehash(struct dentry * entry, struct hlist_head *list) diff --git a/fs/namei.c b/fs/namei.c index 32accb6a672f..57046d98a746 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1802,7 +1802,6 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) up(&dentry->d_inode->i_sem); if (!error) { d_delete(dentry); - fsnotify_rmdir(dentry, dentry->d_inode, dir); } dput(dentry); @@ -1874,9 +1873,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) /* We don't d_delete() NFS sillyrenamed files--they still exist. */ if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { - struct inode *inode = dentry->d_inode; d_delete(dentry); - fsnotify_unlink(dentry, inode, dir); } return error; -- cgit v1.2.2 From 8a9cd6d676728792aaee31f30015d284acd154a3 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Wed, 10 Aug 2005 11:14:39 -0500 Subject: JFS: Fix race in txLock TxAnchor.anon_list is protected by jfsTxnLock (TXN_LOCK), but there was a place in txLock() that was removing an entry from the list without holding the spinlock. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_txnmgr.c | 2 ++ fs/jfs/super.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 3555acff12d0..c7a92f9deb2b 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -657,7 +657,9 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, /* only anonymous txn. * Remove from anon_list */ + TXN_LOCK(); list_del_init(&jfs_ip->anon_inode_list); + TXN_UNLOCK(); } jfs_ip->atlhead = tlck->next; } else { diff --git a/fs/jfs/super.c b/fs/jfs/super.c index c2abdaee0c0b..9ff89720f93b 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -114,6 +114,8 @@ static void jfs_destroy_inode(struct inode *inode) { struct jfs_inode_info *ji = JFS_IP(inode); + BUG_ON(!list_empty(&ji->anon_inode_list)); + spin_lock_irq(&ji->ag_lock); if (ji->active_ag != -1) { struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap; -- cgit v1.2.2 From 1b0a74d1c002320d5488333dd9c72126af1aab02 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sat, 13 Aug 2005 13:15:34 +0200 Subject: [PATCH] Fix error handling in reiserfs Initialize key object ID in inode so that we don't try to remove the inode when we fail on some checks even before we manage to allocate something. Signed-off-by: Jan Kara Signed-off-by: Linus Torvalds --- fs/reiserfs/namei.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index a20bbc1642dc..3549067c42d9 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -593,6 +593,9 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode) */ inode->i_uid = current->fsuid; inode->i_mode = mode; + /* Make inode invalid - just in case we are going to drop it before + * the initialization happens */ + INODE_PKEY(inode)->k_objectid = 0; if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; -- cgit v1.2.2 From d024709deb4997aced6140a62e8ee82b10666c5f Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 14 Aug 2005 16:55:23 -0500 Subject: [PATCH] CIFS: Fix missing entries in search results Fix missing entries in search results when very long file names and more than 50 (or so) of such long search entries in the directory. FindNext could send corrupt last byte of resume name when resume key was a few hundred bytes long file name or longer. Fixes Samba Bug # 2932 Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifssmb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 3c628bf667a5..0db0b313d715 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2602,6 +2602,9 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, if(name_len < PATH_MAX) { memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len); byte_count += name_len; + /* 14 byte parm len above enough for 2 byte null terminator */ + pSMB->ResumeFileName[name_len] = 0; + pSMB->ResumeFileName[name_len+1] = 0; } else { rc = -EINVAL; goto FNext2_err_exit; -- cgit v1.2.2 From 27876d02b30aa34bb1ad35b81ccc40c174282f31 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 14 Aug 2005 16:55:23 -0500 Subject: [PATCH] CIFS: Fix path name conversion for long filenames Fix path name conversion for long filenames when mapchars mount option was specified at mount time. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 6 ++++++ fs/cifs/misc.c | 1 + 2 files changed, 7 insertions(+) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index dab4774ee7bb..3196d4c4eed3 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,9 @@ +Version 1.35 +------------ +Add writepage performance improvements. Fix path name conversions +for long filenames on mounts which were done with "mapchars" mount option +specified. + Version 1.34 ------------ Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 072b4ee8c53e..20ae4153f791 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -611,6 +611,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, src_char = source[i]; switch (src_char) { case 0: + target[j] = 0; goto ctoUCS_out; case ':': target[j] = cpu_to_le16(UNI_COLON); -- cgit v1.2.2 From 0bf955ce98cb3cf40e20d0cc435299eb76e8819e Mon Sep 17 00:00:00 2001 From: Robert Love Date: Mon, 15 Aug 2005 12:27:54 -0400 Subject: [PATCH] inotify: fix idr_get_new_above usage We are saving the wrong thing in ->last_wd. We want the wd, not the return value. Signed-off-by: Robert Love Signed-off-by: Linus Torvalds --- fs/inotify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/inotify.c b/fs/inotify.c index 27ebcac5e07f..868901b1e779 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -402,7 +402,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev, return ERR_PTR(ret); } - dev->last_wd = ret; + dev->last_wd = watch->wd; watch->mask = mask; atomic_set(&watch->count, 0); INIT_LIST_HEAD(&watch->d_list); -- cgit v1.2.2 From 89204c40a03346cd951e698d854105db4cfedc28 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Mon, 15 Aug 2005 12:13:28 -0400 Subject: [PATCH] inotify: add MOVE_SELF event This adds a MOVE_SELF event to inotify. It is sent whenever the inode you are watching is moved. We need this event so that we can catch something like this: - app1: watch /etc/mtab - app2: cp /etc/mtab /tmp/mtab-work mv /etc/mtab /etc/mtab~ mv /tmp/mtab-work /etc/mtab app1 still thinks it's watching /etc/mtab but it's actually watching /etc/mtab~. Signed-off-by: John McCutchan Signed-off-by: Robert Love Signed-off-by: Linus Torvalds --- fs/namei.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index 57046d98a746..b85f158aef0c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2216,7 +2216,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); if (!error) { const char *new_name = old_dentry->d_name.name; - fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, new_dentry->d_inode); + fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, + new_dentry->d_inode, old_dentry->d_inode); } fsnotify_oldname_free(old_name); -- cgit v1.2.2 From e74589ac250e463973361774a90fee2c9d71da02 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Tue, 16 Aug 2005 16:38:28 +0100 Subject: =?UTF-8?q?NTFS:=20Fix=20bug=20in=20mft=20record=20writing=20where?= =?UTF-8?q?=20we=20forgot=20to=20set=20the=20device=20in=20=20=20=20=20=20?= =?UTF-8?q?=20the=20buffers=20when=20mapping=20them=20after=20the=20VM=20h?= =?UTF-8?q?ad=20discarded=20them.=20=20=20=20=20=20=20Thanks=20to=20Martin?= =?UTF-8?q?=20MOKREJ=C5=A0=20for=20the=20bug=20report.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anton Altaparmakov --- fs/ntfs/ChangeLog | 3 +++ fs/ntfs/mft.c | 2 ++ 2 files changed, 5 insertions(+) (limited to 'fs') diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 9709fac6531d..21e21fe519e2 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -174,6 +174,9 @@ ToDo/Notes: fact that the vfs and ntfs inodes are one struct in memory to find the ntfs inode in memory if present. Also, the ntfs inode has its own locking so it does not matter if the vfs inode is locked. + - Fix bug in mft record writing where we forgot to set the device in + the buffers when mapping them after the VM had discarded them + Thanks to Martin MOKREJŠ for the bug report. 2.1.22 - Many bug and race fixes and error handling improvements. diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index ac9ff39aa834..317f7c679fd3 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -533,6 +533,7 @@ int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no, LCN lcn; unsigned int vcn_ofs; + bh->b_bdev = vol->sb->s_bdev; /* Obtain the vcn and offset of the current block. */ vcn = ((VCN)mft_no << vol->mft_record_size_bits) + (block_start - m_start); @@ -725,6 +726,7 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync) LCN lcn; unsigned int vcn_ofs; + bh->b_bdev = vol->sb->s_bdev; /* Obtain the vcn and offset of the current block. */ vcn = ((VCN)ni->mft_no << vol->mft_record_size_bits) + (block_start - m_start); -- cgit v1.2.2 From 58fcb8df0bf663bb6b8f46cd3010bfe8d13d97cf Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 10 Aug 2005 18:15:12 -0400 Subject: [PATCH] NFS: Ensure ACL xdr code doesn't overflow. Signed-off-by: Trond Myklebust Signed-off-by: Linus Torvalds --- fs/nfs_common/nfsacl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 18c58c32e326..251e5a1bb1c4 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c @@ -239,6 +239,7 @@ nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt, if (xdr_decode_word(buf, base, &entries) || entries > NFS_ACL_MAX_ENTRIES) return -EINVAL; + nfsacl_desc.desc.array_maxlen = entries; err = xdr_decode_array2(buf, base + 4, &nfsacl_desc.desc); if (err) return err; -- cgit v1.2.2 From 65e4308d2500e7daf60c3dccc202c61ffb066c63 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 16 Aug 2005 11:49:44 -0400 Subject: [PATCH] NFS: Ensure we always update inode->i_mode when doing O_EXCL creates When the client performs an exclusive create and opens the file for writing, a Netapp filer will first create the file using the mode 01777. It does this since an NFSv3/v4 exclusive create cannot immediately set the mode bits. The 01777 mode then gets put into the inode->i_mode. After the file creation is successful, we then do a setattr to change the mode to the correct value (as per the NFS spec). The problem is that nfs_refresh_inode() no longer updates inode->i_mode, so the latter retains the 01777 mode. A bit later, the VFS notices this, and calls remove_suid(). This of course now resets the file mode to inode->i_mode & 0777. Hey presto, the file mode on the server is now magically changed to 0777. Duh... Fixes http://bugzilla.linux-nfs.org/show_bug.cgi?id=32 Signed-off-by: Trond Myklebust Signed-off-by: Linus Torvalds --- fs/nfs/inode.c | 37 ++++++++++++++++++++++++------------- fs/nfs/nfs3proc.c | 4 ++++ fs/nfs/nfs4proc.c | 10 ++++++++-- fs/nfs/proc.c | 2 ++ 4 files changed, 38 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 4845911f1c63..bb7ca022bcb2 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -814,28 +814,39 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) nfs_wb_all(inode); } error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); - if (error == 0) { + if (error == 0) nfs_refresh_inode(inode, &fattr); + nfs_end_data_update(inode); + unlock_kernel(); + return error; +} + +/** + * nfs_setattr_update_inode - Update inode metadata after a setattr call. + * @inode: pointer to struct inode + * @attr: pointer to struct iattr + * + * Note: we do this in the *proc.c in order to ensure that + * it works for things like exclusive creates too. + */ +void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) +{ + if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { if ((attr->ia_valid & ATTR_MODE) != 0) { - int mode; - mode = inode->i_mode & ~S_IALLUGO; - mode |= attr->ia_mode & S_IALLUGO; + int mode = attr->ia_mode & S_IALLUGO; + mode |= inode->i_mode & ~S_IALLUGO; inode->i_mode = mode; } if ((attr->ia_valid & ATTR_UID) != 0) inode->i_uid = attr->ia_uid; if ((attr->ia_valid & ATTR_GID) != 0) inode->i_gid = attr->ia_gid; - if ((attr->ia_valid & ATTR_SIZE) != 0) { - inode->i_size = attr->ia_size; - vmtruncate(inode, attr->ia_size); - } - } - if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; - nfs_end_data_update(inode); - unlock_kernel(); - return error; + } + if ((attr->ia_valid & ATTR_SIZE) != 0) { + inode->i_size = attr->ia_size; + vmtruncate(inode, attr->ia_size); + } } /* diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 7851569b31c6..2681485cf2d0 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -120,6 +120,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, dprintk("NFS call setattr\n"); fattr->valid = 0; status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0); + if (status == 0) + nfs_setattr_update_inode(inode, sattr); dprintk("NFS reply setattr: %d\n", status); return status; } @@ -370,6 +372,8 @@ again: * not sure this buys us anything (and I'd have * to revamp the NFSv3 XDR code) */ status = nfs3_proc_setattr(dentry, &fattr, sattr); + if (status == 0) + nfs_setattr_update_inode(dentry->d_inode, sattr); nfs_refresh_inode(dentry->d_inode, &fattr); dprintk("NFS reply setattr (post-create): %d\n", status); } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1b76f80aedb9..0c5a308e4963 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -753,6 +753,7 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, .rpc_argp = &arg, .rpc_resp = &res, }; + int status; fattr->valid = 0; @@ -762,7 +763,8 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, } else memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); - return rpc_call_sync(server->client, &msg, 0); + status = rpc_call_sync(server->client, &msg, 0); + return status; } static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, @@ -1145,6 +1147,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, status = nfs4_do_setattr(NFS_SERVER(inode), fattr, NFS_FH(inode), sattr, state); + if (status == 0) + nfs_setattr_update_inode(inode, sattr); if (state != NULL) nfs4_close_state(state, FMODE_WRITE); put_rpccred(cred); @@ -1449,8 +1453,10 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, struct nfs_fattr fattr; status = nfs4_do_setattr(NFS_SERVER(dir), &fattr, NFS_FH(state->inode), sattr, state); - if (status == 0) + if (status == 0) { + nfs_setattr_update_inode(state->inode, sattr); goto out; + } } else if (flags != 0) goto out; nfs4_close_state(state, flags); diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index cedf636bcf3c..be23c3fb9260 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -114,6 +114,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, dprintk("NFS call setattr\n"); fattr->valid = 0; status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0); + if (status == 0) + nfs_setattr_update_inode(inode, sattr); dprintk("NFS reply setattr: %d\n", status); return status; } -- cgit v1.2.2