aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c86
1 files changed, 58 insertions, 28 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 443ebc52e382..1141bd29e4e3 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -54,6 +54,7 @@
54#include <linux/nfsd_idmap.h> 54#include <linux/nfsd_idmap.h>
55#include <linux/security.h> 55#include <linux/security.h>
56#endif /* CONFIG_NFSD_V4 */ 56#endif /* CONFIG_NFSD_V4 */
57#include <linux/jhash.h>
57 58
58#include <asm/uaccess.h> 59#include <asm/uaccess.h>
59 60
@@ -81,10 +82,19 @@ struct raparms {
81 dev_t p_dev; 82 dev_t p_dev;
82 int p_set; 83 int p_set;
83 struct file_ra_state p_ra; 84 struct file_ra_state p_ra;
85 unsigned int p_hindex;
84}; 86};
85 87
88struct raparm_hbucket {
89 struct raparms *pb_head;
90 spinlock_t pb_lock;
91} ____cacheline_aligned_in_smp;
92
86static struct raparms * raparml; 93static struct raparms * raparml;
87static struct raparms * raparm_cache; 94#define RAPARM_HASH_BITS 4
95#define RAPARM_HASH_SIZE (1<<RAPARM_HASH_BITS)
96#define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1)
97static struct raparm_hbucket raparm_hash[RAPARM_HASH_SIZE];
88 98
89/* 99/*
90 * Called from nfsd_lookup and encode_dirent. Check if we have crossed 100 * Called from nfsd_lookup and encode_dirent. Check if we have crossed
@@ -437,13 +447,11 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
437 } else if (error < 0) 447 } else if (error < 0)
438 goto out_nfserr; 448 goto out_nfserr;
439 449
440 if (pacl) { 450 error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
441 error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS); 451 if (error < 0)
442 if (error < 0) 452 goto out_nfserr;
443 goto out_nfserr;
444 }
445 453
446 if (dpacl) { 454 if (S_ISDIR(inode->i_mode)) {
447 error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT); 455 error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
448 if (error < 0) 456 if (error < 0)
449 goto out_nfserr; 457 goto out_nfserr;
@@ -743,16 +751,20 @@ nfsd_sync_dir(struct dentry *dp)
743 * Obtain the readahead parameters for the file 751 * Obtain the readahead parameters for the file
744 * specified by (dev, ino). 752 * specified by (dev, ino).
745 */ 753 */
746static DEFINE_SPINLOCK(ra_lock);
747 754
748static inline struct raparms * 755static inline struct raparms *
749nfsd_get_raparms(dev_t dev, ino_t ino) 756nfsd_get_raparms(dev_t dev, ino_t ino)
750{ 757{
751 struct raparms *ra, **rap, **frap = NULL; 758 struct raparms *ra, **rap, **frap = NULL;
752 int depth = 0; 759 int depth = 0;
760 unsigned int hash;
761 struct raparm_hbucket *rab;
753 762
754 spin_lock(&ra_lock); 763 hash = jhash_2words(dev, ino, 0xfeedbeef) & RAPARM_HASH_MASK;
755 for (rap = &raparm_cache; (ra = *rap); rap = &ra->p_next) { 764 rab = &raparm_hash[hash];
765
766 spin_lock(&rab->pb_lock);
767 for (rap = &rab->pb_head; (ra = *rap); rap = &ra->p_next) {
756 if (ra->p_ino == ino && ra->p_dev == dev) 768 if (ra->p_ino == ino && ra->p_dev == dev)
757 goto found; 769 goto found;
758 depth++; 770 depth++;
@@ -761,7 +773,7 @@ nfsd_get_raparms(dev_t dev, ino_t ino)
761 } 773 }
762 depth = nfsdstats.ra_size*11/10; 774 depth = nfsdstats.ra_size*11/10;
763 if (!frap) { 775 if (!frap) {
764 spin_unlock(&ra_lock); 776 spin_unlock(&rab->pb_lock);
765 return NULL; 777 return NULL;
766 } 778 }
767 rap = frap; 779 rap = frap;
@@ -769,15 +781,16 @@ nfsd_get_raparms(dev_t dev, ino_t ino)
769 ra->p_dev = dev; 781 ra->p_dev = dev;
770 ra->p_ino = ino; 782 ra->p_ino = ino;
771 ra->p_set = 0; 783 ra->p_set = 0;
784 ra->p_hindex = hash;
772found: 785found:
773 if (rap != &raparm_cache) { 786 if (rap != &rab->pb_head) {
774 *rap = ra->p_next; 787 *rap = ra->p_next;
775 ra->p_next = raparm_cache; 788 ra->p_next = rab->pb_head;
776 raparm_cache = ra; 789 rab->pb_head = ra;
777 } 790 }
778 ra->p_count++; 791 ra->p_count++;
779 nfsdstats.ra_depth[depth*10/nfsdstats.ra_size]++; 792 nfsdstats.ra_depth[depth*10/nfsdstats.ra_size]++;
780 spin_unlock(&ra_lock); 793 spin_unlock(&rab->pb_lock);
781 return ra; 794 return ra;
782} 795}
783 796
@@ -791,22 +804,26 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
791{ 804{
792 unsigned long count = desc->count; 805 unsigned long count = desc->count;
793 struct svc_rqst *rqstp = desc->arg.data; 806 struct svc_rqst *rqstp = desc->arg.data;
807 struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
794 808
795 if (size > count) 809 if (size > count)
796 size = count; 810 size = count;
797 811
798 if (rqstp->rq_res.page_len == 0) { 812 if (rqstp->rq_res.page_len == 0) {
799 get_page(page); 813 get_page(page);
800 rqstp->rq_respages[rqstp->rq_resused++] = page; 814 put_page(*pp);
815 *pp = page;
816 rqstp->rq_resused++;
801 rqstp->rq_res.page_base = offset; 817 rqstp->rq_res.page_base = offset;
802 rqstp->rq_res.page_len = size; 818 rqstp->rq_res.page_len = size;
803 } else if (page != rqstp->rq_respages[rqstp->rq_resused-1]) { 819 } else if (page != pp[-1]) {
804 get_page(page); 820 get_page(page);
805 rqstp->rq_respages[rqstp->rq_resused++] = page; 821 put_page(*pp);
822 *pp = page;
823 rqstp->rq_resused++;
806 rqstp->rq_res.page_len += size; 824 rqstp->rq_res.page_len += size;
807 } else { 825 } else
808 rqstp->rq_res.page_len += size; 826 rqstp->rq_res.page_len += size;
809 }
810 827
811 desc->count = count - size; 828 desc->count = count - size;
812 desc->written += size; 829 desc->written += size;
@@ -837,7 +854,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
837 file->f_ra = ra->p_ra; 854 file->f_ra = ra->p_ra;
838 855
839 if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { 856 if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
840 svc_pushback_unused_pages(rqstp); 857 rqstp->rq_resused = 1;
841 err = file->f_op->sendfile(file, &offset, *count, 858 err = file->f_op->sendfile(file, &offset, *count,
842 nfsd_read_actor, rqstp); 859 nfsd_read_actor, rqstp);
843 } else { 860 } else {
@@ -849,11 +866,12 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
849 866
850 /* Write back readahead params */ 867 /* Write back readahead params */
851 if (ra) { 868 if (ra) {
852 spin_lock(&ra_lock); 869 struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex];
870 spin_lock(&rab->pb_lock);
853 ra->p_ra = file->f_ra; 871 ra->p_ra = file->f_ra;
854 ra->p_set = 1; 872 ra->p_set = 1;
855 ra->p_count--; 873 ra->p_count--;
856 spin_unlock(&ra_lock); 874 spin_unlock(&rab->pb_lock);
857 } 875 }
858 876
859 if (err >= 0) { 877 if (err >= 0) {
@@ -1829,11 +1847,11 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
1829void 1847void
1830nfsd_racache_shutdown(void) 1848nfsd_racache_shutdown(void)
1831{ 1849{
1832 if (!raparm_cache) 1850 if (!raparml)
1833 return; 1851 return;
1834 dprintk("nfsd: freeing readahead buffers.\n"); 1852 dprintk("nfsd: freeing readahead buffers.\n");
1835 kfree(raparml); 1853 kfree(raparml);
1836 raparm_cache = raparml = NULL; 1854 raparml = NULL;
1837} 1855}
1838/* 1856/*
1839 * Initialize readahead param cache 1857 * Initialize readahead param cache
@@ -1842,19 +1860,31 @@ int
1842nfsd_racache_init(int cache_size) 1860nfsd_racache_init(int cache_size)
1843{ 1861{
1844 int i; 1862 int i;
1863 int j = 0;
1864 int nperbucket;
1865
1845 1866
1846 if (raparm_cache) 1867 if (raparml)
1847 return 0; 1868 return 0;
1869 if (cache_size < 2*RAPARM_HASH_SIZE)
1870 cache_size = 2*RAPARM_HASH_SIZE;
1848 raparml = kmalloc(sizeof(struct raparms) * cache_size, GFP_KERNEL); 1871 raparml = kmalloc(sizeof(struct raparms) * cache_size, GFP_KERNEL);
1849 1872
1850 if (raparml != NULL) { 1873 if (raparml != NULL) {
1851 dprintk("nfsd: allocating %d readahead buffers.\n", 1874 dprintk("nfsd: allocating %d readahead buffers.\n",
1852 cache_size); 1875 cache_size);
1876 for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) {
1877 raparm_hash[i].pb_head = NULL;
1878 spin_lock_init(&raparm_hash[i].pb_lock);
1879 }
1880 nperbucket = cache_size >> RAPARM_HASH_BITS;
1853 memset(raparml, 0, sizeof(struct raparms) * cache_size); 1881 memset(raparml, 0, sizeof(struct raparms) * cache_size);
1854 for (i = 0; i < cache_size - 1; i++) { 1882 for (i = 0; i < cache_size - 1; i++) {
1855 raparml[i].p_next = raparml + i + 1; 1883 if (i % nperbucket == 0)
1884 raparm_hash[j++].pb_head = raparml + i;
1885 if (i % nperbucket < nperbucket-1)
1886 raparml[i].p_next = raparml + i + 1;
1856 } 1887 }
1857 raparm_cache = raparml;
1858 } else { 1888 } else {
1859 printk(KERN_WARNING 1889 printk(KERN_WARNING
1860 "nfsd: Could not allocate memory read-ahead cache.\n"); 1890 "nfsd: Could not allocate memory read-ahead cache.\n");