diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/libfs.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.c | 118 |
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 | ||
19 | static inline int simple_positive(struct dentry *dentry) | ||
20 | { | ||
21 | return dentry->d_inode && !d_unhashed(dentry); | ||
22 | } | ||
23 | |||
19 | int simple_getattr(struct vfsmount *mnt, struct dentry *dentry, | 24 | int 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 | */ |
40 | static int simple_delete_dentry(struct dentry *dentry) | 45 | static 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 | ||
77 | loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) | 82 | loff_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 | */ |
204 | int get_sb_pseudo(struct file_system_type *fs_type, char *name, | 219 | struct 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 | ||
247 | Enomem: | 262 | Enomem: |
248 | deactivate_locked_super(s); | 263 | deactivate_locked_super(s); |
249 | return -ENOMEM; | 264 | return ERR_PTR(-ENOMEM); |
250 | } | 265 | } |
251 | 266 | ||
252 | int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | 267 | int 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 | ||
264 | static inline int simple_positive(struct dentry *dentry) | ||
265 | { | ||
266 | return dentry->d_inode && !d_unhashed(dentry); | ||
267 | } | ||
268 | |||
269 | int simple_empty(struct dentry *dentry) | 279 | int 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; |
279 | out: | 294 | out: |
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 | */ |
893 | int generic_file_fsync(struct file *file, int datasync) | 908 | int 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 | } |
914 | EXPORT_SYMBOL(generic_file_fsync); | 925 | EXPORT_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 | */ | ||
936 | int 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 | } | ||
954 | EXPORT_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); | |||
926 | EXPORT_SYMBOL(dcache_dir_open); | 966 | EXPORT_SYMBOL(dcache_dir_open); |
927 | EXPORT_SYMBOL(dcache_readdir); | 967 | EXPORT_SYMBOL(dcache_readdir); |
928 | EXPORT_SYMBOL(generic_read_dir); | 968 | EXPORT_SYMBOL(generic_read_dir); |
929 | EXPORT_SYMBOL(get_sb_pseudo); | 969 | EXPORT_SYMBOL(mount_pseudo); |
930 | EXPORT_SYMBOL(simple_write_begin); | 970 | EXPORT_SYMBOL(simple_write_begin); |
931 | EXPORT_SYMBOL(simple_write_end); | 971 | EXPORT_SYMBOL(simple_write_end); |
932 | EXPORT_SYMBOL(simple_dir_inode_operations); | 972 | EXPORT_SYMBOL(simple_dir_inode_operations); |