diff options
Diffstat (limited to 'fs')
71 files changed, 642 insertions, 459 deletions
diff --git a/fs/9p/error.c b/fs/9p/error.c index fee5d19..834cb17 100644 --- a/fs/9p/error.c +++ b/fs/9p/error.c @@ -33,6 +33,7 @@ #include <linux/list.h> #include <linux/jhash.h> +#include <linux/string.h> #include "debug.h" #include "error.h" diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c index 01e26f0..a93c2bf 100644 --- a/fs/9p/trans_sock.c +++ b/fs/9p/trans_sock.c @@ -269,8 +269,7 @@ static void v9fs_sock_close(struct v9fs_transport *trans) dprintk(DEBUG_TRANS, "socket closed\n"); } - if (ts) - kfree(ts); + kfree(ts); trans->priv = NULL; } diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 82303f3..418c374 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -266,7 +266,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->remotename = __getname(); if (!v9ses->remotename) { - putname(v9ses->name); + __putname(v9ses->name); return -ENOMEM; } @@ -411,8 +411,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) if (v9ses->transport) v9ses->transport->close(v9ses->transport); - putname(v9ses->name); - putname(v9ses->remotename); + __putname(v9ses->name); + __putname(v9ses->remotename); } /** diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 2b696ae..be72881 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1105,7 +1105,7 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer, } } - putname(link); + __putname(link); return retval; } @@ -1129,7 +1129,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) len = v9fs_readlink(dentry, link, strlen(link)); if (len < 0) { - putname(link); + __putname(link); link = ERR_PTR(len); } else link[len] = 0; @@ -1152,7 +1152,7 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s); if (!IS_ERR(s)) - putname(s); + __putname(s); } /** @@ -1228,7 +1228,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, FreeMem: kfree(mistat); kfree(fcall); - putname(symname); + __putname(symname); return retval; } @@ -1319,7 +1319,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) FreeMem: kfree(mistat); kfree(fcall); - putname(symname); + __putname(symname); return retval; } @@ -898,6 +898,7 @@ config AFFS_FS config HFS_FS tristate "Apple Macintosh file system support (EXPERIMENTAL)" depends on EXPERIMENTAL + select NLS help If you say Y here, you will be able to mount Macintosh-formatted floppy disks and hard drive partitions with full read-write access. diff --git a/fs/affs/file.c b/fs/affs/file.c index 6744924..f72fb77 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -22,14 +22,13 @@ static int affs_grow_extcache(struct inode *inode, u32 lc_idx); static struct buffer_head *affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext); static inline struct buffer_head *affs_get_extblock(struct inode *inode, u32 ext); static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext); -static ssize_t affs_file_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos); static int affs_file_open(struct inode *inode, struct file *filp); static int affs_file_release(struct inode *inode, struct file *filp); struct file_operations affs_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, - .write = affs_file_write, + .write = generic_file_write, .mmap = generic_file_mmap, .open = affs_file_open, .release = affs_file_release, @@ -473,21 +472,6 @@ affs_getemptyblk_ino(struct inode *inode, int block) return ERR_PTR(err); } -static ssize_t -affs_file_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t retval; - - retval = generic_file_write (file, buf, count, ppos); - if (retval >0) { - struct inode *inode = file->f_dentry->d_inode; - inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; - mark_inode_dirty(inode); - } - return retval; -} - static int affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to) { diff --git a/fs/affs/super.c b/fs/affs/super.c index 9c30807..aaec015 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -35,8 +35,7 @@ affs_put_super(struct super_block *sb) mark_buffer_dirty(sbi->s_root_bh); } - if (sbi->s_prefix) - kfree(sbi->s_prefix); + kfree(sbi->s_prefix); affs_free_bitmap(sb); affs_brelse(sbi->s_root_bh); kfree(sbi); @@ -198,10 +197,9 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s *mount_opts |= SF_MUFS; break; case Opt_prefix: - if (*prefix) { /* Free any previous prefix */ - kfree(*prefix); - *prefix = NULL; - } + /* Free any previous prefix */ + kfree(*prefix); + *prefix = NULL; *prefix = match_strdup(&args[0]); if (!*prefix) return 0; @@ -462,11 +460,9 @@ got_root: out_error: if (root_inode) iput(root_inode); - if (sbi->s_bitmap) - kfree(sbi->s_bitmap); + kfree(sbi->s_bitmap); affs_brelse(root_bh); - if (sbi->s_prefix) - kfree(sbi->s_prefix); + kfree(sbi->s_prefix); kfree(sbi); sb->s_fs_info = NULL; return -EINVAL; diff --git a/fs/afs/file.c b/fs/afs/file.c index 4975c9c..150b192 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -31,24 +31,10 @@ static int afs_file_readpage(struct file *file, struct page *page); static int afs_file_invalidatepage(struct page *page, unsigned long offset); static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); -static ssize_t afs_file_write(struct file *file, const char __user *buf, - size_t size, loff_t *off); - struct inode_operations afs_file_inode_operations = { .getattr = afs_inode_getattr, }; -struct file_operations afs_file_file_operations = { - .read = generic_file_read, - .write = afs_file_write, - .mmap = generic_file_mmap, -#if 0 - .open = afs_file_open, - .release = afs_file_release, - .fsync = afs_file_fsync, -#endif -}; - struct address_space_operations afs_fs_aops = { .readpage = afs_file_readpage, .sync_page = block_sync_page, @@ -59,22 +45,6 @@ struct address_space_operations afs_fs_aops = { /*****************************************************************************/ /* - * AFS file write - */ -static ssize_t afs_file_write(struct file *file, const char __user *buf, - size_t size, loff_t *off) -{ - struct afs_vnode *vnode; - - vnode = AFS_FS_I(file->f_dentry->d_inode); - if (vnode->flags & AFS_VNODE_DELETED) - return -ESTALE; - - return -EIO; -} /* end afs_file_write() */ - -/*****************************************************************************/ -/* * deal with notification that a page was read from the cache */ #ifdef AFS_CACHING_SUPPORT @@ -295,8 +265,7 @@ static int afs_file_releasepage(struct page *page, gfp_t gfp_flags) set_page_private(page, 0); ClearPagePrivate(page); - if (pageio) - kfree(pageio); + kfree(pageio); } _leave(" = 0"); diff --git a/fs/afs/inode.c b/fs/afs/inode.c index c476fde..4ebb30a 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -49,7 +49,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode) case AFS_FTYPE_FILE: inode->i_mode = S_IFREG | vnode->status.mode; inode->i_op = &afs_file_inode_operations; - inode->i_fop = &afs_file_file_operations; + inode->i_fop = &generic_ro_fops; break; case AFS_FTYPE_DIR: inode->i_mode = S_IFDIR | vnode->status.mode; diff --git a/fs/afs/internal.h b/fs/afs/internal.h index f09860b..ab8f87c 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -71,7 +71,6 @@ extern struct file_operations afs_dir_file_operations; */ extern struct address_space_operations afs_fs_aops; extern struct inode_operations afs_file_inode_operations; -extern struct file_operations afs_file_file_operations; #ifdef AFS_CACHING_SUPPORT extern int afs_cache_get_page_cookie(struct page *page, @@ -42,8 +42,9 @@ #endif /*------ sysctl variables----*/ -atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ -unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ +static DEFINE_SPINLOCK(aio_nr_lock); +unsigned long aio_nr; /* current system wide number of aio requests */ +unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ /*----end sysctl variables---*/ static kmem_cache_t *kiocb_cachep; @@ -208,7 +209,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) return ERR_PTR(-EINVAL); } - if (nr_events > aio_max_nr) + if ((unsigned long)nr_events > aio_max_nr) return ERR_PTR(-EAGAIN); ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL); @@ -233,8 +234,14 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) goto out_freectx; /* limit the number of system wide aios */ - atomic_add(ctx->max_reqs, &aio_nr); /* undone by __put_ioctx */ - if (unlikely(atomic_read(&aio_nr) > aio_max_nr)) + spin_lock(&aio_nr_lock); + if (aio_nr + ctx->max_reqs > aio_max_nr || + aio_nr + ctx->max_reqs < aio_nr) + ctx->max_reqs = 0; + else + aio_nr += ctx->max_reqs; + spin_unlock(&aio_nr_lock); + if (ctx->max_reqs == 0) goto out_cleanup; /* now link into global list. kludge. FIXME */ @@ -248,8 +255,6 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) return ctx; out_cleanup: - atomic_sub(ctx->max_reqs, &aio_nr); - ctx->max_reqs = 0; /* prevent __put_ioctx from sub'ing aio_nr */ __put_ioctx(ctx); return ERR_PTR(-EAGAIN); @@ -374,7 +379,12 @@ void fastcall __put_ioctx(struct kioctx *ctx) pr_debug("__put_ioctx: freeing %p\n", ctx); kmem_cache_free(kioctx_cachep, ctx); - atomic_sub(nr_events, &aio_nr); + if (nr_events) { + spin_lock(&aio_nr_lock); + BUG_ON(aio_nr - nr_events > aio_nr); + aio_nr -= nr_events; + spin_unlock(&aio_nr_lock); + } } /* aio_get_req @@ -1258,8 +1268,9 @@ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp) goto out; ret = -EINVAL; - if (unlikely(ctx || (int)nr_events <= 0)) { - pr_debug("EINVAL: io_setup: ctx or nr_events > max\n"); + if (unlikely(ctx || nr_events == 0)) { + pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n", + ctx, nr_events); goto out; } diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c index 1fcaa15..633f628 100644 --- a/fs/autofs/waitq.c +++ b/fs/autofs/waitq.c @@ -150,10 +150,8 @@ int autofs_wait(struct autofs_sb_info *sbi, struct qstr *name) if ( sbi->catatonic ) { /* We might have slept, so check again for catatonic mode */ wq->status = -ENOENT; - if ( wq->name ) { - kfree(wq->name); - wq->name = NULL; - } + kfree(wq->name); + wq->name = NULL; } if ( wq->name ) { diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 0a3c05d..818b37b 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -22,10 +22,8 @@ static void ino_lnkfree(struct autofs_info *ino) { - if (ino->u.symlink) { - kfree(ino->u.symlink); - ino->u.symlink = NULL; - } + kfree(ino->u.symlink); + ino->u.symlink = NULL; } struct autofs_info *autofs4_init_ino(struct autofs_info *ino, diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 3df8628..394ff36 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -243,10 +243,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, if ( sbi->catatonic ) { /* We might have slept, so check again for catatonic mode */ wq->status = -ENOENT; - if ( wq->name ) { - kfree(wq->name); - wq->name = NULL; - } + kfree(wq->name); + wq->name = NULL; } if ( wq->name ) { diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index e0a6025..2d365cb 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -73,12 +73,6 @@ static struct inode_operations befs_dir_inode_operations = { .lookup = befs_lookup, }; -static struct file_operations befs_file_operations = { - .llseek = default_llseek, - .read = generic_file_read, - .mmap = generic_file_readonly_mmap, -}; - static struct address_space_operations befs_aops = { .readpage = befs_readpage, .sync_page = block_sync_page, @@ -398,7 +392,7 @@ befs_read_inode(struct inode *inode) inode->i_mapping->a_ops = &befs_aops; if (S_ISREG(inode->i_mode)) { - inode->i_fop = &befs_file_operations; + inode->i_fop = &generic_ro_fops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &befs_dir_inode_operations; inode->i_fop = &befs_dir_operations; @@ -731,20 +725,16 @@ parse_options(char *options, befs_mount_options * opts) static void befs_put_super(struct super_block *sb) { - if (BEFS_SB(sb)->mount_opts.iocharset) { - kfree(BEFS_SB(sb)->mount_opts.iocharset); - BEFS_SB(sb)->mount_opts.iocharset = NULL; - } + kfree(BEFS_SB(sb)->mount_opts.iocharset); + BEFS_SB(sb)->mount_opts.iocharset = NULL; if (BEFS_SB(sb)->nls) { unload_nls(BEFS_SB(sb)->nls); BEFS_SB(sb)->nls = NULL; } - if (sb->s_fs_info) { - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; - } + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; return; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 6fa6adc..f36f221 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1006,8 +1006,7 @@ out_free_dentry: if (interpreter) fput(interpreter); out_free_interp: - if (elf_interpreter) - kfree(elf_interpreter); + kfree(elf_interpreter); out_free_file: sys_close(elf_exec_fileno); out_free_fh: diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index dda87c4..e0344f6 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -411,16 +411,11 @@ error: allow_write_access(interpreter); fput(interpreter); } - if (interpreter_name) - kfree(interpreter_name); - if (exec_params.phdrs) - kfree(exec_params.phdrs); - if (exec_params.loadmap) - kfree(exec_params.loadmap); - if (interp_params.phdrs) - kfree(interp_params.phdrs); - if (interp_params.loadmap) - kfree(interp_params.loadmap); + kfree(interpreter_name); + kfree(exec_params.phdrs); + kfree(exec_params.loadmap); + kfree(interp_params.phdrs); + kfree(interp_params.loadmap); return retval; /* unrecoverable error - kill the process */ diff --git a/fs/buffer.c b/fs/buffer.c index 35fa349..5287be1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -396,7 +396,7 @@ asmlinkage long sys_fdatasync(unsigned int fd) * private_lock is contended then so is mapping->tree_lock). */ static struct buffer_head * -__find_get_block_slow(struct block_device *bdev, sector_t block, int unused) +__find_get_block_slow(struct block_device *bdev, sector_t block) { struct inode *bd_inode = bdev->bd_inode; struct address_space *bd_mapping = bd_inode->i_mapping; @@ -1438,7 +1438,7 @@ __find_get_block(struct block_device *bdev, sector_t block, int size) struct buffer_head *bh = lookup_bh_lru(bdev, block, size); if (bh == NULL) { - bh = __find_get_block_slow(bdev, block, size); + bh = __find_get_block_slow(bdev, block); if (bh) bh_lru_install(bh); } @@ -1705,7 +1705,7 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block) might_sleep(); - old_bh = __find_get_block_slow(bdev, block, 0); + old_bh = __find_get_block_slow(bdev, block); if (old_bh) { clear_buffer_dirty(old_bh); wait_on_buffer(old_bh); diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 98539e2..086ae8f 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -553,8 +553,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, *(oid + 3))); rc = compare_oid(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN); - if(oid) - kfree(oid); + kfree(oid); if (rc) use_ntlmssp = TRUE; } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d74367a..450ab75 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1265,8 +1265,7 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, the helper that resolves tcp names, mount to it, try to tcon to it unmount it if fail */ - if(referrals) - kfree(referrals); + kfree(referrals); return rc; } @@ -1535,10 +1534,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, memset(&volume_info,0,sizeof(struct smb_vol)); if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1551,10 +1548,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifserror("No username specified "); /* In userspace mount helper we can get user name from alternate locations such as env variables and files on disk */ - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1573,10 +1568,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if(rc <= 0) { /* we failed translating address */ - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1587,19 +1580,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } else if (volume_info.UNCip){ /* BB using ip addr as server name connect to the DFS root below */ cERROR(1,("Connecting to DFS root not implemented yet")); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } else /* which servers DFS root would we conect to */ { cERROR(1, ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1612,10 +1601,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->local_nls = load_nls(volume_info.iocharset); if(cifs_sb->local_nls == NULL) { cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -ELIBACC; } @@ -1630,10 +1617,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, &sin_server6.sin6_addr, volume_info.username, &srvTcp); else { - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1654,10 +1639,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ("Error connecting to IPv4 socket. Aborting operation")); if(csocket != NULL) sock_release(csocket); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return rc; } @@ -1666,10 +1649,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (srvTcp == NULL) { rc = -ENOMEM; sock_release(csocket); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return rc; } else { @@ -1692,10 +1673,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if(rc < 0) { rc = -ENOMEM; sock_release(csocket); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return rc; } @@ -1710,8 +1689,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (existingCifsSes) { pSesInfo = existingCifsSes; cFYI(1, ("Existing smb sess found ")); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.password); /* volume_info.UNC freed at end of function */ } else if (!rc) { cFYI(1, ("Existing smb sess not found ")); @@ -1741,8 +1719,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if(!rc) atomic_inc(&srvTcp->socketUseCount); } else - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.password); } /* search for existing tcon to this server share */ @@ -1821,8 +1798,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, "", cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if(volume_info.UNC) - kfree(volume_info.UNC); + kfree(volume_info.UNC); FreeXid(xid); return -ENODEV; } else { @@ -1925,8 +1901,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, (in which case it is not needed anymore) but when new sesion is created the password ptr is put in the new session structure (in which case the password will be freed at unmount time) */ - if(volume_info.UNC) - kfree(volume_info.UNC); + kfree(volume_info.UNC); FreeXid(xid); return rc; } @@ -3283,8 +3258,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, if ((bcc_ptr + (2 * length)) - pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { - if(tcon->nativeFileSystem) - kfree(tcon->nativeFileSystem); + kfree(tcon->nativeFileSystem); tcon->nativeFileSystem = kzalloc(length + 2, GFP_KERNEL); cifs_strfromUCS_le(tcon->nativeFileSystem, @@ -3301,8 +3275,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, if ((bcc_ptr + length) - pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { - if(tcon->nativeFileSystem) - kfree(tcon->nativeFileSystem); + kfree(tcon->nativeFileSystem); tcon->nativeFileSystem = kzalloc(length + 1, GFP_KERNEL); strncpy(tcon->nativeFileSystem, bcc_ptr, diff --git a/fs/cifs/link.c b/fs/cifs/link.c index b43e071..0f99aae 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -84,10 +84,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, cifsInode->time = 0; /* will force revalidate to go get info when needed */ cifs_hl_exit: - if (fromName) - kfree(fromName); - if (toName) - kfree(toName); + kfree(fromName); + kfree(toName); FreeXid(xid); return rc; } @@ -206,8 +204,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) } } - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); return rc; } @@ -253,8 +250,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) len = buflen; tmpbuffer = kmalloc(len,GFP_KERNEL); if(tmpbuffer == NULL) { - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); return -ENOMEM; } @@ -303,8 +299,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) strncpy(tmpbuffer, referrals, len-1); } } - if(referrals) - kfree(referrals); + kfree(referrals); kfree(tmp_path); } /* BB add code like else decode referrals then memcpy to @@ -323,12 +318,8 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) rc)); } - if (tmpbuffer) { - kfree(tmpbuffer); - } - if (full_path) { - kfree(full_path); - } + kfree(tmpbuffer); + kfree(full_path); FreeXid(xid); return rc; } diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index eba1de9..34a0669 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -98,14 +98,10 @@ sesInfoFree(struct cifsSesInfo *buf_to_free) atomic_dec(&sesInfoAllocCount); list_del(&buf_to_free->cifsSessionList); write_unlock(&GlobalSMBSeslock); - if (buf_to_free->serverOS) - kfree(buf_to_free->serverOS); - if (buf_to_free->serverDomain) - kfree(buf_to_free->serverDomain); - if (buf_to_free->serverNOS) - kfree(buf_to_free->serverNOS); - if (buf_to_free->password) - kfree(buf_to_free->password); + kfree(buf_to_free->serverOS); + kfree(buf_to_free->serverDomain); + kfree(buf_to_free->serverNOS); + kfree(buf_to_free->password); kfree(buf_to_free); } @@ -144,8 +140,7 @@ tconInfoFree(struct cifsTconInfo *buf_to_free) atomic_dec(&tconInfoAllocCount); list_del(&buf_to_free->cifsConnectionList); write_unlock(&GlobalSMBSeslock); - if (buf_to_free->nativeFileSystem) - kfree(buf_to_free->nativeFileSystem); + kfree(buf_to_free->nativeFileSystem); kfree(buf_to_free); } diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index c1e02ef..f375f87 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -87,8 +87,7 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } remove_ea_exit: - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); #endif return rc; @@ -132,8 +131,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, returns as xattrs */ if(value_size > MAX_EA_VALUE_SIZE) { cFYI(1,("size of EA value too large")); - if(full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); return -EOPNOTSUPP; } @@ -195,8 +193,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, } set_ea_exit: - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); #endif return rc; @@ -298,8 +295,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, rc = -EOPNOTSUPP; get_ea_exit: - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); #endif return rc; @@ -345,8 +341,7 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); #endif return rc; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 43dbcb0..4909754 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -2235,7 +2235,8 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) if (err) err = -EFAULT; -out: if (karg) kfree(karg); +out: + kfree(karg); return err; } diff --git a/fs/dcache.c b/fs/dcache.c index e90512e..17e43913 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -644,7 +644,7 @@ void shrink_dcache_parent(struct dentry * parent) * * Prune the dentries that are anonymous * - * parsing d_hash list does not hlist_for_each_rcu() as it + * parsing d_hash list does not hlist_for_each_entry_rcu() as it * done under dcache_lock. * */ @@ -1043,15 +1043,13 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) struct hlist_head *head = d_hash(parent,hash); struct dentry *found = NULL; struct hlist_node *node; + struct dentry *dentry; rcu_read_lock(); - hlist_for_each_rcu(node, head) { - struct dentry *dentry; + hlist_for_each_entry_rcu(dentry, node, head, d_hash) { struct qstr *qstr; - dentry = hlist_entry(node, struct dentry, d_hash); - if (dentry->d_name.hash != hash) continue; if (dentry->d_parent != parent) @@ -1123,7 +1121,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent) spin_lock(&dcache_lock); base = d_hash(dparent, dentry->d_name.hash); hlist_for_each(lhp,base) { - /* hlist_for_each_rcu() not required for d_hash list + /* hlist_for_each_entry_rcu() not required for d_hash list * as it is parsed under dcache_lock */ if (dentry == hlist_entry(lhp, struct dentry, d_hash)) { diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 8b679b6..1274422 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2738,10 +2738,8 @@ static int devfsd_close(struct inode *inode, struct file *file) entry = fs_info->devfsd_first_event; fs_info->devfsd_first_event = NULL; fs_info->devfsd_last_event = NULL; - if (fs_info->devfsd_info) { - kfree(fs_info->devfsd_info); - fs_info->devfsd_info = NULL; - } + kfree(fs_info->devfsd_info); + fs_info->devfsd_info = NULL; spin_unlock(&fs_info->devfsd_buffer_lock); fs_info->devfsd_pgrp = 0; fs_info->devfsd_task = NULL; @@ -77,6 +77,7 @@ #include <linux/kmod.h> #include <linux/namei.h> #include <linux/buffer_head.h> +#include <linux/quotaops.h> #include <asm/uaccess.h> @@ -48,6 +48,7 @@ #include <linux/syscalls.h> #include <linux/rmap.h> #include <linux/acct.h> +#include <linux/cn_proc.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -1096,6 +1097,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) fput(bprm->file); bprm->file = NULL; current->did_exec = 1; + proc_exec_connector(current); return retval; } read_lock(&binfmt_lock); @@ -1509,7 +1511,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) goto close_fail; if (!file->f_op->write) goto close_fail; - if (do_truncate(file->f_dentry, 0) != 0) + if (do_truncate(file->f_dentry, 0, file) != 0) goto close_fail; retval = binfmt->core_dump(signr, regs, file); diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 213148c..6af2f41 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -194,8 +194,7 @@ ext2_get_acl(struct inode *inode, int type) acl = NULL; else acl = ERR_PTR(retval); - if (value) - kfree(value); + kfree(value); if (!IS_ERR(acl)) { switch(type) { @@ -262,8 +261,7 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) error = ext2_xattr_set(inode, name_index, "", value, size, 0); - if (value) - kfree(value); + kfree(value); if (!error) { switch(type) { case ACL_TYPE_ACCESS: diff --git a/fs/file_table.c b/fs/file_table.c index 4dc2055..c3a5e2f 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -35,7 +35,7 @@ static DEFINE_SPINLOCK(filp_count_lock); * context and must be fully threaded - use a local spinlock * to protect files_stat.nr_files */ -void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags) +void filp_ctor(void *objp, struct kmem_cache *cachep, unsigned long cflags) { if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { @@ -46,7 +46,7 @@ void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags) } } -void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags) +void filp_dtor(void *objp, struct kmem_cache *cachep, unsigned long dflags) { unsigned long flags; spin_lock_irqsave(&filp_count_lock, flags); diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index d8be917..927acf7 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -38,7 +38,7 @@ */ -struct kmem_cache_s; +struct kmem_cache; struct super_block; struct vxfs_inode_info; struct inode; @@ -51,7 +51,7 @@ extern daddr_t vxfs_bmap1(struct inode *, long); extern int vxfs_read_fshead(struct super_block *); /* vxfs_inode.c */ -extern struct kmem_cache_s *vxfs_inode_cachep; +extern struct kmem_cache *vxfs_inode_cachep; extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); extern struct inode * vxfs_get_fake_inode(struct super_block *, struct vxfs_inode_info *); diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 9672d2f..f544aae 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -46,15 +46,6 @@ extern struct address_space_operations vxfs_immed_aops; extern struct inode_operations vxfs_immed_symlink_iops; -static struct file_operations vxfs_file_operations = { - .open = generic_file_open, - .llseek = generic_file_llseek, - .read = generic_file_read, - .mmap = generic_file_mmap, - .sendfile = generic_file_sendfile, -}; - - kmem_cache_t *vxfs_inode_cachep; @@ -318,7 +309,7 @@ vxfs_read_inode(struct inode *ip) aops = &vxfs_aops; if (S_ISREG(ip->i_mode)) { - ip->i_fop = &vxfs_file_operations; + ip->i_fop = &generic_ro_fops; ip->i_mapping->a_ops = aops; } else if (S_ISDIR(ip->i_mode)) { ip->i_op = &vxfs_dir_inode_ops; diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c27f8d4..785c721 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -562,7 +562,7 @@ int write_inode_now(struct inode *inode, int sync) }; if (!mapping_cap_writeback_dirty(inode->i_mapping)) - return 0; + wbc.nr_to_write = 0; might_sleep(); spin_lock(&inode_lock); @@ -606,7 +606,7 @@ EXPORT_SYMBOL(sync_inode); * O_SYNC flag set, to flush dirty writes to disk. * * @what is a bitmask, specifying which part of the inode's data should be - * written and waited upon: + * written and waited upon. * * OSYNC_DATA: i_mapping's dirty data * OSYNC_METADATA: the buffers at i_mapping->private_list @@ -672,8 +672,9 @@ int writeback_acquire(struct backing_dev_info *bdi) /** * writeback_in_progress: determine whether there is writeback in progress - * against a backing device. * @bdi: the device's backing_dev_info structure. + * + * Determine whether there is writeback in progress against a backing device. */ int writeback_in_progress(struct backing_dev_info *bdi) { diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a6f90a6..8f873e6 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -184,6 +184,13 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) fuse_putback_request() */ for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) up(&fc->outstanding_sem); + } else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { + /* Special case for failed iget in CREATE */ + u64 nodeid = req->in.h.nodeid; + __fuse_get_request(req); + fuse_reset_request(req); + fuse_send_forget(fc, req, nodeid, 1); + putback = 0; } if (putback) fuse_putback_request(fc, req); diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 70dba72..c045cc7 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -13,6 +13,7 @@ #include <linux/gfp.h> #include <linux/sched.h> #include <linux/namei.h> +#include <linux/mount.h> static inline unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) @@ -134,6 +135,101 @@ static void fuse_invalidate_entry(struct dentry *entry) entry->d_time = jiffies - 1; } +static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, + struct nameidata *nd) +{ + int err; + struct inode *inode; + struct fuse_conn *fc = get_fuse_conn(dir); + struct fuse_req *req; + struct fuse_open_in inarg; + struct fuse_open_out outopen; + struct fuse_entry_out outentry; + struct fuse_inode *fi; + struct fuse_file *ff; + struct file *file; + int flags = nd->intent.open.flags - 1; + + err = -ENOSYS; + if (fc->no_create) + goto out; + + err = -ENAMETOOLONG; + if (entry->d_name.len > FUSE_NAME_MAX) + goto out; + + err = -EINTR; + req = fuse_get_request(fc); + if (!req) + goto out; + + ff = fuse_file_alloc(); + if (!ff) + goto out_put_request; + + flags &= ~O_NOCTTY; + memset(&inarg, 0, sizeof(inarg)); + inarg.flags = flags; + inarg.mode = mode; + req->in.h.opcode = FUSE_CREATE; + req->in.h.nodeid = get_node_id(dir); + req->inode = dir; + req->in.numargs = 2; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + req->in.args[1].size = entry->d_name.len + 1; + req->in.args[1].value = entry->d_name.name; + req->out.numargs = 2; + req->out.args[0].size = sizeof(outentry); + req->out.args[0].value = &outentry; + req->out.args[1].size = sizeof(outopen); + req->out.args[1].value = &outopen; + request_send(fc, req); + err = req->out.h.error; + if (err) { + if (err == -ENOSYS) + fc->no_create = 1; + goto out_free_ff; + } + + err = -EIO; + if (!S_ISREG(outentry.attr.mode)) + goto out_free_ff; + + inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, + &outentry.attr); + err = -ENOMEM; + if (!inode) { + flags &= ~(O_CREAT | O_EXCL | O_TRUNC); + ff->fh = outopen.fh; + fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0); + goto out_put_request; + } + fuse_put_request(fc, req); + entry->d_time = time_to_jiffies(outentry.entry_valid, + outentry.entry_valid_nsec); + fi = get_fuse_inode(inode); + fi->i_time = time_to_jiffies(outentry.attr_valid, + outentry.attr_valid_nsec); + + d_instantiate(entry, inode); + file = lookup_instantiate_filp(nd, entry, generic_file_open); + if (IS_ERR(file)) { + ff->fh = outopen.fh; + fuse_send_release(fc, ff, outentry.nodeid, inode, flags, 0); + return PTR_ERR(file); + } + fuse_finish_open(inode, file, ff, &outopen); + return 0; + + out_free_ff: + fuse_file_free(ff); + out_put_request: + fuse_put_request(fc, req); + out: + return err; +} + static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, struct inode *dir, struct dentry *entry, int mode) @@ -208,6 +304,12 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, static int fuse_create(struct inode *dir, struct dentry *entry, int mode, struct nameidata *nd) { + if (nd && (nd->flags & LOOKUP_CREATE)) { + int err = fuse_create_open(dir, entry, mode, nd); + if (err != -ENOSYS) + return err; + /* Fall back on mknod */ + } return fuse_mknod(dir, entry, mode, 0); } @@ -461,6 +563,38 @@ static int fuse_revalidate(struct dentry *entry) return fuse_do_getattr(inode); } +static int fuse_access(struct inode *inode, int mask) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_req *req; + struct fuse_access_in inarg; + int err; + + if (fc->no_access) + return 0; + + req = fuse_get_request(fc); + if (!req) + return -EINTR; + + memset(&inarg, 0, sizeof(inarg)); + inarg.mask = mask; + req->in.h.opcode = FUSE_ACCESS; + req->in.h.nodeid = get_node_id(inode); + req->inode = inode; + req->in.numargs = 1; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + request_send(fc, req); + err = req->out.h.error; + fuse_put_request(fc, req); + if (err == -ENOSYS) { + fc->no_access = 1; + err = 0; + } + return err; +} + static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) { struct fuse_conn *fc = get_fuse_conn(inode); @@ -491,11 +625,11 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) return err; } else { int mode = inode->i_mode; - if ((mask & MAY_WRITE) && IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) return -EACCES; + + if (nd && (nd->flags & LOOKUP_ACCESS)) + return fuse_access(inode, mask); return 0; } } @@ -629,29 +763,29 @@ static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) return file ? fuse_fsync_common(file, de, datasync, 1) : 0; } -static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr) +static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) { unsigned ivalid = iattr->ia_valid; - unsigned fvalid = 0; - - memset(fattr, 0, sizeof(*fattr)); if (ivalid & ATTR_MODE) - fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode; + arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; if (ivalid & ATTR_UID) - fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid; + arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid; if (ivalid & ATTR_GID) - fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid; + arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid; if (ivalid & ATTR_SIZE) - fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size; + arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; /* You can only _set_ these together (they may change by themselves) */ if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) { - fvalid |= FATTR_ATIME | FATTR_MTIME; - fattr->atime = iattr->ia_atime.tv_sec; - fattr->mtime = iattr->ia_mtime.tv_sec; + arg->valid |= FATTR_ATIME | FATTR_MTIME; + arg->atime = iattr->ia_atime.tv_sec; + arg->mtime = iattr->ia_mtime.tv_sec; + } + if (ivalid & ATTR_FILE) { + struct fuse_file *ff = iattr->ia_file->private_data; + arg->valid |= FATTR_FH; + arg->fh = ff->fh; } - - return fvalid; } static int fuse_setattr(struct dentry *entry, struct iattr *attr) @@ -686,7 +820,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) return -EINTR; memset(&inarg, 0, sizeof(inarg)); - inarg.valid = iattr_to_fattr(attr, &inarg.attr); + iattr_to_fattr(attr, &inarg); req->in.h.opcode = FUSE_SETATTR; req->in.h.nodeid = get_node_id(inode); req->inode = inode; @@ -735,7 +869,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) { struct inode *inode; - int err = fuse_lookup_iget(dir, entry, &inode); + int err; + + err = fuse_lookup_iget(dir, entry, &inode); if (err) return ERR_PTR(err); if (inode && S_ISDIR(inode->i_mode)) { diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 657ab11..2ca8614 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -14,11 +14,69 @@ static struct file_operations fuse_direct_io_file_operations; -int fuse_open_common(struct inode *inode, struct file *file, int isdir) +static int fuse_send_open(struct inode *inode, struct file *file, int isdir, + struct fuse_open_out *outargp) { struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_req *req; struct fuse_open_in inarg; + struct fuse_req *req; + int err; + + req = fuse_get_request(fc); + if (!req) + return -EINTR; + + memset(&inarg, 0, sizeof(inarg)); + inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); + req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; + req->in.h.nodeid = get_node_id(inode); + req->inode = inode; + req->in.numargs = 1; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + req->out.numargs = 1; + req->out.args[0].size = sizeof(*outargp); + req->out.args[0].value = outargp; + request_send(fc, req); + err = req->out.h.error; + fuse_put_request(fc, req); + + return err; +} + +struct fuse_file *fuse_file_alloc(void) +{ + struct fuse_file *ff; + ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); + if (ff) { + ff->release_req = fuse_request_alloc(); + if (!ff->release_req) { + kfree(ff); + ff = NULL; + } + } + return ff; +} + +void fuse_file_free(struct fuse_file *ff) +{ + fuse_request_free(ff->release_req); + kfree(ff); +} + +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg) +{ + if (outarg->open_flags & FOPEN_DIRECT_IO) + file->f_op = &fuse_direct_io_file_operations; + if (!(outarg->open_flags & FOPEN_KEEP_CACHE)) + invalidate_inode_pages(inode->i_mapping); + ff->fh = outarg->fh; + file->private_data = ff; +} + +int fuse_open_common(struct inode *inode, struct file *file, int isdir) +{ struct fuse_open_out outarg; struct fuse_file *ff; int err; @@ -34,73 +92,53 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) /* If opening the root node, no lookup has been performed on it, so the attributes must be refreshed */ if (get_node_id(inode) == FUSE_ROOT_ID) { - int err = fuse_do_getattr(inode); + err = fuse_do_getattr(inode); if (err) return err; } - req = fuse_get_request(fc); - if (!req) - return -EINTR; - - err = -ENOMEM; - ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); + ff = fuse_file_alloc(); if (!ff) - goto out_put_request; + return -ENOMEM; - ff->release_req = fuse_request_alloc(); - if (!ff->release_req) { - kfree(ff); - goto out_put_request; - } - - memset(&inarg, 0, sizeof(inarg)); - inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; - req->in.h.nodeid = get_node_id(inode); - req->inode = inode; - req->in.numargs = 1; - req->in.args[0].size = sizeof(inarg); - req->in.args[0].value = &inarg; - req->out.numargs = 1; - req->out.args[0].size = sizeof(outarg); - req->out.args[0].value = &outarg; - request_send(fc, req); - err = req->out.h.error; - if (err) { - fuse_request_free(ff->release_req); - kfree(ff); - } else { - if (!isdir && (outarg.open_flags & FOPEN_DIRECT_IO)) - file->f_op = &fuse_direct_io_file_operations; - if (!(outarg.open_flags & FOPEN_KEEP_CACHE)) - invalidate_inode_pages(inode->i_mapping); - ff->fh = outarg.fh; - file->private_data = ff; + err = fuse_send_open(inode, file, isdir, &outarg); + if (err) + fuse_file_free(ff); + else { + if (isdir) + outarg.open_flags &= ~FOPEN_DIRECT_IO; + fuse_finish_open(inode, file, ff, &outarg); } - out_put_request: - fuse_put_request(fc, req); return err; } -int fuse_release_common(struct inode *inode, struct file *file, int isdir) +void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, + u64 nodeid, struct inode *inode, int flags, int isdir) { - struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_file *ff = file->private_data; - struct fuse_req *req = ff->release_req; + struct fuse_req * req = ff->release_req; struct fuse_release_in *inarg = &req->misc.release_in; inarg->fh = ff->fh; - inarg->flags = file->f_flags & ~O_EXCL; + inarg->flags = flags; req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; - req->in.h.nodeid = get_node_id(inode); + req->in.h.nodeid = nodeid; req->inode = inode; req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_release_in); req->in.args[0].value = inarg; request_send_background(fc, req); kfree(ff); +} + +int fuse_release_common(struct inode *inode, struct file *file, int isdir) +{ + struct fuse_file *ff = file->private_data; + if (ff) { + struct fuse_conn *fc = get_fuse_conn(inode); + u64 nodeid = get_node_id(inode); + fuse_send_release(fc, ff, nodeid, inode, file->f_flags, isdir); + } /* Return value is ignored by VFS */ return 0; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 5cb456f5..0ea5301 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -266,6 +266,12 @@ struct fuse_conn { /** Is removexattr not implemented by fs? */ unsigned no_removexattr : 1; + /** Is access not implemented by fs? */ + unsigned no_access : 1; + + /** Is create not implemented by fs? */ + unsigned no_create : 1; + /** Backing dev info */ struct backing_dev_info bdi; }; @@ -337,6 +343,17 @@ size_t fuse_send_read_common(struct fuse_req *req, struct file *file, */ int fuse_open_common(struct inode *inode, struct file *file, int isdir); +struct fuse_file *fuse_file_alloc(void); +void fuse_file_free(struct fuse_file *ff); +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg); + +/** + * Send a RELEASE request + */ +void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, + u64 nodeid, struct inode *inode, int flags, int isdir); + /** * Send RELEASE or RELEASEDIR request */ diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index dd71131..a33fb1d 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -294,8 +294,7 @@ static void hostfs_delete_inode(struct inode *inode) static void hostfs_destroy_inode(struct inode *inode) { - if(HOSTFS_I(inode)->host_filename) - kfree(HOSTFS_I(inode)->host_filename); + kfree(HOSTFS_I(inode)->host_filename); /*XXX: This should not happen, probably. The check is here for * additional safety.*/ diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index 1d21307..229ff2f 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c @@ -244,12 +244,12 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, go_up: if (namelen >= 256) { hpfs_error(i->i_sb, "hpfs_add_to_dnode: namelen == %d", namelen); - if (nd) kfree(nd); + kfree(nd); kfree(nname); return 1; } if (!(d = hpfs_map_dnode(i->i_sb, dno, &qbh))) { - if (nd) kfree(nd); + kfree(nd); kfree(nname); return 1; } @@ -257,7 +257,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, if (hpfs_sb(i->i_sb)->sb_chk) if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "hpfs_add_to_dnode")) { hpfs_brelse4(&qbh); - if (nd) kfree(nd); + kfree(nd); kfree(nname); return 1; } @@ -270,7 +270,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, for_all_poss(i, hpfs_pos_subst, 5, t + 1); hpfs_mark_4buffers_dirty(&qbh); hpfs_brelse4(&qbh); - if (nd) kfree(nd); + kfree(nd); kfree(nname); return 0; } diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 8eefa63..63e88d7 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -75,7 +75,7 @@ void hpfs_error(struct super_block *s, char *m,...) } else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n"); else printk("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n"); } else printk("\n"); - if (buf) kfree(buf); + kfree(buf); hpfs_sb(s)->sb_was_error = 1; } @@ -102,8 +102,8 @@ int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2, static void hpfs_put_super(struct super_block *s) { struct hpfs_sb_info *sbi = hpfs_sb(s); - if (sbi->sb_cp_table) kfree(sbi->sb_cp_table); - if (sbi->sb_bmp_dir) kfree(sbi->sb_bmp_dir); + kfree(sbi->sb_cp_table); + kfree(sbi->sb_bmp_dir); unmark_dirty(s); s->s_fs_info = NULL; kfree(sbi); @@ -654,8 +654,8 @@ bail3: brelse(bh1); bail2: brelse(bh0); bail1: bail0: - if (sbi->sb_bmp_dir) kfree(sbi->sb_bmp_dir); - if (sbi->sb_cp_table) kfree(sbi->sb_cp_table); + kfree(sbi->sb_bmp_dir); + kfree(sbi->sb_cp_table); s->s_fs_info = NULL; kfree(sbi); return -EINVAL; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 1652de1..298f08b 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -855,8 +855,7 @@ root_found: if (opt.check == 'r') table++; s->s_root->d_op = &isofs_dentry_ops[table]; - if (opt.iocharset) - kfree(opt.iocharset); + kfree(opt.iocharset); return 0; @@ -895,8 +894,7 @@ out_unknown_format: out_freebh: brelse(bh); out_freesbi: - if (opt.iocharset) - kfree(opt.iocharset); + kfree(opt.iocharset); kfree(sbi); s->s_fs_info = NULL; return -EINVAL; @@ -1164,8 +1162,7 @@ out_nomem: out_noread: printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block); - if (tmpde) - kfree(tmpde); + kfree(tmpde); return -EIO; out_toomany: @@ -1334,8 +1331,7 @@ static void isofs_read_inode(struct inode *inode) init_special_inode(inode, inode->i_mode, inode->i_rdev); out: - if (tmpde) - kfree(tmpde); + kfree(tmpde); if (bh) brelse(bh); return; diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 2a3e310..002ad2b 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -261,10 +261,8 @@ void journal_commit_transaction(journal_t *journal) struct buffer_head *bh = jh2bh(jh); jbd_lock_bh_state(bh); - if (jh->b_committed_data) { - kfree(jh->b_committed_data); - jh->b_committed_data = NULL; - } + kfree(jh->b_committed_data); + jh->b_committed_data = NULL; jbd_unlock_bh_state(bh); } journal_refile_buffer(journal, jh); diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 103c34e..80d7f53 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c @@ -210,7 +210,7 @@ do { \ } while (0) /** - * int journal_recover(journal_t *journal) - recovers a on-disk journal + * journal_recover - recovers a on-disk journal * @journal: the journal to recover * * The primary function for recovering the log contents when mounting a @@ -266,7 +266,7 @@ int journal_recover(journal_t *journal) } /** - * int journal_skip_recovery() - Start journal and wipe exiting records + * journal_skip_recovery - Start journal and wipe exiting records * @journal: journal to startup * * Locate any valid recovery information from the journal and set up the diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 13cb05b..429f4b2 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -227,8 +227,7 @@ repeat_locked: spin_unlock(&transaction->t_handle_lock); spin_unlock(&journal->j_state_lock); out: - if (new_transaction) - kfree(new_transaction); + kfree(new_transaction); return ret; } @@ -725,8 +724,7 @@ done: journal_cancel_revoke(handle, jh); out: - if (frozen_buffer) - kfree(frozen_buffer); + kfree(frozen_buffer); JBUFFER_TRACE(jh, "exit"); return error; @@ -905,8 +903,7 @@ repeat: jbd_unlock_bh_state(bh); out: journal_put_journal_head(jh); - if (committed_data) - kfree(committed_data); + kfree(committed_data); return err; } diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index 27f199e..b2e9542 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c @@ -462,7 +462,7 @@ jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result) } /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); /* Return result */ D3(printk("checksum result: 0x%08x\n", sum)); @@ -1011,12 +1011,12 @@ jffs_scan_flash(struct jffs_control *c) offset , fmc->sector_size); flash_safe_release(fmc->mtd); - kfree (read_buf); + kfree(read_buf); return -1; /* bad, bad, bad! */ } flash_safe_release(fmc->mtd); - kfree (read_buf); + kfree(read_buf); return -EAGAIN; /* erased offending sector. Try mount one more time please. */ } @@ -1112,7 +1112,7 @@ jffs_scan_flash(struct jffs_control *c) if (!node) { if (!(node = jffs_alloc_node())) { /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); /* Release the flash device */ flash_safe_release(fmc->mtd); @@ -1269,7 +1269,7 @@ jffs_scan_flash(struct jffs_control *c) DJM(no_jffs_node--); /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); /* Release the flash device */ flash_safe_release(fmc->mtd); @@ -1296,7 +1296,7 @@ jffs_scan_flash(struct jffs_control *c) flash_safe_release(fmc->flash_part); /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); return -ENOMEM; } @@ -1324,7 +1324,7 @@ jffs_scan_flash(struct jffs_control *c) jffs_build_end(fmc); /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); if(!num_free_space){ printk(KERN_WARNING "jffs_scan_flash(): Did not find even a single " @@ -1747,9 +1747,7 @@ jffs_find_child(struct jffs_file *dir, const char *name, int len) } printk("jffs_find_child(): Didn't find the file \"%s\".\n", (copy ? copy : "")); - if (copy) { - kfree(copy); - } + kfree(copy); }); return f; diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 242cd53..4cebf0e 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -326,8 +326,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) c->wbuf_ofs = ofs + towrite; memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len); /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ - if (buf) - kfree(buf); + kfree(buf); } else { /* OK, now we're left with the dregs in whichever buffer we're using */ if (buf) { diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 87332f3..c5a3364 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -112,8 +112,7 @@ static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_ } } spin_unlock(&host->h_lock); - if (new != NULL) - kfree(new); + kfree(new); return res; } diff --git a/fs/mbcache.c b/fs/mbcache.c index 298997f..0f1e453 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -301,8 +301,7 @@ fail: if (cache) { while (--m >= 0) kfree(cache->c_indexes_hash[m]); - if (cache->c_block_hash) - kfree(cache->c_block_hash); + kfree(cache->c_block_hash); kfree(cache); } return NULL; @@ -1459,7 +1459,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) if (!error) { DQUOT_INIT(inode); - error = do_truncate(dentry, 0); + error = do_truncate(dentry, 0, NULL); } put_write_access(inode); if (error) diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 3976c17..618a327 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -149,8 +149,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct } } spin_unlock(&clp->cl_lock); - if (delegation != NULL) - kfree(delegation); + kfree(delegation); return status; } diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 24d2fbf..6391d89 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1688,8 +1688,7 @@ static void nfs_kill_super(struct super_block *s) rpciod_down(); /* release rpciod */ - if (server->hostname != NULL) - kfree(server->hostname); + kfree(server->hostname); kfree(server); } @@ -1908,8 +1907,7 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) return ERR_PTR(-ENOMEM); } if (copy_from_user(dst, src->data, maxlen)) { - if (p != NULL) - kfree(p); + kfree(p); return ERR_PTR(-EFAULT); } dst[maxlen] = '\0'; @@ -2000,10 +1998,8 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, out_err: s = (struct super_block *)p; out_free: - if (server->mnt_path) - kfree(server->mnt_path); - if (server->hostname) - kfree(server->hostname); + kfree(server->mnt_path); + kfree(server->hostname); kfree(server); return s; } @@ -2023,8 +2019,7 @@ static void nfs4_kill_super(struct super_block *sb) destroy_nfsv4_state(server); - if (server->hostname != NULL) - kfree(server->hostname); + kfree(server->hostname); kfree(server); } diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 52a26ba..0675f32 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -69,10 +69,8 @@ init_nfsv4_state(struct nfs_server *server) void destroy_nfsv4_state(struct nfs_server *server) { - if (server->mnt_path) { - kfree(server->mnt_path); - server->mnt_path = NULL; - } + kfree(server->mnt_path); + server->mnt_path = NULL; if (server->nfs4_state) { nfs4_put_client(server->nfs4_state); server->nfs4_state = NULL; @@ -311,8 +309,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct new = NULL; } spin_unlock(&clp->cl_lock); - if (new) - kfree(new); + kfree(new); if (sp != NULL) return sp; put_rpccred(cred); diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index f732541..d639d17 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -52,8 +52,7 @@ nfs_put_unlinkdata(struct nfs_unlinkdata *data) { if (--data->count == 0) { nfs_detach_unlinkdata(data); - if (data->name.name != NULL) - kfree(data->name.name); + kfree(data->name.name); kfree(data); } } diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 057aff7..417ec02 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -190,8 +190,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) out: if (dom) auth_domain_put(dom); - if (buf) - kfree(buf); + kfree(buf); return err; } @@ -428,8 +427,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) path_release(&nd); if (dom) auth_domain_put(dom); - if (buf) - kfree(buf); + kfree(buf); return err; } diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index e0e134d..9147b85 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -366,7 +366,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, len = args->len = ntohl(*p++); hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; - if (rqstp->rq_arg.len < len + hdr) + if (rqstp->rq_arg.len < hdr || + rqstp->rq_arg.len - hdr < len) return 0; args->vec[0].iov_base = (void*)p; diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 4c41463..dcd6731 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -151,8 +151,7 @@ static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) if (nbytes <= sizeof(argp->tmp)) p = argp->tmp; else { - if (argp->tmpp) - kfree(argp->tmpp); + kfree(argp->tmpp); p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL); if (!p) return NULL; @@ -2476,10 +2475,8 @@ void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args) kfree(args->ops); args->ops = args->iops; } - if (args->tmpp) { - kfree(args->tmpp); - args->tmpp = NULL; - } + kfree(args->tmpp); + args->tmpp = NULL; while (args->to_free) { struct tmpbuf *tb = args->to_free; args->to_free = tb->next; diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index 119e4d4..d852ebb 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -93,8 +93,7 @@ nfsd_cache_shutdown(void) cache_disabled = 1; - if (hash_list) - kfree (hash_list); + kfree (hash_list); hash_list = NULL; } diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 841c562..a0871b3 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -23,6 +23,7 @@ #include <linux/seq_file.h> #include <linux/pagemap.h> #include <linux/init.h> +#include <linux/string.h> #include <linux/nfs.h> #include <linux/nfsd_idmap.h> @@ -35,6 +36,8 @@ #include <asm/uaccess.h> +unsigned int nfsd_versbits = ~0; + /* * We have a single directory with 9 nodes in it. */ @@ -50,8 +53,15 @@ enum { NFSD_List, NFSD_Fh, NFSD_Threads, + NFSD_Versions, + /* + * The below MUST come last. Otherwise we leave a hole in nfsd_files[] + * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops + */ +#ifdef CONFIG_NFSD_V4 NFSD_Leasetime, NFSD_RecoveryDir, +#endif }; /* @@ -66,8 +76,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size); static ssize_t write_getfs(struct file *file, char *buf, size_t size); static ssize_t write_filehandle(struct file *file, char *buf, size_t size); static ssize_t write_threads(struct file *file, char *buf, size_t size); +static ssize_t write_versions(struct file *file, char *buf, size_t size); +#ifdef CONFIG_NFSD_V4 static ssize_t write_leasetime(struct file *file, char *buf, size_t size); static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); +#endif static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Svc] = write_svc, @@ -79,8 +92,11 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Getfs] = write_getfs, [NFSD_Fh] = write_filehandle, [NFSD_Threads] = write_threads, + [NFSD_Versions] = write_versions, +#ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = write_leasetime, [NFSD_RecoveryDir] = write_recoverydir, +#endif }; static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) @@ -104,9 +120,23 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu return rv; } +static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) +{ + if (! file->private_data) { + /* An attempt to read a transaction file without writing + * causes a 0-byte write so that the file can return + * state information + */ + ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos); + if (rv < 0) + return rv; + } + return simple_transaction_read(file, buf, size, pos); +} + static struct file_operations transaction_ops = { .write = nfsctl_transaction_write, - .read = simple_transaction_read, + .read = nfsctl_transaction_read, .release = simple_transaction_release, }; @@ -329,6 +359,70 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) return strlen(buf); } +static ssize_t write_versions(struct file *file, char *buf, size_t size) +{ + /* + * Format: + * [-/+]vers [-/+]vers ... + */ + char *mesg = buf; + char *vers, sign; + int len, num; + ssize_t tlen = 0; + char *sep; + + if (size>0) { + if (nfsd_serv) + return -EBUSY; + if (buf[size-1] != '\n') + return -EINVAL; + buf[size-1] = 0; + + vers = mesg; + len = qword_get(&mesg, vers, size); + if (len <= 0) return -EINVAL; + do { + sign = *vers; + if (sign == '+' || sign == '-') + num = simple_strtol((vers+1), NULL, 0); + else + num = simple_strtol(vers, NULL, 0); + switch(num) { + case 2: + case 3: + case 4: + if (sign != '-') + NFSCTL_VERSET(nfsd_versbits, num); + else + NFSCTL_VERUNSET(nfsd_versbits, num); + break; + default: + return -EINVAL; + } + vers += len + 1; + tlen += len; + } while ((len = qword_get(&mesg, vers, size)) > 0); + /* If all get turned off, turn them back on, as + * having no versions is BAD + */ + if ((nfsd_versbits & NFSCTL_VERALL)==0) + nfsd_versbits = NFSCTL_VERALL; + } + /* Now write current state into reply buffer */ + len = 0; + sep = ""; + for (num=2 ; num <= 4 ; num++) + if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) { + len += sprintf(buf+len, "%s%c%d", sep, + NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-', + num); + sep = " "; + } + len += sprintf(buf+len, "\n"); + return len; +} + +#ifdef CONFIG_NFSD_V4 extern time_t nfs4_leasetime(void); static ssize_t write_leasetime(struct file *file, char *buf, size_t size) @@ -370,6 +464,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) status = nfs4_reset_recoverydir(recdir); return strlen(buf); } +#endif /*----------------------------------------------------------------------------*/ /* @@ -389,6 +484,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, + [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 1697539..89ed046 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -30,6 +30,7 @@ #include <linux/nfsd/nfsd.h> #include <linux/nfsd/stats.h> #include <linux/nfsd/cache.h> +#include <linux/nfsd/syscall.h> #include <linux/lockd/bind.h> #include <linux/nfsacl.h> @@ -52,7 +53,7 @@ extern struct svc_program nfsd_program; static void nfsd(struct svc_rqst *rqstp); struct timeval nfssvc_boot; -static struct svc_serv *nfsd_serv; + struct svc_serv *nfsd_serv; static atomic_t nfsd_busy; static unsigned long nfsd_last_call; static DEFINE_SPINLOCK(nfsd_call_lock); @@ -63,6 +64,31 @@ struct nfsd_list { }; static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list); +static struct svc_version * nfsd_version[] = { + [2] = &nfsd_version2, +#if defined(CONFIG_NFSD_V3) + [3] = &nfsd_version3, +#endif +#if defined(CONFIG_NFSD_V4) + [4] = &nfsd_version4, +#endif +}; + +#define NFSD_MINVERS 2 +#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) +static struct svc_version *nfsd_versions[NFSD_NRVERS]; + +struct svc_program nfsd_program = { + .pg_prog = NFS_PROGRAM, /* program number */ + .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ + .pg_vers = nfsd_versions, /* version table */ + .pg_name = "nfsd", /* program name */ + .pg_class = "nfsd", /* authentication class */ + .pg_stats = &nfsd_svcstats, /* version table */ + .pg_authenticate = &svc_set_client, /* export authentication */ + +}; + /* * Maximum number of nfsd processes */ @@ -80,11 +106,12 @@ int nfsd_svc(unsigned short port, int nrservs) { int error; - int none_left; + int none_left, found_one, i; struct list_head *victim; lock_kernel(); - dprintk("nfsd: creating service\n"); + dprintk("nfsd: creating service: vers 0x%x\n", + nfsd_versbits); error = -EINVAL; if (nrservs <= 0) nrservs = 0; @@ -99,6 +126,27 @@ nfsd_svc(unsigned short port, int nrservs) if (error<0) goto out; if (!nfsd_serv) { + /* + * Use the nfsd_ctlbits to define which + * versions that will be advertised. + * If nfsd_ctlbits doesn't list any version, + * export them all. + */ + found_one = 0; + + for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { + if (NFSCTL_VERISSET(nfsd_versbits, i)) { + nfsd_program.pg_vers[i] = nfsd_version[i]; + found_one = 1; + } else + nfsd_program.pg_vers[i] = NULL; + } + + if (!found_one) { + for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) + nfsd_program.pg_vers[i] = nfsd_version[i]; + } + atomic_set(&nfsd_busy, 0); error = -ENOMEM; nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE); @@ -379,6 +427,7 @@ static struct svc_program nfsd_acl_program = { .pg_name = "nfsd", .pg_class = "nfsd", .pg_stats = &nfsd_acl_svcstats, + .pg_authenticate = &svc_set_client, }; static struct svc_stat nfsd_acl_svcstats = { @@ -389,28 +438,3 @@ static struct svc_stat nfsd_acl_svcstats = { #else #define nfsd_acl_program_p NULL #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ - -extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; - -static struct svc_version * nfsd_version[] = { - [2] = &nfsd_version2, -#if defined(CONFIG_NFSD_V3) - [3] = &nfsd_version3, -#endif -#if defined(CONFIG_NFSD_V4) - [4] = &nfsd_version4, -#endif -}; - -#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) -struct svc_program nfsd_program = { - .pg_next = nfsd_acl_program_p, - .pg_prog = NFS_PROGRAM, /* program number */ - .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ - .pg_vers = nfsd_version, /* version table */ - .pg_name = "nfsd", /* program name */ - .pg_class = "nfsd", /* authentication class */ - .pg_stats = &nfsd_svcstats, /* version table */ - .pg_authenticate = &svc_set_client, /* export authentication */ - -}; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 4f2cd3d..af7c3c3 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -254,12 +254,19 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, /* Get inode */ err = fh_verify(rqstp, fhp, ftype, accmode); - if (err || !iap->ia_valid) + if (err) goto out; dentry = fhp->fh_dentry; inode = dentry->d_inode; + /* Ignore any mode updates on symlinks */ + if (S_ISLNK(inode->i_mode)) + iap->ia_valid &= ~ATTR_MODE; + + if (!iap->ia_valid) + goto out; + /* NFSv2 does not differentiate between "set-[ac]time-to-now" * which only requires access, and "set-[ac]time-to-X" which * requires ownership. @@ -194,7 +194,7 @@ out: return error; } -int do_truncate(struct dentry *dentry, loff_t length) +int do_truncate(struct dentry *dentry, loff_t length, struct file *filp) { int err; struct iattr newattrs; @@ -205,6 +205,10 @@ int do_truncate(struct dentry *dentry, loff_t length) newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; + if (filp) { + newattrs.ia_file = filp; + newattrs.ia_valid |= ATTR_FILE; + } down(&dentry->d_inode->i_sem); err = notify_change(dentry, &newattrs); @@ -262,7 +266,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); - error = do_truncate(nd.dentry, length); + error = do_truncate(nd.dentry, length, NULL); } put_write_access(inode); @@ -314,7 +318,7 @@ static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small) error = locks_verify_truncate(inode, file, length); if (!error) - error = do_truncate(dentry, length); + error = do_truncate(dentry, length, file); out_putf: fput(file); out: @@ -887,6 +891,10 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags) return filp; } +/* + * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an + * error. + */ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) { int error; @@ -894,8 +902,11 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) error = -ENFILE; f = get_empty_filp(); - if (f == NULL) + if (f == NULL) { + dput(dentry); + mntput(mnt); return ERR_PTR(error); + } return __dentry_open(dentry, mnt, flags, f, NULL); } diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 1be11ce..aeb0106 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -1088,8 +1088,7 @@ static void __exit exit_openprom_fs(void) unregister_filesystem(&openprom_fs_type); free_pages ((unsigned long)nodes, alloced); for (i = 0; i < aliases_nodes; i++) - if (alias_names [i]) - kfree (alias_names [i]); + kfree (alias_names [i]); nodes = NULL; } diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index d59dcbf..6327bcb 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c @@ -29,7 +29,7 @@ * cyl-cyl-head-head structure */ static inline int -cchh2blk (cchh_t *ptr, struct hd_geometry *geo) { +cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { return ptr->cc * geo->heads * geo->sectors + ptr->hh * geo->sectors; } @@ -40,7 +40,7 @@ cchh2blk (cchh_t *ptr, struct hd_geometry *geo) { * cyl-cyl-head-head-block structure */ static inline int -cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) { +cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { return ptr->cc * geo->heads * geo->sectors + ptr->hh * geo->sectors + ptr->b; @@ -56,7 +56,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) struct hd_geometry *geo; char type[5] = {0,}; char name[7] = {0,}; - volume_label_t *vlabel; + struct vtoc_volume_label *vlabel; unsigned char *data; Sector sect; @@ -64,7 +64,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) goto out_noinfo; if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL) goto out_nogeo; - if ((vlabel = kmalloc(sizeof(volume_label_t), GFP_KERNEL)) == NULL) + if ((vlabel = kmalloc(sizeof(struct vtoc_volume_label), + GFP_KERNEL)) == NULL) goto out_novlab; if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 || @@ -86,7 +87,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) strncpy(name, data + 8, 6); else strncpy(name, data + 4, 6); - memcpy (vlabel, data, sizeof(volume_label_t)); + memcpy (vlabel, data, sizeof(struct vtoc_volume_label)); put_dev_sector(sect); EBCASC(type, 4); @@ -129,9 +130,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) counter = 0; while ((data = read_dev_sector(bdev, blk*(blocksize/512), §)) != NULL) { - format1_label_t f1; + struct vtoc_format1_label f1; - memcpy(&f1, data, sizeof(format1_label_t)); + memcpy(&f1, data, sizeof(struct vtoc_format1_label)); put_dev_sector(sect); /* skip FMT4 / FMT5 / FMT7 labels */ @@ -15,6 +15,7 @@ #include <linux/security.h> #include <linux/syscalls.h> #include <linux/buffer_head.h> +#include <linux/quotaops.h> /* Check validity of generic quotactl commands */ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c index 2d85dd7..a0f296d 100644 --- a/fs/smbfs/request.c +++ b/fs/smbfs/request.c @@ -786,8 +786,7 @@ int smb_request_recv(struct smb_sb_info *server) /* We should never be called with any of these states */ case SMB_RECV_END: case SMB_RECV_REQUEST: - server->rstate = SMB_RECV_END; - break; + BUG(); } if (result < 0) { diff --git a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c index 0c64bc3..cdc53c4 100644 --- a/fs/smbfs/symlink.c +++ b/fs/smbfs/symlink.c @@ -45,7 +45,7 @@ static void *smb_follow_link(struct dentry *dentry, struct nameidata *nd) int len = smb_proc_read_link(server_from_dentry(dentry), dentry, link, PATH_MAX - 1); if (len < 0) { - putname(link); + __putname(link); link = ERR_PTR(len); } else { link[len] = 0; @@ -59,7 +59,7 @@ static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p) { char *s = nd_get_link(nd); if (!IS_ERR(s)) - putname(s); + __putname(s); } struct inode_operations smb_link_inode_operations = @@ -474,8 +474,6 @@ rescan: return NULL; } -EXPORT_SYMBOL(user_get_super); - asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf) { struct super_block *s; diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 0e54922..6636698 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -39,8 +39,7 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb) {\ if (UDF_SB(X))\ {\ - if (UDF_SB_PARTMAPS(X))\ - kfree(UDF_SB_PARTMAPS(X));\ + kfree(UDF_SB_PARTMAPS(X));\ UDF_SB_PARTMAPS(X) = NULL;\ }\ } diff --git a/fs/ufs/super.c b/fs/ufs/super.c index f036d69..54828eb 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -472,13 +472,14 @@ static int ufs_read_cylinder_structures (struct super_block *sb) { return 1; failed: - if (base) kfree (base); + kfree (base); if (sbi->s_ucg) { for (i = 0; i < uspi->s_ncg; i++) - if (sbi->s_ucg[i]) brelse (sbi->s_ucg[i]); + if (sbi->s_ucg[i]) + brelse (sbi->s_ucg[i]); kfree (sbi->s_ucg); for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) - if (sbi->s_ucpi[i]) kfree (sbi->s_ucpi[i]); + kfree (sbi->s_ucpi[i]); } UFSD(("EXIT (FAILED)\n")) return 0; @@ -981,9 +982,10 @@ magic_found: dalloc_failed: iput(inode); failed: - if (ubh) ubh_brelse_uspi (uspi); - if (uspi) kfree (uspi); - if (sbi) kfree(sbi); + if (ubh) + ubh_brelse_uspi (uspi); + kfree (uspi); + kfree(sbi); sb->s_fs_info = NULL; UFSD(("EXIT (FAILED)\n")) return -EINVAL; @@ -74,8 +74,7 @@ setxattr(struct dentry *d, char __user *name, void __user *value, } out: up(&d->d_inode->i_sem); - if (kvalue) - kfree(kvalue); + kfree(kvalue); return error; } @@ -173,8 +172,7 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) error = -E2BIG; } out: - if (kvalue) - kfree(kvalue); + kfree(kvalue); return error; } @@ -259,8 +257,7 @@ listxattr(struct dentry *d, char __user *list, size_t size) error = -E2BIG; } out: - if (klist) - kfree(klist); + kfree(klist); return error; } diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index 8f82c1a..c64a29cd 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h @@ -30,8 +30,8 @@ #define KM_NOFS 0x0004u #define KM_MAYFAIL 0x0008u -#define kmem_zone kmem_cache_s -#define kmem_zone_t kmem_cache_t +#define kmem_zone kmem_cache +#define kmem_zone_t struct kmem_cache typedef unsigned long xfs_pflags_t; |