2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/kernel.h>
18 #include <linux/jhash.h>
19 #include <linux/namei.h>
20 #include <linux/slab.h>
21 #include <linux/pagemap.h>
25 static int pohmelfs_cmp_hash(struct pohmelfs_name
*n
, u32 hash
)
35 static struct pohmelfs_name
*pohmelfs_search_hash_unprecise(struct pohmelfs_inode
*pi
, u32 hash
)
37 struct rb_node
*n
= pi
->hash_root
.rb_node
;
38 struct pohmelfs_name
*tmp
= NULL
;
42 tmp
= rb_entry(n
, struct pohmelfs_name
, hash_node
);
44 cmp
= pohmelfs_cmp_hash(tmp
, hash
);
57 struct pohmelfs_name
*pohmelfs_search_hash(struct pohmelfs_inode
*pi
, u32 hash
)
59 struct pohmelfs_name
*tmp
;
61 tmp
= pohmelfs_search_hash_unprecise(pi
, hash
);
62 if (tmp
&& (tmp
->hash
== hash
))
68 static void __pohmelfs_name_del(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*node
)
70 rb_erase(&node
->hash_node
, &parent
->hash_root
);
74 * Remove name cache entry from its caches and free it.
76 static void pohmelfs_name_free(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*node
)
78 __pohmelfs_name_del(parent
, node
);
79 list_del(&node
->sync_create_entry
);
83 static struct pohmelfs_name
*pohmelfs_insert_hash(struct pohmelfs_inode
*pi
,
84 struct pohmelfs_name
*new)
86 struct rb_node
**n
= &pi
->hash_root
.rb_node
, *parent
= NULL
;
87 struct pohmelfs_name
*ret
= NULL
, *tmp
;
93 tmp
= rb_entry(parent
, struct pohmelfs_name
, hash_node
);
95 cmp
= pohmelfs_cmp_hash(tmp
, new->hash
);
99 n
= &parent
->rb_right
;
107 printk("%s: exist: parent: %llu, ino: %llu, hash: %x, len: %u, data: '%s', "
108 "new: ino: %llu, hash: %x, len: %u, data: '%s'.\n",
110 ret
->ino
, ret
->hash
, ret
->len
, ret
->data
,
111 new->ino
, new->hash
, new->len
, new->data
);
116 rb_link_node(&new->hash_node
, parent
, n
);
117 rb_insert_color(&new->hash_node
, &pi
->hash_root
);
123 * Free name cache for given inode.
125 void pohmelfs_free_names(struct pohmelfs_inode
*parent
)
127 struct rb_node
*rb_node
;
128 struct pohmelfs_name
*n
;
130 for (rb_node
= rb_first(&parent
->hash_root
); rb_node
;) {
131 n
= rb_entry(rb_node
, struct pohmelfs_name
, hash_node
);
132 rb_node
= rb_next(rb_node
);
134 pohmelfs_name_free(parent
, n
);
138 static void pohmelfs_fix_offset(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*node
)
140 parent
->total_len
-= node
->len
;
144 * Free name cache entry helper.
146 void pohmelfs_name_del(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*node
)
148 pohmelfs_fix_offset(parent
, node
);
149 pohmelfs_name_free(parent
, node
);
153 * Insert new name cache entry into all hash cache.
155 static int pohmelfs_insert_name(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*n
)
157 struct pohmelfs_name
*name
;
159 name
= pohmelfs_insert_hash(parent
, n
);
163 parent
->total_len
+= n
->len
;
164 list_add_tail(&n
->sync_create_entry
, &parent
->sync_create_list
);
170 * Allocate new name cache entry.
172 static struct pohmelfs_name
*pohmelfs_name_alloc(unsigned int len
)
174 struct pohmelfs_name
*n
;
176 n
= kzalloc(sizeof(struct pohmelfs_name
) + len
, GFP_KERNEL
);
180 INIT_LIST_HEAD(&n
->sync_create_entry
);
182 n
->data
= (char *)(n
+1);
188 * Add new name entry into directory's cache.
190 static int pohmelfs_add_dir(struct pohmelfs_sb
*psb
, struct pohmelfs_inode
*parent
,
191 struct pohmelfs_inode
*npi
, struct qstr
*str
, unsigned int mode
, int link
)
194 struct pohmelfs_name
*n
;
196 n
= pohmelfs_name_alloc(str
->len
+ 1);
204 sprintf(n
->data
, "%s", str
->name
);
206 mutex_lock(&parent
->offset_lock
);
207 err
= pohmelfs_insert_name(parent
, n
);
208 mutex_unlock(&parent
->offset_lock
);
225 * Create new inode for given parameters (name, inode info, parent).
226 * This does not create object on the server, it will be synced there during writeback.
228 struct pohmelfs_inode
*pohmelfs_new_inode(struct pohmelfs_sb
*psb
,
229 struct pohmelfs_inode
*parent
, struct qstr
*str
,
230 struct netfs_inode_info
*info
, int link
)
232 struct inode
*new = NULL
;
233 struct pohmelfs_inode
*npi
;
236 dprintk("%s: creating inode: parent: %llu, ino: %llu, str: %p.\n",
237 __func__
, (parent
) ? parent
->ino
: 0, info
->ino
, str
);
240 new = iget_locked(psb
->sb
, info
->ino
);
244 npi
= POHMELFS_I(new);
245 npi
->ino
= info
->ino
;
248 if (new->i_state
& I_NEW
) {
249 dprintk("%s: filling VFS inode: %lu/%llu.\n",
250 __func__
, new->i_ino
, info
->ino
);
251 pohmelfs_fill_inode(new, info
);
253 if (S_ISDIR(info
->mode
)) {
258 s
.hash
= jhash(s
.name
, s
.len
, 0);
260 err
= pohmelfs_add_dir(psb
, npi
, npi
, &s
, info
->mode
, 0);
266 s
.hash
= jhash(s
.name
, s
.len
, 0);
268 err
= pohmelfs_add_dir(psb
, npi
, (parent
) ? parent
: npi
, &s
,
269 (parent
) ? parent
->vfs_inode
.i_mode
: npi
->vfs_inode
.i_mode
, 0);
277 err
= pohmelfs_add_dir(psb
, parent
, npi
, str
, info
->mode
, link
);
279 dprintk("%s: %s inserted name: '%s', new_offset: %llu, ino: %llu, parent: %llu.\n",
280 __func__
, (err
) ? "unsuccessfully" : "successfully",
281 str
->name
, parent
->total_len
, info
->ino
, parent
->ino
);
283 if (err
&& err
!= -EEXIST
)
288 if (new->i_state
& I_NEW
) {
290 mark_inode_dirty(&parent
->vfs_inode
);
291 mark_inode_dirty(new);
294 set_bit(NETFS_INODE_OWNED
, &npi
->state
);
295 npi
->lock_type
= POHMELFS_WRITE_LOCK
;
296 unlock_new_inode(new);
301 printk("%s: putting inode: %p, npi: %p, error: %d.\n", __func__
, new, npi
, err
);
307 static int pohmelfs_remote_sync_complete(struct page
**pages
, unsigned int page_num
,
308 void *private, int err
)
310 struct pohmelfs_inode
*pi
= private;
311 struct pohmelfs_sb
*psb
= POHMELFS_SB(pi
->vfs_inode
.i_sb
);
313 dprintk("%s: ino: %llu, err: %d.\n", __func__
, pi
->ino
, err
);
318 pohmelfs_put_inode(pi
);
324 * Receive directory content from the server.
325 * This should be only done for objects, which were not created locally,
326 * and which were not synced previously.
328 static int pohmelfs_sync_remote_dir(struct pohmelfs_inode
*pi
)
330 struct inode
*inode
= &pi
->vfs_inode
;
331 struct pohmelfs_sb
*psb
= POHMELFS_SB(inode
->i_sb
);
332 long ret
= psb
->wait_on_page_timeout
;
335 dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n",
336 __func__
, pi
->ino
, pi
->state
, test_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
));
338 if (test_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &pi
->state
))
346 err
= pohmelfs_meta_command(pi
, NETFS_READDIR
, NETFS_TRANS_SINGLE_DST
,
347 pohmelfs_remote_sync_complete
, pi
, 0);
352 ret
= wait_event_interruptible_timeout(psb
->wait
,
353 test_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &pi
->state
) || pi
->error
, ret
);
354 dprintk("%s: awake dir: %llu, ret: %ld, err: %d.\n", __func__
, pi
->ino
, ret
, pi
->error
);
368 clear_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
);
373 static int pohmelfs_dir_open(struct inode
*inode
, struct file
*file
)
375 file
->private_data
= NULL
;
380 * VFS readdir callback. Syncs directory content from server if needed,
381 * and provides direntry info to the userspace.
383 static int pohmelfs_readdir(struct file
*file
, void *dirent
, filldir_t filldir
)
385 struct inode
*inode
= file
->f_path
.dentry
->d_inode
;
386 struct pohmelfs_inode
*pi
= POHMELFS_I(inode
);
387 struct pohmelfs_name
*n
;
388 struct rb_node
*rb_node
;
392 dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n",
393 __func__
, pi
->ino
, (u64
)file
->f_pos
,
394 (unsigned long)file
->private_data
);
396 err
= pohmelfs_data_lock(pi
, 0, ~0, POHMELFS_READ_LOCK
);
400 err
= pohmelfs_sync_remote_dir(pi
);
404 if (file
->private_data
&& (file
->private_data
== (void *)(unsigned long)file
->f_pos
))
407 mutex_lock(&pi
->offset_lock
);
408 n
= pohmelfs_search_hash_unprecise(pi
, (unsigned long)file
->private_data
);
411 mode
= (n
->mode
>> 12) & 15;
413 dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, "
414 "mode: %o/%o, fpos: %llu, hash: %08x.\n",
415 __func__
, file
->f_pos
, pi
->ino
, n
->data
, n
->len
,
416 n
->ino
, n
->mode
, mode
, file
->f_pos
, n
->hash
);
418 file
->private_data
= (void *)(unsigned long)n
->hash
;
421 err
= filldir(dirent
, n
->data
, n
->len
, file
->f_pos
, n
->ino
, mode
);
424 dprintk("%s: err: %d.\n", __func__
, err
);
431 rb_node
= rb_next(&n
->hash_node
);
433 if (!rb_node
|| (rb_node
== &n
->hash_node
)) {
434 file
->private_data
= (void *)(unsigned long)file
->f_pos
;
438 n
= rb_entry(rb_node
, struct pohmelfs_name
, hash_node
);
440 mutex_unlock(&pi
->offset_lock
);
445 static loff_t
pohmelfs_dir_lseek(struct file
*file
, loff_t offset
, int origin
)
447 file
->f_pos
= offset
;
448 file
->private_data
= NULL
;
452 const struct file_operations pohmelfs_dir_fops
= {
453 .open
= pohmelfs_dir_open
,
454 .read
= generic_read_dir
,
455 .llseek
= pohmelfs_dir_lseek
,
456 .readdir
= pohmelfs_readdir
,
460 * Lookup single object on server.
462 static int pohmelfs_lookup_single(struct pohmelfs_inode
*parent
,
463 struct qstr
*str
, u64 ino
)
465 struct pohmelfs_sb
*psb
= POHMELFS_SB(parent
->vfs_inode
.i_sb
);
466 long ret
= msecs_to_jiffies(5000);
469 set_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
470 err
= pohmelfs_meta_command_data(parent
, parent
->ino
, NETFS_LOOKUP
,
471 (char *)str
->name
, NETFS_TRANS_SINGLE_DST
, NULL
, NULL
, ino
);
476 ret
= wait_event_interruptible_timeout(psb
->wait
,
477 !test_bit(NETFS_COMMAND_PENDING
, &parent
->state
), ret
);
490 clear_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
492 printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n",
493 __func__
, parent
->ino
, ino
, str
->name
, err
);
499 * VFS lookup callback.
500 * We first try to get inode number from local name cache, if we have one,
501 * then inode can be found in inode cache. If there is no inode or no object in
502 * local cache, try to lookup it on server. This only should be done for directories,
503 * which were not created locally, otherwise remote server does not know about dir at all,
504 * so no need to try to know that.
506 struct dentry
*pohmelfs_lookup(struct inode
*dir
, struct dentry
*dentry
, struct nameidata
*nd
)
508 struct pohmelfs_inode
*parent
= POHMELFS_I(dir
);
509 struct pohmelfs_name
*n
;
510 struct inode
*inode
= NULL
;
511 unsigned long ino
= 0;
512 int err
, lock_type
= POHMELFS_READ_LOCK
, need_lock
= 1;
513 struct qstr str
= dentry
->d_name
;
515 if ((nd
->intent
.open
.flags
& O_ACCMODE
) > 1)
516 lock_type
= POHMELFS_WRITE_LOCK
;
518 if (test_bit(NETFS_INODE_OWNED
, &parent
->state
)) {
519 if (lock_type
== parent
->lock_type
)
521 if ((lock_type
== POHMELFS_READ_LOCK
) && (parent
->lock_type
== POHMELFS_WRITE_LOCK
))
525 if ((lock_type
== POHMELFS_READ_LOCK
) && !test_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &parent
->state
))
528 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
530 mutex_lock(&parent
->offset_lock
);
531 n
= pohmelfs_search_hash(parent
, str
.hash
);
534 mutex_unlock(&parent
->offset_lock
);
536 dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n",
537 __func__
, ino
, inode
, str
.name
, str
.hash
, parent
->state
, need_lock
);
540 inode
= ilookup(dir
->i_sb
, ino
);
545 dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
546 __func__
, dir
, parent
->ino
,
547 str
.name
, str
.len
, parent
->state
, ino
);
554 err
= pohmelfs_data_lock(parent
, 0, ~0, lock_type
);
558 err
= pohmelfs_lookup_single(parent
, &str
, ino
);
563 mutex_lock(&parent
->offset_lock
);
564 n
= pohmelfs_search_hash(parent
, str
.hash
);
567 mutex_unlock(&parent
->offset_lock
);
571 inode
= ilookup(dir
->i_sb
, ino
);
572 dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
573 __func__
, ino
, inode
, str
.name
, str
.hash
);
575 dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
576 __func__
, ino
, str
.name
, str
.hash
);
578 return ERR_PTR(-EACCES
);
581 printk("%s: No inode number : name: '%s', hash: %x.\n",
582 __func__
, str
.name
, str
.hash
);
585 return d_splice_alias(inode
, dentry
);
589 * Create new object in local cache. Object will be synced to server
590 * during writeback for given inode.
592 struct pohmelfs_inode
*pohmelfs_create_entry_local(struct pohmelfs_sb
*psb
,
593 struct pohmelfs_inode
*parent
, struct qstr
*str
, u64 start
, int mode
)
595 struct pohmelfs_inode
*npi
;
597 struct netfs_inode_info info
;
599 dprintk("%s: name: '%s', mode: %o, start: %llu.\n",
600 __func__
, str
->name
, mode
, start
);
606 info
.ino
= pohmelfs_new_ino(psb
);
608 info
.nlink
= S_ISDIR(mode
) ? 2 : 1;
609 info
.uid
= current_fsuid();
610 info
.gid
= current_fsgid();
612 info
.blocksize
= 512;
617 npi
= pohmelfs_new_inode(psb
, parent
, str
, &info
, !!start
);
626 dprintk("%s: err: %d.\n", __func__
, err
);
631 * Create local object and bind it to dentry.
633 static int pohmelfs_create_entry(struct inode
*dir
, struct dentry
*dentry
, u64 start
, int mode
)
635 struct pohmelfs_sb
*psb
= POHMELFS_SB(dir
->i_sb
);
636 struct pohmelfs_inode
*npi
, *parent
;
637 struct qstr str
= dentry
->d_name
;
640 parent
= POHMELFS_I(dir
);
642 err
= pohmelfs_data_lock(parent
, 0, ~0, POHMELFS_WRITE_LOCK
);
646 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
648 npi
= pohmelfs_create_entry_local(psb
, parent
, &str
, start
, mode
);
652 d_instantiate(dentry
, &npi
->vfs_inode
);
654 dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
655 __func__
, parent
->ino
, npi
->ino
, dentry
->d_name
.name
,
656 (signed)dir
->i_nlink
, (signed)npi
->vfs_inode
.i_nlink
);
662 * VFS create and mkdir callbacks.
664 static int pohmelfs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
665 struct nameidata
*nd
)
667 return pohmelfs_create_entry(dir
, dentry
, 0, mode
);
670 static int pohmelfs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
674 inode_inc_link_count(dir
);
675 err
= pohmelfs_create_entry(dir
, dentry
, 0, mode
| S_IFDIR
);
677 inode_dec_link_count(dir
);
682 static int pohmelfs_remove_entry(struct inode
*dir
, struct dentry
*dentry
)
684 struct pohmelfs_sb
*psb
= POHMELFS_SB(dir
->i_sb
);
685 struct inode
*inode
= dentry
->d_inode
;
686 struct pohmelfs_inode
*parent
= POHMELFS_I(dir
), *pi
= POHMELFS_I(inode
);
687 struct pohmelfs_name
*n
;
689 struct qstr str
= dentry
->d_name
;
691 err
= pohmelfs_data_lock(parent
, 0, ~0, POHMELFS_WRITE_LOCK
);
695 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
697 dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n",
698 __func__
, parent
->ino
, pi
->ino
,
699 str
.name
, (signed)inode
->i_nlink
);
703 mutex_lock(&parent
->offset_lock
);
704 n
= pohmelfs_search_hash(parent
, str
.hash
);
706 pohmelfs_fix_offset(parent
, n
);
707 if (test_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
))
708 pohmelfs_remove_child(pi
, n
);
710 pohmelfs_name_free(parent
, n
);
713 mutex_unlock(&parent
->offset_lock
);
716 psb
->avail_size
+= inode
->i_size
;
718 pohmelfs_inode_del_inode(psb
, pi
);
720 mark_inode_dirty(dir
);
722 inode
->i_ctime
= dir
->i_ctime
;
724 inode_dec_link_count(inode
);
731 * Unlink and rmdir VFS callbacks.
733 static int pohmelfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
735 return pohmelfs_remove_entry(dir
, dentry
);
738 static int pohmelfs_rmdir(struct inode
*dir
, struct dentry
*dentry
)
741 struct inode
*inode
= dentry
->d_inode
;
743 dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
744 __func__
, POHMELFS_I(dir
)->ino
, POHMELFS_I(inode
)->ino
,
745 dentry
->d_name
.name
, (signed)dir
->i_nlink
, (signed)inode
->i_nlink
);
747 err
= pohmelfs_remove_entry(dir
, dentry
);
749 inode_dec_link_count(dir
);
750 inode_dec_link_count(inode
);
757 * Link creation is synchronous.
759 * Earth is somewhat round.
761 static int pohmelfs_create_link(struct pohmelfs_inode
*parent
, struct qstr
*obj
,
762 struct pohmelfs_inode
*target
, struct qstr
*tstr
)
764 struct super_block
*sb
= parent
->vfs_inode
.i_sb
;
765 struct pohmelfs_sb
*psb
= POHMELFS_SB(sb
);
766 struct netfs_cmd
*cmd
;
767 struct netfs_trans
*t
;
769 int err
, parent_len
, target_len
= 0, cur_len
, path_size
= 0;
771 err
= pohmelfs_data_lock(parent
, 0, ~0, POHMELFS_WRITE_LOCK
);
775 err
= sb
->s_op
->write_inode(&parent
->vfs_inode
, 0);
780 target_len
= tstr
->len
;
782 parent_len
= pohmelfs_path_length(parent
);
784 target_len
+= pohmelfs_path_length(target
);
786 if (parent_len
< 0) {
791 if (target_len
< 0) {
796 t
= netfs_trans_alloc(psb
, parent_len
+ target_len
+ obj
->len
+ 2, 0, 0);
801 cur_len
= netfs_trans_cur_len(t
);
803 cmd
= netfs_trans_current(t
);
809 data
= (void *)(cmd
+ 1);
810 cur_len
-= sizeof(struct netfs_cmd
);
812 err
= pohmelfs_construct_path_string(parent
, data
, parent_len
);
814 /* Do not place null-byte before the slash */
816 cur_len
-= path_size
;
818 err
= snprintf(data
+ path_size
, cur_len
, "/%s|", obj
->name
);
823 cmd
->ext
= path_size
- 1; /* No | symbol */
826 err
= pohmelfs_construct_path_string(target
, data
+ path_size
, target_len
);
839 if (!target
&& tstr
) {
840 if (tstr
->len
> cur_len
- 1) {
845 err
= snprintf(data
+ path_size
, cur_len
, "%s", tstr
->name
) + 1; /* 0-byte */
851 dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n",
852 __func__
, parent
->ino
, obj
->name
, (target
) ? target
->ino
: 0, (tstr
) ? tstr
->name
: NULL
,
855 cmd
->cmd
= NETFS_LINK
;
856 cmd
->size
= path_size
;
857 cmd
->id
= parent
->ino
;
859 netfs_convert_cmd(cmd
);
861 netfs_trans_update(cmd
, t
, path_size
);
863 err
= netfs_trans_finish(t
, psb
);
877 * VFS hard and soft link callbacks.
879 static int pohmelfs_link(struct dentry
*old_dentry
, struct inode
*dir
,
880 struct dentry
*dentry
)
882 struct inode
*inode
= old_dentry
->d_inode
;
883 struct pohmelfs_inode
*pi
= POHMELFS_I(inode
);
885 struct qstr str
= dentry
->d_name
;
887 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
889 err
= inode
->i_sb
->s_op
->write_inode(inode
, 0);
893 err
= pohmelfs_create_link(POHMELFS_I(dir
), &str
, pi
, NULL
);
897 return pohmelfs_create_entry(dir
, dentry
, pi
->ino
, inode
->i_mode
);
900 static int pohmelfs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symname
)
903 struct qstr str
= dentry
->d_name
;
907 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
909 sym_str
.name
= symname
;
910 sym_str
.len
= strlen(symname
);
912 err
= pohmelfs_create_link(POHMELFS_I(dir
), &str
, NULL
, &sym_str
);
916 err
= pohmelfs_create_entry(dir
, dentry
, 0, S_IFLNK
| S_IRWXU
| S_IRWXG
| S_IRWXO
);
920 inode
= dentry
->d_inode
;
922 err
= page_symlink(inode
, symname
, sym_str
.len
+ 1);
934 static int pohmelfs_send_rename(struct pohmelfs_inode
*pi
, struct pohmelfs_inode
*parent
,
937 int path_len
, err
, total_len
= 0, inode_len
, parent_len
;
939 struct netfs_trans
*t
;
940 struct netfs_cmd
*cmd
;
941 struct pohmelfs_sb
*psb
= POHMELFS_SB(pi
->vfs_inode
.i_sb
);
943 parent_len
= pohmelfs_path_length(parent
);
944 inode_len
= pohmelfs_path_length(pi
);
946 if (parent_len
< 0 || inode_len
< 0)
949 path_len
= parent_len
+ inode_len
+ str
->len
+ 3;
951 t
= netfs_trans_alloc(psb
, path_len
, 0, 0);
955 cmd
= netfs_trans_current(t
);
956 path
= (char *)(cmd
+ 1);
958 err
= pohmelfs_construct_path_string(pi
, path
, inode_len
);
973 err
= pohmelfs_construct_path_string(parent
, path
, parent_len
);
978 * Do not place a null-byte before the final slash and the name.
985 err
= snprintf(path
, path_len
- 1, "/%s", str
->name
);
987 total_len
+= err
+ 1; /* 0 symbol */
990 cmd
->cmd
= NETFS_RENAME
;
992 cmd
->start
= parent
->ino
;
993 cmd
->size
= total_len
;
995 netfs_convert_cmd(cmd
);
997 netfs_trans_update(cmd
, t
, total_len
);
999 return netfs_trans_finish(t
, psb
);
1002 netfs_trans_free(t
);
1006 static int pohmelfs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1007 struct inode
*new_dir
, struct dentry
*new_dentry
)
1009 struct inode
*inode
= old_dentry
->d_inode
;
1010 struct pohmelfs_inode
*old_parent
, *pi
, *new_parent
;
1011 struct qstr str
= new_dentry
->d_name
;
1012 struct pohmelfs_name
*n
;
1013 unsigned int old_hash
;
1016 pi
= POHMELFS_I(inode
);
1017 old_parent
= POHMELFS_I(old_dir
);
1020 new_dir
->i_sb
->s_op
->write_inode(new_dir
, 0);
1022 old_hash
= jhash(old_dentry
->d_name
.name
, old_dentry
->d_name
.len
, 0);
1023 str
.hash
= jhash(new_dentry
->d_name
.name
, new_dentry
->d_name
.len
, 0);
1025 str
.len
= new_dentry
->d_name
.len
;
1026 str
.name
= new_dentry
->d_name
.name
;
1027 str
.hash
= jhash(new_dentry
->d_name
.name
, new_dentry
->d_name
.len
, 0);
1030 new_parent
= POHMELFS_I(new_dir
);
1033 if (S_ISDIR(inode
->i_mode
) &&
1034 new_parent
->total_len
<= 3)
1037 new_parent
= old_parent
;
1040 dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n",
1041 __func__
, pi
->ino
, old_parent
->ino
, old_dentry
->d_name
.name
,
1042 new_parent
->ino
, new_dentry
->d_name
.name
, inode
->i_size
);
1044 if (test_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
) &&
1045 test_bit(NETFS_INODE_OWNED
, &pi
->state
)) {
1046 err
= pohmelfs_send_rename(pi
, new_parent
, &str
);
1051 n
= pohmelfs_name_alloc(str
.len
+ 1);
1055 mutex_lock(&new_parent
->offset_lock
);
1057 n
->mode
= inode
->i_mode
;
1060 sprintf(n
->data
, "%s", str
.name
);
1062 err
= pohmelfs_insert_name(new_parent
, n
);
1063 mutex_unlock(&new_parent
->offset_lock
);
1068 mutex_lock(&old_parent
->offset_lock
);
1069 n
= pohmelfs_search_hash(old_parent
, old_hash
);
1071 pohmelfs_name_del(old_parent
, n
);
1072 mutex_unlock(&old_parent
->offset_lock
);
1074 mark_inode_dirty(inode
);
1075 mark_inode_dirty(&new_parent
->vfs_inode
);
1077 WARN_ON_ONCE(list_empty(&inode
->i_dentry
));
1083 clear_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
);
1085 mutex_unlock(&inode
->i_mutex
);
1090 * POHMELFS directory inode operations.
1092 const struct inode_operations pohmelfs_dir_inode_ops
= {
1093 .link
= pohmelfs_link
,
1094 .symlink
= pohmelfs_symlink
,
1095 .unlink
= pohmelfs_unlink
,
1096 .mkdir
= pohmelfs_mkdir
,
1097 .rmdir
= pohmelfs_rmdir
,
1098 .create
= pohmelfs_create
,
1099 .lookup
= pohmelfs_lookup
,
1100 .setattr
= pohmelfs_setattr
,
1101 .rename
= pohmelfs_rename
,