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/pagemap.h>
24 static int pohmelfs_cmp_hash(struct pohmelfs_name
*n
, u32 hash
)
34 static struct pohmelfs_name
*pohmelfs_search_hash_unprecise(struct pohmelfs_inode
*pi
, u32 hash
)
36 struct rb_node
*n
= pi
->hash_root
.rb_node
;
37 struct pohmelfs_name
*tmp
= NULL
;
41 tmp
= rb_entry(n
, struct pohmelfs_name
, hash_node
);
43 cmp
= pohmelfs_cmp_hash(tmp
, hash
);
56 struct pohmelfs_name
*pohmelfs_search_hash(struct pohmelfs_inode
*pi
, u32 hash
)
58 struct pohmelfs_name
*tmp
;
60 tmp
= pohmelfs_search_hash_unprecise(pi
, hash
);
61 if (tmp
&& (tmp
->hash
== hash
))
67 static void __pohmelfs_name_del(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*node
)
69 rb_erase(&node
->hash_node
, &parent
->hash_root
);
73 * Remove name cache entry from its caches and free it.
75 static void pohmelfs_name_free(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*node
)
77 __pohmelfs_name_del(parent
, node
);
78 list_del(&node
->sync_create_entry
);
82 static struct pohmelfs_name
*pohmelfs_insert_hash(struct pohmelfs_inode
*pi
,
83 struct pohmelfs_name
*new)
85 struct rb_node
**n
= &pi
->hash_root
.rb_node
, *parent
= NULL
;
86 struct pohmelfs_name
*ret
= NULL
, *tmp
;
92 tmp
= rb_entry(parent
, struct pohmelfs_name
, hash_node
);
94 cmp
= pohmelfs_cmp_hash(tmp
, new->hash
);
98 n
= &parent
->rb_right
;
106 printk("%s: exist: parent: %llu, ino: %llu, hash: %x, len: %u, data: '%s', "
107 "new: ino: %llu, hash: %x, len: %u, data: '%s'.\n",
109 ret
->ino
, ret
->hash
, ret
->len
, ret
->data
,
110 new->ino
, new->hash
, new->len
, new->data
);
115 rb_link_node(&new->hash_node
, parent
, n
);
116 rb_insert_color(&new->hash_node
, &pi
->hash_root
);
122 * Free name cache for given inode.
124 void pohmelfs_free_names(struct pohmelfs_inode
*parent
)
126 struct rb_node
*rb_node
;
127 struct pohmelfs_name
*n
;
129 for (rb_node
= rb_first(&parent
->hash_root
); rb_node
;) {
130 n
= rb_entry(rb_node
, struct pohmelfs_name
, hash_node
);
131 rb_node
= rb_next(rb_node
);
133 pohmelfs_name_free(parent
, n
);
137 static void pohmelfs_fix_offset(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*node
)
139 parent
->total_len
-= node
->len
;
143 * Free name cache entry helper.
145 void pohmelfs_name_del(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*node
)
147 pohmelfs_fix_offset(parent
, node
);
148 pohmelfs_name_free(parent
, node
);
152 * Insert new name cache entry into all hash cache.
154 static int pohmelfs_insert_name(struct pohmelfs_inode
*parent
, struct pohmelfs_name
*n
)
156 struct pohmelfs_name
*name
;
158 name
= pohmelfs_insert_hash(parent
, n
);
162 parent
->total_len
+= n
->len
;
163 list_add_tail(&n
->sync_create_entry
, &parent
->sync_create_list
);
169 * Allocate new name cache entry.
171 static struct pohmelfs_name
*pohmelfs_name_alloc(unsigned int len
)
173 struct pohmelfs_name
*n
;
175 n
= kzalloc(sizeof(struct pohmelfs_name
) + len
, GFP_KERNEL
);
179 INIT_LIST_HEAD(&n
->sync_create_entry
);
181 n
->data
= (char *)(n
+1);
187 * Add new name entry into directory's cache.
189 static int pohmelfs_add_dir(struct pohmelfs_sb
*psb
, struct pohmelfs_inode
*parent
,
190 struct pohmelfs_inode
*npi
, struct qstr
*str
, unsigned int mode
, int link
)
193 struct pohmelfs_name
*n
;
195 n
= pohmelfs_name_alloc(str
->len
+ 1);
203 sprintf(n
->data
, "%s", str
->name
);
205 mutex_lock(&parent
->offset_lock
);
206 err
= pohmelfs_insert_name(parent
, n
);
207 mutex_unlock(&parent
->offset_lock
);
224 * Create new inode for given parameters (name, inode info, parent).
225 * This does not create object on the server, it will be synced there during writeback.
227 struct pohmelfs_inode
*pohmelfs_new_inode(struct pohmelfs_sb
*psb
,
228 struct pohmelfs_inode
*parent
, struct qstr
*str
,
229 struct netfs_inode_info
*info
, int link
)
231 struct inode
*new = NULL
;
232 struct pohmelfs_inode
*npi
;
235 dprintk("%s: creating inode: parent: %llu, ino: %llu, str: %p.\n",
236 __func__
, (parent
)?parent
->ino
:0, info
->ino
, str
);
239 new = iget_locked(psb
->sb
, info
->ino
);
243 npi
= POHMELFS_I(new);
244 npi
->ino
= info
->ino
;
247 if (new->i_state
& I_NEW
) {
248 dprintk("%s: filling VFS inode: %lu/%llu.\n",
249 __func__
, new->i_ino
, info
->ino
);
250 pohmelfs_fill_inode(new, info
);
252 if (S_ISDIR(info
->mode
)) {
257 s
.hash
= jhash(s
.name
, s
.len
, 0);
259 err
= pohmelfs_add_dir(psb
, npi
, npi
, &s
, info
->mode
, 0);
265 s
.hash
= jhash(s
.name
, s
.len
, 0);
267 err
= pohmelfs_add_dir(psb
, npi
, (parent
)?parent
:npi
, &s
,
268 (parent
)?parent
->vfs_inode
.i_mode
:npi
->vfs_inode
.i_mode
, 0);
276 err
= pohmelfs_add_dir(psb
, parent
, npi
, str
, info
->mode
, link
);
278 dprintk("%s: %s inserted name: '%s', new_offset: %llu, ino: %llu, parent: %llu.\n",
279 __func__
, (err
)?"unsuccessfully":"successfully",
280 str
->name
, parent
->total_len
, info
->ino
, parent
->ino
);
282 if (err
&& err
!= -EEXIST
)
287 if (new->i_state
& I_NEW
) {
289 mark_inode_dirty(&parent
->vfs_inode
);
290 mark_inode_dirty(new);
293 set_bit(NETFS_INODE_OWNED
, &npi
->state
);
294 npi
->lock_type
= POHMELFS_WRITE_LOCK
;
295 unlock_new_inode(new);
300 printk("%s: putting inode: %p, npi: %p, error: %d.\n", __func__
, new, npi
, err
);
306 static int pohmelfs_remote_sync_complete(struct page
**pages
, unsigned int page_num
,
307 void *private, int err
)
309 struct pohmelfs_inode
*pi
= private;
310 struct pohmelfs_sb
*psb
= POHMELFS_SB(pi
->vfs_inode
.i_sb
);
312 dprintk("%s: ino: %llu, err: %d.\n", __func__
, pi
->ino
, err
);
317 pohmelfs_put_inode(pi
);
323 * Receive directory content from the server.
324 * This should be only done for objects, which were not created locally,
325 * and which were not synced previously.
327 static int pohmelfs_sync_remote_dir(struct pohmelfs_inode
*pi
)
329 struct inode
*inode
= &pi
->vfs_inode
;
330 struct pohmelfs_sb
*psb
= POHMELFS_SB(inode
->i_sb
);
331 long ret
= psb
->wait_on_page_timeout
;
334 dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n",
335 __func__
, pi
->ino
, pi
->state
, test_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
));
337 if (test_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &pi
->state
))
345 err
= pohmelfs_meta_command(pi
, NETFS_READDIR
, NETFS_TRANS_SINGLE_DST
,
346 pohmelfs_remote_sync_complete
, pi
, 0);
351 ret
= wait_event_interruptible_timeout(psb
->wait
,
352 test_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &pi
->state
) || pi
->error
, ret
);
353 dprintk("%s: awake dir: %llu, ret: %ld, err: %d.\n", __func__
, pi
->ino
, ret
, pi
->error
);
367 clear_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
);
372 static int pohmelfs_dir_open(struct inode
*inode
, struct file
*file
)
374 file
->private_data
= NULL
;
379 * VFS readdir callback. Syncs directory content from server if needed,
380 * and provides direntry info to the userspace.
382 static int pohmelfs_readdir(struct file
*file
, void *dirent
, filldir_t filldir
)
384 struct inode
*inode
= file
->f_path
.dentry
->d_inode
;
385 struct pohmelfs_inode
*pi
= POHMELFS_I(inode
);
386 struct pohmelfs_name
*n
;
387 struct rb_node
*rb_node
;
391 dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n",
392 __func__
, pi
->ino
, (u64
)file
->f_pos
,
393 (unsigned long)file
->private_data
);
395 err
= pohmelfs_data_lock(pi
, 0, ~0, POHMELFS_READ_LOCK
);
399 err
= pohmelfs_sync_remote_dir(pi
);
403 if (file
->private_data
&& (file
->private_data
== (void *)(unsigned long)file
->f_pos
))
406 mutex_lock(&pi
->offset_lock
);
407 n
= pohmelfs_search_hash_unprecise(pi
, (unsigned long)file
->private_data
);
410 mode
= (n
->mode
>> 12) & 15;
412 dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, "
413 "mode: %o/%o, fpos: %llu, hash: %08x.\n",
414 __func__
, file
->f_pos
, pi
->ino
, n
->data
, n
->len
,
415 n
->ino
, n
->mode
, mode
, file
->f_pos
, n
->hash
);
417 file
->private_data
= (void *)(unsigned long)n
->hash
;
420 err
= filldir(dirent
, n
->data
, n
->len
, file
->f_pos
, n
->ino
, mode
);
423 dprintk("%s: err: %d.\n", __func__
, err
);
430 rb_node
= rb_next(&n
->hash_node
);
432 if (!rb_node
|| (rb_node
== &n
->hash_node
)) {
433 file
->private_data
= (void *)(unsigned long)file
->f_pos
;
437 n
= rb_entry(rb_node
, struct pohmelfs_name
, hash_node
);
439 mutex_unlock(&pi
->offset_lock
);
444 static loff_t
pohmelfs_dir_lseek(struct file
*file
, loff_t offset
, int origin
)
446 file
->f_pos
= offset
;
447 file
->private_data
= NULL
;
451 const struct file_operations pohmelfs_dir_fops
= {
452 .open
= pohmelfs_dir_open
,
453 .read
= generic_read_dir
,
454 .llseek
= pohmelfs_dir_lseek
,
455 .readdir
= pohmelfs_readdir
,
459 * Lookup single object on server.
461 static int pohmelfs_lookup_single(struct pohmelfs_inode
*parent
,
462 struct qstr
*str
, u64 ino
)
464 struct pohmelfs_sb
*psb
= POHMELFS_SB(parent
->vfs_inode
.i_sb
);
465 long ret
= msecs_to_jiffies(5000);
468 set_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
469 err
= pohmelfs_meta_command_data(parent
, parent
->ino
, NETFS_LOOKUP
,
470 (char *)str
->name
, NETFS_TRANS_SINGLE_DST
, NULL
, NULL
, ino
);
475 ret
= wait_event_interruptible_timeout(psb
->wait
,
476 !test_bit(NETFS_COMMAND_PENDING
, &parent
->state
), ret
);
489 clear_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
491 printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n",
492 __func__
, parent
->ino
, ino
, str
->name
, err
);
498 * VFS lookup callback.
499 * We first try to get inode number from local name cache, if we have one,
500 * then inode can be found in inode cache. If there is no inode or no object in
501 * local cache, try to lookup it on server. This only should be done for directories,
502 * which were not created locally, otherwise remote server does not know about dir at all,
503 * so no need to try to know that.
505 struct dentry
*pohmelfs_lookup(struct inode
*dir
, struct dentry
*dentry
, struct nameidata
*nd
)
507 struct pohmelfs_inode
*parent
= POHMELFS_I(dir
);
508 struct pohmelfs_name
*n
;
509 struct inode
*inode
= NULL
;
510 unsigned long ino
= 0;
511 int err
, lock_type
= POHMELFS_READ_LOCK
, need_lock
= 1;
512 struct qstr str
= dentry
->d_name
;
514 if ((nd
->intent
.open
.flags
& O_ACCMODE
) > 1)
515 lock_type
= POHMELFS_WRITE_LOCK
;
517 if (test_bit(NETFS_INODE_OWNED
, &parent
->state
)) {
518 if (lock_type
== parent
->lock_type
)
520 if ((lock_type
== POHMELFS_READ_LOCK
) && (parent
->lock_type
== POHMELFS_WRITE_LOCK
))
524 if ((lock_type
== POHMELFS_READ_LOCK
) && !test_bit(NETFS_INODE_REMOTE_DIR_SYNCED
, &parent
->state
))
527 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
529 mutex_lock(&parent
->offset_lock
);
530 n
= pohmelfs_search_hash(parent
, str
.hash
);
533 mutex_unlock(&parent
->offset_lock
);
535 dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n",
536 __func__
, ino
, inode
, str
.name
, str
.hash
, parent
->state
, need_lock
);
539 inode
= ilookup(dir
->i_sb
, ino
);
544 dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
545 __func__
, dir
, parent
->ino
,
546 str
.name
, str
.len
, parent
->state
, ino
);
553 err
= pohmelfs_data_lock(parent
, 0, ~0, lock_type
);
557 err
= pohmelfs_lookup_single(parent
, &str
, ino
);
562 mutex_lock(&parent
->offset_lock
);
563 n
= pohmelfs_search_hash(parent
, str
.hash
);
566 mutex_unlock(&parent
->offset_lock
);
570 inode
= ilookup(dir
->i_sb
, ino
);
571 dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
572 __func__
, ino
, inode
, str
.name
, str
.hash
);
574 dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
575 __func__
, ino
, str
.name
, str
.hash
);
577 return ERR_PTR(-EACCES
);
580 printk("%s: No inode number : name: '%s', hash: %x.\n",
581 __func__
, str
.name
, str
.hash
);
584 return d_splice_alias(inode
, dentry
);
588 * Create new object in local cache. Object will be synced to server
589 * during writeback for given inode.
591 struct pohmelfs_inode
*pohmelfs_create_entry_local(struct pohmelfs_sb
*psb
,
592 struct pohmelfs_inode
*parent
, struct qstr
*str
, u64 start
, int mode
)
594 struct pohmelfs_inode
*npi
;
596 struct netfs_inode_info info
;
598 dprintk("%s: name: '%s', mode: %o, start: %llu.\n",
599 __func__
, str
->name
, mode
, start
);
605 info
.ino
= pohmelfs_new_ino(psb
);
607 info
.nlink
= S_ISDIR(mode
)?2:1;
608 info
.uid
= current_fsuid();
609 info
.gid
= current_fsgid();
611 info
.blocksize
= 512;
616 npi
= pohmelfs_new_inode(psb
, parent
, str
, &info
, !!start
);
625 dprintk("%s: err: %d.\n", __func__
, err
);
630 * Create local object and bind it to dentry.
632 static int pohmelfs_create_entry(struct inode
*dir
, struct dentry
*dentry
, u64 start
, int mode
)
634 struct pohmelfs_sb
*psb
= POHMELFS_SB(dir
->i_sb
);
635 struct pohmelfs_inode
*npi
, *parent
;
636 struct qstr str
= dentry
->d_name
;
639 parent
= POHMELFS_I(dir
);
641 err
= pohmelfs_data_lock(parent
, 0, ~0, POHMELFS_WRITE_LOCK
);
645 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
647 npi
= pohmelfs_create_entry_local(psb
, parent
, &str
, start
, mode
);
651 d_instantiate(dentry
, &npi
->vfs_inode
);
653 dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
654 __func__
, parent
->ino
, npi
->ino
, dentry
->d_name
.name
,
655 (signed)dir
->i_nlink
, (signed)npi
->vfs_inode
.i_nlink
);
661 * VFS create and mkdir callbacks.
663 static int pohmelfs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
664 struct nameidata
*nd
)
666 return pohmelfs_create_entry(dir
, dentry
, 0, mode
);
669 static int pohmelfs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
673 inode_inc_link_count(dir
);
674 err
= pohmelfs_create_entry(dir
, dentry
, 0, mode
| S_IFDIR
);
676 inode_dec_link_count(dir
);
681 static int pohmelfs_remove_entry(struct inode
*dir
, struct dentry
*dentry
)
683 struct pohmelfs_sb
*psb
= POHMELFS_SB(dir
->i_sb
);
684 struct inode
*inode
= dentry
->d_inode
;
685 struct pohmelfs_inode
*parent
= POHMELFS_I(dir
), *pi
= POHMELFS_I(inode
);
686 struct pohmelfs_name
*n
;
688 struct qstr str
= dentry
->d_name
;
690 err
= pohmelfs_data_lock(parent
, 0, ~0, POHMELFS_WRITE_LOCK
);
694 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
696 dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n",
697 __func__
, parent
->ino
, pi
->ino
,
698 str
.name
, (signed)inode
->i_nlink
);
702 mutex_lock(&parent
->offset_lock
);
703 n
= pohmelfs_search_hash(parent
, str
.hash
);
705 pohmelfs_fix_offset(parent
, n
);
706 if (test_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
))
707 pohmelfs_remove_child(pi
, n
);
709 pohmelfs_name_free(parent
, n
);
712 mutex_unlock(&parent
->offset_lock
);
715 psb
->avail_size
+= inode
->i_size
;
717 pohmelfs_inode_del_inode(psb
, pi
);
719 mark_inode_dirty(dir
);
721 inode
->i_ctime
= dir
->i_ctime
;
723 inode_dec_link_count(inode
);
725 dprintk("%s: inode: %p, lock: %ld, unhashed: %d.\n",
726 __func__
, pi
, inode
->i_state
& I_LOCK
, hlist_unhashed(&inode
->i_hash
));
732 * Unlink and rmdir VFS callbacks.
734 static int pohmelfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
736 return pohmelfs_remove_entry(dir
, dentry
);
739 static int pohmelfs_rmdir(struct inode
*dir
, struct dentry
*dentry
)
742 struct inode
*inode
= dentry
->d_inode
;
744 dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
745 __func__
, POHMELFS_I(dir
)->ino
, POHMELFS_I(inode
)->ino
,
746 dentry
->d_name
.name
, (signed)dir
->i_nlink
, (signed)inode
->i_nlink
);
748 err
= pohmelfs_remove_entry(dir
, dentry
);
750 inode_dec_link_count(dir
);
751 inode_dec_link_count(inode
);
758 * Link creation is synchronous.
760 * Earth is somewhat round.
762 static int pohmelfs_create_link(struct pohmelfs_inode
*parent
, struct qstr
*obj
,
763 struct pohmelfs_inode
*target
, struct qstr
*tstr
)
765 struct super_block
*sb
= parent
->vfs_inode
.i_sb
;
766 struct pohmelfs_sb
*psb
= POHMELFS_SB(sb
);
767 struct netfs_cmd
*cmd
;
768 struct netfs_trans
*t
;
770 int err
, parent_len
, target_len
= 0, cur_len
, path_size
= 0;
772 err
= pohmelfs_data_lock(parent
, 0, ~0, POHMELFS_WRITE_LOCK
);
776 err
= sb
->s_op
->write_inode(&parent
->vfs_inode
, 0);
781 target_len
= tstr
->len
;
783 parent_len
= pohmelfs_path_length(parent
);
785 target_len
+= pohmelfs_path_length(target
);
787 if (parent_len
< 0) {
792 if (target_len
< 0) {
797 t
= netfs_trans_alloc(psb
, parent_len
+ target_len
+ obj
->len
+ 2, 0, 0);
802 cur_len
= netfs_trans_cur_len(t
);
804 cmd
= netfs_trans_current(t
);
810 data
= (void *)(cmd
+ 1);
811 cur_len
-= sizeof(struct netfs_cmd
);
813 err
= pohmelfs_construct_path_string(parent
, data
, parent_len
);
815 /* Do not place null-byte before the slash */
817 cur_len
-= path_size
;
819 err
= snprintf(data
+ path_size
, cur_len
, "/%s|", obj
->name
);
824 cmd
->ext
= path_size
- 1; /* No | symbol */
827 err
= pohmelfs_construct_path_string(target
, data
+ path_size
, target_len
);
840 if (!target
&& tstr
) {
841 if (tstr
->len
> cur_len
- 1) {
846 err
= snprintf(data
+ path_size
, cur_len
, "%s", tstr
->name
) + 1; /* 0-byte */
852 dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n",
853 __func__
, parent
->ino
, obj
->name
, (target
)?target
->ino
:0, (tstr
)?tstr
->name
:NULL
,
856 cmd
->cmd
= NETFS_LINK
;
857 cmd
->size
= path_size
;
858 cmd
->id
= parent
->ino
;
860 netfs_convert_cmd(cmd
);
862 netfs_trans_update(cmd
, t
, path_size
);
864 err
= netfs_trans_finish(t
, psb
);
878 * VFS hard and soft link callbacks.
880 static int pohmelfs_link(struct dentry
*old_dentry
, struct inode
*dir
,
881 struct dentry
*dentry
)
883 struct inode
*inode
= old_dentry
->d_inode
;
884 struct pohmelfs_inode
*pi
= POHMELFS_I(inode
);
886 struct qstr str
= dentry
->d_name
;
888 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
890 err
= inode
->i_sb
->s_op
->write_inode(inode
, 0);
894 err
= pohmelfs_create_link(POHMELFS_I(dir
), &str
, pi
, NULL
);
898 return pohmelfs_create_entry(dir
, dentry
, pi
->ino
, inode
->i_mode
);
901 static int pohmelfs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symname
)
904 struct qstr str
= dentry
->d_name
;
908 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
910 sym_str
.name
= symname
;
911 sym_str
.len
= strlen(symname
);
913 err
= pohmelfs_create_link(POHMELFS_I(dir
), &str
, NULL
, &sym_str
);
917 err
= pohmelfs_create_entry(dir
, dentry
, 0, S_IFLNK
| S_IRWXU
| S_IRWXG
| S_IRWXO
);
921 inode
= dentry
->d_inode
;
923 err
= page_symlink(inode
, symname
, sym_str
.len
+ 1);
935 static int pohmelfs_send_rename(struct pohmelfs_inode
*pi
, struct pohmelfs_inode
*parent
,
938 int path_len
, err
, total_len
= 0, inode_len
, parent_len
;
940 struct netfs_trans
*t
;
941 struct netfs_cmd
*cmd
;
942 struct pohmelfs_sb
*psb
= POHMELFS_SB(pi
->vfs_inode
.i_sb
);
944 parent_len
= pohmelfs_path_length(parent
);
945 inode_len
= pohmelfs_path_length(pi
);
947 if (parent_len
< 0 || inode_len
< 0)
950 path_len
= parent_len
+ inode_len
+ str
->len
+ 3;
952 t
= netfs_trans_alloc(psb
, path_len
, 0, 0);
956 cmd
= netfs_trans_current(t
);
957 path
= (char *)(cmd
+ 1);
959 err
= pohmelfs_construct_path_string(pi
, path
, inode_len
);
974 err
= pohmelfs_construct_path_string(parent
, path
, parent_len
);
979 * Do not place a null-byte before the final slash and the name.
986 err
= snprintf(path
, path_len
- 1, "/%s", str
->name
);
988 total_len
+= err
+ 1; /* 0 symbol */
991 cmd
->cmd
= NETFS_RENAME
;
993 cmd
->start
= parent
->ino
;
994 cmd
->size
= total_len
;
996 netfs_convert_cmd(cmd
);
998 netfs_trans_update(cmd
, t
, total_len
);
1000 return netfs_trans_finish(t
, psb
);
1003 netfs_trans_free(t
);
1007 static int pohmelfs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
1008 struct inode
*new_dir
, struct dentry
*new_dentry
)
1010 struct inode
*inode
= old_dentry
->d_inode
;
1011 struct pohmelfs_inode
*old_parent
, *pi
, *new_parent
;
1012 struct qstr str
= new_dentry
->d_name
;
1013 struct pohmelfs_name
*n
;
1014 unsigned int old_hash
;
1017 pi
= POHMELFS_I(inode
);
1018 old_parent
= POHMELFS_I(old_dir
);
1021 new_dir
->i_sb
->s_op
->write_inode(new_dir
, 0);
1023 old_hash
= jhash(old_dentry
->d_name
.name
, old_dentry
->d_name
.len
, 0);
1024 str
.hash
= jhash(new_dentry
->d_name
.name
, new_dentry
->d_name
.len
, 0);
1026 str
.len
= new_dentry
->d_name
.len
;
1027 str
.name
= new_dentry
->d_name
.name
;
1028 str
.hash
= jhash(new_dentry
->d_name
.name
, new_dentry
->d_name
.len
, 0);
1031 new_parent
= POHMELFS_I(new_dir
);
1034 if (S_ISDIR(inode
->i_mode
) &&
1035 new_parent
->total_len
<= 3)
1038 new_parent
= old_parent
;
1041 dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n",
1042 __func__
, pi
->ino
, old_parent
->ino
, old_dentry
->d_name
.name
,
1043 new_parent
->ino
, new_dentry
->d_name
.name
, inode
->i_size
);
1045 if (test_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
) &&
1046 test_bit(NETFS_INODE_OWNED
, &pi
->state
)) {
1047 err
= pohmelfs_send_rename(pi
, new_parent
, &str
);
1052 n
= pohmelfs_name_alloc(str
.len
+ 1);
1056 mutex_lock(&new_parent
->offset_lock
);
1058 n
->mode
= inode
->i_mode
;
1061 sprintf(n
->data
, "%s", str
.name
);
1063 err
= pohmelfs_insert_name(new_parent
, n
);
1064 mutex_unlock(&new_parent
->offset_lock
);
1069 mutex_lock(&old_parent
->offset_lock
);
1070 n
= pohmelfs_search_hash(old_parent
, old_hash
);
1072 pohmelfs_name_del(old_parent
, n
);
1073 mutex_unlock(&old_parent
->offset_lock
);
1075 mark_inode_dirty(inode
);
1076 mark_inode_dirty(&new_parent
->vfs_inode
);
1078 WARN_ON_ONCE(list_empty(&inode
->i_dentry
));
1084 clear_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
);
1086 mutex_unlock(&inode
->i_mutex
);
1091 * POHMELFS directory inode operations.
1093 const struct inode_operations pohmelfs_dir_inode_ops
= {
1094 .link
= pohmelfs_link
,
1095 .symlink
= pohmelfs_symlink
,
1096 .unlink
= pohmelfs_unlink
,
1097 .mkdir
= pohmelfs_mkdir
,
1098 .rmdir
= pohmelfs_rmdir
,
1099 .create
= pohmelfs_create
,
1100 .lookup
= pohmelfs_lookup
,
1101 .setattr
= pohmelfs_setattr
,
1102 .rename
= pohmelfs_rename
,