aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hostfs/hostfs_kern.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hostfs/hostfs_kern.c')
-rw-r--r--fs/hostfs/hostfs_kern.c112
1 files changed, 62 insertions, 50 deletions
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index e021188ca110..b83a0343378b 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -24,6 +24,7 @@ struct hostfs_inode_info {
24 int fd; 24 int fd;
25 fmode_t mode; 25 fmode_t mode;
26 struct inode vfs_inode; 26 struct inode vfs_inode;
27 struct mutex open_mutex;
27}; 28};
28 29
29static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) 30static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
@@ -92,16 +93,22 @@ static char *__dentry_name(struct dentry *dentry, char *name)
92 __putname(name); 93 __putname(name);
93 return NULL; 94 return NULL;
94 } 95 }
96
97 /*
98 * This function relies on the fact that dentry_path_raw() will place
99 * the path name at the end of the provided buffer.
100 */
101 BUG_ON(p + strlen(p) + 1 != name + PATH_MAX);
102
95 strlcpy(name, root, PATH_MAX); 103 strlcpy(name, root, PATH_MAX);
96 if (len > p - name) { 104 if (len > p - name) {
97 __putname(name); 105 __putname(name);
98 return NULL; 106 return NULL;
99 } 107 }
100 if (p > name + len) { 108
101 char *s = name + len; 109 if (p > name + len)
102 while ((*s++ = *p++) != '\0') 110 strcpy(name + len, p);
103 ; 111
104 }
105 return name; 112 return name;
106} 113}
107 114
@@ -135,21 +142,19 @@ static char *follow_link(char *link)
135 int len, n; 142 int len, n;
136 char *name, *resolved, *end; 143 char *name, *resolved, *end;
137 144
138 len = 64; 145 name = __getname();
139 while (1) { 146 if (!name) {
140 n = -ENOMEM; 147 n = -ENOMEM;
141 name = kmalloc(len, GFP_KERNEL); 148 goto out_free;
142 if (name == NULL)
143 goto out;
144
145 n = hostfs_do_readlink(link, name, len);
146 if (n < len)
147 break;
148 len *= 2;
149 kfree(name);
150 } 149 }
150
151 n = hostfs_do_readlink(link, name, PATH_MAX);
151 if (n < 0) 152 if (n < 0)
152 goto out_free; 153 goto out_free;
154 else if (n == PATH_MAX) {
155 n = -E2BIG;
156 goto out_free;
157 }
153 158
154 if (*name == '/') 159 if (*name == '/')
155 return name; 160 return name;
@@ -168,13 +173,12 @@ static char *follow_link(char *link)
168 } 173 }
169 174
170 sprintf(resolved, "%s%s", link, name); 175 sprintf(resolved, "%s%s", link, name);
171 kfree(name); 176 __putname(name);
172 kfree(link); 177 kfree(link);
173 return resolved; 178 return resolved;
174 179
175 out_free: 180 out_free:
176 kfree(name); 181 __putname(name);
177 out:
178 return ERR_PTR(n); 182 return ERR_PTR(n);
179} 183}
180 184
@@ -225,6 +229,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
225 hi->fd = -1; 229 hi->fd = -1;
226 hi->mode = 0; 230 hi->mode = 0;
227 inode_init_once(&hi->vfs_inode); 231 inode_init_once(&hi->vfs_inode);
232 mutex_init(&hi->open_mutex);
228 return &hi->vfs_inode; 233 return &hi->vfs_inode;
229} 234}
230 235
@@ -257,6 +262,9 @@ static int hostfs_show_options(struct seq_file *seq, struct dentry *root)
257 if (strlen(root_path) > offset) 262 if (strlen(root_path) > offset)
258 seq_printf(seq, ",%s", root_path + offset); 263 seq_printf(seq, ",%s", root_path + offset);
259 264
265 if (append)
266 seq_puts(seq, ",append");
267
260 return 0; 268 return 0;
261} 269}
262 270
@@ -284,6 +292,7 @@ static int hostfs_readdir(struct file *file, struct dir_context *ctx)
284 if (dir == NULL) 292 if (dir == NULL)
285 return -error; 293 return -error;
286 next = ctx->pos; 294 next = ctx->pos;
295 seek_dir(dir, next);
287 while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) { 296 while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) {
288 if (!dir_emit(ctx, name, len, ino, type)) 297 if (!dir_emit(ctx, name, len, ino, type))
289 break; 298 break;
@@ -293,13 +302,12 @@ static int hostfs_readdir(struct file *file, struct dir_context *ctx)
293 return 0; 302 return 0;
294} 303}
295 304
296static int hostfs_file_open(struct inode *ino, struct file *file) 305static int hostfs_open(struct inode *ino, struct file *file)
297{ 306{
298 static DEFINE_MUTEX(open_mutex);
299 char *name; 307 char *name;
300 fmode_t mode = 0; 308 fmode_t mode;
301 int err; 309 int err;
302 int r = 0, w = 0, fd; 310 int r, w, fd;
303 311
304 mode = file->f_mode & (FMODE_READ | FMODE_WRITE); 312 mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
305 if ((mode & HOSTFS_I(ino)->mode) == mode) 313 if ((mode & HOSTFS_I(ino)->mode) == mode)
@@ -308,12 +316,12 @@ static int hostfs_file_open(struct inode *ino, struct file *file)
308 mode |= HOSTFS_I(ino)->mode; 316 mode |= HOSTFS_I(ino)->mode;
309 317
310retry: 318retry:
319 r = w = 0;
320
311 if (mode & FMODE_READ) 321 if (mode & FMODE_READ)
312 r = 1; 322 r = 1;
313 if (mode & FMODE_WRITE) 323 if (mode & FMODE_WRITE)
314 w = 1; 324 r = w = 1;
315 if (w)
316 r = 1;
317 325
318 name = dentry_name(file->f_path.dentry); 326 name = dentry_name(file->f_path.dentry);
319 if (name == NULL) 327 if (name == NULL)
@@ -324,15 +332,16 @@ retry:
324 if (fd < 0) 332 if (fd < 0)
325 return fd; 333 return fd;
326 334
327 mutex_lock(&open_mutex); 335 mutex_lock(&HOSTFS_I(ino)->open_mutex);
328 /* somebody else had handled it first? */ 336 /* somebody else had handled it first? */
329 if ((mode & HOSTFS_I(ino)->mode) == mode) { 337 if ((mode & HOSTFS_I(ino)->mode) == mode) {
330 mutex_unlock(&open_mutex); 338 mutex_unlock(&HOSTFS_I(ino)->open_mutex);
339 close_file(&fd);
331 return 0; 340 return 0;
332 } 341 }
333 if ((mode | HOSTFS_I(ino)->mode) != mode) { 342 if ((mode | HOSTFS_I(ino)->mode) != mode) {
334 mode |= HOSTFS_I(ino)->mode; 343 mode |= HOSTFS_I(ino)->mode;
335 mutex_unlock(&open_mutex); 344 mutex_unlock(&HOSTFS_I(ino)->open_mutex);
336 close_file(&fd); 345 close_file(&fd);
337 goto retry; 346 goto retry;
338 } 347 }
@@ -342,12 +351,12 @@ retry:
342 err = replace_file(fd, HOSTFS_I(ino)->fd); 351 err = replace_file(fd, HOSTFS_I(ino)->fd);
343 close_file(&fd); 352 close_file(&fd);
344 if (err < 0) { 353 if (err < 0) {
345 mutex_unlock(&open_mutex); 354 mutex_unlock(&HOSTFS_I(ino)->open_mutex);
346 return err; 355 return err;
347 } 356 }
348 } 357 }
349 HOSTFS_I(ino)->mode = mode; 358 HOSTFS_I(ino)->mode = mode;
350 mutex_unlock(&open_mutex); 359 mutex_unlock(&HOSTFS_I(ino)->open_mutex);
351 360
352 return 0; 361 return 0;
353} 362}
@@ -382,7 +391,7 @@ static const struct file_operations hostfs_file_fops = {
382 .read_iter = generic_file_read_iter, 391 .read_iter = generic_file_read_iter,
383 .write_iter = generic_file_write_iter, 392 .write_iter = generic_file_write_iter,
384 .mmap = generic_file_mmap, 393 .mmap = generic_file_mmap,
385 .open = hostfs_file_open, 394 .open = hostfs_open,
386 .release = hostfs_file_release, 395 .release = hostfs_file_release,
387 .fsync = hostfs_fsync, 396 .fsync = hostfs_fsync,
388}; 397};
@@ -391,6 +400,8 @@ static const struct file_operations hostfs_dir_fops = {
391 .llseek = generic_file_llseek, 400 .llseek = generic_file_llseek,
392 .iterate = hostfs_readdir, 401 .iterate = hostfs_readdir,
393 .read = generic_read_dir, 402 .read = generic_read_dir,
403 .open = hostfs_open,
404 .fsync = hostfs_fsync,
394}; 405};
395 406
396static int hostfs_writepage(struct page *page, struct writeback_control *wbc) 407static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
@@ -398,7 +409,7 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
398 struct address_space *mapping = page->mapping; 409 struct address_space *mapping = page->mapping;
399 struct inode *inode = mapping->host; 410 struct inode *inode = mapping->host;
400 char *buffer; 411 char *buffer;
401 unsigned long long base; 412 loff_t base = page_offset(page);
402 int count = PAGE_CACHE_SIZE; 413 int count = PAGE_CACHE_SIZE;
403 int end_index = inode->i_size >> PAGE_CACHE_SHIFT; 414 int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
404 int err; 415 int err;
@@ -407,7 +418,6 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
407 count = inode->i_size & (PAGE_CACHE_SIZE-1); 418 count = inode->i_size & (PAGE_CACHE_SIZE-1);
408 419
409 buffer = kmap(page); 420 buffer = kmap(page);
410 base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
411 421
412 err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count); 422 err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
413 if (err != count) { 423 if (err != count) {
@@ -432,26 +442,29 @@ static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
432static int hostfs_readpage(struct file *file, struct page *page) 442static int hostfs_readpage(struct file *file, struct page *page)
433{ 443{
434 char *buffer; 444 char *buffer;
435 long long start; 445 loff_t start = page_offset(page);
436 int err = 0; 446 int bytes_read, ret = 0;
437 447
438 start = (long long) page->index << PAGE_CACHE_SHIFT;
439 buffer = kmap(page); 448 buffer = kmap(page);
440 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer, 449 bytes_read = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
441 PAGE_CACHE_SIZE); 450 PAGE_CACHE_SIZE);
442 if (err < 0) 451 if (bytes_read < 0) {
452 ClearPageUptodate(page);
453 SetPageError(page);
454 ret = bytes_read;
443 goto out; 455 goto out;
456 }
444 457
445 memset(&buffer[err], 0, PAGE_CACHE_SIZE - err); 458 memset(buffer + bytes_read, 0, PAGE_CACHE_SIZE - bytes_read);
446 459
447 flush_dcache_page(page); 460 ClearPageError(page);
448 SetPageUptodate(page); 461 SetPageUptodate(page);
449 if (PageError(page)) ClearPageError(page); 462
450 err = 0;
451 out: 463 out:
464 flush_dcache_page(page);
452 kunmap(page); 465 kunmap(page);
453 unlock_page(page); 466 unlock_page(page);
454 return err; 467 return ret;
455} 468}
456 469
457static int hostfs_write_begin(struct file *file, struct address_space *mapping, 470static int hostfs_write_begin(struct file *file, struct address_space *mapping,
@@ -528,11 +541,13 @@ static int read_name(struct inode *ino, char *name)
528 init_special_inode(ino, st.mode & S_IFMT, rdev); 541 init_special_inode(ino, st.mode & S_IFMT, rdev);
529 ino->i_op = &hostfs_iops; 542 ino->i_op = &hostfs_iops;
530 break; 543 break;
531 544 case S_IFREG:
532 default:
533 ino->i_op = &hostfs_iops; 545 ino->i_op = &hostfs_iops;
534 ino->i_fop = &hostfs_file_fops; 546 ino->i_fop = &hostfs_file_fops;
535 ino->i_mapping->a_ops = &hostfs_aops; 547 ino->i_mapping->a_ops = &hostfs_aops;
548 break;
549 default:
550 return -EIO;
536 } 551 }
537 552
538 ino->i_ino = st.ino; 553 ino->i_ino = st.ino;
@@ -566,10 +581,7 @@ static int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
566 if (name == NULL) 581 if (name == NULL)
567 goto out_put; 582 goto out_put;
568 583
569 fd = file_create(name, 584 fd = file_create(name, mode & S_IFMT);
570 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
571 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
572 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
573 if (fd < 0) 585 if (fd < 0)
574 error = fd; 586 error = fd;
575 else 587 else