diff options
author | Steve French <cifs.adm@hostme.bitkeeper.com> | 2004-07-10 21:07:02 -0700 |
---|---|---|
committer | Steve French <cifs.adm@hostme.bitkeeper.com> | 2004-07-10 21:07:02 -0700 |
commit | 5d456f60c995e32970f7e32dd3365e63c3fdc64b (patch) | |
tree | d5e632b7d04dbc62ed1600bb0036fae61c4ea3d3 /fs | |
parent | 8540342d7331064ac1da8d967ecaa59e896db026 (diff) | |
parent | 8319ca6ae5f27bc30724728c3400e3eda249d250 (diff) | |
download | history-5d456f60c995e32970f7e32dd3365e63c3fdc64b.tar.gz |
Merge bk://linux.bkbits.net/linux-2.5
into hostme.bitkeeper.com:/repos/c/cifs/linux-2.5cifs
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig | 46 | ||||
-rw-r--r-- | fs/afs/cmservice.c | 4 | ||||
-rw-r--r-- | fs/afs/internal.h | 2 | ||||
-rw-r--r-- | fs/afs/mntpt.c | 12 | ||||
-rw-r--r-- | fs/afs/super.c | 2 | ||||
-rw-r--r-- | fs/buffer.c | 31 | ||||
-rw-r--r-- | fs/dquot.c | 59 | ||||
-rw-r--r-- | fs/inode.c | 12 | ||||
-rw-r--r-- | fs/jffs/inode-v23.c | 28 | ||||
-rw-r--r-- | fs/jffs/intrep.c | 62 | ||||
-rw-r--r-- | fs/jffs/jffs_fm.c | 54 | ||||
-rw-r--r-- | fs/jffs2/os-linux.h | 5 | ||||
-rw-r--r-- | fs/jffs2/wbuf.c | 8 | ||||
-rw-r--r-- | fs/jffs2/write.c | 4 | ||||
-rw-r--r-- | fs/jffs2/writev.c | 4 | ||||
-rw-r--r-- | fs/jfs/jfs_dtree.c | 38 | ||||
-rw-r--r-- | fs/jfs/jfs_imap.c | 6 | ||||
-rw-r--r-- | fs/jfs/jfs_metapage.c | 6 | ||||
-rw-r--r-- | fs/jfs/jfs_mount.c | 2 | ||||
-rw-r--r-- | fs/jfs/jfs_txnmgr.c | 10 | ||||
-rw-r--r-- | fs/jfs/jfs_uniupr.c | 2 | ||||
-rw-r--r-- | fs/jfs/jfs_xtree.c | 30 | ||||
-rw-r--r-- | fs/jfs/namei.c | 4 | ||||
-rw-r--r-- | fs/jfs/super.c | 8 | ||||
-rw-r--r-- | fs/jfs/xattr.c | 6 | ||||
-rw-r--r-- | fs/mpage.c | 35 | ||||
-rw-r--r-- | fs/namei.c | 10 | ||||
-rw-r--r-- | fs/namespace.c | 215 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 10 | ||||
-rw-r--r-- | fs/read_write.c | 10 | ||||
-rw-r--r-- | fs/smbfs/file.c | 2 | ||||
-rw-r--r-- | fs/smbfs/proc.c | 12 | ||||
-rw-r--r-- | fs/super.c | 3 | ||||
-rw-r--r-- | fs/udf/super.c | 8 |
34 files changed, 458 insertions, 292 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 55d99d885c03ee..fe7868a8e0f30a 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -7,47 +7,14 @@ menu "File systems" config EXT2_FS tristate "Second extended fs support" help - This is the de facto standard Linux file system (method to organize - files on a storage device) for hard disks. - - You want to say Y here, unless you intend to use Linux exclusively - from inside a DOS partition using the UMSDOS file system. The - advantage of the latter is that you can get away without - repartitioning your hard drive (which often implies backing - everything up and restoring afterwards); the disadvantage is that - Linux becomes susceptible to DOS viruses and that UMSDOS is somewhat - slower than ext2fs. Even if you want to run Linux in this fashion, - it might be a good idea to have ext2fs around: it enables you to - read more floppy disks and facilitates the transition to a *real* - Linux partition later. Another (rare) case which doesn't require - ext2fs is a diskless Linux box which mounts all files over the - network using NFS (in this case it's sufficient to say Y to "NFS - file system support" below). Saying Y here will enlarge your kernel - by about 44 KB. - - The Ext2fs-Undeletion mini-HOWTO, available from - <http://www.tldp.org/docs.html#howto>, gives information about - how to retrieve deleted files on ext2fs file systems. - - To change the behavior of ext2 file systems, you can use the tune2fs - utility ("man tune2fs"). To modify attributes of files and - directories on ext2 file systems, use chattr ("man chattr"). - - Ext2fs partitions can be read from within DOS using the ext2tool - command line tool package (available from - <ftp://ibiblio.org/pub/Linux/system/filesystems/ext2/>) and from - within Windows NT using the ext2nt command line tool package from - <ftp://ibiblio.org/pub/Linux/utils/dos/>. Explore2fs is a - graphical explorer for ext2fs partitions which runs on Windows 95 - and Windows NT and includes experimental write support; it is - available from - <http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm>. + Ext2 is a standard Linux file system for hard disks. To compile this file system support as a module, choose M here: the module will be called ext2. Be aware however that the file system of your root partition (the one containing the directory /) cannot - be compiled as a module, and so this could be dangerous. Most - everyone wants to say Y here. + be compiled as a module, and so this could be dangerous. + + If unsure, say Y. config EXT2_FS_XATTR bool "Ext2 extended attributes" @@ -575,6 +542,11 @@ config UDF_FS If unsure, say N. +config UDF_NLS + bool + default y + depends on (UDF_FS=m && NLS) || (UDF_FS=y && NLS=y) + endmenu menu "DOS/FAT/NT Filesystems" diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index 289489da3ca242..1f968366e6517c 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -307,10 +307,8 @@ int afscm_start(void) if (ret < 0) goto kill; -#ifdef AFS_AUTOMOUNT_SUPPORT afs_kafstimod_add_timer(&afs_mntpt_expiry_timer, afs_mntpt_expiry_timeout * HZ); -#endif } afscm_usage++; @@ -392,9 +390,7 @@ void afscm_stop(void) } spin_unlock(&kafscmd_attention_lock); -#ifdef AFS_AUTOMOUNT_SUPPORT afs_kafstimod_del_timer(&afs_mntpt_expiry_timer); -#endif } up_write(&afscm_sem); diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 11ef8c5568b2be..f09860b45c1a30 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -107,11 +107,9 @@ extern struct cachefs_netfs afs_cache_netfs; */ extern struct inode_operations afs_mntpt_inode_operations; extern struct file_operations afs_mntpt_file_operations; -#ifdef AFS_AUTOMOUNT_SUPPORT extern struct afs_timer afs_mntpt_expiry_timer; extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; extern unsigned long afs_mntpt_expiry_timeout; -#endif extern int afs_mntpt_check_symlink(struct afs_vnode *vnode); diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 3a36a3ca5e3965..aab380e7e6dba2 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -30,10 +30,7 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd); static int afs_mntpt_open(struct inode *inode, struct file *file); - -#ifdef AFS_AUTOMOUNT_SUPPORT static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); -#endif struct file_operations afs_mntpt_file_operations = { .open = afs_mntpt_open, @@ -41,14 +38,11 @@ struct file_operations afs_mntpt_file_operations = { struct inode_operations afs_mntpt_inode_operations = { .lookup = afs_mntpt_lookup, -#ifdef AFS_AUTOMOUNT_SUPPORT .follow_link = afs_mntpt_follow_link, -#endif .readlink = page_readlink, .getattr = afs_inode_getattr, }; -#ifdef AFS_AUTOMOUNT_SUPPORT static LIST_HEAD(afs_vfsmounts); static void afs_mntpt_expiry_timed_out(struct afs_timer *timer); @@ -60,7 +54,6 @@ struct afs_timer_ops afs_mntpt_expiry_timer_ops = { struct afs_timer afs_mntpt_expiry_timer; unsigned long afs_mntpt_expiry_timeout = 20; -#endif /*****************************************************************************/ /* @@ -156,7 +149,6 @@ static int afs_mntpt_open(struct inode *inode, struct file *file) return -EREMOTE; } /* end afs_mntpt_open() */ -#ifdef AFS_AUTOMOUNT_SUPPORT /*****************************************************************************/ /* * create a vfsmount to be automounted @@ -168,6 +160,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) struct page *page = NULL; size_t size; char *buf, *devname = NULL, *options = NULL; + filler_t *filler; int ret; kenter("{%s}", mntpt->d_name.name); @@ -189,7 +182,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) goto error; /* read the contents of the AFS special symlink */ - filler_t *filler = mntpt->d_inode->i_mapping->a_ops->readpage; + filler = mntpt->d_inode->i_mapping->a_ops->readpage; page = read_cache_page(mntpt->d_inode->i_mapping, 0, filler, NULL); if (IS_ERR(page)) { @@ -288,4 +281,3 @@ static void afs_mntpt_expiry_timed_out(struct afs_timer *timer) kleave(""); } /* end afs_mntpt_expiry_timed_out() */ -#endif diff --git a/fs/afs/super.c b/fs/afs/super.c index bdf830191f6242..d6fa8e5999df9a 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -78,9 +78,7 @@ int __init afs_fs_init(void) _enter(""); -#ifdef AFS_AUTOMOUNT_SUPPORT afs_timer_init(&afs_mntpt_expiry_timer, &afs_mntpt_expiry_timer_ops); -#endif /* create ourselves an inode cache */ atomic_set(&afs_count_active_inodes, 0); diff --git a/fs/buffer.c b/fs/buffer.c index 9d34cf52696b1b..c70e72ef5c6274 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1588,10 +1588,9 @@ __bread(struct block_device *bdev, sector_t block, int size) EXPORT_SYMBOL(__bread); /* - * invalidate_bh_lrus() is called rarely - at unmount. Because it is only for - * unmount it only needs to ensure that all buffers from the target device are - * invalidated on return and it doesn't need to worry about new buffers from - * that device being added - the unmount code has to prevent that. + * invalidate_bh_lrus() is called rarely - but not only at unmount. + * This doesn't race because it runs in each cpu either in irq + * or with preempt disabled. */ static void invalidate_bh_lru(void *arg) { @@ -1807,10 +1806,10 @@ EXPORT_SYMBOL(unmap_underlying_metadata); * state inside lock_buffer(). * * If block_write_full_page() is called for regular writeback - * (called_for_sync() is false) then it will redirty a page which has a locked - * buffer. This only can happen if someone has written the buffer directly, - * with submit_bh(). At the address_space level PageWriteback prevents this - * contention from occurring. + * (wbc->sync_mode == WB_SYNC_NONE) then it will redirty a page which has a + * locked buffer. This only can happen if someone has written the buffer + * directly, with submit_bh(). At the address_space level PageWriteback + * prevents this contention from occurring. */ static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block, struct writeback_control *wbc) @@ -1899,14 +1898,14 @@ static int __block_write_full_page(struct inode *inode, struct page *page, } } while ((bh = bh->b_this_page) != head); + /* + * The page and its buffers are protected by PageWriteback(), so we can + * drop the bh refcounts early. + */ BUG_ON(PageWriteback(page)); - set_page_writeback(page); /* Keeps try_to_free_buffers() away */ + set_page_writeback(page); unlock_page(page); - /* - * The page may come unlocked any time after the *first* submit_bh() - * call. Be careful with its buffers. - */ do { struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) { @@ -1936,6 +1935,10 @@ done: if (uptodate) SetPageUptodate(page); end_page_writeback(page); + /* + * The page and buffer_heads can be released at any time from + * here on. + */ wbc->pages_skipped++; /* We didn't write this page */ } return err; @@ -2723,7 +2726,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block, /* * The page straddles i_size. It must be zeroed out on each and every - * writepage invocation because it may be mmapped. "A file is mapped + * writepage invokation because it may be mmapped. "A file is mapped * in multiples of the page size. For a file that is not a multiple of * the page size, the remaining memory is zeroed when mapped, and * writes to that region are not written out to the file." diff --git a/fs/dquot.c b/fs/dquot.c index 748beac66e02c2..35c84acdcc8003 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -96,9 +96,11 @@ * * Any operation working on dquots via inode pointers must hold dqptr_sem. If * operation is just reading pointers from inode (or not using them at all) the - * read lock is enough. If pointers are altered function must hold write lock. - * If operation is holding reference to dquot in other way (e.g. quotactl ops) - * it must be guarded by dqonoff_sem. + * read lock is enough. If pointers are altered function must hold write lock + * (these locking rules also apply for S_NOQUOTA flag in the inode - note that + * for altering the flag i_sem is also needed). If operation is holding + * reference to dquot in other way (e.g. quotactl ops) it must be guarded by + * dqonoff_sem. * This locking assures that: * a) update/access to dquot pointers in inode is serialized * b) everyone is guarded against invalidate_dquots() @@ -112,7 +114,7 @@ * operations on dquots don't hold dq_lock as they copy data under dq_data_lock * spinlock to internal buffers before writing. * - * Lock ordering (including some related VFS locks) is the following: + * Lock ordering (including related VFS locks) is following: * i_sem > dqonoff_sem > iprune_sem > journal_lock > dqptr_sem > * > dquot->dq_lock > dqio_sem * i_sem on quota files is special (it's below dqio_sem) @@ -204,9 +206,12 @@ struct dqstats dqstats; static void dqput(struct dquot *dquot); -static inline int const hashfn(struct super_block *sb, unsigned int id, int type) +static inline unsigned int +hashfn(const struct super_block *sb, unsigned int id, int type) { - unsigned long tmp = (((unsigned long)sb>>L1_CACHE_SHIFT) ^ id) * (MAXQUOTAS - type); + unsigned long tmp; + + tmp = (((unsigned long)sb>>L1_CACHE_SHIFT) ^ id) * (MAXQUOTAS - type); return (tmp + (tmp >> dq_hash_bits)) & dq_hash_mask; } @@ -686,16 +691,8 @@ static inline int dqput_blocks(struct dquot *dquot) int remove_inode_dquot_ref(struct inode *inode, int type, struct list_head *tofree_head) { struct dquot *dquot = inode->i_dquot[type]; - int cnt; inode->i_dquot[type] = NODQUOT; - /* any other quota in use? */ - for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt] != NODQUOT) - goto put_it; - } - inode->i_flags &= ~S_QUOTA; -put_it: if (dquot != NODQUOT) { if (dqput_blocks(dquot)) { #ifdef __DQUOT_PARANOIA @@ -956,8 +953,6 @@ int dquot_initialize(struct inode *inode, int type) break; } inode->i_dquot[cnt] = dqget(inode->i_sb, id, cnt); - if (inode->i_dquot[cnt]) - inode->i_flags |= S_QUOTA; } } out_err: @@ -974,7 +969,6 @@ int dquot_drop(struct inode *inode) int cnt; down_write(&sb_dqopt(inode->i_sb)->dqptr_sem); - inode->i_flags &= ~S_QUOTA; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (inode->i_dquot[cnt] != NODQUOT) { dqput(inode->i_dquot[cnt]); @@ -1367,7 +1361,7 @@ static int vfs_quota_on_file(struct file *f, int type, int format_id) struct quota_info *dqopt = sb_dqopt(sb); struct dquot *to_drop[MAXQUOTAS]; int error, cnt; - unsigned int oldflags; + unsigned int oldflags = -1; if (!fmt) return -ESRCH; @@ -1379,22 +1373,26 @@ static int vfs_quota_on_file(struct file *f, int type, int format_id) if (!S_ISREG(inode->i_mode)) goto out_fmt; + down(&inode->i_sem); down(&dqopt->dqonoff_sem); if (sb_has_quota_enabled(sb, type)) { + up(&inode->i_sem); error = -EBUSY; goto out_lock; } - oldflags = inode->i_flags; - dqopt->files[type] = f; - error = -EINVAL; - if (!fmt->qf_ops->check_quota_file(sb, type)) - goto out_file_init; /* We don't want quota and atime on quota files (deadlocks possible) * We also need to set GFP mask differently because we cannot recurse * into filesystem when allocating page for quota inode */ down_write(&dqopt->dqptr_sem); + oldflags = inode->i_flags & (S_NOATIME | S_NOQUOTA); inode->i_flags |= S_NOQUOTA | S_NOATIME; + up_write(&dqopt->dqptr_sem); + up(&inode->i_sem); + dqopt->files[type] = f; + error = -EINVAL; + if (!fmt->qf_ops->check_quota_file(sb, type)) + goto out_file_init; /* * We write to quota files deep within filesystem code. We don't want * the VFS to reenter filesystem code when it tries to allocate a @@ -1404,11 +1402,11 @@ static int vfs_quota_on_file(struct file *f, int type, int format_id) mapping_set_gfp_mask(inode->i_mapping, mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); + down_write(&dqopt->dqptr_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { to_drop[cnt] = inode->i_dquot[cnt]; inode->i_dquot[cnt] = NODQUOT; } - inode->i_flags &= ~S_QUOTA; up_write(&dqopt->dqptr_sem); /* We must put dquots outside of dqptr_sem because we may need to * start transaction for dquot_release() */ @@ -1434,11 +1432,20 @@ static int vfs_quota_on_file(struct file *f, int type, int format_id) return 0; out_file_init: - inode->i_flags = oldflags; dqopt->files[type] = NULL; out_lock: - up_write(&dqopt->dqptr_sem); up(&dqopt->dqonoff_sem); + if (oldflags != -1) { + down(&inode->i_sem); + down_write(&dqopt->dqptr_sem); + /* Reset the NOATIME flag back. I know it could change in the + * mean time but playing with NOATIME flags on a quota file is + * never a good idea */ + inode->i_flags &= ~(S_NOATIME | S_NOQUOTA); + inode->i_flags |= oldflags; + up_write(&dqopt->dqptr_sem); + up(&inode->i_sem); + } out_fmt: put_quota_format(fmt); diff --git a/fs/inode.c b/fs/inode.c index 5cd72ced8c9e5e..ec0945963c930a 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1235,26 +1235,26 @@ void remove_dquot_ref(struct super_block *sb, int type, struct list_head *tofree if (!sb->dq_op) return; /* nothing to do */ spin_lock(&inode_lock); /* This lock is for inodes code */ - /* We don't have to lock against quota code - test IS_QUOTAINIT is just for speedup... */ - + + /* We hold dqptr_sem so we are safe against the quota code */ list_for_each(act_head, &inode_in_use) { inode = list_entry(act_head, struct inode, i_list); - if (inode->i_sb == sb && IS_QUOTAINIT(inode)) + if (inode->i_sb == sb && !IS_NOQUOTA(inode)) remove_inode_dquot_ref(inode, type, tofree_head); } list_for_each(act_head, &inode_unused) { inode = list_entry(act_head, struct inode, i_list); - if (inode->i_sb == sb && IS_QUOTAINIT(inode)) + if (inode->i_sb == sb && !IS_NOQUOTA(inode)) remove_inode_dquot_ref(inode, type, tofree_head); } list_for_each(act_head, &sb->s_dirty) { inode = list_entry(act_head, struct inode, i_list); - if (IS_QUOTAINIT(inode)) + if (!IS_NOQUOTA(inode)) remove_inode_dquot_ref(inode, type, tofree_head); } list_for_each(act_head, &sb->s_io) { inode = list_entry(act_head, struct inode, i_list); - if (IS_QUOTAINIT(inode)) + if (!IS_NOQUOTA(inode)) remove_inode_dquot_ref(inode, type, tofree_head); } spin_unlock(&inode_lock); diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 4d34ba69c3066a..1173626cadfdbf 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -315,7 +315,7 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr) } /* Write this node to the flash. */ - if ((res = jffs_write_node(c, new_node, &raw_inode, f->name, 0, recoverable, f)) < 0) { + if ((res = jffs_write_node(c, new_node, &raw_inode, f->name, NULL, recoverable, f)) < 0) { D(printk("jffs_notify_change(): The write failed!\n")); jffs_free_node(new_node); D3(printk (KERN_NOTICE "n_c(): up biglock\n")); @@ -323,7 +323,7 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr) goto out; } - jffs_insert_node(c, f, &raw_inode, 0, new_node); + jffs_insert_node(c, f, &raw_inode, NULL, new_node); mark_inode_dirty(inode); D3(printk (KERN_NOTICE "n_c(): up biglock\n")); @@ -879,14 +879,14 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode) /* Write the new node to the flash. */ if ((result = jffs_write_node(c, node, &raw_inode, - dentry->d_name.name, 0, 0, NULL)) < 0) { + dentry->d_name.name, NULL, 0, NULL)) < 0) { D(printk("jffs_mkdir(): jffs_write_node() failed.\n")); jffs_free_node(node); goto jffs_mkdir_end; } /* Insert the new node into the file system. */ - if ((result = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, + if ((result = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name, node)) < 0) { goto jffs_mkdir_end; } @@ -959,7 +959,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type) struct jffs_file *dir_f; /* The file-to-remove's parent. */ struct jffs_file *del_f; /* The file to remove. */ struct jffs_node *del_node; - struct inode *inode = 0; + struct inode *inode = NULL; int result = 0; D1({ @@ -1041,7 +1041,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type) raw_inode.deleted = 1; /* Write the new node to the flash memory. */ - if (jffs_write_node(c, del_node, &raw_inode, 0, 0, 1, del_f) < 0) { + if (jffs_write_node(c, del_node, &raw_inode, NULL, NULL, 1, del_f) < 0) { jffs_free_node(del_node); result = -EIO; goto jffs_remove_end; @@ -1049,7 +1049,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type) /* Update the file. This operation will make the file disappear from the in-memory file system structures. */ - jffs_insert_node(c, del_f, &raw_inode, 0, del_node); + jffs_insert_node(c, del_f, &raw_inode, NULL, del_node); dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(dir); @@ -1070,7 +1070,7 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct jffs_raw_inode raw_inode; struct jffs_file *dir_f; - struct jffs_node *node = 0; + struct jffs_node *node = NULL; struct jffs_control *c; struct inode *inode; int result = 0; @@ -1127,7 +1127,7 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) } /* Insert the new node into the file system. */ - if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, + if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name, node)) < 0) { result = err; goto jffs_mknod_end; @@ -1237,7 +1237,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) } /* Insert the new node into the file system. */ - if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, + if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name, node)) < 0) { goto jffs_symlink_end; } @@ -1333,14 +1333,14 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode, /* Write the new node to the flash. */ if ((err = jffs_write_node(c, node, &raw_inode, - dentry->d_name.name, 0, 0, NULL)) < 0) { + dentry->d_name.name, NULL, 0, NULL)) < 0) { D(printk("jffs_create(): jffs_write_node() failed.\n")); jffs_free_node(node); goto jffs_create_end; } /* Insert the new node into the file system. */ - if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name, + if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name, node)) < 0) { goto jffs_create_end; } @@ -1501,7 +1501,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count, pos += err; /* Insert the new node into the file system. */ - if ((err = jffs_insert_node(c, f, &raw_inode, 0, node)) < 0) { + if ((err = jffs_insert_node(c, f, &raw_inode, NULL, node)) < 0) { goto out; } @@ -1750,7 +1750,7 @@ jffs_delete_inode(struct inode *inode) lock_kernel(); inode->i_size = 0; inode->i_blocks = 0; - inode->u.generic_ip = 0; + inode->u.generic_ip = NULL; clear_inode(inode); if (inode->i_nlink == 0) { c = (struct jffs_control *) inode->i_sb->s_fs_info; diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index 816f07676539c1..273a3c9cc5b0f0 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c @@ -209,7 +209,7 @@ flash_safe_write(struct mtd_info *mtd, loff_t to, static int -flash_safe_writev(struct mtd_info *mtd, const struct iovec *vecs, +flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long iovec_cnt, loff_t to) { size_t retlen, retlen_a; @@ -409,7 +409,7 @@ jffs_create_file(struct jffs_control *c, if (!(f = (struct jffs_file *)kmalloc(sizeof(struct jffs_file), GFP_KERNEL))) { D(printk("jffs_create_file(): Failed!\n")); - return 0; + return NULL; } no_jffs_file++; memset(f, 0, sizeof(struct jffs_file)); @@ -438,8 +438,8 @@ jffs_create_control(struct super_block *sb) goto fail_control; } DJM(no_jffs_control++); - c->root = 0; - c->gc_task = 0; + c->root = NULL; + c->gc_task = NULL; c->hash_len = JFFS_HASH_SIZE; s = sizeof(struct list_head) * c->hash_len; if (!(c->hash = (struct list_head *)kmalloc(s, GFP_KERNEL))) { @@ -752,7 +752,7 @@ jffs_scan_flash(struct jffs_control *c) { char name[JFFS_MAX_NAME_LEN + 2]; struct jffs_raw_inode raw_inode; - struct jffs_node *node = 0; + struct jffs_node *node = NULL; struct jffs_fmcontrol *fmc = c->fmc; __u32 checksum; __u8 tmp_accurate; @@ -904,7 +904,7 @@ jffs_scan_flash(struct jffs_control *c) D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n", (unsigned int) start, (unsigned int) (pos - start))); jffs_fmalloced(fmc, (__u32) start, - (__u32) (pos - start), 0); + (__u32) (pos - start), NULL); }else{ /* "Flipping bits" detected. This means that our scan for them did not catch this offset. See check_partly_erased_sectors() for @@ -964,7 +964,7 @@ jffs_scan_flash(struct jffs_control *c) D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n", (unsigned int) start, (unsigned int) (pos - start))); jffs_fmalloced(fmc, (__u32) start, - (__u32) (pos - start), 0); + (__u32) (pos - start), NULL); } } @@ -986,7 +986,7 @@ jffs_scan_flash(struct jffs_control *c) D1(printk("jffs_scan_flash(): 0x00 ended at " "pos 0x%lx.\n", (long)pos)); jffs_fmalloced(fmc, (__u32) start, - (__u32) (pos - start), 0); + (__u32) (pos - start), NULL); continue; case JFFS_MAGIC_BITMASK: @@ -1020,7 +1020,7 @@ jffs_scan_flash(struct jffs_control *c) which really does contain crap. */ jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), - 0); + NULL); continue; }/* switch */ @@ -1067,7 +1067,7 @@ jffs_scan_flash(struct jffs_control *c) checksum, raw_inode.chksum)); pos += sizeof(struct jffs_raw_inode); jffs_fmalloced(fmc, (__u32) start, - (__u32) (pos - start), 0); + (__u32) (pos - start), NULL); /* Reuse this unused struct jffs_node. */ continue; } @@ -1121,7 +1121,7 @@ jffs_scan_flash(struct jffs_control *c) "raw_inode.nchksum = %u\n", checksum, raw_inode.nchksum)); jffs_fmalloced(fmc, (__u32) start, - (__u32) (pos - start), 0); + (__u32) (pos - start), NULL); /* Reuse this unused struct jffs_node. */ continue; } @@ -1139,7 +1139,7 @@ jffs_scan_flash(struct jffs_control *c) if (jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize, &checksum)) { printk("jffs_checksum_flash() failed to calculate a checksum\n"); jffs_fmalloced(fmc, (__u32) start, - (__u32) (pos - start), 0); + (__u32) (pos - start), NULL); /* Reuse this unused struct jffs_node. */ continue; } @@ -1152,7 +1152,7 @@ jffs_scan_flash(struct jffs_control *c) "raw_inode.dchksum = %u\n", checksum, raw_inode.dchksum)); jffs_fmalloced(fmc, (__u32) start, - (__u32) (pos - start), 0); + (__u32) (pos - start), NULL); /* Reuse this unused struct jffs_node. */ continue; } @@ -1194,7 +1194,7 @@ jffs_scan_flash(struct jffs_control *c) return -ENOMEM; } - if ((err = jffs_insert_node(c, 0, &raw_inode, + if ((err = jffs_insert_node(c, NULL, &raw_inode, name, node)) < 0) { printk("JFFS: Failed to handle raw inode. " "(err = %d)\n", err); @@ -1224,11 +1224,11 @@ jffs_scan_flash(struct jffs_control *c) node->data_size = 0; } D3(jffs_print_node(node)); - node = 0; /* Don't free the node! */ + node = NULL; /* Don't free the node! */ } else { jffs_fmalloced(fmc, (__u32) start, - (__u32) (pos - start), 0); + (__u32) (pos - start), NULL); D3(printk("jffs_scan_flash(): Just found an obsolete " "raw_inode. Continuing the scan...\n")); /* Reuse this unused struct jffs_node. */ @@ -1312,8 +1312,8 @@ jffs_insert_node(struct jffs_control *c, struct jffs_file *f, /* This is the first node. */ f->version_head = node; f->version_tail = node; - node->version_prev = 0; - node->version_next = 0; + node->version_prev = NULL; + node->version_next = NULL; f->highest_version = node->version; update_name = 1; f->mode = raw_inode->mode; @@ -1328,7 +1328,7 @@ jffs_insert_node(struct jffs_control *c, struct jffs_file *f, /* Insert at the end of the list. I.e. this node is the newest one so far. */ node->version_prev = f->version_tail; - node->version_next = 0; + node->version_next = NULL; f->version_tail->version_next = node; f->version_tail = node; f->highest_version = node->version; @@ -1343,7 +1343,7 @@ jffs_insert_node(struct jffs_control *c, struct jffs_file *f, } else if (f->version_head->version > node->version) { /* Insert at the bottom of the list. */ - node->version_prev = 0; + node->version_prev = NULL; node->version_next = f->version_head; f->version_head->version_prev = node; f->version_head = node; @@ -1556,9 +1556,9 @@ jffs_insert_file_into_tree(struct jffs_file *f) if (!(parent = jffs_find_file(f->c, f->pino))) { if (f->pino == 0) { f->c->root = f; - f->parent = 0; - f->sibling_prev = 0; - f->sibling_next = 0; + f->parent = NULL; + f->sibling_prev = NULL; + f->sibling_next = NULL; return 0; } else { @@ -1573,7 +1573,7 @@ jffs_insert_file_into_tree(struct jffs_file *f) if (f->sibling_next) { f->sibling_next->sibling_prev = f; } - f->sibling_prev = 0; + f->sibling_prev = NULL; parent->children = f; return 0; } @@ -1740,7 +1740,7 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node, { struct jffs_fmcontrol *fmc = c->fmc; struct jffs_fm *fm; - struct iovec node_iovec[4]; + struct kvec node_iovec[4]; unsigned long iovec_cnt; __u32 pos; @@ -2311,7 +2311,7 @@ jffs_insert_data(struct jffs_file *f, struct jffs_node *node) retry: if (node->data_offset == f->size) { /* A simple append. This is the most common operation. */ - node->range_next = 0; + node->range_next = NULL; node->range_prev = f->range_tail; if (node->range_prev) { node->range_prev->range_next = node; @@ -2389,10 +2389,10 @@ jffs_insert_data(struct jffs_file *f, struct jffs_node *node) virtual_node->removed_size = 0; virtual_node->fm_offset = 0; virtual_node->name_size = 0; - virtual_node->fm = 0; /* This is a virtual data holder. */ - virtual_node->version_prev = 0; - virtual_node->version_next = 0; - virtual_node->range_next = 0; + virtual_node->fm = NULL; /* This is a virtual data holder. */ + virtual_node->version_prev = NULL; + virtual_node->version_next = NULL; + virtual_node->range_next = NULL; /* Are there any data at all in the file yet? */ if (f->range_head) { @@ -2407,7 +2407,7 @@ jffs_insert_data(struct jffs_file *f, struct jffs_node *node) else { virtual_node->data_offset = 0; virtual_node->data_size = node->data_offset; - virtual_node->range_prev = 0; + virtual_node->range_prev = NULL; f->range_head = virtual_node; } diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c index 71cda0ca0d1dd7..1597328f01cefc 100644 --- a/fs/jffs/jffs_fm.c +++ b/fs/jffs/jffs_fm.c @@ -77,10 +77,10 @@ jffs_build_begin(struct jffs_control *c, int unit) fmc->min_free_size = fmc->sector_size << 2; fmc->mtd = mtd; fmc->c = c; - fmc->head = 0; - fmc->tail = 0; - fmc->head_extra = 0; - fmc->tail_extra = 0; + fmc->head = NULL; + fmc->tail = NULL; + fmc->head_extra = NULL; + fmc->tail_extra = NULL; init_MUTEX(&fmc->biglock); return fmc; } @@ -102,8 +102,8 @@ jffs_build_end(struct jffs_fmcontrol *fmc) fmc->head->prev = fmc->tail_extra; fmc->head = fmc->head_extra; } - fmc->head_extra = 0; /* These two instructions should be omitted. */ - fmc->tail_extra = 0; + fmc->head_extra = NULL; /* These two instructions should be omitted. */ + fmc->tail_extra = NULL; D3(jffs_print_fmcontrol(fmc)); } @@ -205,7 +205,7 @@ jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node, D2(printk("jffs_fmalloc(): fmc = 0x%p, size = %d, " "node = 0x%p\n", fmc, size, node)); - *result = 0; + *result = NULL; if (!(fm = jffs_alloc_fm())) { D(printk("jffs_fmalloc(): kmalloc() failed! (fm)\n")); @@ -234,7 +234,7 @@ jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node, } DJM(no_jffs_node_ref++); fm->nodes->node = node; - fm->nodes->next = 0; + fm->nodes->next = NULL; if (fmc->tail) { fm->offset = fmc->tail->offset + fmc->tail->size; if (fm->offset == fmc->flash_size) { @@ -264,7 +264,7 @@ jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node, else { fm->offset = fmc->tail->offset + fmc->tail->size; fm->size = free_chunk_size1; - fm->nodes = 0; + fm->nodes = NULL; fmc->free_size -= fm->size; fmc->dirty_size += fm->size; /* Changed by simonk. This seemingly fixes a bug that caused infinite garbage collection. @@ -273,9 +273,9 @@ jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node, */ } - fm->next = 0; + fm->next = NULL; if (!fmc->head) { - fm->prev = 0; + fm->prev = NULL; fmc->head = fm; fmc->tail = fm; } @@ -309,13 +309,13 @@ jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, struct jffs_node *no ASSERT(if (!fmc || !fm || !fm->nodes) { printk(KERN_ERR "jffs_fmfree(): fmc: 0x%p, fm: 0x%p, " "fm->nodes: 0x%p\n", - fmc, fm, (fm ? fm->nodes : 0)); + fmc, fm, (fm ? fm->nodes : NULL)); return -1; }); /* Find the reference to the node that is going to be removed and remove it. */ - for (ref = fm->nodes, prev = 0; ref; ref = ref->next) { + for (ref = fm->nodes, prev = NULL; ref; ref = ref->next) { if (ref->node == node) { if (prev) { prev->next = ref->next; @@ -368,13 +368,13 @@ jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size, if (!(fm = jffs_alloc_fm())) { D(printk("jffs_fmalloced(0x%p, %u, %u, 0x%p): failed!\n", fmc, offset, size, node)); - return 0; + return NULL; } fm->offset = offset; fm->size = size; - fm->prev = 0; - fm->next = 0; - fm->nodes = 0; + fm->prev = NULL; + fm->next = NULL; + fm->nodes = NULL; if (node) { /* `node' exists and it should be associated with the jffs_fm structure `fm'. */ @@ -383,11 +383,11 @@ jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size, GFP_KERNEL))) { D(printk("jffs_fmalloced(): !fm->nodes\n")); jffs_free_fm(fm); - return 0; + return NULL; } DJM(no_jffs_node_ref++); fm->nodes->node = node; - fm->nodes->next = 0; + fm->nodes->next = NULL; fmc->used_size += size; fmc->free_size -= size; } @@ -454,7 +454,7 @@ jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, __u32 size) if (fm->nodes) { kfree(fm->nodes); DJM(no_jffs_node_ref--); - fm->nodes = 0; + fm->nodes = NULL; } fmc->used_size -= fm->size; if (fm == fmc->tail) { @@ -476,12 +476,12 @@ jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size) __u32 pos = 0; if (size == 0) { - return 0; + return NULL; } ASSERT(if (!fmc) { printk(KERN_ERR "jffs_cut_node(): fmc == NULL\n"); - return 0; + return NULL; }); fm = fmc->head; @@ -495,7 +495,7 @@ jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size) break; } else { - fm = 0; + fm = NULL; break; } } @@ -524,7 +524,7 @@ jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size) erased_size -= fm->size; del = fm; fm = fm->next; - fm->prev = 0; + fm->prev = NULL; fmc->head = fm; jffs_free_fm(del); } @@ -543,17 +543,17 @@ jffs_get_oldest_node(struct jffs_fmcontrol *fmc) { struct jffs_fm *fm; struct jffs_node_ref *nref; - struct jffs_node *node = 0; + struct jffs_node *node = NULL; ASSERT(if (!fmc) { printk(KERN_ERR "jffs_get_oldest_node(): fmc == NULL\n"); - return 0; + return NULL; }); for (fm = fmc->head; fm && !fm->nodes; fm = fm->next); if (!fm) { - return 0; + return NULL; } /* The oldest node is the last one in the reference list. This list diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 91401c1c9dca70..11f3a5a35dfe28 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -132,8 +132,9 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_wbuf_dirty(c) (!!(c)->wbuf_len) struct kstatfs; +struct kvec; /* wbuf.c */ -int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino); +int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino); int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf); int jffs2_check_oob_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,int mode); @@ -185,7 +186,7 @@ int jffs2_remount_fs (struct super_block *, int *, char *); int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); /* writev.c */ -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, +int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); /* super.c */ diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index ecfb155cb82bd9..956f98d8dd3599 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -544,9 +544,9 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) #define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) #define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) -int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) +int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) { - struct iovec outvecs[3]; + struct kvec outvecs[3]; uint32_t totlen = 0; uint32_t split_ofs = 0; uint32_t old_totlen; @@ -751,11 +751,11 @@ alldone: /* * This is the entry for flash write. - * Check, if we work on NAND FLASH, if so build an iovec and write it via vritev + * Check, if we work on NAND FLASH, if so build an kvec and write it via vritev */ int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf) { - struct iovec vecs[1]; + struct kvec vecs[1]; if (jffs2_can_mark_obsolete(c)) return c->mtd->write(c->mtd, ofs, len, retlen, buf); diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index f28d9d5bcd36a9..11c76104521582 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -92,7 +92,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 struct jffs2_raw_node_ref *raw; struct jffs2_full_dnode *fn; size_t retlen; - struct iovec vecs[2]; + struct kvec vecs[2]; int ret; int retried = 0; unsigned long cnt = 2; @@ -233,7 +233,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; size_t retlen; - struct iovec vecs[2]; + struct kvec vecs[2]; int retried = 0; int ret; diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index 80cd3820373f74..c88bf7336e5091 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -18,7 +18,7 @@ /* This ought to be in core MTD code. All registered MTD devices without writev should have this put in place. Bug the MTD maintainer */ -static inline int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs, +static inline int mtd_fake_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { unsigned long i; @@ -39,7 +39,7 @@ static inline int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs return ret; } -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs, +int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { if (c->mtd->writev) diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index dc749c2e6fa87c..71e797774c088e 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -259,19 +259,19 @@ static struct dir_table_slot *find_index(struct inode *ip, u32 index, jfs_warn("find_entry called with index = %d", index); maxWarnings--; } - return 0; + return NULL; } if (index >= jfs_ip->next_index) { jfs_warn("find_entry called with index >= next_index"); - return 0; + return NULL; } if (jfs_ip->next_index <= (MAX_INLINE_DIRTABLE_ENTRY + 1)) { /* * Inline directory table */ - *mp = 0; + *mp = NULL; slot = &jfs_ip->i_dirtable[index - 2]; } else { offset = (index - 2) * sizeof(struct dir_table_slot); @@ -281,7 +281,7 @@ static struct dir_table_slot *find_index(struct inode *ip, u32 index, if (*mp && (*lblock != blkno)) { release_metapage(*mp); - *mp = 0; + *mp = NULL; } if (*mp == 0) { *lblock = blkno; @@ -289,7 +289,7 @@ static struct dir_table_slot *find_index(struct inode *ip, u32 index, } if (*mp == 0) { jfs_err("free_index: error reading directory table"); - return 0; + return NULL; } slot = @@ -490,7 +490,7 @@ static void free_index(tid_t tid, struct inode *ip, u32 index, u32 next) { struct dir_table_slot *dirtab_slot; s64 lblock; - struct metapage *mp = 0; + struct metapage *mp = NULL; dirtab_slot = find_index(ip, index, &mp, &lblock); @@ -543,7 +543,7 @@ static int read_index(struct inode *ip, u32 index, struct dir_table_slot * dirtab_slot) { s64 lblock; - struct metapage *mp = 0; + struct metapage *mp = NULL; struct dir_table_slot *slot; slot = find_index(ip, index, &mp, &lblock); @@ -850,7 +850,7 @@ int dtInsert(tid_t tid, struct inode *ip, data.leaf.ip = ip; } else { n = NDTLEAF_LEGACY(name->namlen); - data.leaf.ip = 0; /* signifies legacy directory format */ + data.leaf.ip = NULL; /* signifies legacy directory format */ } data.leaf.ino = cpu_to_le32(*fsn); @@ -940,7 +940,7 @@ static int dtSplitUp(tid_t tid, int xlen, xsize; struct pxdlist pxdlist; pxd_t *pxd; - struct component_name key = { 0, 0 }; + struct component_name key = { 0, NULL }; ddata_t *data = split->data; int n; struct dt_lock *dtlck; @@ -1550,7 +1550,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split, if ((rp->header.flag & BT_LEAF) && DO_INDEX(ip)) { s64 lblock; - mp = 0; + mp = NULL; stbl = DT_GETSTBL(rp); for (n = 0; n < rp->header.nextindex; n++) { ldtentry = (struct ldtentry *) & rp->slot[stbl[n]]; @@ -1676,7 +1676,7 @@ static int dtExtendPage(tid_t tid, if (DO_INDEX(ip)) { s64 lblock; - mp = 0; + mp = NULL; stbl = DT_GETSTBL(sp); for (n = 0; n < sp->header.nextindex; n++) { ldtentry = @@ -1970,7 +1970,7 @@ static int dtSplitRoot(tid_t tid, */ if ((rp->header.flag & BT_LEAF) && DO_INDEX(ip)) { s64 lblock; - struct metapage *mp = 0; + struct metapage *mp = NULL; struct ldtentry *ldtentry; stbl = DT_GETSTBL(rp); @@ -2181,7 +2181,7 @@ int dtDelete(tid_t tid, if (DO_INDEX(ip) && index < p->header.nextindex) { s64 lblock; - imp = 0; + imp = NULL; stbl = DT_GETSTBL(p); for (i = index; i < p->header.nextindex; i++) { ldtentry = @@ -3873,8 +3873,8 @@ static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key, ddata_t * data, struct dt_lock ** dtlock) { struct dtslot *h, *t; - struct ldtentry *lh = 0; - struct idtentry *ih = 0; + struct ldtentry *lh = NULL; + struct idtentry *ih = NULL; int hsi, fsi, klen, len, nextindex; wchar_t *kname, *name; s8 *stbl; @@ -3883,7 +3883,7 @@ static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key, struct lv *lv; int xsi, n; s64 bn = 0; - struct metapage *mp = 0; + struct metapage *mp = NULL; klen = key->namlen; kname = key->name; @@ -3999,7 +3999,7 @@ static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key, * Need to update slot number for entries that moved * in the stbl */ - mp = 0; + mp = NULL; for (n = index + 1; n <= nextindex; n++) { lh = (struct ldtentry *) & (p->slot[stbl[n]]); modify_index(data->leaf.tid, data->leaf.ip, @@ -4035,8 +4035,8 @@ static void dtMoveEntry(dtpage_t * sp, int si, dtpage_t * dp, int dsi; /* dst slot index */ s8 *sstbl, *dstbl; /* sorted entry table */ int snamlen, len; - struct ldtentry *slh, *dlh = 0; - struct idtentry *sih, *dih = 0; + struct ldtentry *slh, *dlh = NULL; + struct idtentry *sih, *dih = NULL; struct dtslot *h, *s, *d; struct dt_lock *sdtlck = *sdtlock, *ddtlck = *ddtlock; struct lv *slv, *dlv; diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 865334f6c8afce..86246f4db7a6fd 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -2061,7 +2061,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) { int extno, bitno, agno, sword, rc; struct metapage *amp = NULL, *bmp = NULL; - struct iag *aiagp = 0, *biagp = 0; + struct iag *aiagp = NULL, *biagp = NULL; u32 mask; /* check if this is the last free inode within the iag. @@ -2207,7 +2207,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) { int agno, iagno, fwd, back, freei = 0, sword, rc; - struct iag *aiagp = 0, *biagp = 0, *ciagp = 0; + struct iag *aiagp = NULL, *biagp = NULL, *ciagp = NULL; struct metapage *amp, *bmp, *cmp, *dmp; struct inode *ipimap; s64 blkno, hint; @@ -2910,7 +2910,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) { int rc, rcx = 0; struct inomap *imap = JFS_IP(ipimap)->i_imap; - struct iag *iagp = 0, *hiagp = 0; + struct iag *iagp = NULL, *hiagp = NULL; struct bmap *mp = JFS_SBI(ipbmap->i_sb)->bmap; struct metapage *bp, *hbp; int i, n, head; diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 8c94bb015c845f..dd6578b7d3b260 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -320,7 +320,7 @@ again: atomic_set(&mp->nohomeok,0); mp->mapping = mapping; mp->index = lblock; - mp->page = 0; + mp->page = NULL; mp->logical_size = size; add_to_hash(mp, hash_ptr); spin_unlock(&meta_lock); @@ -465,7 +465,7 @@ void release_metapage(struct metapage * mp) set_bit(META_stale, &mp->flag); spin_unlock(&meta_lock); kunmap(mp->page); - mp->data = 0; + mp->data = NULL; if (test_bit(META_dirty, &mp->flag)) __write_metapage(mp); if (test_bit(META_sync, &mp->flag)) { @@ -491,7 +491,7 @@ void release_metapage(struct metapage * mp) */ log = mp->log; LOGSYNC_LOCK(log); - mp->log = 0; + mp->log = NULL; mp->lsn = 0; mp->clsn = 0; log->count--; diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index 3de7db13d2574b..fad757e9ea5348 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -166,7 +166,7 @@ int jfs_mount(struct super_block *sb) } } else /* Secondary aggregate inode table is not valid */ - sbi->ipaimap2 = 0; + sbi->ipaimap2 = NULL; /* * mount (the only/single) fileset diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 7e08dd5025ada2..f4bd79b705f6ff 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -330,9 +330,9 @@ int txInit(void) void txExit(void) { vfree(TxLock); - TxLock = 0; + TxLock = NULL; vfree(TxBlock); - TxBlock = 0; + TxBlock = NULL; } @@ -1554,7 +1554,7 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, hold_metapage(mp, 0); atomic_dec(&mp->nohomeok); discard_metapage(mp); - tlck->mp = 0; + tlck->mp = NULL; return 0; } @@ -2270,7 +2270,7 @@ static void txUpdateMap(struct tblock * tblk) struct pxd_lock pxdlock; int maptype; int k, nlock; - struct metapage *mp = 0; + struct metapage *mp = NULL; ipimap = JFS_SBI(tblk->sb)->ipimap; @@ -2358,7 +2358,7 @@ static void txUpdateMap(struct tblock * tblk) assert(atomic_read(&mp->nohomeok) == 1); atomic_dec(&mp->nohomeok); discard_metapage(mp); - tlck->mp = 0; + tlck->mp = NULL; } } /* diff --git a/fs/jfs/jfs_uniupr.c b/fs/jfs/jfs_uniupr.c index af63d97bb1af52..4ab185d26308b9 100644 --- a/fs/jfs/jfs_uniupr.c +++ b/fs/jfs/jfs_uniupr.c @@ -130,5 +130,5 @@ UNICASERANGE UniUpperRange[] = { { 0x0490, 0x04cc, UniCaseRangeU0490 }, { 0x1e00, 0x1ffc, UniCaseRangeU1e00 }, { 0xff40, 0xff5a, UniCaseRangeUff40 }, - { 0, 0, 0 } + { 0 } }; diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c index fab2bbcfe09b49..5aa647326887e3 100644 --- a/fs/jfs/jfs_xtree.c +++ b/fs/jfs/jfs_xtree.c @@ -1222,7 +1222,7 @@ xtSplitPage(tid_t tid, struct inode *ip, struct pxdlist *pxdlist; pxd_t *pxd; struct tlock *tlck; - struct xtlock *sxtlck = 0, *rxtlck = 0; + struct xtlock *sxtlck = NULL, *rxtlck = NULL; smp = split->mp; sp = XT_PAGE(ip, smp); @@ -1603,7 +1603,7 @@ int xtExtend(tid_t tid, /* transaction id */ xad_t *xad; s64 xaddr; struct tlock *tlck; - struct xtlock *xtlck = 0; + struct xtlock *xtlck = NULL; int rootsplit = 0; jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen); @@ -1957,7 +1957,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) int nxlen, xlen, lxlen, rxlen; s64 nxaddr, xaddr; struct tlock *tlck; - struct xtlock *xtlck = 0; + struct xtlock *xtlck = NULL; int rootsplit = 0, newpage = 0; /* there must exist extent to be tailgated */ @@ -3416,9 +3416,9 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) int xlen, len, freexlen; struct btstack btstack; struct btframe *parent; - struct tblock *tblk = 0; - struct tlock *tlck = 0; - struct xtlock *xtlck = 0; + struct tblock *tblk = NULL; + struct tlock *tlck = NULL; + struct xtlock *xtlck = NULL; struct xdlistlock xadlock; /* maplock for COMMIT_WMAP */ struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */ s64 nfreed; @@ -3614,7 +3614,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) pxdlock->flag = mlckFREEPXD; PXDaddress(&pxdlock->pxd, xaddr); PXDlength(&pxdlock->pxd, freexlen); - txFreeMap(ip, pxdlock, 0, COMMIT_WMAP); + txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); /* reset map lock */ xadlock.flag = mlckFREEXADLIST; @@ -3642,8 +3642,8 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) xadlock.count = le16_to_cpu(p->header.nextindex) - nextindex; - txFreeMap(ip, (struct maplock *) & xadlock, 0, - COMMIT_WMAP); + txFreeMap(ip, (struct maplock *) & xadlock, + NULL, COMMIT_WMAP); } p->header.nextindex = cpu_to_le16(nextindex); } @@ -3672,7 +3672,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) xadlock.xdlist = &p->xad[XTENTRYSTART]; xadlock.count = le16_to_cpu(p->header.nextindex) - XTENTRYSTART; - txFreeMap(ip, (struct maplock *) & xadlock, 0, COMMIT_WMAP); + txFreeMap(ip, (struct maplock *) & xadlock, NULL, COMMIT_WMAP); } if (p->header.flag & BT_ROOT) { @@ -3747,8 +3747,8 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) xadlock.count = le16_to_cpu(p->header.nextindex) - index - 1; - txFreeMap(ip, (struct maplock *) & xadlock, 0, - COMMIT_WMAP); + txFreeMap(ip, (struct maplock *) & xadlock, + NULL, COMMIT_WMAP); } BT_MARK_DIRTY(mp, ip); @@ -3819,7 +3819,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) xadlock.count = le16_to_cpu(p->header.nextindex) - XTENTRYSTART; - txFreeMap(ip, (struct maplock *) & xadlock, 0, + txFreeMap(ip, (struct maplock *) & xadlock, NULL, COMMIT_WMAP); } BT_MARK_DIRTY(mp, ip); @@ -3956,11 +3956,11 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) struct btframe *parent; int rc; struct tblock *tblk; - struct tlock *tlck = 0; + struct tlock *tlck = NULL; xad_t *xad; int xlen; s64 xoff; - struct xtlock *xtlck = 0; + struct xtlock *xtlck = NULL; /* save object truncation type */ tblk = tid_to_tblock(tid); diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 998410cccaa03e..871371d5a1aa32 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -702,7 +702,7 @@ int freeZeroLink(struct inode *ip) pxdlock->flag = mlckFREEPXD; PXDaddress(&pxdlock->pxd, xaddr); PXDlength(&pxdlock->pxd, xlen); - txFreeMap(ip, pxdlock, 0, COMMIT_WMAP); + txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); } /* @@ -722,7 +722,7 @@ int freeZeroLink(struct inode *ip) pxdlock->flag = mlckFREEPXD; PXDaddress(&pxdlock->pxd, xaddr); PXDlength(&pxdlock->pxd, xlen); - txFreeMap(ip, pxdlock, 0, COMMIT_WMAP); + txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); } /* diff --git a/fs/jfs/super.c b/fs/jfs/super.c index d359c26195cfbf..18fdb77086a0ee 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -422,7 +422,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) goto out_kfree; } if (sb->s_flags & MS_RDONLY) - sbi->log = 0; + sbi->log = NULL; else { rc = jfs_mount_rw(sb, 0); if (rc) { @@ -600,7 +600,7 @@ static int __init init_jfs_fs(void) /* * I/O completion thread (endio) */ - jfsIOthread = kernel_thread(jfsIOWait, 0, CLONE_KERNEL); + jfsIOthread = kernel_thread(jfsIOWait, NULL, CLONE_KERNEL); if (jfsIOthread < 0) { jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsIOthread); goto end_txmngr; @@ -613,7 +613,7 @@ static int __init init_jfs_fs(void) commit_threads = MAX_COMMIT_THREADS; for (i = 0; i < commit_threads; i++) { - jfsCommitThread[i] = kernel_thread(jfs_lazycommit, 0, + jfsCommitThread[i] = kernel_thread(jfs_lazycommit, NULL, CLONE_KERNEL); if (jfsCommitThread[i] < 0) { jfs_err("init_jfs_fs: fork failed w/rc = %d", @@ -625,7 +625,7 @@ static int __init init_jfs_fs(void) wait_for_completion(&jfsIOwait); } - jfsSyncThread = kernel_thread(jfs_sync, 0, CLONE_KERNEL); + jfsSyncThread = kernel_thread(jfs_sync, NULL, CLONE_KERNEL); if (jfsSyncThread < 0) { jfs_err("init_jfs_fs: fork failed w/rc = %d", jfsSyncThread); goto kill_committask; diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index c786348cdb00fa..cf3fba6e5d7811 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -592,7 +592,7 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size) if (new_size == 0) { ea_release(inode, ea_buf); - ea_buf = 0; + ea_buf = NULL; } else if (ea_buf->flag & EA_INLINE) { assert(new_size <= sizeof (ji->i_inline_ea)); ji->mode2 &= ~INLINEEA; @@ -633,7 +633,7 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size) } ji->ea = ea_buf->new_ea; } else { - txEA(tid, inode, &ji->ea, 0); + txEA(tid, inode, &ji->ea, NULL); if (ji->ea.flag & DXD_INLINE) ji->mode2 |= INLINEEA; ji->ea.flag = 0; @@ -1039,5 +1039,5 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) int jfs_removexattr(struct dentry *dentry, const char *name) { - return __jfs_setxattr(dentry->d_inode, name, 0, 0, XATTR_REPLACE); + return __jfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE); } diff --git a/fs/mpage.c b/fs/mpage.c index a22fc8f0ba9b05..79fdc78455b979 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -404,6 +404,7 @@ mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, struct block_device *boundary_bdev = NULL; int length; struct buffer_head map_bh; + loff_t i_size = i_size_read(inode); if (page_has_buffers(page)) { struct buffer_head *head = page_buffers(page); @@ -460,7 +461,7 @@ mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, */ BUG_ON(!PageUptodate(page)); block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits); - last_block = (i_size_read(inode) - 1) >> blkbits; + last_block = (i_size - 1) >> blkbits; map_bh.b_page = page; for (page_block = 0; page_block < blocks_per_page; ) { @@ -489,9 +490,18 @@ mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, first_unmapped = page_block; - end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; +page_is_mapped: + end_index = i_size >> PAGE_CACHE_SHIFT; if (page->index >= end_index) { - unsigned offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1); + /* + * The page straddles i_size. It must be zeroed out on each + * and every writepage invokation because it may be mmapped. + * "A file is mapped in multiples of the page size. For a file + * that is not a multiple of the page size, the remaining memory + * is zeroed when mapped, and writes to that region are not + * written out to the file." + */ + unsigned offset = i_size & (PAGE_CACHE_SIZE - 1); char *kaddr; if (page->index > end_index || !offset) @@ -502,8 +512,6 @@ mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, kunmap_atomic(kaddr, KM_USER0); } -page_is_mapped: - /* * This page will go to BIO. Do we need to send this BIO off first? */ @@ -519,6 +527,17 @@ alloc_new: } /* + * Must try to add the page before marking the buffer clean or + * the confused fail path above (OOM) will be very confused when + * it finds all bh marked clean (i.e. it will not write anything) + */ + length = first_unmapped << blkbits; + if (bio_add_page(bio, page, length, 0) < length) { + bio = mpage_bio_submit(WRITE, bio); + goto alloc_new; + } + + /* * OK, we have our BIO, so we can now mark the buffers clean. Make * sure to only clean buffers which we know we'll be writing. */ @@ -538,12 +557,6 @@ alloc_new: try_to_free_buffers(page); } - length = first_unmapped << blkbits; - if (bio_add_page(bio, page, length, 0) < length) { - bio = mpage_bio_submit(WRITE, bio); - goto alloc_new; - } - BUG_ON(PageWriteback(page)); set_page_writeback(page); unlock_page(page); diff --git a/fs/namei.c b/fs/namei.c index 3db4da5a2116ed..bbadcf782e92f7 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -279,6 +279,16 @@ void path_release(struct nameidata *nd) } /* + * umount() mustn't call path_release()/mntput() as that would clear + * mnt_expiry_mark + */ +void path_release_on_umount(struct nameidata *nd) +{ + dput(nd->dentry); + _mntput(nd->mnt); +} + +/* * Internal lookup() using the new generic dcache. * SMP-safe */ diff --git a/fs/namespace.c b/fs/namespace.c index f3ab6910fdf130..759527b1efe2ce 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -60,6 +60,7 @@ struct vfsmount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); + INIT_LIST_HEAD(&mnt->mnt_fslink); if (name) { int size = strlen(name)+1; char *newname = kmalloc(size, GFP_KERNEL); @@ -106,13 +107,9 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) EXPORT_SYMBOL(lookup_mnt); -static int check_mnt(struct vfsmount *mnt) +static inline int check_mnt(struct vfsmount *mnt) { - spin_lock(&vfsmount_lock); - while (mnt->mnt_parent != mnt) - mnt = mnt->mnt_parent; - spin_unlock(&vfsmount_lock); - return mnt == current->namespace->root; + return mnt->mnt_namespace == current->namespace; } static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) @@ -164,6 +161,14 @@ 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; + + /* stick the duplicate mount on the same expiry list + * as the original if that was on one */ + spin_lock(&vfsmount_lock); + if (!list_empty(&old->mnt_fslink)) + list_add(&mnt->mnt_fslink, &old->mnt_fslink); + spin_unlock(&vfsmount_lock); } return mnt; } @@ -346,6 +351,7 @@ void umount_tree(struct vfsmount *mnt) while (!list_empty(&kill)) { mnt = list_entry(kill.next, struct vfsmount, mnt_list); list_del_init(&mnt->mnt_list); + list_del_init(&mnt->mnt_fslink); if (mnt->mnt_parent == mnt) { spin_unlock(&vfsmount_lock); } else { @@ -369,6 +375,24 @@ static int do_umount(struct vfsmount *mnt, int flags) return retval; /* + * Allow userspace to request a mountpoint be expired rather than + * unmounting unconditionally. Unmount only happens if: + * (1) the mark is already set (the mark is cleared by mntput()) + * (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount] + */ + if (flags & MNT_EXPIRE) { + if (mnt == current->fs->rootmnt || + flags & (MNT_FORCE | MNT_DETACH)) + return -EINVAL; + + if (atomic_read(&mnt->mnt_count) != 2) + return -EBUSY; + + if (!xchg(&mnt->mnt_expiry_mark, 1)) + return -EAGAIN; + } + + /* * If we may have to abort operations to get out of this * mount, and they will themselves hold resources we must * allow the fs to do things. In the Unix tradition of @@ -461,7 +485,7 @@ asmlinkage long sys_umount(char __user * name, int flags) retval = do_umount(nd.mnt, flags); dput_and_out: - path_release(&nd); + path_release_on_umount(&nd); out: return retval; } @@ -618,6 +642,11 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) } if (mnt) { + /* stop bind mounts from expiring */ + spin_lock(&vfsmount_lock); + list_del_init(&mnt->mnt_fslink); + spin_unlock(&vfsmount_lock); + err = graft_tree(mnt, nd); if (err) { spin_lock(&vfsmount_lock); @@ -638,7 +667,8 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) * on it - tough luck. */ -static int do_remount(struct nameidata *nd,int flags,int mnt_flags,void *data) +static int do_remount(struct nameidata *nd, int flags, int mnt_flags, + void *data) { int err; struct super_block * sb = nd->mnt->mnt_sb; @@ -710,6 +740,10 @@ static int do_move_mount(struct nameidata *nd, char *old_name) detach_mnt(old_nd.mnt, &parent_nd); attach_mnt(old_nd.mnt, nd); + + /* if the mount is moved, it should no longer be expire + * automatically */ + list_del_init(&old_nd.mnt->mnt_fslink); out2: spin_unlock(&vfsmount_lock); out1: @@ -722,11 +756,14 @@ out: return err; } -static int do_add_mount(struct nameidata *nd, char *type, int flags, +/* + * create a new mount for userspace and request it to be added into the + * namespace's tree + */ +static int do_new_mount(struct nameidata *nd, char *type, int flags, int mnt_flags, char *name, void *data) { struct vfsmount *mnt; - int err; if (!type || !memchr(type, 0, PAGE_SIZE)) return -EINVAL; @@ -736,9 +773,20 @@ static int do_add_mount(struct nameidata *nd, char *type, int flags, return -EPERM; mnt = do_kern_mount(type, flags, name, data); - err = PTR_ERR(mnt); if (IS_ERR(mnt)) - goto out; + return PTR_ERR(mnt); + + return do_add_mount(mnt, nd, mnt_flags, NULL); +} + +/* + * add a mount into a namespace's mount tree + * - provide the option of adding the new mount to an expiration list + */ +int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, + int mnt_flags, struct list_head *fslist) +{ + int err; down_write(¤t->namespace->sem); /* Something was mounted here while we slept */ @@ -750,22 +798,143 @@ static int do_add_mount(struct nameidata *nd, char *type, int flags, /* Refuse the same filesystem on the same mount point */ err = -EBUSY; - if (nd->mnt->mnt_sb == mnt->mnt_sb && nd->mnt->mnt_root == nd->dentry) + if (nd->mnt->mnt_sb == newmnt->mnt_sb && + nd->mnt->mnt_root == nd->dentry) goto unlock; err = -EINVAL; - if (S_ISLNK(mnt->mnt_root->d_inode->i_mode)) + if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode)) goto unlock; - mnt->mnt_flags = mnt_flags; - err = graft_tree(mnt, nd); + newmnt->mnt_flags = mnt_flags; + err = graft_tree(newmnt, nd); + + if (err == 0 && fslist) { + /* add to the specified expiration list */ + spin_lock(&vfsmount_lock); + list_add_tail(&newmnt->mnt_fslink, fslist); + spin_unlock(&vfsmount_lock); + } + unlock: up_write(¤t->namespace->sem); - mntput(mnt); -out: + mntput(newmnt); return err; } +EXPORT_SYMBOL_GPL(do_add_mount); + +/* + * process a list of expirable mountpoints with the intent of discarding any + * mountpoints that aren't in use and haven't been touched since last we came + * here + */ +void mark_mounts_for_expiry(struct list_head *mounts) +{ + struct namespace *namespace; + struct list_head graveyard, *_p, *_n; + struct vfsmount *mnt; + + if (list_empty(mounts)) + return; + + INIT_LIST_HEAD(&graveyard); + + spin_lock(&vfsmount_lock); + + /* extract from the expiration list every vfsmount that matches the + * following criteria: + * - only referenced by its parent vfsmount + * - still marked for expiry (marked on the last call here; marks are + * cleared by mntput()) + */ + list_for_each_safe(_p, _n, mounts) { + mnt = list_entry(_p, struct vfsmount, mnt_fslink); + + if (!xchg(&mnt->mnt_expiry_mark, 1) || + atomic_read(&mnt->mnt_count) != 1) + continue; + + mntget(mnt); + list_move(&mnt->mnt_fslink, &graveyard); + } + + /* + * go through the vfsmounts we've just consigned to the graveyard to + * - check that they're still dead + * - delete the vfsmount from the appropriate namespace under lock + * - dispose of the corpse + */ + while (!list_empty(&graveyard)) { + mnt = list_entry(graveyard.next, struct vfsmount, mnt_fslink); + list_del_init(&mnt->mnt_fslink); + + /* don't do anything if the namespace is dead - all the + * vfsmounts from it are going away anyway */ + namespace = mnt->mnt_namespace; + if (!namespace || atomic_read(&namespace->count) <= 0) + continue; + get_namespace(namespace); + + spin_unlock(&vfsmount_lock); + down_write(&namespace->sem); + spin_lock(&vfsmount_lock); + + /* check that it is still dead: the count should now be 2 - as + * contributed by the vfsmount parent and the mntget above */ + if (atomic_read(&mnt->mnt_count) == 2) { + struct vfsmount *xdmnt; + struct dentry *xdentry; + + /* delete from the namespace */ + list_del_init(&mnt->mnt_list); + list_del_init(&mnt->mnt_child); + list_del_init(&mnt->mnt_hash); + mnt->mnt_mountpoint->d_mounted--; + + xdentry = mnt->mnt_mountpoint; + mnt->mnt_mountpoint = mnt->mnt_root; + xdmnt = mnt->mnt_parent; + mnt->mnt_parent = mnt; + + spin_unlock(&vfsmount_lock); + + mntput(xdmnt); + dput(xdentry); + + /* now lay it to rest if this was the last ref on the + * superblock */ + if (atomic_read(&mnt->mnt_sb->s_active) == 1) { + /* last instance - try to be smart */ + lock_kernel(); + DQUOT_OFF(mnt->mnt_sb); + acct_auto_close(mnt->mnt_sb); + unlock_kernel(); + } + + mntput(mnt); + } + else { + /* someone brought it back to life whilst we didn't + * have any locks held so return it to the expiration + * list */ + list_add_tail(&mnt->mnt_fslink, mounts); + spin_unlock(&vfsmount_lock); + } + + up_write(&namespace->sem); + + mntput(mnt); + put_namespace(namespace); + + spin_lock(&vfsmount_lock); + } + + spin_unlock(&vfsmount_lock); +} + +EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); + int copy_mount_options (const void __user *data, unsigned long *where) { int i; @@ -860,7 +1029,7 @@ long do_mount(char * dev_name, char * dir_name, char *type_page, else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); else - retval = do_add_mount(&nd, type_page, flags, mnt_flags, + retval = do_new_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page); dput_out: path_release(&nd); @@ -1185,6 +1354,7 @@ static void __init init_mount_tree(void) init_rwsem(&namespace->sem); list_add(&mnt->mnt_list, &namespace->list); namespace->root = mnt; + mnt->mnt_namespace = namespace; init_task.namespace = namespace; read_lock(&tasklist_lock); @@ -1252,8 +1422,15 @@ void __init mnt_init(unsigned long mempages) void __put_namespace(struct namespace *namespace) { + struct vfsmount *mnt; + down_write(&namespace->sem); spin_lock(&vfsmount_lock); + + list_for_each_entry(mnt, &namespace->list, mnt_list) { + mnt->mnt_namespace = NULL; + } + umount_tree(namespace->root); spin_unlock(&vfsmount_lock); up_write(&namespace->sem); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 3c57bc31f5213c..f7ac90d1596167 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1477,10 +1477,12 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file); if (err) goto out; - if (offset > ~(u32) 0) - goto out_close; - file.f_pos = offset; + offset = vfs_llseek(&file, offset, 0); + if (offset < 0) { + err = nfserrno((int)offset); + goto out_close; + } /* * Read the directory entries. This silly loop is necessary because @@ -1496,7 +1498,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, err = nfserrno(err); else err = cdp->err; - *offsetp = file.f_pos; + *offsetp = vfs_llseek(&file, 0, 1); if (err == nfserr_eof || err == nfserr_toosmall) err = nfs_ok; /* can still be found in ->err */ diff --git a/fs/read_write.c b/fs/read_write.c index f765a22b49cb50..481332642515c0 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -76,14 +76,12 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin) unlock_kernel(); return retval; } - EXPORT_SYMBOL(remote_llseek); loff_t no_llseek(struct file *file, loff_t offset, int origin) { return -ESPIPE; } - EXPORT_SYMBOL(no_llseek); loff_t default_llseek(struct file *file, loff_t offset, int origin) @@ -109,10 +107,9 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin) unlock_kernel(); return retval; } - EXPORT_SYMBOL(default_llseek); -static inline loff_t llseek(struct file *file, loff_t offset, int origin) +loff_t vfs_llseek(struct file *file, loff_t offset, int origin) { loff_t (*fn)(struct file *, loff_t, int); @@ -121,6 +118,7 @@ static inline loff_t llseek(struct file *file, loff_t offset, int origin) fn = file->f_op->llseek; return fn(file, offset, origin); } +EXPORT_SYMBOL(vfs_llseek); asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) { @@ -135,7 +133,7 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) retval = -EINVAL; if (origin <= 2) { - loff_t res = llseek(file, offset, origin); + loff_t res = vfs_llseek(file, offset, origin); retval = res; if (res != (loff_t)retval) retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ @@ -165,7 +163,7 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, if (origin > 2) goto out_putf; - offset = llseek(file, ((loff_t) offset_high << 32) | offset_low, + offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low, origin); retval = (int)offset; diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index 12fc56cac3a90d..b28f42e3bf08db 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -271,7 +271,7 @@ smb_file_sendfile(struct file *file, loff_t *ppos, status = smb_revalidate_inode(dentry); if (status) { - PARANOIA("%s/%s validation failed, error=%zd\n", + PARANOIA("%s/%s validation failed, error=%Zd\n", DENTRY_PATH(dentry), status); goto out; } diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index da0f1642689a85..8096d74922eca2 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c @@ -2309,16 +2309,14 @@ smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir, */ mask = param + 12; - mask_len = smb_encode_path(server, mask, SMB_MAXPATHLEN+1, dir, &star); - if (mask_len < 0) { - result = mask_len; + result = smb_encode_path(server, mask, SMB_MAXPATHLEN+1, dir, &star); + if (result <= 0) goto out_free; - } - mask_len--; /* mask_len is strlen, not #bytes */ + mask_len = result - 1; /* mask_len is strlen, not #bytes */ + result = 0; first = 1; VERBOSE("starting mask_len=%d, mask=%s\n", mask_len, mask); - result = 0; entries_seen = 2; ff_eos = 0; @@ -2464,8 +2462,6 @@ smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir, /* * Update the mask string for the next message. */ - if (mask_len < 0) - mask_len = 0; if (mask_len > 255) mask_len = 255; if (mask_len) diff --git a/fs/super.c b/fs/super.c index ca60ada578b55e..38c23bf558d498 100644 --- a/fs/super.c +++ b/fs/super.c @@ -793,6 +793,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) mnt->mnt_root = dget(sb->s_root); mnt->mnt_mountpoint = sb->s_root; mnt->mnt_parent = mnt; + mnt->mnt_namespace = current->namespace; up_write(&sb->s_umount); put_filesystem(type); return mnt; @@ -809,6 +810,8 @@ out: return (struct vfsmount *)sb; } +EXPORT_SYMBOL_GPL(do_kern_mount); + struct vfsmount *kern_mount(struct file_system_type *type) { return do_kern_mount(type->name, 0, type->name, NULL); diff --git a/fs/udf/super.c b/fs/udf/super.c index bbad84970ebbf6..54e1ecffa07a89 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -417,7 +417,7 @@ udf_parse_options(char *options, struct udf_options *uopt) case Opt_utf8: uopt->flags |= (1 << UDF_FLAG_UTF8); break; -#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE) +#ifdef CONFIG_UDF_NLS case Opt_iocharset: uopt->nls_map = load_nls(args[0].from); uopt->flags |= (1 << UDF_FLAG_NLS_MAP); @@ -1518,7 +1518,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) "utf8 cannot be combined with iocharset\n"); goto error_out; } -#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE) +#ifdef CONFIG_UDF_NLS if ((uopt.flags & (1 << UDF_FLAG_NLS_MAP)) && !uopt.nls_map) { uopt.nls_map = load_nls_default(); @@ -1668,7 +1668,7 @@ error_out: udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]); } } -#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE) +#ifdef CONFIG_UDF_NLS if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) unload_nls(UDF_SB(sb)->s_nls_map); #endif @@ -1746,7 +1746,7 @@ udf_put_super(struct super_block *sb) udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]); } } -#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE) +#ifdef CONFIG_UDF_NLS if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) unload_nls(UDF_SB(sb)->s_nls_map); #endif |