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
= msecs_to_jiffies(25000);
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
);
365 clear_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
);
370 static int pohmelfs_dir_open(struct inode
*inode
, struct file
*file
)
372 file
->private_data
= NULL
;
377 * VFS readdir callback. Syncs directory content from server if needed,
378 * and provides direntry info to the userspace.
380 static int pohmelfs_readdir(struct file
*file
, void *dirent
, filldir_t filldir
)
382 struct inode
*inode
= file
->f_path
.dentry
->d_inode
;
383 struct pohmelfs_inode
*pi
= POHMELFS_I(inode
);
384 struct pohmelfs_name
*n
;
385 struct rb_node
*rb_node
;
389 dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n",
390 __func__
, pi
->ino
, (u64
)file
->f_pos
,
391 (unsigned long)file
->private_data
);
393 err
= pohmelfs_data_lock(pi
, 0, ~0, POHMELFS_READ_LOCK
);
397 err
= pohmelfs_sync_remote_dir(pi
);
401 if (file
->private_data
&& (file
->private_data
== (void *)(unsigned long)file
->f_pos
))
404 mutex_lock(&pi
->offset_lock
);
405 n
= pohmelfs_search_hash_unprecise(pi
, (unsigned long)file
->private_data
);
408 mode
= (n
->mode
>> 12) & 15;
410 dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, "
411 "mode: %o/%o, fpos: %llu, hash: %08x.\n",
412 __func__
, file
->f_pos
, pi
->ino
, n
->data
, n
->len
,
413 n
->ino
, n
->mode
, mode
, file
->f_pos
, n
->hash
);
415 file
->private_data
= (void *)n
->hash
;
418 err
= filldir(dirent
, n
->data
, n
->len
, file
->f_pos
, n
->ino
, mode
);
421 dprintk("%s: err: %d.\n", __func__
, err
);
428 rb_node
= rb_next(&n
->hash_node
);
430 if (!rb_node
|| (rb_node
== &n
->hash_node
)) {
431 file
->private_data
= (void *)(unsigned long)file
->f_pos
;
435 n
= rb_entry(rb_node
, struct pohmelfs_name
, hash_node
);
437 mutex_unlock(&pi
->offset_lock
);
442 static loff_t
pohmelfs_dir_lseek(struct file
*file
, loff_t offset
, int origin
)
444 file
->f_pos
= offset
;
445 file
->private_data
= NULL
;
449 const struct file_operations pohmelfs_dir_fops
= {
450 .open
= pohmelfs_dir_open
,
451 .read
= generic_read_dir
,
452 .llseek
= pohmelfs_dir_lseek
,
453 .readdir
= pohmelfs_readdir
,
457 * Lookup single object on server.
459 static int pohmelfs_lookup_single(struct pohmelfs_inode
*parent
,
460 struct qstr
*str
, u64 ino
)
462 struct pohmelfs_sb
*psb
= POHMELFS_SB(parent
->vfs_inode
.i_sb
);
463 long ret
= msecs_to_jiffies(5000);
466 set_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
467 err
= pohmelfs_meta_command_data(parent
, parent
->ino
, NETFS_LOOKUP
,
468 (char *)str
->name
, NETFS_TRANS_SINGLE_DST
, NULL
, NULL
, ino
);
473 ret
= wait_event_interruptible_timeout(psb
->wait
,
474 !test_bit(NETFS_COMMAND_PENDING
, &parent
->state
), ret
);
477 else if (signal_pending(current
))
486 clear_bit(NETFS_COMMAND_PENDING
, &parent
->state
);
488 printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n",
489 __func__
, parent
->ino
, ino
, str
->name
, err
);
495 * VFS lookup callback.
496 * We first try to get inode number from local name cache, if we have one,
497 * then inode can be found in inode cache. If there is no inode or no object in
498 * local cache, try to lookup it on server. This only should be done for directories,
499 * which were not created locally, otherwise remote server does not know about dir at all,
500 * so no need to try to know that.
502 struct dentry
*pohmelfs_lookup(struct inode
*dir
, struct dentry
*dentry
, struct nameidata
*nd
)
504 struct pohmelfs_inode
*parent
= POHMELFS_I(dir
);
505 struct pohmelfs_name
*n
;
506 struct inode
*inode
= NULL
;
507 unsigned long ino
= 0;
508 int err
, lock_type
= POHMELFS_READ_LOCK
, need_lock
;
509 struct qstr str
= dentry
->d_name
;
511 if ((nd
->intent
.open
.flags
& O_ACCMODE
) > 1)
512 lock_type
= POHMELFS_WRITE_LOCK
;
514 need_lock
= pohmelfs_need_lock(parent
, lock_type
);
516 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
518 mutex_lock(&parent
->offset_lock
);
519 n
= pohmelfs_search_hash(parent
, str
.hash
);
522 mutex_unlock(&parent
->offset_lock
);
524 dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n",
525 __func__
, ino
, inode
, str
.name
, str
.hash
, parent
->state
, need_lock
);
528 inode
= ilookup(dir
->i_sb
, ino
);
533 dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n",
534 __func__
, dir
, parent
->ino
,
535 str
.name
, str
.len
, parent
->state
, ino
);
542 err
= pohmelfs_data_lock(parent
, 0, ~0, lock_type
);
546 err
= pohmelfs_lookup_single(parent
, &str
, ino
);
551 mutex_lock(&parent
->offset_lock
);
552 n
= pohmelfs_search_hash(parent
, str
.hash
);
555 mutex_unlock(&parent
->offset_lock
);
559 inode
= ilookup(dir
->i_sb
, ino
);
560 dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n",
561 __func__
, ino
, inode
, str
.name
, str
.hash
);
563 dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n",
564 __func__
, ino
, str
.name
, str
.hash
);
566 return ERR_PTR(-EACCES
);
569 printk("%s: No inode number : name: '%s', hash: %x.\n",
570 __func__
, str
.name
, str
.hash
);
573 return d_splice_alias(inode
, dentry
);
577 * Create new object in local cache. Object will be synced to server
578 * during writeback for given inode.
580 struct pohmelfs_inode
*pohmelfs_create_entry_local(struct pohmelfs_sb
*psb
,
581 struct pohmelfs_inode
*parent
, struct qstr
*str
, u64 start
, int mode
)
583 struct pohmelfs_inode
*npi
;
585 struct netfs_inode_info info
;
587 dprintk("%s: name: '%s', mode: %o, start: %llu.\n",
588 __func__
, str
->name
, mode
, start
);
594 info
.ino
= pohmelfs_new_ino(psb
);
596 info
.nlink
= S_ISDIR(mode
)?2:1;
597 info
.uid
= current_fsuid();
598 info
.gid
= current_fsgid();
600 info
.blocksize
= 512;
605 npi
= pohmelfs_new_inode(psb
, parent
, str
, &info
, !!start
);
614 dprintk("%s: err: %d.\n", __func__
, err
);
619 * Create local object and bind it to dentry.
621 static int pohmelfs_create_entry(struct inode
*dir
, struct dentry
*dentry
, u64 start
, int mode
)
623 struct pohmelfs_sb
*psb
= POHMELFS_SB(dir
->i_sb
);
624 struct pohmelfs_inode
*npi
, *parent
;
625 struct qstr str
= dentry
->d_name
;
628 parent
= POHMELFS_I(dir
);
630 err
= pohmelfs_data_lock(parent
, 0, ~0, POHMELFS_WRITE_LOCK
);
634 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
636 npi
= pohmelfs_create_entry_local(psb
, parent
, &str
, start
, mode
);
640 d_instantiate(dentry
, &npi
->vfs_inode
);
642 dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
643 __func__
, parent
->ino
, npi
->ino
, dentry
->d_name
.name
,
644 (signed)dir
->i_nlink
, (signed)npi
->vfs_inode
.i_nlink
);
650 * VFS create and mkdir callbacks.
652 static int pohmelfs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
653 struct nameidata
*nd
)
655 return pohmelfs_create_entry(dir
, dentry
, 0, mode
);
658 static int pohmelfs_mkdir(struct inode
*dir
, struct dentry
*dentry
, int mode
)
662 inode_inc_link_count(dir
);
663 err
= pohmelfs_create_entry(dir
, dentry
, 0, mode
| S_IFDIR
);
665 inode_dec_link_count(dir
);
670 static int pohmelfs_remove_entry(struct inode
*dir
, struct dentry
*dentry
)
672 struct pohmelfs_sb
*psb
= POHMELFS_SB(dir
->i_sb
);
673 struct inode
*inode
= dentry
->d_inode
;
674 struct pohmelfs_inode
*parent
= POHMELFS_I(dir
), *pi
= POHMELFS_I(inode
);
675 struct pohmelfs_name
*n
;
677 struct qstr str
= dentry
->d_name
;
679 err
= pohmelfs_data_lock(parent
, 0, ~0, POHMELFS_WRITE_LOCK
);
683 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
685 dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n",
686 __func__
, parent
->ino
, pi
->ino
,
687 str
.name
, (signed)inode
->i_nlink
);
691 mutex_lock(&parent
->offset_lock
);
692 n
= pohmelfs_search_hash(parent
, str
.hash
);
694 pohmelfs_fix_offset(parent
, n
);
695 if (test_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
)) {
696 pohmelfs_remove_child(pi
, n
);
698 pohmelfs_name_free(parent
, n
);
701 mutex_unlock(&parent
->offset_lock
);
704 psb
->avail_size
+= inode
->i_size
;
706 pohmelfs_inode_del_inode(psb
, pi
);
708 mark_inode_dirty(dir
);
710 inode
->i_ctime
= dir
->i_ctime
;
712 inode_dec_link_count(inode
);
714 dprintk("%s: inode: %p, lock: %ld, unhashed: %d.\n",
715 __func__
, pi
, inode
->i_state
& I_LOCK
, hlist_unhashed(&inode
->i_hash
));
721 * Unlink and rmdir VFS callbacks.
723 static int pohmelfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
725 return pohmelfs_remove_entry(dir
, dentry
);
728 static int pohmelfs_rmdir(struct inode
*dir
, struct dentry
*dentry
)
731 struct inode
*inode
= dentry
->d_inode
;
733 dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n",
734 __func__
, POHMELFS_I(dir
)->ino
, POHMELFS_I(inode
)->ino
,
735 dentry
->d_name
.name
, (signed)dir
->i_nlink
, (signed)inode
->i_nlink
);
737 err
= pohmelfs_remove_entry(dir
, dentry
);
739 inode_dec_link_count(dir
);
740 inode_dec_link_count(inode
);
747 * Link creation is synchronous.
749 * Earth is somewhat round.
751 static int pohmelfs_create_link(struct pohmelfs_inode
*parent
, struct qstr
*obj
,
752 struct pohmelfs_inode
*target
, struct qstr
*tstr
)
754 struct super_block
*sb
= parent
->vfs_inode
.i_sb
;
755 struct pohmelfs_sb
*psb
= POHMELFS_SB(sb
);
756 struct netfs_cmd
*cmd
;
757 struct netfs_trans
*t
;
759 int err
, parent_len
, target_len
= 0, cur_len
, path_size
= 0;
761 err
= pohmelfs_data_lock(parent
, 0, ~0, POHMELFS_WRITE_LOCK
);
765 err
= sb
->s_op
->write_inode(&parent
->vfs_inode
, 0);
770 target_len
= tstr
->len
;
772 parent_len
= pohmelfs_path_length(parent
);
774 target_len
+= pohmelfs_path_length(target
);
776 if (parent_len
< 0) {
781 if (target_len
< 0) {
786 t
= netfs_trans_alloc(psb
, parent_len
+ target_len
+ obj
->len
+ 2, 0, 0);
791 cur_len
= netfs_trans_cur_len(t
);
793 cmd
= netfs_trans_current(t
);
799 data
= (void *)(cmd
+ 1);
800 cur_len
-= sizeof(struct netfs_cmd
);
802 err
= pohmelfs_construct_path_string(parent
, data
, parent_len
);
804 /* Do not place null-byte before the slash */
806 cur_len
-= path_size
;
808 err
= snprintf(data
+ path_size
, cur_len
, "/%s|", obj
->name
);
813 cmd
->ext
= path_size
- 1; /* No | symbol */
816 err
= pohmelfs_construct_path_string(target
, data
+ path_size
, target_len
);
829 if (!target
&& tstr
) {
830 if (tstr
->len
> cur_len
- 1) {
835 err
= snprintf(data
+ path_size
, cur_len
, "%s", tstr
->name
) + 1; /* 0-byte */
841 dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n",
842 __func__
, parent
->ino
, obj
->name
, (target
)?target
->ino
:0, (tstr
)?tstr
->name
:NULL
,
845 cmd
->cmd
= NETFS_LINK
;
846 cmd
->size
= path_size
;
847 cmd
->id
= parent
->ino
;
849 netfs_convert_cmd(cmd
);
851 netfs_trans_update(cmd
, t
, path_size
);
853 err
= netfs_trans_finish(t
, psb
);
867 * VFS hard and soft link callbacks.
869 static int pohmelfs_link(struct dentry
*old_dentry
, struct inode
*dir
,
870 struct dentry
*dentry
)
872 struct inode
*inode
= old_dentry
->d_inode
;
873 struct pohmelfs_inode
*pi
= POHMELFS_I(inode
);
875 struct qstr str
= dentry
->d_name
;
877 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
879 err
= inode
->i_sb
->s_op
->write_inode(inode
, 0);
883 err
= pohmelfs_create_link(POHMELFS_I(dir
), &str
, pi
, NULL
);
887 return pohmelfs_create_entry(dir
, dentry
, pi
->ino
, inode
->i_mode
);
890 static int pohmelfs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symname
)
893 struct qstr str
= dentry
->d_name
;
897 str
.hash
= jhash(dentry
->d_name
.name
, dentry
->d_name
.len
, 0);
899 sym_str
.name
= symname
;
900 sym_str
.len
= strlen(symname
);
902 err
= pohmelfs_create_link(POHMELFS_I(dir
), &str
, NULL
, &sym_str
);
906 err
= pohmelfs_create_entry(dir
, dentry
, 0, S_IFLNK
| S_IRWXU
| S_IRWXG
| S_IRWXO
);
910 inode
= dentry
->d_inode
;
912 err
= page_symlink(inode
, symname
, sym_str
.len
+ 1);
924 static int pohmelfs_send_rename(struct pohmelfs_inode
*pi
, struct pohmelfs_inode
*parent
,
927 int path_len
, err
, total_len
= 0, inode_len
, parent_len
;
929 struct netfs_trans
*t
;
930 struct netfs_cmd
*cmd
;
931 struct pohmelfs_sb
*psb
= POHMELFS_SB(pi
->vfs_inode
.i_sb
);
933 parent_len
= pohmelfs_path_length(parent
);
934 inode_len
= pohmelfs_path_length(pi
);
936 if (parent_len
< 0 || inode_len
< 0)
939 path_len
= parent_len
+ inode_len
+ str
->len
+ 3;
941 t
= netfs_trans_alloc(psb
, path_len
, 0, 0);
945 cmd
= netfs_trans_current(t
);
946 path
= (char *)(cmd
+ 1);
948 err
= pohmelfs_construct_path_string(pi
, path
, inode_len
);
963 err
= pohmelfs_construct_path_string(parent
, path
, parent_len
);
968 * Do not place a null-byte before the final slash and the name.
975 err
= snprintf(path
, path_len
- 1, "/%s", str
->name
);
977 total_len
+= err
+ 1; /* 0 symbol */
980 cmd
->cmd
= NETFS_RENAME
;
982 cmd
->start
= parent
->ino
;
983 cmd
->size
= total_len
;
985 netfs_convert_cmd(cmd
);
987 netfs_trans_update(cmd
, t
, total_len
);
989 return netfs_trans_finish(t
, psb
);
996 static int pohmelfs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
997 struct inode
*new_dir
, struct dentry
*new_dentry
)
999 struct inode
*inode
= old_dentry
->d_inode
;
1000 struct pohmelfs_inode
*old_parent
, *pi
, *new_parent
;
1001 struct qstr str
= new_dentry
->d_name
;
1002 struct pohmelfs_name
*n
;
1003 unsigned int old_hash
;
1006 pi
= POHMELFS_I(inode
);
1007 old_parent
= POHMELFS_I(old_dir
);
1010 new_dir
->i_sb
->s_op
->write_inode(new_dir
, 0);
1013 old_hash
= jhash(old_dentry
->d_name
.name
, old_dentry
->d_name
.len
, 0);
1014 str
.hash
= jhash(new_dentry
->d_name
.name
, new_dentry
->d_name
.len
, 0);
1016 str
.len
= new_dentry
->d_name
.len
;
1017 str
.name
= new_dentry
->d_name
.name
;
1018 str
.hash
= jhash(new_dentry
->d_name
.name
, new_dentry
->d_name
.len
, 0);
1021 new_parent
= POHMELFS_I(new_dir
);
1024 if (S_ISDIR(inode
->i_mode
) &&
1025 new_parent
->total_len
<= 3)
1028 new_parent
= old_parent
;
1031 dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n",
1032 __func__
, pi
->ino
, old_parent
->ino
, old_dentry
->d_name
.name
,
1033 new_parent
->ino
, new_dentry
->d_name
.name
, inode
->i_size
);
1035 if (test_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
) &&
1036 test_bit(NETFS_INODE_OWNED
, &pi
->state
)) {
1037 err
= pohmelfs_send_rename(pi
, new_parent
, &str
);
1042 n
= pohmelfs_name_alloc(str
.len
+ 1);
1046 mutex_lock(&new_parent
->offset_lock
);
1048 n
->mode
= inode
->i_mode
;
1051 sprintf(n
->data
, "%s", str
.name
);
1053 err
= pohmelfs_insert_name(new_parent
, n
);
1054 mutex_unlock(&new_parent
->offset_lock
);
1059 mutex_lock(&old_parent
->offset_lock
);
1060 n
= pohmelfs_search_hash(old_parent
, old_hash
);
1062 pohmelfs_name_del(old_parent
, n
);
1063 mutex_unlock(&old_parent
->offset_lock
);
1065 mark_inode_dirty(inode
);
1066 mark_inode_dirty(&new_parent
->vfs_inode
);
1068 WARN_ON_ONCE(list_empty(&inode
->i_dentry
));
1074 clear_bit(NETFS_INODE_REMOTE_SYNCED
, &pi
->state
);
1076 mutex_unlock(&inode
->i_mutex
);
1081 * POHMELFS directory inode operations.
1083 const struct inode_operations pohmelfs_dir_inode_ops
= {
1084 .link
= pohmelfs_link
,
1085 .symlink
= pohmelfs_symlink
,
1086 .unlink
= pohmelfs_unlink
,
1087 .mkdir
= pohmelfs_mkdir
,
1088 .rmdir
= pohmelfs_rmdir
,
1089 .create
= pohmelfs_create
,
1090 .lookup
= pohmelfs_lookup
,
1091 .setattr
= pohmelfs_setattr
,
1092 .rename
= pohmelfs_rename
,