커널 sget()함수 분석 질문

yeilho의 이미지

안녕하세요.

커널 소스를 보는데, 이해가 되지 않는 부분이 있어서 질문 올립니다.
아래 함수는 sget() 함수로 보통 마운트 할때 불려지는 함수입니다.
제가 궁금한 내용은 만약에 test 하고 set 함수가 제공되었고, 특히 test함수가 해당 sb가 있으면 1을 리턴하고 그렇지 않으면 0을 리턴한다고 했을때 코드가 어떻게 흘러가야
err = set(s, data);
라인으로 갈수 있는지 잘 모르겠습니다.

저의 부족한 실력으로 인해 함수를 읽다보니 위의 언급한 라인 밑으로는 내려가는 경우를 찾을수가 없네요.

조언 부탁드립니다.

struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
                        void *data)
{
        struct super_block *s = NULL;
        struct list_head *p;
        int err;

retry:
        spin_lock(&sb_lock);
        if (test) list_for_each(p, &type->fs_supers) {
                struct super_block *old;
                old = list_entry(p, struct super_block, s_instances);
                if (!test(old, data))
                        continue;
                if (!grab_super(old))
                        goto retry;
                if (s)
                        destroy_super(s);
                return old;
        }
        if (!s) {
                spin_unlock(&sb_lock);
                s = alloc_super();
                if (!s)
                        return ERR_PTR(-ENOMEM);
                goto retry;
        }

        err = set(s, data);
        if (err) {
                spin_unlock(&sb_lock);
                destroy_super(s);
                return ERR_PTR(err);
        }
        s->s_type = type;
        strlcpy(s->s_id, type->name, sizeof(s->s_id));
        list_add_tail(&s->s_list, &super_blocks);
        list_add(&s->s_instances, &type->fs_supers);
        spin_unlock(&sb_lock);
        get_filesystem(type);
        return s;
}
yeilho의 이미지

글을 올리고 다시 소스를 보니까 답이 보이는것 같습니다. :D

아마도 처음에 loop을 돌때는 해당 sb가 없을거구, 그러니까
아래 문장으로 내려가서 메모리를 할당한후, 다시 retry:로 올라갑니다.

        if (!s) { 
                spin_unlock(&sb_lock); 
                s = alloc_super(); 
                if (!s) 
                        return ERR_PTR(-ENOMEM); 
                goto retry; 
        } 

그리고 나서, loop을 돌다가 저희가 할당한 sb을 만나는 경우, 아래 문장에서 다시 retry:로 가게 되니까 destroy_super()로 내려가지 않습니다.

if (!grab_super(old)) 
    goto retry;

loop을 다돌고 나서 이번에 if(!s) {...} 를 만나게 되면 이미 메모리가 할당 되어 있으니까 set() 문장으로 결국 내려가게 되는군요.

혹시 제해석이 틀렸다면 지적 부탁드릴께요.
감사합니다.

일호 <><

Linux rules!!!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.