rendered paste bodydiff --git a/fs/fuse/control.c b/fs/fuse/control.cindex 99c99df..8f0b537 100644Binary files a/fs/fuse/control.c and b/fs/fuse/control.c differdiff --git a/fs/fuse/dev.c b/fs/fuse/dev.cindex 6484eb7..51d9e33 100644--- a/fs/fuse/dev.c+++ b/fs/fuse/dev.c@@ -250,7 +250,7 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req) static void flush_bg_queue(struct fuse_conn *fc) {- while (fc->active_background < FUSE_MAX_BACKGROUND &&+ while (fc->active_background < fc->max_background && !list_empty(&fc->bg_queue)) { struct fuse_req *req; @@ -280,11 +280,11 @@ __releases(&fc->lock) list_del(&req->intr_entry); req->state = FUSE_REQ_FINISHED; if (req->background) {- if (fc->num_background == FUSE_MAX_BACKGROUND) {+ if (fc->num_background == fc->max_background) { fc->blocked = 0; wake_up_all(&fc->blocked_waitq); }- if (fc->num_background == FUSE_CONGESTION_THRESHOLD &&+ if (fc->num_background == fc->congestion_threshold && fc->connected && fc->bdi_initialized) { clear_bdi_congested(&fc->bdi, BLK_RW_SYNC); clear_bdi_congested(&fc->bdi, BLK_RW_ASYNC);@@ -410,9 +410,9 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc, { req->background = 1; fc->num_background++;- if (fc->num_background == FUSE_MAX_BACKGROUND)+ if (fc->num_background == fc->max_background) fc->blocked = 1;- if (fc->num_background == FUSE_CONGESTION_THRESHOLD &&+ if (fc->num_background == fc->congestion_threshold && fc->bdi_initialized) { set_bdi_congested(&fc->bdi, BLK_RW_SYNC); set_bdi_congested(&fc->bdi, BLK_RW_ASYNC);diff --git a/fs/fuse/dir.c b/fs/fuse/dir.cindex 573437c..beb8a4b 100644--- a/fs/fuse/dir.c+++ b/fs/fuse/dir.c@@ -718,8 +718,10 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, fuse_invalidate_attr(newdir); /* newent will end up negative */- if (newent->d_inode)+ if (newent->d_inode) {+ fuse_invalidate_attr(newent->d_inode); fuse_invalidate_entry_cache(newent);+ } } else if (err == -EINTR) { /* If request was interrupted, DEITY only knows if the rename actually took place. If the invalidation@@ -1282,14 +1284,19 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, return 0; if (attr->ia_valid & ATTR_SIZE) {- unsigned long limit;- if (IS_SWAPFILE(inode))- return -ETXTBSY;- limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;- if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {- send_sig(SIGXFSZ, current, 0);- return -EFBIG;- }+ unsigned long limit;+ if (IS_SWAPFILE(inode))+ return -ETXTBSY;+ limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;+ if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {+ send_sig(SIGXFSZ, current, 0);+ return -EFBIG;+ }+ /* Enable this in 2.6.32 + err = inode_newsize_ok(inode, attr->ia_size);+ if (err)+ return err;+ */ is_truncate = true; } @@ -1356,8 +1363,11 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. */ if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {- if (outarg.attr.size < oldsize)- fuse_truncate(inode->i_mapping, outarg.attr.size);+ if (outarg.attr.size < oldsize)+ fuse_truncate(inode->i_mapping, outarg.attr.size);+ /* Enable this in 2.6.32+ truncate_pagecache(inode, oldsize, outarg.attr.size);+ */ invalidate_inode_pages2(inode->i_mapping); } diff --git a/fs/fuse/file.c b/fs/fuse/file.cindex dedc81b..cbdbe6f 100644--- a/fs/fuse/file.c+++ b/fs/fuse/file.c@@ -1492,7 +1492,8 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf, break; } }- fuse_put_request(fc, req);+ if (!IS_ERR(req))+ fuse_put_request(fc, req); if (res > 0) *ppos = pos; @@ -1733,7 +1734,7 @@ static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) return 0; } -static struct vm_operations_struct fuse_file_vm_ops = {+static const struct vm_operations_struct fuse_file_vm_ops = { .close = fuse_vma_close, .fault = filemap_fault, .page_mkwrite = fuse_page_mkwrite,@@ -2033,7 +2034,7 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov, kaddr += copy; } - kunmap(map);+ kunmap(page); } return 0;diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.hindex d430ba5..5fdde74 100644--- a/fs/fuse/fuse_i.h+++ b/fs/fuse/fuse_i.h@@ -25,12 +25,6 @@ /** Max number of pages that can be used in a single read request */ #define FUSE_MAX_PAGES_PER_REQ 32 -/** Maximum number of outstanding background requests */-#define FUSE_MAX_BACKGROUND 12--/** Congestion starts at 75% of maximum */-#define FUSE_CONGESTION_THRESHOLD (FUSE_MAX_BACKGROUND * 75 / 100)- /** Bias for fi->writectr, meaning new writepages must not be sent */ #define FUSE_NOWRITE INT_MIN @@ -38,7 +32,7 @@ #define FUSE_NAME_MAX 1024 /** Number of dentries for each connection in the control filesystem */-#define FUSE_CTL_NUM_DENTRIES 3+#define FUSE_CTL_NUM_DENTRIES 5 /** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem module will check permissions based on the file mode. Otherwise no@@ -55,6 +49,10 @@ extern struct list_head fuse_conn_list; /** Global mutex protecting fuse_conn_list and the control filesystem */ extern struct mutex fuse_mutex; +/** Module parameters */+extern unsigned max_user_bgreq; +extern unsigned max_user_congthresh;+ /** number of fcntl calls to fuse */ extern unsigned fuse_fcntl_count; @@ -374,6 +372,12 @@ struct fuse_conn { /** rbtree of fuse_files waiting for poll events indexed by ph */ struct rb_root polled_files; + /** Maximum number of outstanding background requests */+ unsigned max_background;++ /** Number of background requests at which congestion starts */+ unsigned congestion_threshold;+ /** Number of requests currently in the background */ unsigned num_background; @@ -628,6 +632,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, u64 attr_valid); +/* Added for 2.6.31 compatibility */ void fuse_truncate(struct address_space *mapping, loff_t offset); /**diff --git a/fs/fuse/inode.c b/fs/fuse/inode.cindex 96b1c94..71fdd6d 100644--- a/fs/fuse/inode.c+++ b/fs/fuse/inode.c@@ -14,6 +14,7 @@ #include <linux/seq_file.h> #include <linux/init.h> #include <linux/module.h>+#include <linux/moduleparam.h> #include <linux/parser.h> #include <linux/statfs.h> #include <linux/random.h>@@ -27,13 +28,39 @@ MODULE_LICENSE("GPL"); static struct kmem_cache *fuse_inode_cachep; struct list_head fuse_conn_list; DEFINE_MUTEX(fuse_mutex);-+/* Enable for 2.6.32+static int set_global_limit(const char *val, struct kernel_param *kp);+*/+unsigned max_user_bgreq;+/*+module_param_call(max_user_bgreq, set_global_limit, param_get_uint,+ &max_user_bgreq, 0644);+__MODULE_PARM_TYPE(max_user_bgreq, "uint");+MODULE_PARM_DESC(max_user_bgreq,+ "Global limit for the maximum number of backgrounded requests an "+ "unprivileged user can set");+*/+unsigned max_user_congthresh;+/*+module_param_call(max_user_congthresh, set_global_limit, param_get_uint,+ &max_user_congthresh, 0644);+__MODULE_PARM_TYPE(max_user_congthresh, "uint");+MODULE_PARM_DESC(max_user_congthresh,+ "Global limit for the maximum congestion threshold an "+ "unprivileged user can set");+*/ unsigned fuse_fcntl_count; #define FUSE_SUPER_MAGIC 0x65735546 #define FUSE_DEFAULT_BLKSIZE 512 +/** Maximum number of outstanding background requests */+#define FUSE_DEFAULT_MAX_BACKGROUND 12++/** Congestion starts at 75% of maximum */+#define FUSE_DEFAULT_CONGESTION_THRESHOLD (FUSE_DEFAULT_MAX_BACKGROUND * 3 / 4)+ struct fuse_mount_data { int fd; unsigned rootmode;@@ -123,14 +150,16 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) return 0; } +/* Added for 2.6.31 backward compatibility */ void fuse_truncate(struct address_space *mapping, loff_t offset) {- /* See vmtruncate() */- unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);- truncate_inode_pages(mapping, offset);- unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);+ /* See vmtruncate() */+ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);+ truncate_inode_pages(mapping, offset);+ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); } + void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, u64 attr_valid) {@@ -188,8 +217,10 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, spin_unlock(&fc->lock); if (S_ISREG(inode->i_mode) && oldsize != attr->size) {- if (attr->size < oldsize)- fuse_truncate(inode->i_mapping, attr->size);+ if (attr->size < oldsize)+ fuse_truncate(inode->i_mapping, attr->size);+ /* Enable for 2.6.32 */+ /* truncate_pagecache(inode, oldsize, attr->size); */ invalidate_inode_pages2(inode->i_mapping); } }@@ -525,6 +556,10 @@ void fuse_conn_init(struct fuse_conn *fc) INIT_LIST_HEAD(&fc->bg_queue); INIT_LIST_HEAD(&fc->entry); atomic_set(&fc->num_waiting, 0);+ /* Enable this in 2.6.32+ fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND;+ fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD;+ */ fc->khctr = 0; fc->polled_files = RB_ROOT; fc->reqctr = 0;@@ -735,6 +770,57 @@ static const struct super_operations fuse_super_operations = { .show_options = fuse_show_options, }; +/* Enable for 2.6.32+static void sanitize_global_limit(unsigned *limit)+{+ if (*limit == 0)+ *limit = ((num_physpages << PAGE_SHIFT) >> 13) /+ sizeof(struct fuse_req);++ if (*limit >= 1 << 16)+ *limit = (1 << 16) - 1;+}++static int set_global_limit(const char *val, struct kernel_param *kp)+{+ int rv;++ rv = param_set_uint(val, kp);+ if (rv)+ return rv;++ sanitize_global_limit((unsigned *)kp->arg);++ return 0;+}+++static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg)+{+ int cap_sys_admin = capable(CAP_SYS_ADMIN);++ if (arg->minor < 13)+ return;++ sanitize_global_limit(&max_user_bgreq);+ sanitize_global_limit(&max_user_congthresh);++ if (arg->max_background) {+ fc->max_background = arg->max_background;++ if (!cap_sys_admin && fc->max_background > max_user_bgreq)+ fc->max_background = max_user_bgreq;+ }+ if (arg->congestion_threshold) {+ fc->congestion_threshold = arg->congestion_threshold;++ if (!cap_sys_admin &&+ fc->congestion_threshold > max_user_congthresh)+ fc->congestion_threshold = max_user_congthresh;+ }+}+*/+ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) { struct fuse_init_out *arg = &req->misc.init_out;@@ -744,6 +830,9 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) else { unsigned long ra_pages; + /* Enable this in 2.6.32 */+ /* process_init_limits(fc, arg); */+ if (arg->minor >= 6) { ra_pages = arg->max_readahead / PAGE_CACHE_SIZE; if (arg->flags & FUSE_ASYNC_READ)@@ -808,7 +897,8 @@ static void fuse_free_conn(struct fuse_conn *fc) static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) { int err;-+ /* Enable for kernel 2.6.32 */+ /* fc->bdi.name = "fuse"; */ fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; fc->bdi.unplug_io_fn = default_unplug_io_fn; /* fuse does it's own writeback accounting */@@ -901,6 +991,9 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) if (err) goto err_put_conn; + /* Enable this in 2.6.32 */+ /* sb->s_bdi = &fc->bdi; */+ /* Handle umasking inside the fuse code */ if (sb->s_flags & MS_POSIXACL) fc->dont_mask = 1;@@ -1157,6 +1250,11 @@ static int __init fuse_init(void) if (res) goto err_sysfs_cleanup; + /* Enable 2.6.32+ sanitize_global_limit(&max_user_bgreq);+ sanitize_global_limit(&max_user_congthresh);+ */+ return 0; err_sysfs_cleanup: