aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2008-02-08 07:20:26 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:22:34 -0500
commit8b88b0998e35d239e74446cc30f354bdab86df89 (patch)
treec13773b744cf12b1e30ec9336a4acaf21e46c6d9
parentefae09f3e99fcc1bdead7bc23a508b3bade3f82f (diff)
libfs: allow error return from simple attributes
Sometimes simple attributes might need to return an error, e.g. for acquiring a mutex interruptibly. In fact we have that situation in spufs already which is the original user of the simple attributes. This patch merged the temporarily forked attributes in spufs back into the main ones and allows to return errors. [akpm@linux-foundation.org: build fix] Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: <stefano.brivio@polimi.it> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Greg KH <greg@kroah.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/avr32/kernel/ocd.c18
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c8
-rw-r--r--fs/debugfs/file.c32
-rw-r--r--fs/libfs.c21
-rw-r--r--include/linux/fs.h2
-rw-r--r--lib/fault-inject.c19
-rw-r--r--virt/kvm/kvm_main.c16
7 files changed, 69 insertions, 47 deletions
diff --git a/arch/avr32/kernel/ocd.c b/arch/avr32/kernel/ocd.c
index c4f023294d75..1b0245d4e0ca 100644
--- a/arch/avr32/kernel/ocd.c
+++ b/arch/avr32/kernel/ocd.c
@@ -90,25 +90,29 @@ static struct dentry *ocd_debugfs_DC;
90static struct dentry *ocd_debugfs_DS; 90static struct dentry *ocd_debugfs_DS;
91static struct dentry *ocd_debugfs_count; 91static struct dentry *ocd_debugfs_count;
92 92
93static u64 ocd_DC_get(void *data) 93static int ocd_DC_get(void *data, u64 *val)
94{ 94{
95 return ocd_read(DC); 95 *val = ocd_read(DC);
96 return 0;
96} 97}
97static void ocd_DC_set(void *data, u64 val) 98static int ocd_DC_set(void *data, u64 val)
98{ 99{
99 ocd_write(DC, val); 100 ocd_write(DC, val);
101 return 0;
100} 102}
101DEFINE_SIMPLE_ATTRIBUTE(fops_DC, ocd_DC_get, ocd_DC_set, "0x%08llx\n"); 103DEFINE_SIMPLE_ATTRIBUTE(fops_DC, ocd_DC_get, ocd_DC_set, "0x%08llx\n");
102 104
103static u64 ocd_DS_get(void *data) 105static int ocd_DS_get(void *data, u64 *val)
104{ 106{
105 return ocd_read(DS); 107 *val = ocd_read(DS);
108 return 0;
106} 109}
107DEFINE_SIMPLE_ATTRIBUTE(fops_DS, ocd_DS_get, NULL, "0x%08llx\n"); 110DEFINE_SIMPLE_ATTRIBUTE(fops_DS, ocd_DS_get, NULL, "0x%08llx\n");
108 111
109static u64 ocd_count_get(void *data) 112static int ocd_count_get(void *data, u64 *val)
110{ 113{
111 return ocd_count; 114 *val = ocd_count;
115 return 0;
112} 116}
113DEFINE_SIMPLE_ATTRIBUTE(fops_count, ocd_count_get, NULL, "%lld\n"); 117DEFINE_SIMPLE_ATTRIBUTE(fops_count, ocd_count_get, NULL, "%lld\n");
114 118
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 1018acd1746b..9326714717ca 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -460,7 +460,7 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
460 if (!i->i_openers++) 460 if (!i->i_openers++)
461 ctx->cntl = inode->i_mapping; 461 ctx->cntl = inode->i_mapping;
462 mutex_unlock(&ctx->mapping_lock); 462 mutex_unlock(&ctx->mapping_lock);
463 return spufs_attr_open(inode, file, spufs_cntl_get, 463 return simple_attr_open(inode, file, spufs_cntl_get,
464 spufs_cntl_set, "0x%08lx"); 464 spufs_cntl_set, "0x%08lx");
465} 465}
466 466
@@ -470,7 +470,7 @@ spufs_cntl_release(struct inode *inode, struct file *file)
470 struct spufs_inode_info *i = SPUFS_I(inode); 470 struct spufs_inode_info *i = SPUFS_I(inode);
471 struct spu_context *ctx = i->i_ctx; 471 struct spu_context *ctx = i->i_ctx;
472 472
473 spufs_attr_release(inode, file); 473 simple_attr_close(inode, file);
474 474
475 mutex_lock(&ctx->mapping_lock); 475 mutex_lock(&ctx->mapping_lock);
476 if (!--i->i_openers) 476 if (!--i->i_openers)
@@ -482,8 +482,8 @@ spufs_cntl_release(struct inode *inode, struct file *file)
482static const struct file_operations spufs_cntl_fops = { 482static const struct file_operations spufs_cntl_fops = {
483 .open = spufs_cntl_open, 483 .open = spufs_cntl_open,
484 .release = spufs_cntl_release, 484 .release = spufs_cntl_release,
485 .read = spufs_attr_read, 485 .read = simple_attr_read,
486 .write = spufs_attr_write, 486 .write = simple_attr_write,
487 .mmap = spufs_cntl_mmap, 487 .mmap = spufs_cntl_mmap,
488}; 488};
489 489
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index fa6b7f7ff914..fddffe4851f5 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -56,13 +56,15 @@ const struct inode_operations debugfs_link_operations = {
56 .follow_link = debugfs_follow_link, 56 .follow_link = debugfs_follow_link,
57}; 57};
58 58
59static void debugfs_u8_set(void *data, u64 val) 59static int debugfs_u8_set(void *data, u64 val)
60{ 60{
61 *(u8 *)data = val; 61 *(u8 *)data = val;
62 return 0;
62} 63}
63static u64 debugfs_u8_get(void *data) 64static int debugfs_u8_get(void *data, u64 *val)
64{ 65{
65 return *(u8 *)data; 66 *val = *(u8 *)data;
67 return 0;
66} 68}
67DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); 69DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
68 70
@@ -97,13 +99,15 @@ struct dentry *debugfs_create_u8(const char *name, mode_t mode,
97} 99}
98EXPORT_SYMBOL_GPL(debugfs_create_u8); 100EXPORT_SYMBOL_GPL(debugfs_create_u8);
99 101
100static void debugfs_u16_set(void *data, u64 val) 102static int debugfs_u16_set(void *data, u64 val)
101{ 103{
102 *(u16 *)data = val; 104 *(u16 *)data = val;
105 return 0;
103} 106}
104static u64 debugfs_u16_get(void *data) 107static int debugfs_u16_get(void *data, u64 *val)
105{ 108{
106 return *(u16 *)data; 109 *val = *(u16 *)data;
110 return 0;
107} 111}
108DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); 112DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
109 113
@@ -138,13 +142,15 @@ struct dentry *debugfs_create_u16(const char *name, mode_t mode,
138} 142}
139EXPORT_SYMBOL_GPL(debugfs_create_u16); 143EXPORT_SYMBOL_GPL(debugfs_create_u16);
140 144
141static void debugfs_u32_set(void *data, u64 val) 145static int debugfs_u32_set(void *data, u64 val)
142{ 146{
143 *(u32 *)data = val; 147 *(u32 *)data = val;
148 return 0;
144} 149}
145static u64 debugfs_u32_get(void *data) 150static int debugfs_u32_get(void *data, u64 *val)
146{ 151{
147 return *(u32 *)data; 152 *val = *(u32 *)data;
153 return 0;
148} 154}
149DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); 155DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
150 156
@@ -179,14 +185,16 @@ struct dentry *debugfs_create_u32(const char *name, mode_t mode,
179} 185}
180EXPORT_SYMBOL_GPL(debugfs_create_u32); 186EXPORT_SYMBOL_GPL(debugfs_create_u32);
181 187
182static void debugfs_u64_set(void *data, u64 val) 188static int debugfs_u64_set(void *data, u64 val)
183{ 189{
184 *(u64 *)data = val; 190 *(u64 *)data = val;
191 return 0;
185} 192}
186 193
187static u64 debugfs_u64_get(void *data) 194static int debugfs_u64_get(void *data, u64 *val)
188{ 195{
189 return *(u64 *)data; 196 *val = *(u64 *)data;
197 return 0;
190} 198}
191DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); 199DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n");
192 200
diff --git a/fs/libfs.c b/fs/libfs.c
index 5523bde96387..2319415ddb5e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -583,8 +583,8 @@ int simple_transaction_release(struct inode *inode, struct file *file)
583/* Simple attribute files */ 583/* Simple attribute files */
584 584
585struct simple_attr { 585struct simple_attr {
586 u64 (*get)(void *); 586 int (*get)(void *, u64 *);
587 void (*set)(void *, u64); 587 int (*set)(void *, u64);
588 char get_buf[24]; /* enough to store a u64 and "\n\0" */ 588 char get_buf[24]; /* enough to store a u64 and "\n\0" */
589 char set_buf[24]; 589 char set_buf[24];
590 void *data; 590 void *data;
@@ -595,7 +595,7 @@ struct simple_attr {
595/* simple_attr_open is called by an actual attribute open file operation 595/* simple_attr_open is called by an actual attribute open file operation
596 * to set the attribute specific access operations. */ 596 * to set the attribute specific access operations. */
597int simple_attr_open(struct inode *inode, struct file *file, 597int simple_attr_open(struct inode *inode, struct file *file,
598 u64 (*get)(void *), void (*set)(void *, u64), 598 int (*get)(void *, u64 *), int (*set)(void *, u64),
599 const char *fmt) 599 const char *fmt)
600{ 600{
601 struct simple_attr *attr; 601 struct simple_attr *attr;
@@ -635,14 +635,20 @@ ssize_t simple_attr_read(struct file *file, char __user *buf,
635 return -EACCES; 635 return -EACCES;
636 636
637 mutex_lock(&attr->mutex); 637 mutex_lock(&attr->mutex);
638 if (*ppos) /* continued read */ 638 if (*ppos) { /* continued read */
639 size = strlen(attr->get_buf); 639 size = strlen(attr->get_buf);
640 else /* first read */ 640 } else { /* first read */
641 u64 val;
642 ret = attr->get(attr->data, &val);
643 if (ret)
644 goto out;
645
641 size = scnprintf(attr->get_buf, sizeof(attr->get_buf), 646 size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
642 attr->fmt, 647 attr->fmt, (unsigned long long)val);
643 (unsigned long long)attr->get(attr->data)); 648 }
644 649
645 ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size); 650 ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
651out:
646 mutex_unlock(&attr->mutex); 652 mutex_unlock(&attr->mutex);
647 return ret; 653 return ret;
648} 654}
@@ -657,7 +663,6 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
657 ssize_t ret; 663 ssize_t ret;
658 664
659 attr = file->private_data; 665 attr = file->private_data;
660
661 if (!attr->set) 666 if (!attr->set)
662 return -EACCES; 667 return -EACCES;
663 668
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 36b7abefacbe..ebe996ac2589 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2068,7 +2068,7 @@ __simple_attr_check_format(const char *fmt, ...)
2068} 2068}
2069 2069
2070int simple_attr_open(struct inode *inode, struct file *file, 2070int simple_attr_open(struct inode *inode, struct file *file,
2071 u64 (*get)(void *), void (*set)(void *, u64), 2071 int (*get)(void *, u64 *), int (*set)(void *, u64),
2072 const char *fmt); 2072 const char *fmt);
2073int simple_attr_close(struct inode *inode, struct file *file); 2073int simple_attr_close(struct inode *inode, struct file *file);
2074ssize_t simple_attr_read(struct file *file, char __user *buf, 2074ssize_t simple_attr_read(struct file *file, char __user *buf,
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index 23985a278bbb..a50a311554cc 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -134,23 +134,26 @@ bool should_fail(struct fault_attr *attr, ssize_t size)
134 134
135#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS 135#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
136 136
137static void debugfs_ul_set(void *data, u64 val) 137static int debugfs_ul_set(void *data, u64 val)
138{ 138{
139 *(unsigned long *)data = val; 139 *(unsigned long *)data = val;
140 return 0;
140} 141}
141 142
142#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER 143#ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
143static void debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val) 144static int debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val)
144{ 145{
145 *(unsigned long *)data = 146 *(unsigned long *)data =
146 val < MAX_STACK_TRACE_DEPTH ? 147 val < MAX_STACK_TRACE_DEPTH ?
147 val : MAX_STACK_TRACE_DEPTH; 148 val : MAX_STACK_TRACE_DEPTH;
149 return 0;
148} 150}
149#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */ 151#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
150 152
151static u64 debugfs_ul_get(void *data) 153static int debugfs_ul_get(void *data, u64 *val)
152{ 154{
153 return *(unsigned long *)data; 155 *val = *(unsigned long *)data;
156 return 0;
154} 157}
155 158
156DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n"); 159DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n");
@@ -174,14 +177,16 @@ static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
174} 177}
175#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */ 178#endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
176 179
177static void debugfs_atomic_t_set(void *data, u64 val) 180static int debugfs_atomic_t_set(void *data, u64 val)
178{ 181{
179 atomic_set((atomic_t *)data, val); 182 atomic_set((atomic_t *)data, val);
183 return 0;
180} 184}
181 185
182static u64 debugfs_atomic_t_get(void *data) 186static int debugfs_atomic_t_get(void *data, u64 *val)
183{ 187{
184 return atomic_read((atomic_t *)data); 188 *val = atomic_read((atomic_t *)data);
189 return 0;
185} 190}
186 191
187DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, 192DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get,
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 3c4fe26096fc..32fbf8006969 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1186,38 +1186,38 @@ static struct notifier_block kvm_cpu_notifier = {
1186 .priority = 20, /* must be > scheduler priority */ 1186 .priority = 20, /* must be > scheduler priority */
1187}; 1187};
1188 1188
1189static u64 vm_stat_get(void *_offset) 1189static int vm_stat_get(void *_offset, u64 *val)
1190{ 1190{
1191 unsigned offset = (long)_offset; 1191 unsigned offset = (long)_offset;
1192 u64 total = 0;
1193 struct kvm *kvm; 1192 struct kvm *kvm;
1194 1193
1194 *val = 0;
1195 spin_lock(&kvm_lock); 1195 spin_lock(&kvm_lock);
1196 list_for_each_entry(kvm, &vm_list, vm_list) 1196 list_for_each_entry(kvm, &vm_list, vm_list)
1197 total += *(u32 *)((void *)kvm + offset); 1197 *val += *(u32 *)((void *)kvm + offset);
1198 spin_unlock(&kvm_lock); 1198 spin_unlock(&kvm_lock);
1199 return total; 1199 return 0;
1200} 1200}
1201 1201
1202DEFINE_SIMPLE_ATTRIBUTE(vm_stat_fops, vm_stat_get, NULL, "%llu\n"); 1202DEFINE_SIMPLE_ATTRIBUTE(vm_stat_fops, vm_stat_get, NULL, "%llu\n");
1203 1203
1204static u64 vcpu_stat_get(void *_offset) 1204static int vcpu_stat_get(void *_offset, u64 *val)
1205{ 1205{
1206 unsigned offset = (long)_offset; 1206 unsigned offset = (long)_offset;
1207 u64 total = 0;
1208 struct kvm *kvm; 1207 struct kvm *kvm;
1209 struct kvm_vcpu *vcpu; 1208 struct kvm_vcpu *vcpu;
1210 int i; 1209 int i;
1211 1210
1211 *val = 0;
1212 spin_lock(&kvm_lock); 1212 spin_lock(&kvm_lock);
1213 list_for_each_entry(kvm, &vm_list, vm_list) 1213 list_for_each_entry(kvm, &vm_list, vm_list)
1214 for (i = 0; i < KVM_MAX_VCPUS; ++i) { 1214 for (i = 0; i < KVM_MAX_VCPUS; ++i) {
1215 vcpu = kvm->vcpus[i]; 1215 vcpu = kvm->vcpus[i];
1216 if (vcpu) 1216 if (vcpu)
1217 total += *(u32 *)((void *)vcpu + offset); 1217 *val += *(u32 *)((void *)vcpu + offset);
1218 } 1218 }
1219 spin_unlock(&kvm_lock); 1219 spin_unlock(&kvm_lock);
1220 return total; 1220 return 0;
1221} 1221}
1222 1222
1223DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_fops, vcpu_stat_get, NULL, "%llu\n"); 1223DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_fops, vcpu_stat_get, NULL, "%llu\n");