diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig | 9 | ||||
-rw-r--r-- | fs/compat_ioctl.c | 6 | ||||
-rw-r--r-- | fs/exec.c | 6 | ||||
-rw-r--r-- | fs/ext2/ext2.h | 7 | ||||
-rw-r--r-- | fs/fuse/dir.c | 81 | ||||
-rw-r--r-- | fs/fuse/file.c | 47 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 5 | ||||
-rw-r--r-- | fs/fuse/inode.c | 4 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/cluster/masklog.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/dcache.c | 20 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmmaster.c | 4 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 19 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/localalloc.c | 5 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 6 | ||||
-rw-r--r-- | fs/proc/base.c | 51 | ||||
-rw-r--r-- | fs/proc/generic.c | 37 | ||||
-rw-r--r-- | fs/proc/internal.h | 2 | ||||
-rw-r--r-- | fs/proc/root.c | 2 | ||||
-rw-r--r-- | fs/sysfs/file.c | 6 |
21 files changed, 198 insertions, 129 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 429a0022850..635f3e286ad 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -459,6 +459,15 @@ config OCFS2_DEBUG_MASKLOG This option will enlarge your kernel, but it allows debugging of ocfs2 filesystem issues. +config OCFS2_DEBUG_FS + bool "OCFS2 expensive checks" + depends on OCFS2_FS + default n + help + This option will enable expensive consistency checks. Enable + this option for debugging only as it is likely to decrease + performance of the filesystem. + config MINIX_FS tristate "Minix fs support" help diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index bd26e4cbb99..e8b7c3a98a5 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1954,6 +1954,12 @@ ULONG_IOCTL(TIOCSCTTY) COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSERGETLSR) +#ifdef TCGETS2 +COMPATIBLE_IOCTL(TCGETS2) +COMPATIBLE_IOCTL(TCSETS2) +COMPATIBLE_IOCTL(TCSETSW2) +COMPATIBLE_IOCTL(TCSETSF2) +#endif /* Little f */ COMPATIBLE_IOCTL(FIOCLEX) COMPATIBLE_IOCTL(FIONCLEX) diff --git a/fs/exec.c b/fs/exec.c index 4ccaaa4b13b..282240afe99 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1780,6 +1780,12 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) but keep the previous behaviour for now. */ if (!ispipe && !S_ISREG(inode->i_mode)) goto close_fail; + /* + * Dont allow local users get cute and trick others to coredump + * into their pre-created files: + */ + if (inode->i_uid != current->fsuid) + goto close_fail; if (!file->f_op) goto close_fail; if (!file->f_op->write) diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 7730388c493..c87ae29c19c 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -178,3 +178,10 @@ extern const struct inode_operations ext2_special_inode_operations; /* symlink.c */ extern const struct inode_operations ext2_fast_symlink_inode_operations; extern const struct inode_operations ext2_symlink_inode_operations; + +static inline ext2_fsblk_t +ext2_group_first_block_no(struct super_block *sb, unsigned long group_no) +{ + return group_no * (ext2_fsblk_t)EXT2_BLOCKS_PER_GROUP(sb) + + le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block); +} diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 3763757f9fe..80d2f5292cf 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -132,6 +132,21 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir, req->out.args[0].value = outarg; } +static u64 fuse_get_attr_version(struct fuse_conn *fc) +{ + u64 curr_version; + + /* + * The spin lock isn't actually needed on 64bit archs, but we + * don't yet care too much about such optimizations. + */ + spin_lock(&fc->lock); + curr_version = fc->attr_version; + spin_unlock(&fc->lock); + + return curr_version; +} + /* * Check whether the dentry is still valid * @@ -171,9 +186,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) return 0; } - spin_lock(&fc->lock); - attr_version = fc->attr_version; - spin_unlock(&fc->lock); + attr_version = fuse_get_attr_version(fc); parent = dget_parent(entry); fuse_lookup_init(req, parent->d_inode, entry, &outarg); @@ -264,9 +277,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, return ERR_PTR(PTR_ERR(forget_req)); } - spin_lock(&fc->lock); - attr_version = fc->attr_version; - spin_unlock(&fc->lock); + attr_version = fuse_get_attr_version(fc); fuse_lookup_init(req, dir, entry, &outarg); request_send(fc, req); @@ -646,6 +657,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, err = req->out.h.error; fuse_put_request(fc, req); if (!err) { + /* ctime changes */ + fuse_invalidate_attr(oldent->d_inode); + fuse_invalidate_attr(olddir); if (olddir != newdir) fuse_invalidate_attr(newdir); @@ -733,9 +747,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, if (IS_ERR(req)) return PTR_ERR(req); - spin_lock(&fc->lock); - attr_version = fc->attr_version; - spin_unlock(&fc->lock); + attr_version = fuse_get_attr_version(fc); memset(&inarg, 0, sizeof(inarg)); memset(&outarg, 0, sizeof(outarg)); @@ -775,6 +787,31 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, return err; } +int fuse_update_attributes(struct inode *inode, struct kstat *stat, + struct file *file, bool *refreshed) +{ + struct fuse_inode *fi = get_fuse_inode(inode); + int err; + bool r; + + if (fi->i_time < get_jiffies_64()) { + r = true; + err = fuse_do_getattr(inode, stat, file); + } else { + r = false; + err = 0; + if (stat) { + generic_fillattr(inode, stat); + stat->mode = fi->orig_i_mode; + } + } + + if (refreshed != NULL) + *refreshed = r; + + return err; +} + /* * Calling into a user-controlled filesystem gives the filesystem * daemon ptrace-like capabilities over the requester process. This @@ -862,14 +899,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) */ if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { - struct fuse_inode *fi = get_fuse_inode(inode); - if (fi->i_time < get_jiffies_64()) { - err = fuse_do_getattr(inode, NULL, NULL); - if (err) - return err; - - refreshed = true; - } + err = fuse_update_attributes(inode, NULL, NULL, &refreshed); + if (err) + return err; } if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { @@ -935,7 +967,6 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) struct page *page; struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_file *ff = file->private_data; struct fuse_req *req; if (is_bad_inode(inode)) @@ -952,7 +983,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) } req->num_pages = 1; req->pages[0] = page; - fuse_read_fill(req, ff, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); + fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); request_send(fc, req); nbytes = req->out.args[0].size; err = req->out.h.error; @@ -1173,22 +1204,12 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, struct kstat *stat) { struct inode *inode = entry->d_inode; - struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_conn *fc = get_fuse_conn(inode); - int err; if (!fuse_allow_task(fc, current)) return -EACCES; - if (fi->i_time < get_jiffies_64()) - err = fuse_do_getattr(inode, stat, NULL); - else { - err = 0; - generic_fillattr(inode, stat); - stat->mode = fi->orig_i_mode; - } - - return err; + return fuse_update_attributes(inode, stat, NULL, NULL); } static int fuse_setxattr(struct dentry *entry, const char *name, diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 535b3739900..bb05d227cf3 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -289,14 +289,16 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) return fuse_fsync_common(file, de, datasync, 0); } -void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, +void fuse_read_fill(struct fuse_req *req, struct file *file, struct inode *inode, loff_t pos, size_t count, int opcode) { struct fuse_read_in *inarg = &req->misc.read_in; + struct fuse_file *ff = file->private_data; inarg->fh = ff->fh; inarg->offset = pos; inarg->size = count; + inarg->flags = file->f_flags; req->in.h.opcode = opcode; req->in.h.nodeid = get_node_id(inode); req->in.numargs = 1; @@ -313,9 +315,8 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file, fl_owner_t owner) { struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_file *ff = file->private_data; - fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); + fuse_read_fill(req, file, inode, pos, count, FUSE_READ); if (owner != NULL) { struct fuse_read_in *inarg = &req->misc.read_in; @@ -376,15 +377,16 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) fuse_put_request(fc, req); } -static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, +static void fuse_send_readpages(struct fuse_req *req, struct file *file, struct inode *inode) { struct fuse_conn *fc = get_fuse_conn(inode); loff_t pos = page_offset(req->pages[0]); size_t count = req->num_pages << PAGE_CACHE_SHIFT; req->out.page_zeroing = 1; - fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); + fuse_read_fill(req, file, inode, pos, count, FUSE_READ); if (fc->async_read) { + struct fuse_file *ff = file->private_data; req->ff = fuse_file_get(ff); req->end = fuse_readpages_end; request_send_background(fc, req); @@ -396,7 +398,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, struct fuse_fill_data { struct fuse_req *req; - struct fuse_file *ff; + struct file *file; struct inode *inode; }; @@ -411,7 +413,7 @@ static int fuse_readpages_fill(void *_data, struct page *page) (req->num_pages == FUSE_MAX_PAGES_PER_REQ || (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || req->pages[req->num_pages - 1]->index + 1 != page->index)) { - fuse_send_readpages(req, data->ff, inode); + fuse_send_readpages(req, data->file, inode); data->req = req = fuse_get_req(fc); if (IS_ERR(req)) { unlock_page(page); @@ -435,7 +437,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, if (is_bad_inode(inode)) goto out; - data.ff = file->private_data; + data.file = file; data.inode = inode; data.req = fuse_get_req(fc); err = PTR_ERR(data.req); @@ -445,7 +447,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); if (!err) { if (data.req->num_pages) - fuse_send_readpages(data.req, data.ff, inode); + fuse_send_readpages(data.req, file, inode); else fuse_put_request(fc, data.req); } @@ -453,11 +455,31 @@ out: return err; } -static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, +static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + struct inode *inode = iocb->ki_filp->f_mapping->host; + + if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { + int err; + /* + * If trying to read past EOF, make sure the i_size + * attribute is up-to-date. + */ + err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); + if (err) + return err; + } + + return generic_file_aio_read(iocb, iov, nr_segs, pos); +} + +static void fuse_write_fill(struct fuse_req *req, struct file *file, struct inode *inode, loff_t pos, size_t count, int writepage) { struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_file *ff = file->private_data; struct fuse_write_in *inarg = &req->misc.write.in; struct fuse_write_out *outarg = &req->misc.write.out; @@ -466,6 +488,7 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, inarg->offset = pos; inarg->size = count; inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; + inarg->flags = file->f_flags; req->in.h.opcode = FUSE_WRITE; req->in.h.nodeid = get_node_id(inode); req->in.argpages = 1; @@ -486,7 +509,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, fl_owner_t owner) { struct fuse_conn *fc = get_fuse_conn(inode); - fuse_write_fill(req, file->private_data, inode, pos, count, 0); + fuse_write_fill(req, file, inode, pos, count, 0); if (owner != NULL) { struct fuse_write_in *inarg = &req->misc.write.in; inarg->write_flags |= FUSE_WRITE_LOCKOWNER; @@ -887,7 +910,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) static const struct file_operations fuse_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, - .aio_read = generic_file_aio_read, + .aio_read = fuse_file_aio_read, .write = do_sync_write, .aio_write = generic_file_aio_write, .mmap = fuse_file_mmap, diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6c5461de1a5..3ab8a3048e8 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -447,7 +447,7 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, /** * Initialize READ or READDIR request */ -void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, +void fuse_read_fill(struct fuse_req *req, struct file *file, struct inode *inode, loff_t pos, size_t count, int opcode); /** @@ -593,3 +593,6 @@ int fuse_valid_type(int m); int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); + +int fuse_update_attributes(struct inode *inode, struct kstat *stat, + struct file *file, bool *refreshed); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9a68d697084..84f9f7dfdf5 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -56,6 +56,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) fi->i_time = 0; fi->nodeid = 0; fi->nlookup = 0; + fi->attr_version = 0; INIT_LIST_HEAD(&fi->write_files); fi->forget_req = fuse_request_alloc(); if (!fi->forget_req) { @@ -562,8 +563,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) arg->major = FUSE_KERNEL_VERSION; arg->minor = FUSE_KERNEL_MINOR_VERSION; arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; - arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_FILE_OPS | - FUSE_ATOMIC_O_TRUNC; + arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC; req->in.h.opcode = FUSE_INIT; req->in.numargs = 1; req->in.args[0].size = sizeof(*arg); diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 556e34ccb00..56f7790cad4 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -1514,7 +1514,7 @@ int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size) { struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; - if (new_size < le16_to_cpu(di->id2.i_data.id_count)) + if (new_size <= le16_to_cpu(di->id2.i_data.id_count)) return 1; return 0; } diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index cd046060114..597e064bb94 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -212,7 +212,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; #define mlog_errno(st) do { \ int _st = (st); \ if (_st != -ERESTARTSYS && _st != -EINTR && \ - _st != AOP_TRUNCATED_PAGE) \ + _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC) \ mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ } while (0) diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 1957a5ed219..9923278ea6d 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -344,12 +344,24 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode) { struct ocfs2_dentry_lock *dl = dentry->d_fsdata; - mlog_bug_on_msg(!dl && !(dentry->d_flags & DCACHE_DISCONNECTED), - "dentry: %.*s\n", dentry->d_name.len, - dentry->d_name.name); + if (!dl) { + /* + * No dentry lock is ok if we're disconnected or + * unhashed. + */ + if (!(dentry->d_flags & DCACHE_DISCONNECTED) && + !d_unhashed(dentry)) { + unsigned long long ino = 0ULL; + if (inode) + ino = (unsigned long long)OCFS2_I(inode)->ip_blkno; + mlog(ML_ERROR, "Dentry is missing cluster lock. " + "inode: %llu, d_flags: 0x%x, d_name: %.*s\n", + ino, dentry->d_flags, dentry->d_name.len, + dentry->d_name.name); + } - if (!dl) goto out; + } mlog_bug_on_msg(dl->dl_count == 0, "dentry: %.*s, count: %u\n", dentry->d_name.len, dentry->d_name.name, diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 62e4a7daa28..a54d33d95ad 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -908,7 +908,7 @@ lookup: * but they might own this lockres. wait on them. */ bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); if (bit < O2NM_MAX_NODES) { - mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to" + mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " "recover before lock mastery can begin\n", dlm->name, namelen, (char *)lockid, bit); wait_on_recovery = 1; @@ -962,7 +962,7 @@ redo_request: spin_lock(&dlm->spinlock); bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); if (bit < O2NM_MAX_NODES) { - mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to" + mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " "recover before lock mastery can begin\n", dlm->name, namelen, (char *)lockid, bit); wait_on_recovery = 1; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index bbac7cd33e0..b75b2e1f0e4 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -399,7 +399,7 @@ static int ocfs2_truncate_file(struct inode *inode, if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { status = ocfs2_truncate_inline(inode, di_bh, new_i_size, - i_size_read(inode), 0); + i_size_read(inode), 1); if (status) mlog_errno(status); @@ -1521,6 +1521,7 @@ static int ocfs2_remove_inode_range(struct inode *inode, u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_cached_dealloc_ctxt dealloc; + struct address_space *mapping = inode->i_mapping; ocfs2_init_dealloc_ctxt(&dealloc); @@ -1529,10 +1530,20 @@ static int ocfs2_remove_inode_range(struct inode *inode, if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { ret = ocfs2_truncate_inline(inode, di_bh, byte_start, - byte_start + byte_len, 1); - if (ret) + byte_start + byte_len, 0); + if (ret) { mlog_errno(ret); - return ret; + goto out; + } + /* + * There's no need to get fancy with the page cache + * truncate of an inline-data inode. We're talking + * about less than a page here, which will be cached + * in the dinode buffer anyway. + */ + unmap_mapping_range(mapping, 0, 0, 0); + truncate_inode_pages(mapping, 0); + goto out; } trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 1d5e0cb0fda..ebb2bbe30f3 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -455,8 +455,8 @@ static int ocfs2_read_locked_inode(struct inode *inode, status = -EINVAL; fe = (struct ocfs2_dinode *) bh->b_data; if (!OCFS2_IS_VALID_DINODE(fe)) { - mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n", - (unsigned long long)le64_to_cpu(fe->i_blkno), 7, + mlog(0, "Invalid dinode #%llu: signature = %.*s\n", + (unsigned long long)args->fi_blkno, 7, fe->i_signature); goto bail; } @@ -863,7 +863,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode, status = ocfs2_try_open_lock(inode, 1); if (status == -EAGAIN) { status = 0; - mlog(0, "Skipping delete of %llu because it is in use on" + mlog(0, "Skipping delete of %llu because it is in use on " "other nodes\n", (unsigned long long)oi->ip_blkno); goto bail; } diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index d272847d5a0..58ea88b5af3 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -484,6 +484,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; +#ifdef OCFS2_DEBUG_FS if (le32_to_cpu(alloc->id1.bitmap1.i_used) != ocfs2_local_alloc_count_bits(alloc)) { ocfs2_error(osb->sb, "local alloc inode %llu says it has " @@ -494,6 +495,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, status = -EIO; goto bail; } +#endif free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) - le32_to_cpu(alloc->id1.bitmap1.i_used); @@ -712,9 +714,8 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, void *bitmap; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); - mlog_entry("total = %u, COUNT = %u, used = %u\n", + mlog_entry("total = %u, used = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total), - ocfs2_local_alloc_count_bits(alloc), le32_to_cpu(alloc->id1.bitmap1.i_used)); if (!alloc->id1.bitmap1.i_total) { diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index be562ac3e89..5ee77542066 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -438,14 +438,14 @@ unlock_osb: } if (!ret) { - if (!ocfs2_is_hard_readonly(osb)) - ocfs2_set_journal_params(osb); - /* Only save off the new mount options in case of a successful * remount. */ osb->s_mount_opt = parsed_options.mount_opt; osb->s_atime_quantum = parsed_options.atime_quantum; osb->preferred_slot = parsed_options.slot; + + if (!ocfs2_is_hard_readonly(osb)) + ocfs2_set_journal_params(osb); } out: return ret; diff --git a/fs/proc/base.c b/fs/proc/base.c index a17c2685907..02a63ac0417 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2411,19 +2411,23 @@ out: * Find the first task with tgid >= tgid * */ -static struct task_struct *next_tgid(unsigned int tgid, - struct pid_namespace *ns) -{ +struct tgid_iter { + unsigned int tgid; struct task_struct *task; +}; +static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter) +{ struct pid *pid; + if (iter.task) + put_task_struct(iter.task); rcu_read_lock(); retry: - task = NULL; - pid = find_ge_pid(tgid, ns); + iter.task = NULL; + pid = find_ge_pid(iter.tgid, ns); if (pid) { - tgid = pid_nr_ns(pid, ns) + 1; - task = pid_task(pid, PIDTYPE_PID); + iter.tgid = pid_nr_ns(pid, ns); + iter.task = pid_task(pid, PIDTYPE_PID); /* What we to know is if the pid we have find is the * pid of a thread_group_leader. Testing for task * being a thread_group_leader is the obvious thing @@ -2436,23 +2440,25 @@ retry: * found doesn't happen to be a thread group leader. * As we don't care in the case of readdir. */ - if (!task || !has_group_leader_pid(task)) + if (!iter.task || !has_group_leader_pid(iter.task)) { + iter.tgid += 1; goto retry; - get_task_struct(task); + } + get_task_struct(iter.task); } rcu_read_unlock(); - return task; + return iter; } #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, - struct task_struct *task, int tgid) + struct tgid_iter iter) { char name[PROC_NUMBUF]; - int len = snprintf(name, sizeof(name), "%d", tgid); + int len = snprintf(name, sizeof(name), "%d", iter.tgid); return proc_fill_cache(filp, dirent, filldir, name, len, - proc_pid_instantiate, task, NULL); + proc_pid_instantiate, iter.task, NULL); } /* for the /proc/ directory itself, after non-process stuff has been done */ @@ -2460,8 +2466,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) { unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); - struct task_struct *task; - int tgid; + struct tgid_iter iter; struct pid_namespace *ns; if (!reaper) @@ -2474,14 +2479,14 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) } ns = filp->f_dentry->d_sb->s_fs_info; - tgid = filp->f_pos - TGID_OFFSET; - for (task = next_tgid(tgid, ns); - task; - put_task_struct(task), task = next_tgid(tgid + 1, ns)) { - tgid = task_pid_nr_ns(task, ns); - filp->f_pos = tgid + TGID_OFFSET; - if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { - put_task_struct(task); + iter.task = NULL; + iter.tgid = filp->f_pos - TGID_OFFSET; + for (iter = next_tgid(ns, iter); + iter.task; + iter.tgid += 1, iter = next_tgid(ns, iter)) { + filp->f_pos = iter.tgid + TGID_OFFSET; + if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { + put_task_struct(iter.task); goto out; } } diff --git a/fs/proc/generic.c b/fs/proc/generic.c index a9806bc21ec..39f3d651903 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -555,41 +555,6 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp return 0; } -/* - * Kill an inode that got unregistered.. - */ -static void proc_kill_inodes(struct proc_dir_entry *de) -{ - struct list_head *p; - struct super_block *sb; - - /* - * Actually it's a partial revoke(). - */ - spin_lock(&sb_lock); - list_for_each_entry(sb, &proc_fs_type.fs_supers, s_instances) { - file_list_lock(); - list_for_each(p, &sb->s_files) { - struct file *filp = list_entry(p, struct file, - f_u.fu_list); - struct dentry *dentry = filp->f_path.dentry; - struct inode *inode; - const struct file_operations *fops; - - if (dentry->d_op != &proc_dentry_operations) - continue; - inode = dentry->d_inode; - if (PDE(inode) != de) - continue; - fops = filp->f_op; - filp->f_op = NULL; - fops_put(fops); - } - file_list_unlock(); - } - spin_unlock(&sb_lock); -} - static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, const char *name, mode_t mode, @@ -764,8 +729,6 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) continue_removing: if (S_ISDIR(de->mode)) parent->nlink--; - if (!S_ISREG(de->mode)) - proc_kill_inodes(de); de->nlink = 0; WARN_ON(de->subdir); if (!atomic_read(&de->count)) diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 1b2b6c6bb47..1820eb2ef76 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -78,5 +78,3 @@ static inline int proc_fd(struct inode *inode) { return PROC_I(inode)->fd; } - -extern struct file_system_type proc_fs_type; diff --git a/fs/proc/root.c b/fs/proc/root.c index 1f86bb860e0..ec9cb3b6c93 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -98,7 +98,7 @@ static void proc_kill_sb(struct super_block *sb) put_pid_ns(ns); } -struct file_system_type proc_fs_type = { +static struct file_system_type proc_fs_type = { .name = "proc", .get_sb = proc_get_sb, .kill_sb = proc_kill_sb, diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 27d1785b764..4045bdcc4b3 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -119,7 +119,11 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer sysfs_put_active_two(attr_sd); - BUG_ON(count > (ssize_t)PAGE_SIZE); + /* + * The code works fine with PAGE_SIZE return but it's likely to + * indicate truncated result or overflow in normal use cases. + */ + BUG_ON(count >= (ssize_t)PAGE_SIZE); if (count >= 0) { buffer->needs_read_fill = 0; buffer->count = count; |