Whamcloud - gitweb
land b_hd_sec: perm/acl authorization for remote users.
[fs/lustre-release.git] / lustre / llite / namei.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  *  derived in small part from linux/fs/ext2/namei.c
22  *
23  *  Copyright (C) 1991, 1992  Linus Torvalds
24  *
25  *  Big-endian to little-endian byte-swapping/bitmaps by
26  *        David S. Miller (davem@caip.rutgers.edu), 1995
27  *  Directory entry file type support and forward compatibility hooks
28  *      for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
29  */
30
31 #include <linux/fs.h>
32 #include <linux/sched.h>
33 #include <linux/mm.h>
34 #include <linux/smp_lock.h>
35 #include <linux/quotaops.h>
36 #include <linux/highmem.h>
37 #include <linux/pagemap.h>
38
39 #define DEBUG_SUBSYSTEM S_LLITE
40
41 #include <linux/obd_support.h>
42 #include <linux/lustre_lite.h>
43 #include <linux/lustre_dlm.h>
44 #include <linux/lustre_version.h>
45 #include "llite_internal.h"
46
47 /* methods */
48
49 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
50 static int ll_test_inode(struct inode *inode, unsigned long ino, void *opaque)
51 #else
52 static int ll_test_inode(struct inode *inode, void *opaque)
53 #endif
54 {
55         static int last_ino, last_gen, last_count;
56         struct lustre_md *md = opaque;
57
58         if (!(md->body->valid & (OBD_MD_FLGENER | OBD_MD_FLID))) {
59                 CERROR("MDS body missing inum or generation\n");
60                 return 0;
61         }
62
63         if (last_ino == id_ino(&md->body->id1) &&
64             last_gen == id_gen(&md->body->id1) &&
65             last_count < 500) {
66                 last_count++;
67         } else {
68                 if (last_count > 1)
69                         CDEBUG(D_VFSTRACE, "compared %u/%u %u times\n",
70                                last_ino, last_gen, last_count);
71                 last_count = 0;
72                 last_ino = id_ino(&md->body->id1);
73                 last_gen = id_gen(&md->body->id1);
74                 CDEBUG(D_VFSTRACE,
75                        "comparing inode %p ino "DLID4" to body "DLID4"\n",
76                        inode, OLID4(&ll_i2info(inode)->lli_id),
77                        OLID4(&md->body->id1));
78         }
79
80 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
81         if (inode->i_ino != id_ino(&md->body->id1))
82                 return 0;
83 #endif
84         if (inode->i_generation != id_gen(&md->body->id1))
85                 return 0;
86
87         if (id_group(&ll_i2info(inode)->lli_id) != id_group(&md->body->id1))
88                 return 0;
89         
90         /* apply the attributes in 'opaque' to this inode. */
91         ll_update_inode(inode, md);
92         return 1;
93 }
94
95 extern struct dentry_operations ll_d_ops;
96
97 int ll_unlock(__u32 mode, struct lustre_handle *lockh)
98 {
99         ENTRY;
100
101         ldlm_lock_decref(lockh, mode);
102
103         RETURN(0);
104 }
105
106 /*
107  * get an inode by inode number (already instantiated by the intent lookup).
108  * Returns inode or NULL.
109  */
110 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
111 int ll_set_inode(struct inode *inode, void *opaque)
112 {
113         ll_read_inode2(inode, opaque);
114         return 0;
115 }
116
117 struct inode *ll_iget(struct super_block *sb, ino_t hash,
118                       struct lustre_md *md)
119 {
120         struct inode *inode;
121
122         LASSERT(hash != 0);
123         inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md);
124
125         if (inode) {
126                 if (inode->i_state & I_NEW)
127                         unlock_new_inode(inode);
128                 CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
129                        inode->i_generation, inode);
130         }
131
132         return inode;
133 }
134 #else
135 struct inode *ll_iget(struct super_block *sb, ino_t hash,
136                       struct lustre_md *md)
137 {
138         struct inode *inode;
139         LASSERT(hash != 0);
140         inode = iget4(sb, hash, ll_test_inode, md);
141         if (inode)
142                 CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
143                        inode->i_generation, inode);
144         return inode;
145 }
146 #endif
147
148 int ll_mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
149                         void *data, int flag)
150 {
151         int rc;
152         struct lustre_handle lockh;
153         ENTRY;
154
155         switch (flag) {
156         case LDLM_CB_BLOCKING:
157                 ldlm_lock2handle(lock, &lockh);
158                 rc = ldlm_cli_cancel(&lockh);
159                 if (rc < 0) {
160                         CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
161                         RETURN(rc);
162                 }
163                 break;
164         case LDLM_CB_CANCELING: {
165                 struct inode *inode = ll_inode_from_lock(lock);
166                 struct ll_inode_info *li = ll_i2info(inode);
167                 __u64 bits = lock->l_policy_data.l_inodebits.bits;
168
169                 /* For lookup locks: Invalidate all dentries associated with
170                    this inode, for UPDATE locks - invalidate directory pages */
171                 if (inode == NULL)
172                         break;
173
174                 if (lock->l_resource->lr_name.name[0] != id_fid(&li->lli_id) ||
175                     lock->l_resource->lr_name.name[1] != id_group(&li->lli_id)) {
176                         LDLM_ERROR(lock, "data mismatch with object %lu/%lu",
177                                    (unsigned long)id_fid(&li->lli_id),
178                                    (unsigned long)id_group(&li->lli_id));
179                 }
180
181                 if (bits & MDS_INODELOCK_OPEN) {
182                         int flags = 0;
183                         switch (lock->l_req_mode) {
184                         case LCK_CW:
185                                 flags = FMODE_WRITE;
186                                 break;
187                         case LCK_PR:
188                                 flags = FMODE_EXEC;
189                                 break;
190                         case LCK_CR:
191                                 flags = FMODE_READ;
192                                 break;
193                         default:
194                                 CERROR("Unexpected lock mode for OPEN lock "
195                                        "%d, inode %ld\n", lock->l_req_mode,
196                                        inode->i_ino);
197                         }
198                         ll_md_real_close(ll_i2mdexp(inode), inode, flags);
199                 }
200
201                 if ((bits & MDS_INODELOCK_UPDATE) && LLI_HAVE_FLSIZE(inode)) {
202                         CDEBUG(D_OTHER, "isize for %lu/%u(%p) from mds "
203                                "is not actual\n", inode->i_ino,
204                                inode->i_generation, inode);
205                         clear_bit(LLI_F_HAVE_MDS_SIZE_LOCK,
206                                   &(ll_i2info(inode)->lli_flags));
207                 }
208
209
210                 /* If lookup lock is cancelled, we just drop the dentry and
211                    this will cause us to reget data from MDS when we'd want to
212                    access this dentry/inode again. If this is lock on
213                    other parts of inode that is cancelled, we do not need to do
214                    much (but need to discard data from readdir, if any), since
215                    abscence of lock will cause ll_revalidate_it (called from
216                    stat() and similar functions) to renew the data anyway */
217                 if (S_ISDIR(inode->i_mode) &&
218                     (bits & MDS_INODELOCK_UPDATE)) {
219                         CDEBUG(D_INODE, "invalidating inode %lu/%u(%p)\n",
220                                inode->i_ino, inode->i_generation, inode);
221                         truncate_inode_pages(inode->i_mapping, 0);
222                 }
223
224                 /* we can't invalide acl here: suppose we touch a new file
225                  * under a dir, blocking ast on dir will lead to open failure
226                  * on client, although succeed on mds. it's kind of weird,
227                  * the real fix i think is improve client-vfs interaction.
228                  */
229 #if 0
230                 ll_inode_invalidate_acl(inode);
231 #endif
232
233                 if (inode->i_sb->s_root &&
234                     inode != inode->i_sb->s_root->d_inode &&
235                     (bits & MDS_INODELOCK_LOOKUP))
236                         ll_unhash_aliases(inode);
237                 iput(inode);
238                 break;
239         }
240         default:
241                 LBUG();
242         }
243
244         RETURN(0);
245 }
246
247 /* Search "inode"'s alias list for a dentry that has the same name and parent as
248  * de.  If found, return it.  If not found, return de. */
249 struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
250 {
251         struct list_head *tmp;
252
253         spin_lock(&dcache_lock);
254         list_for_each(tmp, &inode->i_dentry) {
255                 struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
256
257                 /* We are called here with 'de' already on the aliases list. */
258                 if (dentry == de) {
259                         CERROR("whoops\n");
260                         continue;
261                 }
262
263                 if (dentry->d_parent != de->d_parent)
264                         continue;
265
266                 if (dentry->d_name.len != de->d_name.len)
267                         continue;
268
269                 if (memcmp(dentry->d_name.name, de->d_name.name,
270                            de->d_name.len) != 0)
271                         continue;
272
273                 if (!list_empty(&dentry->d_lru))
274                         list_del_init(&dentry->d_lru);
275
276                 hlist_del_init(&dentry->d_hash);
277                 __d_rehash(dentry); /* avoid taking dcache_lock inside */
278                 spin_unlock(&dcache_lock);
279                 atomic_inc(&dentry->d_count);
280                 iput(inode);
281                 dentry->d_flags &= ~DCACHE_LUSTRE_INVALID;
282                 CDEBUG(D_DENTRY, "alias dentry %*s (%p) parent %p inode %p "
283                        "refc %d\n", de->d_name.len, de->d_name.name, de,
284                        de->d_parent, de->d_inode, atomic_read(&de->d_count));
285                 return dentry;
286         }
287
288         spin_unlock(&dcache_lock);
289
290         return de;
291 }
292
293 static int lookup_it_finish(struct ptlrpc_request *request, int offset,
294                             struct lookup_intent *it, void *data)
295 {
296         struct it_cb_data *icbd = data;
297         struct dentry **de = icbd->icbd_childp;
298         struct inode *parent = icbd->icbd_parent;
299         struct ll_sb_info *sbi = ll_i2sbi(parent);
300         struct dentry *dentry = *de, *saved = *de;
301         struct inode *inode = NULL;
302         int rc;
303
304         /* NB 1 request reference will be taken away by ll_intent_lock()
305          * when I return */
306         if (!it_disposition(it, DISP_LOOKUP_NEG)) {
307                 ENTRY;
308
309                 rc = ll_prep_inode(sbi->ll_dt_exp, sbi->ll_md_exp,
310                                    &inode, request, offset, dentry->d_sb);
311                 if (rc)
312                         RETURN(rc);
313
314                 CDEBUG(D_DLMTRACE, "setting l_data to inode %p (%lu/%u)\n",
315                        inode, inode->i_ino, inode->i_generation);
316                 
317                 mdc_set_lock_data(NULL, &LUSTRE_IT(it)->it_lock_handle, inode);
318                 
319                 /* If this is a stat, get the authoritative file size */
320                 if (it->it_op == IT_GETATTR && S_ISREG(inode->i_mode) &&
321                     ll_i2info(inode)->lli_smd != NULL) {
322                         struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
323                         ldlm_error_t rc;
324
325                         LASSERT(lsm->lsm_object_id != 0);
326
327                         /* bug 2334: drop MDS lock before acquiring OST lock */
328                         ll_intent_drop_lock(it);
329
330                         if (!LLI_HAVE_FLSIZE(inode)) {
331                                 CDEBUG(D_INODE, "retrieve size from OSS\n");
332                                 rc = ll_glimpse_size(inode);
333                                 if (rc) {
334                                         iput(inode);
335                                         RETURN(rc);
336                                 }
337                         }
338                 }
339
340                 dentry = *de = ll_find_alias(inode, dentry);
341         } else {
342                 ENTRY;
343         }
344
345         dentry->d_op = &ll_d_ops;
346         ll_set_dd(dentry);
347
348         if (dentry == saved)
349                 d_add(dentry, inode);
350
351         RETURN(0);
352 }
353
354 static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
355                                    struct nameidata *nd, int flags)
356 {
357         struct lookup_intent *it = flags ? &nd->intent.open : NULL;
358         struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
359         struct dentry *save = dentry, *retval;
360         struct ptlrpc_request *req = NULL;
361         int rc, gns_it, gns_flags;
362         struct it_cb_data icbd;
363         struct lustre_id pid;
364         ENTRY;
365
366         if (dentry->d_name.len > EXT3_NAME_LEN)
367                 RETURN(ERR_PTR(-ENAMETOOLONG));
368
369         CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n",
370                dentry->d_name.len, dentry->d_name.name, parent->i_ino,
371                parent->i_generation, parent, LL_IT2STR(it));
372
373         if (d_mountpoint(dentry))
374                 CERROR("Tell Peter, lookup on mtpt, it %s\n", LL_IT2STR(it));
375
376         if (nd != NULL)
377                 nd->mnt->mnt_last_used = jiffies;
378
379         gns_it = nd ? nd->intent.open.it_op : IT_OPEN;
380         gns_flags = nd ? nd->flags : LOOKUP_CONTINUE;
381         ll_frob_intent(&it, &lookup_it);
382
383         icbd.icbd_childp = &dentry;
384         icbd.icbd_parent = parent;
385         ll_inode2id(&pid, parent);
386
387         rc = md_intent_lock(ll_i2mdexp(parent), &pid, (char *)dentry->d_name.name,
388                             dentry->d_name.len, NULL, 0, NULL, it, flags, &req,
389                             ll_mdc_blocking_ast);
390         if (rc < 0)
391                 GOTO(out, retval = ERR_PTR(rc));
392
393         rc = lookup_it_finish(req, 1, it, &icbd);
394         if (rc != 0) {
395                 ll_intent_release(it);
396                 GOTO(out, retval = ERR_PTR(rc));
397         }
398
399         ll_lookup_finish_locks(it, dentry);
400
401         if (nd && dentry->d_inode != NULL &&
402             dentry->d_inode->i_mode & S_ISUID && S_ISDIR(dentry->d_inode->i_mode) &&
403             ((gns_flags & LOOKUP_CONTINUE) || (gns_it & (IT_CHDIR | IT_OPEN))))
404         {
405                 CDEBUG(D_DENTRY, "possible GNS dentry %*s %p found, "
406                        "mounting it\n", (int)dentry->d_name.len,
407                        dentry->d_name.name, dentry);
408                 
409                 rc = ll_gns_mount_object(dentry, nd->mnt);
410                 if (rc) {
411                         /* 
412                          * just reporting about GNS failures, lookup() is
413                          * successful, do not stop it.
414                          *
415                          * GNS failure may be that object is found in SUID bit
416                          * marked dir but it is not regular file and we should
417                          * lookup further until we find correct mount
418                          * object. This will allow to perform GNS mount is the
419                          * following case for instance:
420                          *
421                          * /mnt/lustre/gns_mount/.mntinfo/.mntinfo/..../.mntinfo
422                          * where all ".mntinfo" are dirs and only last one is
423                          * reg file.
424                          */
425                         CDEBUG(D_DENTRY, "failed to mount %*s, err %d\n",
426                                (int)dentry->d_name.len, dentry->d_name.name, rc);
427                 }
428         }
429         
430         if (dentry == save)
431                 GOTO(out, retval = NULL);
432         else
433                 GOTO(out, retval = dentry);
434  out:
435         if (req)
436                 ptlrpc_req_finished(req);
437         if (it == &lookup_it)
438                 ll_intent_release(it);
439         if (dentry->d_inode)
440                 CDEBUG(D_INODE, "lookup 0x%p in %lu/%lu: %*s -> %lu/%lu\n",
441                        dentry,
442                        (unsigned long) parent->i_ino,
443                        (unsigned long) parent->i_generation,
444                        dentry->d_name.len, dentry->d_name.name,
445                        (unsigned long) dentry->d_inode->i_ino,
446                        (unsigned long) dentry->d_inode->i_generation);
447         else
448                 CDEBUG(D_INODE, "lookup 0x%p in %lu/%lu: %*s -> ??\n",
449                        dentry,
450                        (unsigned long) parent->i_ino,
451                        (unsigned long) parent->i_generation,
452                        dentry->d_name.len, dentry->d_name.name);
453         return retval;
454 }
455
456 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
457 static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
458                                    struct nameidata *nd)
459 {
460         struct dentry *de;
461         ENTRY;
462
463         if (nd && nd->flags & LOOKUP_LAST && !(nd->flags & LOOKUP_LINK_NOTLAST))
464                 de = ll_lookup_it(parent, dentry, nd, nd->flags);
465         else
466                 de = ll_lookup_it(parent, dentry, nd, 0);
467
468         RETURN(de);
469 }
470 #endif
471
472 /* We depend on "mode" being set with the proper file type/umask by now */
473 static struct inode *ll_create_node(struct inode *dir, const char *name,
474                                     int namelen, const void *data, int datalen,
475                                     int mode, __u64 extra,
476                                     struct lookup_intent *it)
477 {
478         struct inode *inode = NULL;
479         struct ptlrpc_request *request = NULL;
480         struct ll_sb_info *sbi = ll_i2sbi(dir);
481         int rc;
482         ENTRY;
483
484
485         LASSERT(it && LUSTRE_IT(it)->it_disposition);
486   
487         request = LUSTRE_IT(it)->it_data;
488         rc = ll_prep_inode(sbi->ll_dt_exp, sbi->ll_md_exp,
489                            &inode, request, 1, dir->i_sb);
490         if (rc)
491                 GOTO(out, inode = ERR_PTR(rc));
492
493         LASSERT(list_empty(&inode->i_dentry));
494
495         /* We asked for a lock on the directory, but were granted a
496          * lock on the inode.  Since we finally have an inode pointer,
497          * stuff it in the lock. */
498         CDEBUG(D_DLMTRACE, "setting l_ast_data to inode %p (%lu/%u)\n",
499                inode, inode->i_ino, inode->i_generation);
500         mdc_set_lock_data(NULL, &LUSTRE_IT(it)->it_lock_handle, inode);
501         EXIT;
502  out:
503         ptlrpc_req_finished(request);
504         return inode;
505 }
506
507 /*
508  * By the time this is called, we already have created the directory cache
509  * entry for the new file, but it is so far negative - it has no inode.
510  *
511  * We defer creating the OBD object(s) until open, to keep the intent and
512  * non-intent code paths similar, and also because we do not have the MDS
513  * inode number before calling ll_create_node() (which is needed for LOV),
514  * so we would need to do yet another RPC to the MDS to store the LOV EA
515  * data on the MDS.  If needed, we would pass the PACKED lmm as data and
516  * lmm_size in datalen (the MDS still has code which will handle that).
517  *
518  * If the create succeeds, we fill in the inode information
519  * with d_instantiate().
520  */
521 static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode,
522                         struct lookup_intent *it)
523 {
524         struct inode *inode;
525         struct ptlrpc_request *request = LUSTRE_IT(it)->it_data;
526         struct obd_export *md_exp = ll_i2mdexp(dir); 
527         int rc = 0;
528         ENTRY;
529
530         CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n",
531                dentry->d_name.len, dentry->d_name.name, dir->i_ino,
532                dir->i_generation, dir, LL_IT2STR(it));
533
534         rc = it_open_error(DISP_OPEN_CREATE, it);
535         if (rc)
536                 RETURN(rc);
537
538         mdc_store_inode_generation(md_exp, request, MDS_REQ_INTENT_REC_OFF, 1);
539         inode = ll_create_node(dir, (char *)dentry->d_name.name,
540                                dentry->d_name.len, NULL, 0, mode, 0, it);
541         if (IS_ERR(inode))
542                 RETURN(PTR_ERR(inode));
543
544         d_instantiate(dentry, inode);
545         RETURN(0);
546 }
547
548 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
549 static int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
550 {
551         return ll_create_it(dir, dentry, mode, &nd->intent.open);
552 }
553 #endif
554
555 static void ll_update_times(struct ptlrpc_request *request, int offset,
556                             struct inode *inode)
557 {
558         struct mds_body *body = lustre_msg_buf(request->rq_repmsg, offset,
559                                                sizeof(*body));
560         LASSERT(body);
561
562         if (body->valid & OBD_MD_FLMTIME &&
563             body->mtime > LTIME_S(inode->i_mtime)) {
564                 CDEBUG(D_INODE, "setting ino %lu mtime from %lu to %u\n",
565                        inode->i_ino, LTIME_S(inode->i_mtime), body->mtime);
566                 LTIME_S(inode->i_mtime) = body->mtime;
567         }
568         if (body->valid & OBD_MD_FLCTIME &&
569             body->ctime > LTIME_S(inode->i_ctime))
570                 LTIME_S(inode->i_ctime) = body->ctime;
571 }
572
573 static int ll_mknod_raw(struct nameidata *nd, int mode, dev_t rdev)
574 {
575         struct ptlrpc_request *request = NULL;
576         struct inode *dir = nd->dentry->d_inode;
577         struct ll_sb_info *sbi = ll_i2sbi(dir);
578         struct mdc_op_data *op_data;
579         int err = -EMLINK;
580         ENTRY;
581
582         CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
583                nd->last.len, nd->last.name, dir->i_ino,
584                dir->i_generation, dir);
585
586         mode &= ~current->fs->umask;
587
588         switch (mode & S_IFMT) {
589         case 0:
590         case S_IFREG:
591                 mode |= S_IFREG; /* for mode = 0 case, fallthrough */
592         case S_IFCHR:
593         case S_IFBLK:
594         case S_IFIFO:
595         case S_IFSOCK:
596                 OBD_ALLOC(op_data, sizeof(*op_data));
597                 if (op_data == NULL)
598                         RETURN(-ENOMEM);
599                 ll_prepare_mdc_data(op_data, dir, NULL,
600                                     (char *)nd->last.name, 
601                                     nd->last.len, 0);
602                 
603                 err = md_create(sbi->ll_md_exp, op_data, NULL, 0, mode,
604                                 current->fsuid, current->fsgid, rdev,
605                                 &request);
606                 OBD_FREE(op_data, sizeof(*op_data));
607                 if (err == 0)
608                         ll_update_times(request, 0, dir);
609                 ptlrpc_req_finished(request);
610                 break;
611         case S_IFDIR:
612                 err = -EPERM;
613                 break;
614         default:
615                 err = -EINVAL;
616         }
617         RETURN(err);
618 }
619
620 static int ll_mknod(struct inode *dir, struct dentry *dchild,
621                     int mode, ll_dev_t rdev)
622 {
623         struct ptlrpc_request *request = NULL;
624         struct inode *inode = NULL;
625         struct ll_sb_info *sbi = ll_i2sbi(dir);
626         struct mdc_op_data *op_data;
627         int err = -EMLINK;
628         ENTRY;
629
630         CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
631                dchild->d_name.len, dchild->d_name.name,
632                dir->i_ino, dir->i_generation, dir);
633
634         mode &= ~current->fs->umask;
635
636         switch (mode & S_IFMT) {
637         case 0:
638         case S_IFREG:
639                 mode |= S_IFREG; /* for mode = 0 case, fallthrough */
640         case S_IFCHR:
641         case S_IFBLK:
642         case S_IFIFO:
643         case S_IFSOCK:
644                 OBD_ALLOC(op_data, sizeof(*op_data));
645                 if (op_data == NULL)
646                         RETURN(-ENOMEM);
647
648                 ll_prepare_mdc_data(op_data, dir, NULL,
649                                     (char *)dchild->d_name.name, 
650                                     dchild->d_name.len, 0);
651                 
652                 err = md_create(sbi->ll_md_exp, op_data, NULL, 0, mode,
653                                 current->fsuid, current->fsgid, rdev,
654                                 &request);
655                 OBD_FREE(op_data, sizeof(*op_data));
656                 if (err)
657                         GOTO(out_err, err);
658
659                 ll_update_times(request, 0, dir);
660                 err = ll_prep_inode(sbi->ll_dt_exp, sbi->ll_md_exp,
661                                     &inode, request, 0, dchild->d_sb);
662                 if (err)
663                         GOTO(out_err, err);
664                 break;
665         case S_IFDIR:
666                 RETURN(-EPERM);
667                 break;
668         default:
669                 RETURN(-EINVAL);
670         }
671
672         d_instantiate(dchild, inode);
673         EXIT;
674  out_err:
675         ptlrpc_req_finished(request);
676         return err;
677 }
678
679 static int ll_symlink_raw(struct nameidata *nd, const char *tgt)
680 {
681         const char *name = (char *)nd->last.name;
682         struct inode *dir = nd->dentry->d_inode;
683         struct ptlrpc_request *request = NULL;
684         struct ll_sb_info *sbi = ll_i2sbi(dir);
685         struct mdc_op_data *op_data;
686         int len = nd->last.len;
687         int err = -EMLINK;
688         ENTRY;
689
690         CDEBUG(D_VFSTRACE, "VFS Op:name=%*s,dir=%lu/%u(%p),target=%s\n",
691                nd->last.len, nd->last.name, dir->i_ino, dir->i_generation,
692                dir, tgt);
693
694         if (dir->i_nlink >= EXT3_LINK_MAX)
695                 RETURN(err);
696
697         OBD_ALLOC(op_data, sizeof(*op_data));
698         if (op_data == NULL)
699                 RETURN(-ENOMEM);
700         ll_prepare_mdc_data(op_data, dir, NULL, name, len, 0);
701         LASSERT(tgt);
702         err = md_create(sbi->ll_md_exp, op_data,
703                         tgt, strlen(tgt) + 1, S_IFLNK | S_IRWXUGO,
704                         current->fsuid, current->fsgid, 0, &request);
705         OBD_FREE(op_data, sizeof(*op_data));
706         if (err == 0)
707                 ll_update_times(request, 0, dir);
708         
709         ptlrpc_req_finished(request);
710         RETURN(err);
711 }
712
713 static int ll_link_raw(struct nameidata *srcnd, struct nameidata *tgtnd)
714 {
715         struct inode *src = srcnd->dentry->d_inode;
716         struct inode *dir = tgtnd->dentry->d_inode;
717         struct ptlrpc_request *request = NULL;
718         struct ll_sb_info *sbi = ll_i2sbi(dir);
719         struct mdc_op_data *op_data;
720         int err;
721         ENTRY;
722
723         CDEBUG(D_VFSTRACE,
724                "VFS Op: inode=%lu/%u(%p), dir=%lu/%u(%p), target=%.*s\n",
725                src->i_ino, src->i_generation, src, dir->i_ino,
726                dir->i_generation, dir, tgtnd->last.len, tgtnd->last.name);
727
728         OBD_ALLOC(op_data, sizeof(*op_data));
729         if (op_data == NULL)
730                 RETURN(-ENOMEM);
731
732         ll_prepare_mdc_data(op_data, src, dir,
733                             (char *)tgtnd->last.name, 
734                             tgtnd->last.len, 0);
735         
736         err = md_link(sbi->ll_md_exp, op_data, &request);
737         OBD_FREE(op_data, sizeof(*op_data));
738         if (err == 0)
739                 ll_update_times(request, 0, dir);
740         ptlrpc_req_finished(request);
741         RETURN(err);
742 }
743
744
745 static int ll_mkdir_raw(struct nameidata *nd, int mode)
746 {
747         struct inode *dir = nd->dentry->d_inode;
748         struct ptlrpc_request *request = NULL;
749         struct ll_sb_info *sbi = ll_i2sbi(dir);
750         struct mdc_op_data *op_data;
751         int err = -EMLINK;
752         ENTRY;
753         CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
754                nd->last.len, nd->last.name, dir->i_ino, dir->i_generation, dir);
755
756         mode = (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask) | S_IFDIR;
757         OBD_ALLOC(op_data, sizeof(*op_data));
758         if (op_data == NULL)
759                 RETURN(-ENOMEM);
760
761         ll_prepare_mdc_data(op_data, dir, NULL,
762                             (char *)nd->last.name, 
763                             nd->last.len, 0);
764         
765         err = md_create(sbi->ll_md_exp, op_data, NULL, 0, mode,
766                         current->fsuid, current->fsgid, 0, &request);
767         OBD_FREE(op_data, sizeof(*op_data));
768         if (err == 0)
769                 ll_update_times(request, 0, dir);
770         ptlrpc_req_finished(request);
771         RETURN(err);
772 }
773
774 static int ll_rmdir_raw(struct nameidata *nd)
775 {
776         struct inode *dir = nd->dentry->d_inode;
777         struct ptlrpc_request *request = NULL;
778         struct mdc_op_data *op_data;
779         int rc;
780
781         ENTRY;
782         CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
783                nd->last.len, nd->last.name, dir->i_ino,
784                dir->i_generation, dir);
785
786         OBD_ALLOC(op_data, sizeof(*op_data));
787         if (op_data == NULL)
788                 RETURN(-ENOMEM);
789
790         ll_prepare_mdc_data(op_data, dir, NULL,
791                             (char *)nd->last.name, 
792                             nd->last.len, S_IFDIR);
793         
794         rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request);
795         OBD_FREE(op_data, sizeof(*op_data));
796         if (rc == 0)
797                 ll_update_times(request, 0, dir);
798         ptlrpc_req_finished(request);
799         RETURN(rc);
800 }
801
802 static int ll_unlink_raw(struct nameidata *nd)
803 {
804         struct inode *dir = nd->dentry->d_inode;
805         struct ptlrpc_request *request = NULL;
806         struct mdc_op_data *op_data;
807         int rc;
808         ENTRY;
809         CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
810                nd->last.len, nd->last.name, dir->i_ino,
811                dir->i_generation, dir);
812
813         OBD_ALLOC(op_data, sizeof(*op_data));
814         if (op_data == NULL)
815                 RETURN(-ENOMEM);
816         ll_prepare_mdc_data(op_data, dir, NULL,
817                             (char *)nd->last.name, nd->last.len, 0);
818         rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request);
819         OBD_FREE(op_data, sizeof(*op_data));
820         if (rc)
821                 GOTO(out, rc);
822         ll_update_times(request, 0, dir);
823         EXIT;
824 out:
825         ptlrpc_req_finished(request);
826         return rc;
827 }
828
829 static int ll_rename_raw(struct nameidata *srcnd, struct nameidata *tgtnd)
830 {
831         struct inode *src = srcnd->dentry->d_inode;
832         struct inode *tgt = tgtnd->dentry->d_inode;
833         struct ptlrpc_request *request = NULL;
834         struct ll_sb_info *sbi = ll_i2sbi(src);
835         struct mdc_op_data *op_data;
836         int err;
837         ENTRY;
838         
839         if (srcnd->mnt != tgtnd->mnt)
840                 RETURN(-EXDEV);
841
842         CDEBUG(D_VFSTRACE,"VFS Op:oldname=%.*s,src_dir=%lu/%u(%p),newname=%.*s,"
843                "tgt_dir=%lu/%u(%p)\n", srcnd->last.len, srcnd->last.name,
844                src->i_ino, src->i_generation, src, tgtnd->last.len,
845                tgtnd->last.name, tgt->i_ino, tgt->i_generation, tgt);
846
847         OBD_ALLOC(op_data, sizeof(*op_data));
848         if (op_data == NULL)
849                 RETURN(-ENOMEM);
850         ll_prepare_mdc_data(op_data, src, tgt, NULL, 0, 0);
851         err = md_rename(sbi->ll_md_exp, op_data, (char *)srcnd->last.name, 
852                         srcnd->last.len, (char *)tgtnd->last.name,
853                         tgtnd->last.len, &request);
854         OBD_FREE(op_data, sizeof(*op_data));
855         if (!err) {
856                 ll_update_times(request, 0, src);
857                 ll_update_times(request, 0, tgt);
858         }
859
860         ptlrpc_req_finished(request);
861         RETURN(err);
862 }
863
864 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
865 #define LLITE_IT_RAWOPS (IT_MKNOD|IT_MKDIR|IT_SYMLINK|IT_LINK|IT_UNLINK|IT_RMDIR|IT_RENAME)
866 static int ll_rawop_from_intent(struct nameidata *nd)
867 {
868         int error = 0;
869
870         if (!nd || !(nd->intent.open.op & LLITE_IT_RAWOPS))
871                 return 0;
872
873         switch (nd->intent.open.op) {
874         case IT_MKNOD:
875                 error = ll_mknod_raw(nd, nd->intent.open.create_mode,
876                                      nd->intent.open.create.dev);
877                 break;
878         case IT_MKDIR:
879                 error = ll_mkdir_raw(nd, nd->intent.open.create_mode);
880                 break;
881         case IT_RMDIR:
882                 error = ll_rmdir_raw(nd);
883                 break;
884         case IT_UNLINK:
885                 error = ll_unlink_raw(nd);
886                 break;
887         case IT_SYMLINK:
888                 LASSERT(nd->intent.open.create.link);
889                 error = ll_symlink_raw(nd, nd->intent.open.create.link);
890                 break;
891         case IT_LINK:
892                 error = ll_link_raw(nd->intent.open.create.source_nd, nd);
893                 break;
894         case IT_RENAME:
895                 LASSERT(nd->intent.open.create.source_nd);
896                 error = ll_rename_raw(nd->intent.open.create.source_nd, nd);
897                 break;
898         default:
899                 LBUG();
900         }
901         if (error != -EOPNOTSUPP)
902                 nd->intent.open.flags |= IT_STATUS_RAW;
903
904         return error;
905 }
906 #endif
907
908 struct inode_operations ll_dir_inode_operations = {
909         .mknod              = ll_mknod,
910         .setattr            = ll_setattr,
911 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
912         .create_it          = ll_create_it,
913         .lookup_it          = ll_lookup_it,
914         .revalidate_it      = ll_inode_revalidate_it,
915 #else
916         .lookup             = ll_lookup_nd,
917         .create             = ll_create_nd,
918         .getattr            = ll_getattr,
919         .endparentlookup    = ll_rawop_from_intent,
920 #endif
921         .setxattr           = ll_setxattr,
922         .getxattr           = ll_getxattr,
923         .listxattr          = ll_listxattr,
924         .removexattr        = ll_removexattr,
925         .permission         = ll_inode_permission,
926 };