aboutsummaryrefslogtreecommitdiffstats
path: root/fs/libfs.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/libfs.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/libfs.c')
-rw-r--r--fs/libfs.c118
1 files changed, 79 insertions, 39 deletions
diff --git a/fs/libfs.c b/fs/libfs.c
index 0a9da95317f7..275ca4749a2e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -16,6 +16,11 @@
16 16
17#include <asm/uaccess.h> 17#include <asm/uaccess.h>
18 18
19static inline int simple_positive(struct dentry *dentry)
20{
21 return dentry->d_inode && !d_unhashed(dentry);
22}
23
19int simple_getattr(struct vfsmount *mnt, struct dentry *dentry, 24int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
20 struct kstat *stat) 25 struct kstat *stat)
21{ 26{
@@ -37,7 +42,7 @@ int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
37 * Retaining negative dentries for an in-memory filesystem just wastes 42 * Retaining negative dentries for an in-memory filesystem just wastes
38 * memory and lookup time: arrange for them to be deleted immediately. 43 * memory and lookup time: arrange for them to be deleted immediately.
39 */ 44 */
40static int simple_delete_dentry(struct dentry *dentry) 45static int simple_delete_dentry(const struct dentry *dentry)
41{ 46{
42 return 1; 47 return 1;
43} 48}
@@ -54,7 +59,7 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct na
54 59
55 if (dentry->d_name.len > NAME_MAX) 60 if (dentry->d_name.len > NAME_MAX)
56 return ERR_PTR(-ENAMETOOLONG); 61 return ERR_PTR(-ENAMETOOLONG);
57 dentry->d_op = &simple_dentry_operations; 62 d_set_d_op(dentry, &simple_dentry_operations);
58 d_add(dentry, NULL); 63 d_add(dentry, NULL);
59 return NULL; 64 return NULL;
60} 65}
@@ -76,7 +81,8 @@ int dcache_dir_close(struct inode *inode, struct file *file)
76 81
77loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) 82loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
78{ 83{
79 mutex_lock(&file->f_path.dentry->d_inode->i_mutex); 84 struct dentry *dentry = file->f_path.dentry;
85 mutex_lock(&dentry->d_inode->i_mutex);
80 switch (origin) { 86 switch (origin) {
81 case 1: 87 case 1:
82 offset += file->f_pos; 88 offset += file->f_pos;
@@ -84,7 +90,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
84 if (offset >= 0) 90 if (offset >= 0)
85 break; 91 break;
86 default: 92 default:
87 mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); 93 mutex_unlock(&dentry->d_inode->i_mutex);
88 return -EINVAL; 94 return -EINVAL;
89 } 95 }
90 if (offset != file->f_pos) { 96 if (offset != file->f_pos) {
@@ -94,21 +100,24 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
94 struct dentry *cursor = file->private_data; 100 struct dentry *cursor = file->private_data;
95 loff_t n = file->f_pos - 2; 101 loff_t n = file->f_pos - 2;
96 102
97 spin_lock(&dcache_lock); 103 spin_lock(&dentry->d_lock);
104 /* d_lock not required for cursor */
98 list_del(&cursor->d_u.d_child); 105 list_del(&cursor->d_u.d_child);
99 p = file->f_path.dentry->d_subdirs.next; 106 p = dentry->d_subdirs.next;
100 while (n && p != &file->f_path.dentry->d_subdirs) { 107 while (n && p != &dentry->d_subdirs) {
101 struct dentry *next; 108 struct dentry *next;
102 next = list_entry(p, struct dentry, d_u.d_child); 109 next = list_entry(p, struct dentry, d_u.d_child);
103 if (!d_unhashed(next) && next->d_inode) 110 spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
111 if (simple_positive(next))
104 n--; 112 n--;
113 spin_unlock(&next->d_lock);
105 p = p->next; 114 p = p->next;
106 } 115 }
107 list_add_tail(&cursor->d_u.d_child, p); 116 list_add_tail(&cursor->d_u.d_child, p);
108 spin_unlock(&dcache_lock); 117 spin_unlock(&dentry->d_lock);
109 } 118 }
110 } 119 }
111 mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); 120 mutex_unlock(&dentry->d_inode->i_mutex);
112 return offset; 121 return offset;
113} 122}
114 123
@@ -148,29 +157,35 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
148 i++; 157 i++;
149 /* fallthrough */ 158 /* fallthrough */
150 default: 159 default:
151 spin_lock(&dcache_lock); 160 spin_lock(&dentry->d_lock);
152 if (filp->f_pos == 2) 161 if (filp->f_pos == 2)
153 list_move(q, &dentry->d_subdirs); 162 list_move(q, &dentry->d_subdirs);
154 163
155 for (p=q->next; p != &dentry->d_subdirs; p=p->next) { 164 for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
156 struct dentry *next; 165 struct dentry *next;
157 next = list_entry(p, struct dentry, d_u.d_child); 166 next = list_entry(p, struct dentry, d_u.d_child);
158 if (d_unhashed(next) || !next->d_inode) 167 spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
168 if (!simple_positive(next)) {
169 spin_unlock(&next->d_lock);
159 continue; 170 continue;
171 }
160 172
161 spin_unlock(&dcache_lock); 173 spin_unlock(&next->d_lock);
174 spin_unlock(&dentry->d_lock);
162 if (filldir(dirent, next->d_name.name, 175 if (filldir(dirent, next->d_name.name,
163 next->d_name.len, filp->f_pos, 176 next->d_name.len, filp->f_pos,
164 next->d_inode->i_ino, 177 next->d_inode->i_ino,
165 dt_type(next->d_inode)) < 0) 178 dt_type(next->d_inode)) < 0)
166 return 0; 179 return 0;
167 spin_lock(&dcache_lock); 180 spin_lock(&dentry->d_lock);
181 spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
168 /* next is still alive */ 182 /* next is still alive */
169 list_move(q, p); 183 list_move(q, p);
184 spin_unlock(&next->d_lock);
170 p = q; 185 p = q;
171 filp->f_pos++; 186 filp->f_pos++;
172 } 187 }
173 spin_unlock(&dcache_lock); 188 spin_unlock(&dentry->d_lock);
174 } 189 }
175 return 0; 190 return 0;
176} 191}
@@ -201,9 +216,9 @@ static const struct super_operations simple_super_operations = {
201 * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that 216 * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
202 * will never be mountable) 217 * will never be mountable)
203 */ 218 */
204int get_sb_pseudo(struct file_system_type *fs_type, char *name, 219struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
205 const struct super_operations *ops, unsigned long magic, 220 const struct super_operations *ops,
206 struct vfsmount *mnt) 221 const struct dentry_operations *dops, unsigned long magic)
207{ 222{
208 struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); 223 struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
209 struct dentry *dentry; 224 struct dentry *dentry;
@@ -211,7 +226,7 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
211 struct qstr d_name = {.name = name, .len = strlen(name)}; 226 struct qstr d_name = {.name = name, .len = strlen(name)};
212 227
213 if (IS_ERR(s)) 228 if (IS_ERR(s))
214 return PTR_ERR(s); 229 return ERR_CAST(s);
215 230
216 s->s_flags = MS_NOUSER; 231 s->s_flags = MS_NOUSER;
217 s->s_maxbytes = MAX_LFS_FILESIZE; 232 s->s_maxbytes = MAX_LFS_FILESIZE;
@@ -240,13 +255,13 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
240 dentry->d_parent = dentry; 255 dentry->d_parent = dentry;
241 d_instantiate(dentry, root); 256 d_instantiate(dentry, root);
242 s->s_root = dentry; 257 s->s_root = dentry;
258 s->s_d_op = dops;
243 s->s_flags |= MS_ACTIVE; 259 s->s_flags |= MS_ACTIVE;
244 simple_set_mnt(mnt, s); 260 return dget(s->s_root);
245 return 0;
246 261
247Enomem: 262Enomem:
248 deactivate_locked_super(s); 263 deactivate_locked_super(s);
249 return -ENOMEM; 264 return ERR_PTR(-ENOMEM);
250} 265}
251 266
252int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) 267int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
@@ -255,29 +270,29 @@ int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *den
255 270
256 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; 271 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
257 inc_nlink(inode); 272 inc_nlink(inode);
258 atomic_inc(&inode->i_count); 273 ihold(inode);
259 dget(dentry); 274 dget(dentry);
260 d_instantiate(dentry, inode); 275 d_instantiate(dentry, inode);
261 return 0; 276 return 0;
262} 277}
263 278
264static inline int simple_positive(struct dentry *dentry)
265{
266 return dentry->d_inode && !d_unhashed(dentry);
267}
268
269int simple_empty(struct dentry *dentry) 279int simple_empty(struct dentry *dentry)
270{ 280{
271 struct dentry *child; 281 struct dentry *child;
272 int ret = 0; 282 int ret = 0;
273 283
274 spin_lock(&dcache_lock); 284 spin_lock(&dentry->d_lock);
275 list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) 285 list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
276 if (simple_positive(child)) 286 spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
287 if (simple_positive(child)) {
288 spin_unlock(&child->d_lock);
277 goto out; 289 goto out;
290 }
291 spin_unlock(&child->d_lock);
292 }
278 ret = 1; 293 ret = 1;
279out: 294out:
280 spin_unlock(&dcache_lock); 295 spin_unlock(&dentry->d_lock);
281 return ret; 296 return ret;
282} 297}
283 298
@@ -807,7 +822,7 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
807 goto out; 822 goto out;
808 823
809 attr->set_buf[size] = '\0'; 824 attr->set_buf[size] = '\0';
810 val = simple_strtol(attr->set_buf, NULL, 0); 825 val = simple_strtoll(attr->set_buf, NULL, 0);
811 ret = attr->set(attr->data, val); 826 ret = attr->set(attr->data, val);
812 if (ret == 0) 827 if (ret == 0)
813 ret = len; /* on success, claim we got the whole input */ 828 ret = len; /* on success, claim we got the whole input */
@@ -892,10 +907,6 @@ EXPORT_SYMBOL_GPL(generic_fh_to_parent);
892 */ 907 */
893int generic_file_fsync(struct file *file, int datasync) 908int generic_file_fsync(struct file *file, int datasync)
894{ 909{
895 struct writeback_control wbc = {
896 .sync_mode = WB_SYNC_ALL,
897 .nr_to_write = 0, /* metadata-only; caller takes care of data */
898 };
899 struct inode *inode = file->f_mapping->host; 910 struct inode *inode = file->f_mapping->host;
900 int err; 911 int err;
901 int ret; 912 int ret;
@@ -906,13 +917,42 @@ int generic_file_fsync(struct file *file, int datasync)
906 if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) 917 if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
907 return ret; 918 return ret;
908 919
909 err = sync_inode(inode, &wbc); 920 err = sync_inode_metadata(inode, 1);
910 if (ret == 0) 921 if (ret == 0)
911 ret = err; 922 ret = err;
912 return ret; 923 return ret;
913} 924}
914EXPORT_SYMBOL(generic_file_fsync); 925EXPORT_SYMBOL(generic_file_fsync);
915 926
927/**
928 * generic_check_addressable - Check addressability of file system
929 * @blocksize_bits: log of file system block size
930 * @num_blocks: number of blocks in file system
931 *
932 * Determine whether a file system with @num_blocks blocks (and a
933 * block size of 2**@blocksize_bits) is addressable by the sector_t
934 * and page cache of the system. Return 0 if so and -EFBIG otherwise.
935 */
936int generic_check_addressable(unsigned blocksize_bits, u64 num_blocks)
937{
938 u64 last_fs_block = num_blocks - 1;
939 u64 last_fs_page =
940 last_fs_block >> (PAGE_CACHE_SHIFT - blocksize_bits);
941
942 if (unlikely(num_blocks == 0))
943 return 0;
944
945 if ((blocksize_bits < 9) || (blocksize_bits > PAGE_CACHE_SHIFT))
946 return -EINVAL;
947
948 if ((last_fs_block > (sector_t)(~0ULL) >> (blocksize_bits - 9)) ||
949 (last_fs_page > (pgoff_t)(~0ULL))) {
950 return -EFBIG;
951 }
952 return 0;
953}
954EXPORT_SYMBOL(generic_check_addressable);
955
916/* 956/*
917 * No-op implementation of ->fsync for in-memory filesystems. 957 * No-op implementation of ->fsync for in-memory filesystems.
918 */ 958 */
@@ -926,7 +966,7 @@ EXPORT_SYMBOL(dcache_dir_lseek);
926EXPORT_SYMBOL(dcache_dir_open); 966EXPORT_SYMBOL(dcache_dir_open);
927EXPORT_SYMBOL(dcache_readdir); 967EXPORT_SYMBOL(dcache_readdir);
928EXPORT_SYMBOL(generic_read_dir); 968EXPORT_SYMBOL(generic_read_dir);
929EXPORT_SYMBOL(get_sb_pseudo); 969EXPORT_SYMBOL(mount_pseudo);
930EXPORT_SYMBOL(simple_write_begin); 970EXPORT_SYMBOL(simple_write_begin);
931EXPORT_SYMBOL(simple_write_end); 971EXPORT_SYMBOL(simple_write_end);
932EXPORT_SYMBOL(simple_dir_inode_operations); 972EXPORT_SYMBOL(simple_dir_inode_operations);